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
