[clang] [Clang][Sema] Fix an ICE where structured binding packs within a lambda should be diagnosed immediately (PR #214716)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 7 05:43:28 PDT 2026
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 <babadany2999 at gmail.com>
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 <babadany2999 at gmail.com>
---
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 at -1 {{expression contains unexpanded parameter pack 'tmp'}}
+ // expected-error at -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 at -1 {{expression contains unexpanded parameter pack 'tmp'}}
+ // expected-error at -2 {{pack expansion does not contain any unexpanded parameter packs}}
+}
+
+template void g<void>();
+}
More information about the cfe-commits
mailing list