[clang] [Clang] Fix a DeclContext mismatch when parsing nested lambda parameters (PR #112177)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 14 18:42:18 PDT 2024


https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/112177

>From 78657277495bbd1f82faef655c49320a4315272f Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Mon, 14 Oct 2024 17:42:17 +0800
Subject: [PATCH 1/4] [Clang] Fix a DeclContext mismatch when parsing nested
 lambda parameters

---
 clang/docs/ReleaseNotes.rst                   |  2 ++
 clang/lib/Sema/SemaExpr.cpp                   |  9 ++++++++
 clang/lib/Sema/SemaExprCXX.cpp                |  2 +-
 .../SemaCXX/lambda-capture-type-deduction.cpp | 23 +++++++++++++++++++
 4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8d02cc3eae9fd9..3d6da43cf02f69 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -487,6 +487,8 @@ Bug Fixes to C++ Support
 - Clang now uses the correct set of template argument lists when comparing the constraints of
   out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of
   a class template. (#GH102320)
+- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in
+  certain situations. (#GH47400), (#GH90896)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f930a21ea870ec..dd6ac26cf49b94 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18843,7 +18843,16 @@ bool Sema::tryCaptureVariable(
   // We need to sync up the Declaration Context with the
   // FunctionScopeIndexToStopAt
   if (FunctionScopeIndexToStopAt) {
+    assert(!FunctionScopes.empty() && "No function scopes to stop at?");
     unsigned FSIndex = FunctionScopes.size() - 1;
+    // When we're parsing the lambda parameter list, the current DeclContext is
+    // NOT the lambda but its parent. So move away the current LSI before
+    // aligning DC and FunctionScopeIndexToStopAt.
+    if (auto *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[FSIndex]);
+        LSI && !LSI->AfterParameterList)
+      --FSIndex;
+    assert(MaxFunctionScopesIndex <= FSIndex &&
+           "FSIndex is larger than the size of function scopes?");
     while (FSIndex != MaxFunctionScopesIndex) {
       DC = getLambdaAwareParentOfDeclContext(DC);
       --FSIndex;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d490452e91c3bb..09ab83dcf21c22 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -8679,7 +8679,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
   while (isa_and_nonnull<CapturedDecl>(DC))
     DC = DC->getParent();
   assert(
-      CurrentLSI->CallOperator == DC &&
+      (CurrentLSI->CallOperator == DC || !CurrentLSI->AfterParameterList) &&
       "The current call operator must be synchronized with Sema's CurContext");
 #endif // NDEBUG
 
diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
index 7bf36a6a9cab73..32f09b38f84e23 100644
--- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
@@ -297,3 +297,26 @@ void __trans_tmp_1() {
 }
 
 }
+
+namespace GH47400 {
+
+struct Foo {};
+
+template <int, Foo f> struct Arr {};
+
+template <int> struct S {};
+
+constexpr bool foo() {
+  constexpr Foo f; // f constitutes an ODR-use
+  [&]<int is>() {
+    [&](Arr<is, f>) {}({});
+  }.template operator()<42>();
+
+  constexpr int C = 1;
+  []() {
+    [](S<C>) { }; // ... while C doesn't
+  };
+  return true;
+}
+
+} // namespace GH47400

>From 85b1f38fc34b77b23d10e2ae4124872659bd2573 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Mon, 14 Oct 2024 19:20:30 +0800
Subject: [PATCH 2/4] Fix tests

---
 clang/test/SemaCXX/lambda-capture-type-deduction.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
index 32f09b38f84e23..253d0f429abbed 100644
--- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
@@ -302,20 +302,20 @@ namespace GH47400 {
 
 struct Foo {};
 
-template <int, Foo f> struct Arr {};
+template <int, Foo> struct Arr {};
 
 template <int> struct S {};
 
 constexpr bool foo() {
-  constexpr Foo f; // f constitutes an ODR-use
+  constexpr Foo f;
   [&]<int is>() {
-    [&](Arr<is, f>) {}({});
+    [&](Arr<is, f>) {}({}); // f constitutes an ODR-use
   }.template operator()<42>();
 
   constexpr int C = 1;
-  []() {
-    [](S<C>) { }; // ... while C doesn't
-  };
+  [] {
+    [](S<C>) { }({}); // ... while C doesn't
+  }();
   return true;
 }
 

>From 6fe91020f9564b2177ecd8f8a66b6d02ae9c5f4d Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Mon, 14 Oct 2024 19:51:02 +0800
Subject: [PATCH 3/4] Clarify the assertion intents

---
 clang/lib/Sema/SemaExpr.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index dd6ac26cf49b94..0075ec86823920 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18852,7 +18852,8 @@ bool Sema::tryCaptureVariable(
         LSI && !LSI->AfterParameterList)
       --FSIndex;
     assert(MaxFunctionScopesIndex <= FSIndex &&
-           "FSIndex is larger than the size of function scopes?");
+           "FunctionScopeIndexToStopAt should be no larger than FSIndex into "
+           "FunctionScopes.");
     while (FSIndex != MaxFunctionScopesIndex) {
       DC = getLambdaAwareParentOfDeclContext(DC);
       --FSIndex;

>From 4b78a50b8e5ca98e603e57c5f8b67f62d59bb917 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 15 Oct 2024 09:38:57 +0800
Subject: [PATCH 4/4] Guard the case FSIndex == 0; remove unnecessary return
 value in tests

---
 clang/lib/Sema/SemaExpr.cpp                          | 4 ++--
 clang/test/SemaCXX/lambda-capture-type-deduction.cpp | 3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0075ec86823920..a253cc26d6c60e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18849,10 +18849,10 @@ bool Sema::tryCaptureVariable(
     // NOT the lambda but its parent. So move away the current LSI before
     // aligning DC and FunctionScopeIndexToStopAt.
     if (auto *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[FSIndex]);
-        LSI && !LSI->AfterParameterList)
+        FSIndex && LSI && !LSI->AfterParameterList)
       --FSIndex;
     assert(MaxFunctionScopesIndex <= FSIndex &&
-           "FunctionScopeIndexToStopAt should be no larger than FSIndex into "
+           "FunctionScopeIndexToStopAt should be no greater than FSIndex into "
            "FunctionScopes.");
     while (FSIndex != MaxFunctionScopesIndex) {
       DC = getLambdaAwareParentOfDeclContext(DC);
diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
index 253d0f429abbed..a86f3018989927 100644
--- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp
@@ -306,7 +306,7 @@ template <int, Foo> struct Arr {};
 
 template <int> struct S {};
 
-constexpr bool foo() {
+constexpr void foo() {
   constexpr Foo f;
   [&]<int is>() {
     [&](Arr<is, f>) {}({}); // f constitutes an ODR-use
@@ -316,7 +316,6 @@ constexpr bool foo() {
   [] {
     [](S<C>) { }({}); // ... while C doesn't
   }();
-  return true;
 }
 
 } // namespace GH47400



More information about the cfe-commits mailing list