diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index babade1c70b06..d3757c833ef83 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -157,6 +157,10 @@ Bug Fixes to C++ Support (`#35574 _`) and (`#27224 _`). +- Clang emits an error on substitution failure within lambda body inside a + requires-expression. This fixes: + (`#64138 _`). + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 8702e2ca3a1b3..e7318880af8d3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1074,7 +1074,6 @@ std::optional Sema::isSFINAEContext() const { if (InNonInstantiationSFINAEContext) return std::optional(nullptr); - bool SawLambdaSubstitution = false; for (SmallVectorImpl::const_reverse_iterator Active = CodeSynthesisContexts.rbegin(), ActiveEnd = CodeSynthesisContexts.rend(); @@ -1101,10 +1100,8 @@ std::optional Sema::isSFINAEContext() const { // A lambda-expression appearing in a function type or a template // parameter is not considered part of the immediate context for the // purposes of template argument deduction. - - // We need to check parents. - SawLambdaSubstitution = true; - break; + // CWG2672: A lambda-expression body is never in the immediate context. + return std::nullopt; case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: case CodeSynthesisContext::PriorTemplateArgumentSubstitution: @@ -1120,8 +1117,6 @@ std::optional Sema::isSFINAEContext() const { // We're either substituting explicitly-specified template arguments, // deduced template arguments. SFINAE applies unless we are in a lambda // expression, see [temp.deduct]p9. - if (SawLambdaSubstitution) - return std::nullopt; [[fallthrough]]; case CodeSynthesisContext::ConstraintSubstitution: case CodeSynthesisContext::RequirementInstantiation: diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index e4b6156235ecc..8dd07b63deb43 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -150,3 +150,24 @@ static_assert(__is_same(decltype(i), I)); J j = { "ghi" }; // expected-error {{no viable constructor or deduction guide}} } + +namespace dr2672 { // dr2672: 18 open +template +void f(T) requires requires { []() { T::invalid; } (); }; // expected-error{{type 'int' cannot be used prior to '::'}} + // expected-note@-1{{while substituting into a lambda expression here}} + // expected-note@-2{{in instantiation of requirement here}} + // expected-note@-3{{while substituting template arguments into constraint expression here}} +void f(...); + +template +void bar(T) requires requires { + decltype([]() -> T {})::foo(); +}; +void bar(...); + +void m() { + f(0); // expected-note {{while checking constraint satisfaction for template 'f' required here}} + // expected-note@-1 {{in instantiation of function template specialization}} + bar(0); +} +} diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp index 179c7327ebdff..10d4c2228ec9b 100644 --- a/clang/test/SemaCXX/lambda-unevaluated.cpp +++ b/clang/test/SemaCXX/lambda-unevaluated.cpp @@ -155,17 +155,24 @@ struct WithFoo { static void foo(); }; template concept lambda_works = requires { - []() { T::foo(); }; + []() { T::foo(); }; // expected-error{{type 'int' cannot be used prior to '::'}} + // expected-note@-1{{while substituting into a lambda expression here}} + // expected-note@-2{{in instantiation of requirement here}} + // expected-note@-4{{while substituting template arguments into constraint expression here}} }; -static_assert(!lambda_works); +static_assert(!lambda_works); // expected-note {{while checking the satisfaction of concept 'lambda_works' requested here}} static_assert(lambda_works); template -int* func(T) requires requires { []() { T::foo(); }; }; +int* func(T) requires requires { []() { T::foo(); }; }; // expected-error{{type 'int' cannot be used prior to '::'}} + // expected-note@-1{{while substituting into a lambda expression here}} + // expected-note@-2{{in instantiation of requirement here}} + // expected-note@-3{{while substituting template arguments into constraint expression here}} double* func(...); -static_assert(__is_same(decltype(func(0)), double*)); +static_assert(__is_same(decltype(func(0)), double*)); // expected-note {{while checking constraint satisfaction for template 'func' required here}} + // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func'}} static_assert(__is_same(decltype(func(WithFoo())), int*)); template diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index c950b5b08d1af..d044679d617a9 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -15839,7 +15839,7 @@

C++ defect report implementation status

2672 open Lambda body SFINAE is still required, contrary to intent and note - Not resolved + Clang 18 2673