Fznamznon created this revision. Herald added a project: All. Fznamznon requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Per CWG 2672 substitution failure within the body of a lambda inside a requires-expression should be a hard error. Fixes https://github.com/llvm/llvm-project/issues/64138 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D156993 Files: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/SemaCXX/lambda-unevaluated.cpp Index: clang/test/SemaCXX/lambda-unevaluated.cpp =================================================================== --- clang/test/SemaCXX/lambda-unevaluated.cpp +++ clang/test/SemaCXX/lambda-unevaluated.cpp @@ -155,17 +155,24 @@ template <class T> 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<int>); +static_assert(!lambda_works<int>); // expected-note {{while checking the satisfaction of concept 'lambda_works<int>' requested here}} static_assert(lambda_works<WithFoo>); template <class T> -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<int>' required here}} + // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func<int>'}} static_assert(__is_same(decltype(func(WithFoo())), int*)); template <class T> Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1074,7 +1074,6 @@ if (InNonInstantiationSFINAEContext) return std::optional<TemplateDeductionInfo *>(nullptr); - bool SawLambdaSubstitution = false; for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator Active = CodeSynthesisContexts.rbegin(), ActiveEnd = CodeSynthesisContexts.rend(); @@ -1101,10 +1100,7 @@ // 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; + return std::nullopt; case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: case CodeSynthesisContext::PriorTemplateArgumentSubstitution: @@ -1120,8 +1116,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: Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -132,6 +132,10 @@ (`#35574 <https://github.com/llvm/llvm-project/issues/35574>_`) and (`#27224 <https://github.com/llvm/llvm-project/issues/27224>_`). +- Clang emits an error on substitution failure within lambda body inside a + requires-expression. This fixes: + (`#64138 <https://github.com/llvm/llvm-project/issues/64138>_`). + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template.
Index: clang/test/SemaCXX/lambda-unevaluated.cpp =================================================================== --- clang/test/SemaCXX/lambda-unevaluated.cpp +++ clang/test/SemaCXX/lambda-unevaluated.cpp @@ -155,17 +155,24 @@ template <class T> 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<int>); +static_assert(!lambda_works<int>); // expected-note {{while checking the satisfaction of concept 'lambda_works<int>' requested here}} static_assert(lambda_works<WithFoo>); template <class T> -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<int>' required here}} + // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func<int>'}} static_assert(__is_same(decltype(func(WithFoo())), int*)); template <class T> Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1074,7 +1074,6 @@ if (InNonInstantiationSFINAEContext) return std::optional<TemplateDeductionInfo *>(nullptr); - bool SawLambdaSubstitution = false; for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator Active = CodeSynthesisContexts.rbegin(), ActiveEnd = CodeSynthesisContexts.rend(); @@ -1101,10 +1100,7 @@ // 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; + return std::nullopt; case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: case CodeSynthesisContext::PriorTemplateArgumentSubstitution: @@ -1120,8 +1116,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: Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -132,6 +132,10 @@ (`#35574 <https://github.com/llvm/llvm-project/issues/35574>_`) and (`#27224 <https://github.com/llvm/llvm-project/issues/27224>_`). +- Clang emits an error on substitution failure within lambda body inside a + requires-expression. This fixes: + (`#64138 <https://github.com/llvm/llvm-project/issues/64138>_`). + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits