forked from OSchip/llvm-project
[Concepts] Fix placeholder constraints when references are involved
Placeholder types were not checked for constraint satisfaction when modified by references or pointers. The behavior now matches that of GCC and MSVC. Are there other modifiers we might need to "peel"? I'm not sure my approach to this is the 'right' way to fix this, the loop feels a bit clunky. GitHub issues [[ https://github.com/llvm/llvm-project/issues/54443 | #54443 ]], [[ https://github.com/llvm/llvm-project/issues/53911 | #53911 ]] Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D122083
This commit is contained in:
parent
da167a53c8
commit
94fd00f41e
|
@ -65,6 +65,10 @@ Bug Fixes
|
|||
fixes `Issue 53044 <https://github.com/llvm/llvm-project/issues/53044>`_.
|
||||
- Allow `-Wno-gnu` to silence GNU extension diagnostics for pointer arithmetic
|
||||
diagnostics. Fixes `Issue 54444 <https://github.com/llvm/llvm-project/issues/54444>`_.
|
||||
- Placeholder constraints, as in `Concept auto x = f();`, were not checked when modifiers
|
||||
like ``auto&`` or ``auto**`` were added. These constraints are now checked.
|
||||
This fixes `Issue 53911 <https://github.com/llvm/llvm-project/issues/53911>`_
|
||||
and `Issue 54443 <https://github.com/llvm/llvm-project/issues/54443>`_.
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -4769,12 +4769,13 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
|
|||
return DAR_FailedAlreadyDiagnosed;
|
||||
}
|
||||
|
||||
if (const auto *AT = Type.getType()->getAs<AutoType>()) {
|
||||
QualType MaybeAuto = Type.getType().getNonReferenceType();
|
||||
while (MaybeAuto->isPointerType())
|
||||
MaybeAuto = MaybeAuto->getPointeeType();
|
||||
if (const auto *AT = MaybeAuto->getAs<AutoType>()) {
|
||||
if (AT->isConstrained() && !IgnoreConstraints) {
|
||||
auto ConstraintsResult =
|
||||
CheckDeducedPlaceholderConstraints(*this, *AT,
|
||||
Type.getContainedAutoTypeLoc(),
|
||||
DeducedType);
|
||||
auto ConstraintsResult = CheckDeducedPlaceholderConstraints(
|
||||
*this, *AT, Type.getContainedAutoTypeLoc(), DeducedType);
|
||||
if (ConstraintsResult != DAR_Succeeded)
|
||||
return ConstraintsResult;
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ namespace PR50561 {
|
|||
}
|
||||
|
||||
namespace PR49188 {
|
||||
template<class T> concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
|
||||
template<class T> concept C = false; // expected-note 7 {{because 'false' evaluated to false}}
|
||||
|
||||
C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
|
||||
return void();
|
||||
|
@ -189,7 +189,7 @@ namespace PR49188 {
|
|||
}
|
||||
C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
|
||||
}
|
||||
C auto& f7() { // expected-error {{cannot form a reference to 'void'}}
|
||||
C auto& f7() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
|
||||
return void();
|
||||
}
|
||||
C auto& f8() {
|
||||
|
@ -199,13 +199,16 @@ namespace PR49188 {
|
|||
}
|
||||
}
|
||||
namespace PR53911 {
|
||||
template<class T> concept C = false;
|
||||
template<class T> concept C = false; // expected-note 3 {{because 'false' evaluated to false}}
|
||||
|
||||
C auto *f1() {
|
||||
return (void*)nullptr; // FIXME: should error
|
||||
C auto *f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
|
||||
return (void*)nullptr;
|
||||
}
|
||||
C auto *f2() {
|
||||
return (int*)nullptr; // FIXME: should error
|
||||
C auto *f2() { // expected-error {{deduced type 'int' does not satisfy 'C'}}
|
||||
return (int*)nullptr;
|
||||
}
|
||||
C auto *****f3() { // expected-error {{deduced type 'int' does not satisfy 'C'}}
|
||||
return (int*****)nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,3 +225,34 @@ struct B {
|
|||
};
|
||||
void (*f2)() = B::f; // expected-error {{address of overloaded function 'f' does not match required type}}
|
||||
}
|
||||
|
||||
namespace PR54443 {
|
||||
|
||||
template <class T, class U>
|
||||
struct is_same { static constexpr bool value = false; };
|
||||
|
||||
template <class T>
|
||||
struct is_same<T, T> { static constexpr bool value = true; };
|
||||
|
||||
template <class T, class U>
|
||||
concept same_as = is_same<T, U>::value; // expected-note-re 4 {{because {{.*}} evaluated to false}}
|
||||
|
||||
int const &f();
|
||||
|
||||
same_as<int const> auto i1 = f(); // expected-error {{deduced type 'int' does not satisfy 'same_as<const int>'}}
|
||||
same_as<int const> auto &i2 = f();
|
||||
same_as<int const> auto &&i3 = f(); // expected-error {{deduced type 'const int &' does not satisfy 'same_as<const int>'}}
|
||||
|
||||
same_as<int const &> auto i4 = f(); // expected-error {{deduced type 'int' does not satisfy 'same_as<const int &>'}}
|
||||
same_as<int const &> auto &i5 = f(); // expected-error {{deduced type 'const int' does not satisfy 'same_as<const int &>'}}
|
||||
same_as<int const &> auto &&i6 = f();
|
||||
|
||||
template <class T>
|
||||
concept C = false; // expected-note 3 {{because 'false' evaluated to false}}
|
||||
|
||||
int **const &g();
|
||||
|
||||
C auto **j1 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
|
||||
C auto **&j2 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
|
||||
C auto **&&j3 = g(); // expected-error {{deduced type 'int' does not satisfy 'C'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue