https://github.com/babadany2999 updated 
https://github.com/llvm/llvm-project/pull/214716

>From af68f517aefadb3c4f49aa1cff879328a8de64fa Mon Sep 17 00:00:00 2001
From: Baba Dan Constantin <[email protected]>
Date: Sat, 8 Aug 2026 16:23:15 +0300
Subject: [PATCH] [Clang][Sema] Fix an ICE where structured binding packs
 within a lambda should be diagnosed immediately. (#214160)

Signed-off-by: Baba Dan Constantin <[email protected]>
---
 clang/docs/ReleaseNotes.md      |   3 +
 clang/lib/Sema/SemaDeclCXX.cpp  |   6 +
 clang/test/SemaCXX/GH214160.cpp | 291 ++++++++++++++++++++++++++++++++
 3 files changed, 300 insertions(+)
 create mode 100644 clang/test/SemaCXX/GH214160.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index a00b725143d49..42de9d57d5e80 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -366,6 +366,9 @@ features cannot lower the translation-unit ABI level;
 - Fixed USR generation for declarations whose signature mentions a class-type
   non-type template parameter. (#GH212351)
 - Clang now defines the GCC-compatible predefined macro `__SIG_ATOMIC_TYPE__`. 
(#GH213895)
+- Fixed an ICE where structured binding packs within a lambda were
+  considered for delayed diagnostics, when they should be diagnosed
+  immediately. (#GH214160)
 
 #### Bug Fixes to Compiler Builtins
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 47b01b913b428..66c77a63fced6 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -914,6 +914,12 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
 
     auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name, QT);
 
+    if (BD->isParameterPack()) {
+      if (auto *CSI = getEnclosingLambdaOrBlock()) {
+        CSI->LocalPacks.push_back(BD);
+      }
+    }
+
     ProcessDeclAttributeList(S, BD, *B.Attrs);
 
     // Find the shadowed declaration before filtering for scope.
diff --git a/clang/test/SemaCXX/GH214160.cpp b/clang/test/SemaCXX/GH214160.cpp
new file mode 100644
index 0000000000000..bab9d69de122c
--- /dev/null
+++ b/clang/test/SemaCXX/GH214160.cpp
@@ -0,0 +1,291 @@
+// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify %s
+
+namespace GH214160 {
+struct A {
+int x, y;
+};
+
+template <typename = void>
+void non_constexpr_right_unary() {
+  ([&]{ auto [...tmp] = A{}; tmp; }(), ...);
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_right_unary<void>();
+
+template <typename = void>
+constexpr void constexpr_right_unary() {
+  ([&]{ auto [...tmp] = A{}; tmp; }(), ...);
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_right_unary<void>();
+
+template <typename = void>
+void non_constexpr_left_unary() {
+  (..., [&]{ auto [...tmp] = A{}; tmp; }());
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_left_unary<void>();
+
+template <typename = void>
+constexpr void constexpr_left_unary() {
+  (..., [&]{ auto [...tmp] = A{}; tmp; }());
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_left_unary<void>();
+
+// When pack is already expanded ([...tmp])
+template <typename = void>
+void non_constexpr_right_unary_expanded() {
+  ([&]{ auto [...tmp] = A{}; ((void)tmp, ...); }(), ...);
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_right_unary_expanded<void>();
+
+template <typename = void>
+constexpr void constexpr_right_unary_expanded() {
+  ([&]{ auto [...tmp] = A{}; ((void)tmp, ...); }(), ...);
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_right_unary_expanded<void>();
+
+template <typename = void>
+void non_constexpr_left_unary_expanded() {
+  (..., [&]{ auto [...tmp] = A{}; ((void)tmp, ...); }());
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_left_unary_expanded<void>();
+
+template <typename = void>
+constexpr void constexpr_left_unary_expanded() {
+  (..., [&]{ auto [...tmp] = A{}; ((void)tmp, ...); }());
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_left_unary_expanded<void>();
+
+template <typename = void>
+void non_constexpr_right_binary() {
+  ([&]{ auto [...tmp] = A{}; tmp; }() + ... + 0);
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_right_binary<void>();
+
+template <typename = void>
+constexpr void constexpr_right_binary() {
+  ([&]{ auto [...tmp] = A{}; tmp; }() + ... + 0);
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_right_binary<void>();
+
+template <typename = void>
+void non_constexpr_left_binary() {
+  (0 + ... + [&]{ auto [...tmp] = A{}; tmp; }());
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_left_binary<void>();
+
+template <typename = void>
+constexpr void constexpr_left_binary() {
+  (0 + ... + [&]{ auto [...tmp] = A{}; tmp; }());
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_left_binary<void>();
+
+// When pack is already expanded ([...tmp])
+template <typename = void>
+void non_constexpr_right_binary_expanded() {
+  ([&]{ auto [...tmp] = A{}; ((void)tmp, ...); }() + ... + 0);
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_right_binary_expanded<void>();
+
+template <typename = void>
+constexpr void constexpr_right_binary_expanded() {
+  ([&]{ auto [...tmp] = A{}; ((void)tmp, ...); }() + ... + 0);
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_right_binary_expanded<void>();
+
+template <typename = void>
+void non_constexpr_left_binary_expanded() {
+  (0 + ... + [&]{ auto [...tmp] = A{}; ((void)tmp, ...); }());
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void non_constexpr_left_binary_expanded<void>();
+
+template <typename = void>
+constexpr void constexpr_left_binary_expanded() {
+  (0 + ... + [&]{ auto [...tmp] = A{}; ((void)tmp, ...); }());
+  // expected-error@-1 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void constexpr_left_binary_expanded<void>();
+
+// The following should produce no unexpanded pack errors as they are valid 
expressions
+
+template <typename = void>
+void non_constexpr_right_unary_same_scope() {
+  auto [...tmp] = A{};
+  ([&]{ (void)tmp; }(), ...);
+}
+
+template void non_constexpr_right_unary_same_scope<void>();
+
+template <typename = void>
+constexpr void constexpr_right_unary_same_scope() {
+  auto [...tmp] = A{};
+  ([&]{ (void)tmp; }(), ...);
+}
+
+template void constexpr_right_unary_same_scope<void>();
+
+template <typename = void>
+void non_constexpr_left_unary_same_scope() {
+  auto [...tmp] = A{};
+  (..., [&]{ (void)tmp; }());
+}
+
+template void non_constexpr_left_unary_same_scope<void>();
+
+template <typename = void>
+constexpr void constexpr_left_unary_same_scope() {
+  auto [...tmp] = A{};
+  (..., [&]{ (void)tmp; }());
+}
+
+template void constexpr_left_unary_same_scope<void>();
+
+template <typename = void>
+void non_constexpr_right_binary_same_scope() {
+  auto [...tmp] = A{};
+  (void)([&]{ (void)tmp; return 0; }() + ... + 0);
+}
+
+template void non_constexpr_right_binary_same_scope<void>();
+
+template <typename = void>
+constexpr void constexpr_right_binary_same_scope() {
+  auto [...tmp] = A{};
+  (void)([&]{ (void)tmp; return 0; }() + ... + 0);
+}
+
+template void constexpr_right_binary_same_scope<void>();
+
+template <typename = void>
+void non_constexpr_left_binary_same_scope() {
+  auto [...tmp] = A{};
+  (void)(0 + ... + [&]{ (void)tmp; return 0; }());
+}
+
+template void non_constexpr_left_binary_same_scope<void>();
+
+template <typename = void>
+constexpr void constexpr_left_binary_same_scope() {
+  auto [...tmp] = A{};
+  (void)(0 + ... + [&]{ (void)tmp; return 0; }());
+}
+
+template void constexpr_left_binary_same_scope<void>();
+
+template <typename = void>
+void non_constexpr_right_unary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    ([&]{ (void)tmp; }(), ...);
+  }();
+}
+
+template void non_constexpr_right_unary_same_scope_enclosed<void>();
+
+template <typename = void>
+constexpr void constexpr_right_unary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    ([&]{ (void)tmp; }(), ...);
+  }();
+}
+
+template void constexpr_right_unary_same_scope_enclosed<void>();
+
+template <typename = void>
+void non_constexpr_left_unary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    (..., [&]{ (void)tmp; }());
+  }();
+}
+
+template void non_constexpr_left_unary_same_scope_enclosed<void>();
+
+template <typename = void>
+constexpr void constexpr_left_unary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    (..., [&]{ (void)tmp; }());
+  }();
+}
+
+template void constexpr_left_unary_same_scope_enclosed<void>();
+
+template <typename = void>
+void non_constexpr_right_binary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    (void)([&]{ (void)tmp; return 0; }() + ... + 0);
+  }();
+}
+
+template void non_constexpr_right_binary_same_scope_enclosed<void>();
+
+template <typename = void>
+constexpr void constexpr_right_binary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    (void)([&]{ (void)tmp; return 0; }() + ... + 0);
+  }();
+}
+
+template void constexpr_right_binary_same_scope_enclosed<void>();
+
+template <typename = void>
+void non_constexpr_left_binary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    (void)(0 + ... + [&]{ (void)tmp; return 0; }());
+  }();
+}
+
+template void non_constexpr_left_binary_same_scope_enclosed<void>();
+
+template <typename = void>
+constexpr void constexpr_left_binary_same_scope_enclosed() {
+  [] {
+    auto [...tmp] = A{};
+    (void)(0 + ... + [&]{ (void)tmp; return 0; }());
+  }();
+}
+
+template void constexpr_left_binary_same_scope_enclosed<void>();
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to