diff options
author | Younan Zhang <zyn7109@gmail.com> | 2025-01-21 14:16:17 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-21 14:16:17 +0800 |
commit | f07e5162d0e67ec980e0ea282cf294f377407b10 (patch) | |
tree | 22a13be1969bcc3b787b82802662193944f8260c /clang/lib/Sema | |
parent | 5cde6d2fdf1e2ededf10ac0a30187c3359a93828 (diff) | |
download | llvm-f07e5162d0e67ec980e0ea282cf294f377407b10.zip llvm-f07e5162d0e67ec980e0ea282cf294f377407b10.tar.gz llvm-f07e5162d0e67ec980e0ea282cf294f377407b10.tar.bz2 |
[Clang] Delegate part of SetupConstraintScope's job to LambdaScopeForCallOperatorInstantiationRAII (#123687)
Now that the RAII object has a dedicate logic for handling nested
lambdas, where the inner lambda could reference any
captures/variables/parameters from the outer lambda, we can shift the
responsibility for managing lambdas away from SetupConstraintScope().
I think this also makes the structure clearer.
Fixes https://github.com/llvm/llvm-project/issues/123441
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 28 |
2 files changed, 18 insertions, 22 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 539de00..6a40a59 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -752,6 +752,9 @@ bool Sema::SetupConstraintScope( FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, const MultiLevelTemplateArgumentList &MLTAL, LocalInstantiationScope &Scope) { + assert(!isLambdaCallOperator(FD) && + "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda " + "instantiations"); if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); InstantiatingTemplate Inst( @@ -777,14 +780,8 @@ bool Sema::SetupConstraintScope( // If this is a member function, make sure we get the parameters that // reference the original primary template. - // We walk up the instantiated template chain so that nested lambdas get - // handled properly. - // We should only collect instantiated parameters from the primary template. - // Otherwise, we may have mismatched template parameter depth! if (FunctionTemplateDecl *FromMemTempl = PrimaryTemplate->getInstantiatedFromMemberTemplate()) { - while (FromMemTempl->getInstantiatedFromMemberTemplate()) - FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate(); if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL)) return true; @@ -834,6 +831,9 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope( /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); + // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII. + if (isLambdaCallOperator(FD)) + return MLTAL; if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) return std::nullopt; diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 0c5467c..87b3ca5 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -2408,35 +2408,31 @@ Sema::LambdaScopeForCallOperatorInstantiationRAII:: if (!ShouldAddDeclsFromParentScope) return; - FunctionDecl *InnermostFD = FD, *InnermostFDPattern = FDPattern; llvm::SmallVector<std::pair<FunctionDecl *, FunctionDecl *>, 4> - ParentInstantiations; - while (true) { + InstantiationAndPatterns; + while (FDPattern && FD) { + InstantiationAndPatterns.emplace_back(FDPattern, FD); + FDPattern = dyn_cast<FunctionDecl>(getLambdaAwareParentOfDeclContext(FDPattern)); FD = dyn_cast<FunctionDecl>(getLambdaAwareParentOfDeclContext(FD)); - - 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` - // }; + // the outer instantiations can be found when referenced from within inner + // lambdas. + // + // auto L = [](auto... x) { + // return [](decltype(x)... y) { }; // Instantiating y needs x + // }; + // - for (const auto &[FDPattern, FD] : llvm::reverse(ParentInstantiations)) { + for (auto [FDPattern, FD] : llvm::reverse(InstantiationAndPatterns)) { SemaRef.addInstantiatedParametersToScope(FD, FDPattern, Scope, MLTAL); SemaRef.addInstantiatedLocalVarsToScope(FD, FDPattern, Scope); if (isLambdaCallOperator(FD)) SemaRef.addInstantiatedCapturesToScope(FD, FDPattern, Scope, MLTAL); } - - SemaRef.addInstantiatedCapturesToScope(InnermostFD, InnermostFDPattern, Scope, - MLTAL); } |