diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c720e47dbe35b7..8f6c8b98b1322d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -929,6 +929,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Fixed a crash in constraint instantiation under nested lambdas with dependent parameters. - Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368). - Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849) - Fixed a failed assertion when attempting to convert an integer representing the difference diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index ca9c7cb9faadfb..e461827be1e9de 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -2379,23 +2379,37 @@ Sema::LambdaScopeForCallOperatorInstantiationRAII:: SemaRef.RebuildLambdaScopeInfo(cast(FD)); - FunctionDecl *Pattern = getPatternFunctionDecl(FD); - if (Pattern) { - SemaRef.addInstantiatedCapturesToScope(FD, Pattern, Scope, MLTAL); + FunctionDecl *FDPattern = getPatternFunctionDecl(FD); + if (!FDPattern) + return; - FunctionDecl *ParentFD = FD; - while (ShouldAddDeclsFromParentScope) { + SemaRef.addInstantiatedCapturesToScope(FD, FDPattern, Scope, MLTAL); - ParentFD = - dyn_cast(getLambdaAwareParentOfDeclContext(ParentFD)); - Pattern = - dyn_cast(getLambdaAwareParentOfDeclContext(Pattern)); + if (!ShouldAddDeclsFromParentScope) + return; - if (!ParentFD || !Pattern) - break; + llvm::SmallVector, 4> + ParentInstantiations; + while (true) { + FDPattern = + dyn_cast(getLambdaAwareParentOfDeclContext(FDPattern)); + FD = dyn_cast(getLambdaAwareParentOfDeclContext(FD)); - SemaRef.addInstantiatedParametersToScope(ParentFD, Pattern, Scope, MLTAL); - SemaRef.addInstantiatedLocalVarsToScope(ParentFD, Pattern, Scope); - } + if (!FDPattern || !FD) + break; + + ParentInstantiations.emplace_back(FDPattern, FD); + } + + // Add instantiated parameters and local vars to scopes, starting from the + // outermost lambda to the innermost lambda. This ordering ensures that + // parameters in inner lambdas can correctly depend on those defined + // in outer lambdas, e.g. auto L = [](auto... x) { + // return [](decltype(x)... y) { }; // `y` depends on `x` + // }; + + for (const auto &[FDPattern, FD] : llvm::reverse(ParentInstantiations)) { + SemaRef.addInstantiatedParametersToScope(FD, FDPattern, Scope, MLTAL); + SemaRef.addInstantiatedLocalVarsToScope(FD, FDPattern, Scope); } } diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index 280be71284f971..252ef08549a486 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -237,3 +237,17 @@ concept D = []() { return true; }(); D auto x = 0; } // namespace GH93821 + +namespace dependent_param_concept { +template void sink(Ts...) {} +void dependent_param() { + auto L = [](auto... x) { + return [](decltype(x)... y) { + return [](int z) + requires requires { sink(y..., z); } + {}; + }; + }; + L(0, 1)(1, 2)(1); +} +} // namespace dependent_param_concept