[llvm-branch-commits] [clang] release/20.x: [Clang] Handle instantiating captures in addInstantiatedCapturesToScope() (#128478) (PR #128639)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Feb 25 08:30:34 PST 2025
https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/128639
>From d919b8d97b12c24a13e1e92aa66ef1421e20104b Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 25 Feb 2025 14:35:07 +0800
Subject: [PATCH] [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
(cherry picked from commit ecc7e6ce4cd57a614985e95daf7027918cb8723e)
---
clang/lib/Sema/SemaConcept.cpp | 25 ++++++++++++++++++++-
clang/test/SemaTemplate/concepts-lambda.cpp | 18 +++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 8a77cbf8c9477..a7b609f7f3ce4 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);
};
diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp
index 306f86cfcb28f..dcb09c76d26b6 100644
--- a/clang/test/SemaTemplate/concepts-lambda.cpp
+++ b/clang/test/SemaTemplate/concepts-lambda.cpp
@@ -307,3 +307,21 @@ void test() {
}
}
+
+namespace GH128175 {
+
+template <class> void f() {
+ [i{0}] {
+ [&] {
+ [&] {
+ []()
+ requires true
+ {}();
+ }();
+ }();
+ }();
+}
+
+template void f<int>();
+
+}
More information about the llvm-branch-commits
mailing list