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

>From 58d4552a53536b2a153a45ff0452c216664aa1d7 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)

Signed-off-by: Baba Dan Constantin <[email protected]>
---
 clang/docs/ReleaseNotes.md                 |   3 +
 clang/lib/Sema/SemaDeclCXX.cpp             |   5 +
 clang/test/SemaCXX/cxx2c-decomposition.cpp | 125 +++++++++++++++++++++
 3 files changed, 133 insertions(+)

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..0a035f4cd1c7c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1655,16 +1655,19 @@ 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>()) {
     if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT))
       DD->setInvalidDecl();
+    CleanupVarDeclMarking();
     return;
   }
   if (auto *CT = DecompType->getAs<ComplexType>()) {
     if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT))
       DD->setInvalidDecl();
+    CleanupVarDeclMarking();
     return;
   }
 
@@ -1680,6 +1683,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 +1705,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-decomposition.cpp 
b/clang/test/SemaCXX/cxx2c-decomposition.cpp
index 2ab26b1313518..b2235375db6c4 100644
--- a/clang/test/SemaCXX/cxx2c-decomposition.cpp
+++ b/clang/test/SemaCXX/cxx2c-decomposition.cpp
@@ -155,3 +155,128 @@ constexpr auto [e1] = E(true);
 //   expected-note@-1 {{in implicit initialization of binding declaration 
'e1'}} \
 //   expected-note@-1 {{reference to temporary is not a constant expression}} \
 //   expected-note@#E-get {{temporary created here}}
+
+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 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>();
+
+// Test case: vector type(GCC generic vector type)
+typedef int v4si __attribute__ ((vector_size (8)));
+
+template <typename = void>
+void i() {
+  constexpr v4si vector_type{};
+  constexpr auto [x, y] = vector_type;
+  constexpr auto [...xs] = vector_type;
+}
+
+template void i<void>();
+
+// Test case: complex type
+template <typename = void>
+void j() {
+  constexpr _Complex float complex_type{};
+  constexpr auto [x, y] = complex_type;
+  constexpr auto [...xs] = complex_type;
+}
+
+template void j<void>();
+} // namespace GH170991

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

Reply via email to