[clang] [Clang][SemaCXX] Fix bug where unexpanded lambda captures where assumed to have size 1 (PR #101385)

Mital Ashok via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 31 11:44:51 PDT 2024


https://github.com/MitalAshok created https://github.com/llvm/llvm-project/pull/101385

Fixes #63677

>From 555373715bc2eb025d6580129cead087f7f45ed1 Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Fri, 7 Jul 2023 14:31:03 +0100
Subject: [PATCH] [Clang][SemaCXX] Fix bug where unexpanded lambda captures
 where assumed to have size 1

---
 clang/docs/ReleaseNotes.rst                  |  1 +
 clang/lib/Sema/SemaTemplateInstantiate.cpp   |  3 ++-
 clang/lib/Sema/TreeTransform.h               |  6 ++---
 clang/test/SemaCXX/lambda-pack-expansion.cpp | 27 ++++++++++++++++++++
 4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c2e0282d1c72..2f4158ac36ac2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -170,6 +170,7 @@ Bug Fixes to C++ Support
 - Fixed a failed assertion when checking invalid delete operator declaration. (#GH96191)
 - Fix a crash when checking destructor reference with an invalid initializer. (#GH97230)
 - Clang now correctly parses potentially declarative nested-name-specifiers in pointer-to-member declarators.
+- Fix init-capture packs having a size of one before being instantiated. (#GH63677)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8995d461362d7..de470739ab78e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1447,7 +1447,8 @@ namespace {
     }
 
     void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
-      if (Old->isParameterPack()) {
+      if (Old->isParameterPack() &&
+          (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
         SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
         for (auto *New : NewDecls)
           SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 8d3e1edf7a45d..540e1e0cb8df0 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14340,14 +14340,14 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
               OldVD->getInit()->getSourceRange(), Unexpanded, Expand,
               RetainExpansion, NumExpansions))
         return ExprError();
+      assert(!RetainExpansion && "Should not need to retain expansion after a "
+                                 "capture since it cannot be extended");
       if (Expand) {
         for (unsigned I = 0; I != *NumExpansions; ++I) {
           Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
           SubstInitCapture(SourceLocation(), std::nullopt);
         }
-      }
-      if (!Expand || RetainExpansion) {
-        ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+      } else {
         SubstInitCapture(ExpansionTL.getEllipsisLoc(), NumExpansions);
         Result.EllipsisLoc = ExpansionTL.getEllipsisLoc();
       }
diff --git a/clang/test/SemaCXX/lambda-pack-expansion.cpp b/clang/test/SemaCXX/lambda-pack-expansion.cpp
index 221d1d01a06ae..77b2e244753a9 100644
--- a/clang/test/SemaCXX/lambda-pack-expansion.cpp
+++ b/clang/test/SemaCXX/lambda-pack-expansion.cpp
@@ -41,3 +41,30 @@ int h(Ts... ts) {
 }
 
 }
+
+namespace GH63677 {
+
+template<typename>
+void f() {
+  []<typename... Ts>() -> void {
+    [...us = Ts{}]{
+      (Ts(us), ...);
+    };
+  }.template operator()<int, int>();
+}
+
+template void f<int>();
+
+template <class>
+inline constexpr auto fun =
+  []<class... Ts>(Ts... ts) {
+    return [... us = (Ts&&) ts]<class Fun>(Fun&& fn) mutable {
+      return static_cast<Fun&&>(fn)(static_cast<Ts&&>(us)...);
+    };
+  };
+
+void f() {
+  [[maybe_unused]] auto s = fun<int>(1, 2, 3, 4);
+}
+
+}



More information about the cfe-commits mailing list