diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -132,6 +132,10 @@ (`#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 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1074,7 +1074,6 @@ if (InNonInstantiationSFINAEContext) return std::optional(nullptr); - bool SawLambdaSubstitution = false; for (SmallVectorImpl::const_reverse_iterator Active = CodeSynthesisContexts.rbegin(), ActiveEnd = CodeSynthesisContexts.rend(); @@ -1101,10 +1100,8 @@ // 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 @@ // 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 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -150,3 +150,24 @@ 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 --- a/clang/test/SemaCXX/lambda-unevaluated.cpp +++ b/clang/test/SemaCXX/lambda-unevaluated.cpp @@ -155,17 +155,24 @@ 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 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -15839,7 +15839,7 @@ 2672 open Lambda body SFINAE is still required, contrary to intent and note - Not resolved + Clang 18 2673