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

As proposed by other reviewers in #214160, I believe that we should restrict 
the code which delays diagnostics about unexpanded packs if it is within a 
lambda, if that unexpanded pack is a structured binding pack, and instead 
diagnose it directly.

Fixes #214160

My understanding of this area(and other areas) of Sema is fairly limited, so, 
if this breaks any contract and the proper fix is somewhere else or perhaps 
something else entirely, please do point me in the right direction.

>From 7e1728ebddec1d5a54fd2f94abdc7efd90f498cd Mon Sep 17 00:00:00 2001
From: Baba Dan Constantin <[email protected]>
Date: Fri, 7 Aug 2026 15:35:43 +0300
Subject: [PATCH] [Clang][Sema] Fix an ICE where structured binding packs
 within a lambda were using delayed diagnostics, when they should be diagnosed
 immediately

Signed-off-by: Baba Dan Constantin <[email protected]>
---
 clang/docs/ReleaseNotes.md              |  3 +++
 clang/lib/Sema/SemaTemplateVariadic.cpp | 15 +++++++++++-
 clang/test/SemaCXX/GH214160.cpp         | 31 +++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)
 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/SemaTemplateVariadic.cpp 
b/clang/lib/Sema/SemaTemplateVariadic.cpp
index c26a96eae9f66..3e228b7de4d72 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -428,6 +428,13 @@ bool Sema::isUnexpandedParameterPackPermitted() {
   return false;
 }
 
+static bool isStructuredBindingPack(const UnexpandedParameterPack &Pack) {
+  if (auto *ND = Pack.first.dyn_cast<NamedDecl *>()) {
+    return isa<BindingDecl>(ND);
+  }
+  return false;
+}
+
 /// Diagnose all of the unexpanded parameter packs in the given
 /// vector.
 bool
@@ -442,6 +449,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
   // parameter pack, and we are done. Analogously for blocks.
   // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it
   // later.
+  bool HasNonDelayablePack = false;
   SmallVector<UnexpandedParameterPack, 4> ParamPackReferences;
   if (sema::CapturingScopeInfo *CSI = getEnclosingLambdaOrBlock()) {
     for (auto &Pack : Unexpanded) {
@@ -454,6 +462,11 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
       };
       if (llvm::any_of(CSI->LocalPacks, DeclaresThisPack))
         ParamPackReferences.push_back(Pack);
+
+      // Structured binding packs should not participate in delayed lambda
+      // diagnostics, and should instead be diagnosed immediately
+      if (isStructuredBindingPack(Pack))
+        HasNonDelayablePack = true;
     }
 
     if (ParamPackReferences.empty()) {
@@ -483,7 +496,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
           break;
       }
 
-      if (!EnclosingStmtExpr) {
+      if (!EnclosingStmtExpr && !HasNonDelayablePack) {
         CSI->ContainsUnexpandedParameterPack = true;
         return false;
       }
diff --git a/clang/test/SemaCXX/GH214160.cpp b/clang/test/SemaCXX/GH214160.cpp
new file mode 100644
index 0000000000000..11d1c284409d7
--- /dev/null
+++ b/clang/test/SemaCXX/GH214160.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify %s
+
+namespace GH214160 {
+// Test case: non-constexpr
+struct A {
+  int x, y;
+};
+
+template <typename = void>
+void f() {
+  ([&]{ 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 f<void>();
+
+// Test case: constexpr
+struct B {
+    int x, y;
+};
+
+template <typename = void>
+constexpr void g() {
+    ([&]{ auto [...tmp] = B{}; 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 g<void>();
+}

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

Reply via email to