diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -65,6 +65,10 @@ fixes `Issue 53044 `_. - Allow `-Wno-gnu` to silence GNU extension diagnostics for pointer arithmetic diagnostics. Fixes `Issue 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 `_ + and `Issue 54443 `_. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4769,12 +4769,13 @@ return DAR_FailedAlreadyDiagnosed; } - if (const auto *AT = Type.getType()->getAs()) { + QualType MaybeAuto = Type.getType().getNonReferenceType(); + while (MaybeAuto->isPointerType()) + MaybeAuto = MaybeAuto->getPointeeType(); + if (const auto *AT = MaybeAuto->getAs()) { 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; } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -171,7 +171,7 @@ } namespace PR49188 { - template concept C = false; // expected-note 6 {{because 'false' evaluated to false}} + template 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 @@ } 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 PR53911 { - template concept C = false; + template 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 @@ }; void (*f2)() = B::f; // expected-error {{address of overloaded function 'f' does not match required type}} } + +namespace PR54443 { + +template +struct is_same { static constexpr bool value = false; }; + +template +struct is_same { static constexpr bool value = true; }; + +template +concept same_as = is_same::value; // expected-note-re 4 {{because {{.*}} evaluated to false}} + +int const &f(); + +same_as auto i1 = f(); // expected-error {{deduced type 'int' does not satisfy 'same_as'}} +same_as auto &i2 = f(); +same_as auto &&i3 = f(); // expected-error {{deduced type 'const int &' does not satisfy 'same_as'}} + +same_as auto i4 = f(); // expected-error {{deduced type 'int' does not satisfy 'same_as'}} +same_as auto &i5 = f(); // expected-error {{deduced type 'const int' does not satisfy 'same_as'}} +same_as auto &&i6 = f(); + +template +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'}} +}