aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaConcept.cpp
diff options
context:
space:
mode:
authorYounan Zhang <zyn7109@gmail.com>2025-02-25 14:35:07 +0800
committerGitHub <noreply@github.com>2025-02-25 14:35:07 +0800
commitecc7e6ce4cd57a614985e95daf7027918cb8723e (patch)
tree06223c1816165028677fd875127d4d83248d0946 /clang/lib/Sema/SemaConcept.cpp
parent83ddb43cad3ee32b0df81aa641c4c0275334729d (diff)
downloadllvm-ecc7e6ce4cd57a614985e95daf7027918cb8723e.zip
llvm-ecc7e6ce4cd57a614985e95daf7027918cb8723e.tar.gz
llvm-ecc7e6ce4cd57a614985e95daf7027918cb8723e.tar.bz2
[Clang] Handle instantiating captures in addInstantiatedCapturesToScope() (#128478)
addInstantiatedCapturesToScope() might be called when transforming a lambda body. In this situation, it would look into all the lambda's parents and figure out all the instantiated captures. However, the instantiated captures are not visible from lambda's class decl until the lambda is rebuilt (i.e. after the lambda body transform). So this patch corrects that by also examining the LambdaScopeInfo, serving as a workaround for not having deferred lambda body instantiation in Clang 20, to avoid regressing some real-world use cases. Fixes #128175
Diffstat (limited to 'clang/lib/Sema/SemaConcept.cpp')
-rw-r--r--clang/lib/Sema/SemaConcept.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 8a77cbf..a7b609f 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -711,9 +711,32 @@ bool Sema::addInstantiatedCapturesToScope(
unsigned Instantiated = 0;
+ // FIXME: This is a workaround for not having deferred lambda body
+ // instantiation.
+ // When transforming a lambda's body, if we encounter another call to a
+ // nested lambda that contains a constraint expression, we add all of the
+ // outer lambda's instantiated captures to the current instantiation scope to
+ // facilitate constraint evaluation. However, these captures don't appear in
+ // the CXXRecordDecl until after the lambda expression is rebuilt, so we
+ // pull them out from the corresponding LSI.
+ LambdaScopeInfo *InstantiatingScope = nullptr;
+ if (LambdaPattern->capture_size() && !LambdaClass->capture_size()) {
+ for (FunctionScopeInfo *Scope : llvm::reverse(FunctionScopes)) {
+ auto *LSI = dyn_cast<LambdaScopeInfo>(Scope);
+ if (!LSI ||
+ LSI->CallOperator->getTemplateInstantiationPattern() != PatternDecl)
+ continue;
+ InstantiatingScope = LSI;
+ break;
+ }
+ assert(InstantiatingScope);
+ }
+
auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
unsigned Index) {
- ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
+ ValueDecl *CapturedVar =
+ InstantiatingScope ? InstantiatingScope->Captures[Index].getVariable()
+ : LambdaClass->getCapture(Index)->getCapturedVar();
assert(CapturedVar->isInitCapture());
Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
};