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

Reply via email to