https://github.com/zyn0217 created 
https://github.com/llvm/llvm-project/pull/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

>From 841215d2015ddd7cc4253129534f435f83cd2883 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7...@gmail.com>
Date: Mon, 24 Feb 2025 15:19:29 +0800
Subject: [PATCH] [Clang] Handle instantiating captures in
 addInstantiatedCapturesToScope()

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.
---
 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..7fff29f5ca167 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 an
+  // inline lambda that contains a constraint expression, we add all of the
+  // parent 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>();
+
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to