https://github.com/babadany2999 updated https://github.com/llvm/llvm-project/pull/213534
>From 24c61e8709fcc5d656c1c8379d61846320389896 Mon Sep 17 00:00:00 2001 From: Baba Dan Constantin <[email protected]> Date: Sun, 2 Aug 2026 14:35:25 +0300 Subject: [PATCH] [clang][constexpr] Fix assertion failure in constexpr structured binding pack evaluation (#GH170991) --- clang/docs/ReleaseNotes.md | 3 + clang/lib/Sema/SemaDeclCXX.cpp | 3 + .../cxx2c-binding-pack-constexpr-crash.cpp | 111 ++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 clang/test/SemaCXX/cxx2c-binding-pack-constexpr-crash.cpp diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 7108392abbaa1..3d73e420fe5b4 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -424,6 +424,9 @@ features cannot lower the translation-unit ABI level; copy so the union's object representation is copied, matching the defaulted union copy constructor. +- Fixed an assertion failure when evaluating C++26 `constexpr` structured binding packs during template + instantiation. (#GH170991) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 47b01b913b428..645994603dabd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1655,6 +1655,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { if (auto *CAT = Context.getAsConstantArrayType(DecompType)) { if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT)) DD->setInvalidDecl(); + CleanupVarDeclMarking(); return; } if (auto *VT = DecompType->getAs<VectorType>()) { @@ -1680,6 +1681,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { case IsTupleLike::TupleLike: if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize)) DD->setInvalidDecl(); + CleanupVarDeclMarking(); return; case IsTupleLike::NotTupleLike: @@ -1701,6 +1703,7 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { // E or of the same unambiguous public base class of E, ... if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD)) DD->setInvalidDecl(); + CleanupVarDeclMarking(); } UnsignedOrNone Sema::GetDecompositionElementCount(QualType T, diff --git a/clang/test/SemaCXX/cxx2c-binding-pack-constexpr-crash.cpp b/clang/test/SemaCXX/cxx2c-binding-pack-constexpr-crash.cpp new file mode 100644 index 0000000000000..6c41e4f332749 --- /dev/null +++ b/clang/test/SemaCXX/cxx2c-binding-pack-constexpr-crash.cpp @@ -0,0 +1,111 @@ +// RUN: %clang -fsyntax-only -std=c++26 %s + +namespace GH170991 { +// Test case: struct +struct S { int x{}; }; + +template <typename = void> +void f() { + constexpr S s; + constexpr auto [x] = s; + constexpr auto [...xs] = s; +} + +template void f<void>(); + +// Test case: array +template <typename = void> +void g() { + constexpr int a[2]{}; + constexpr auto [x, y] = a; + constexpr auto [...xs] = a; +} + +template void g<void>(); +} // namespace GH170991 + +// Test case: tuple-like +namespace std { +template <typename T> +struct tuple_size; +template <unsigned I, typename T> +struct tuple_element; +} // namespace std + +namespace GH170991 { +struct TupleLikeFnTemplate { + int x = 100; + char y = 'D'; + + // If a search for the name get in the scope of E [...] the initializer is e.get<i>() + template <unsigned I> + constexpr decltype(auto) get() const& { + if constexpr (I == 0) return 500; + else return y; + } +}; + +struct TupleLikeADL { + int x = 100; + char y = 'D'; +}; + +// Otherwise, the initializer is get<i>(e)[...] +template <unsigned I> +constexpr decltype(auto) get(const TupleLikeADL& t) { + if constexpr (I == 0) return 500; + else return t.y; +} +} // namespace GH170991 + +namespace std { +template <> +struct tuple_size<const GH170991::TupleLikeFnTemplate> { + static constexpr unsigned value = 2; +}; +template <> +struct tuple_size<const GH170991::TupleLikeADL> { + static constexpr unsigned value = 2; +}; + +template <> +struct tuple_element<0, const GH170991::TupleLikeFnTemplate> { + using type = int; +}; +template <> +struct tuple_element<0, const GH170991::TupleLikeADL> { + using type = int; +}; + +template <> +struct tuple_element<1, const GH170991::TupleLikeFnTemplate> { + using type = char; +}; +template <> +struct tuple_element<1, const GH170991::TupleLikeADL> { + using type = char; +}; +} // namespace std + +namespace GH170991 { +template <typename = void> +void h() { + constexpr TupleLikeFnTemplate fn_template{}; + constexpr auto [x, y] = fn_template; + static_assert(x == 500); // Proves tuple_like.get<0>(tuple-like decomposition) was called + static_assert(y == 'D'); + constexpr auto [...xs] = fn_template; + static_assert(xs...[0] == 500); + static_assert(xs...[1] == 'D'); + + constexpr TupleLikeADL adl{}; + constexpr auto [x2, y2] = adl; + static_assert(x2 == 500); // Proves get<0>(tuple-like decomposition) was called + static_assert(y2 == 'D'); + constexpr auto [...xs2] = adl; + static_assert(xs2...[0] == 500); + static_assert(xs2...[1] == 'D'); +} + +template void h<void>(); +} // namespace GH170991 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
