[clang] [Clang][P1061] Fix invalid pack binding crash (PR #135129)

Jason Rice via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 9 21:51:39 PDT 2025


https://github.com/ricejasonf created https://github.com/llvm/llvm-project/pull/135129

Fixes #134882 

Consider
```
struct foo { char a; int b; };
constexpr foo t{'a', 1};
constexpr auto [...m] = t;
```
Without the `constexpr` qualifier, the decomposition declaration just happens to not crash in the call to `DeclMustBeEmitted` because it returns early because of its "discardable gval linkage". So, the fix is in `flat_bindings` where we cannot assume the pack binding is valid. There is also a fix along the same vein from a suggestion made by @shafik. The tests are still building on my machine, but I thought I would submit this to get eyes on it earlier since it is trivial.

>From 27290e3c7dc2a36a33e4582758d875704c7cbe33 Mon Sep 17 00:00:00 2001
From: Jason Rice <ricejasonf at gmail.com>
Date: Wed, 9 Apr 2025 21:31:00 -0700
Subject: [PATCH] [Clang][P1061] Fix invalid pack binding crash

---
 clang/include/clang/AST/DeclCXX.h                     | 2 +-
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp        | 5 ++---
 clang/test/SemaCXX/cxx2c-binding-pack-nontemplate.cpp | 6 ++++++
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 56cec07ec0293..ba6d87f8158ab 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -4281,7 +4281,7 @@ class DecompositionDecl final
         [](BindingDecl *BD) { return BD->isParameterPack(); });
 
     Bindings = Bindings.drop_front(BeforePackBindings.size());
-    if (!Bindings.empty()) {
+    if (!Bindings.empty() && Bindings.front()->getBinding()) {
       PackBindings = Bindings.front()->getBindingPackDecls();
       Bindings = Bindings.drop_front();
     }
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e0f7ccc4674d8..4f7410c9bf0d8 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1597,11 +1597,10 @@ Decl *TemplateDeclInstantiator::VisitDecompositionDecl(DecompositionDecl *D) {
   auto *NewDD = cast_if_present<DecompositionDecl>(
       VisitVarDecl(D, /*InstantiatingVarTemplate=*/false, &NewBindingArray));
 
-  if (!NewDD || NewDD->isInvalidDecl())
+  if (!NewDD || NewDD->isInvalidDecl()) {
     for (auto *NewBD : NewBindings)
       NewBD->setInvalidDecl();
-
-  if (OldBindingPack) {
+  } else if (OldBindingPack) {
     // Mark the bindings in the pack as instantiated.
     auto Bindings = NewDD->bindings();
     BindingDecl *NewBindingPack = *llvm::find_if(
diff --git a/clang/test/SemaCXX/cxx2c-binding-pack-nontemplate.cpp b/clang/test/SemaCXX/cxx2c-binding-pack-nontemplate.cpp
index ea94757dc66b6..1818dc699c71c 100644
--- a/clang/test/SemaCXX/cxx2c-binding-pack-nontemplate.cpp
+++ b/clang/test/SemaCXX/cxx2c-binding-pack-nontemplate.cpp
@@ -8,4 +8,10 @@ void decompose_array() {
   // cxx23-warning at +2 {{structured binding packs are a C++2c extension}}
   // nontemplate-error at +1 {{pack declaration outside of template}}
   auto [x, ...rest, y] = arr;
+
+  // cxx26-warning at +4 {{structured binding packs are incompatible with C++ standards before C++2c}}
+  // cxx23-warning at +3 {{structured binding packs are a C++2c extension}}
+  // nontemplate-error at +2 {{decomposition declaration cannot be declared 'constexpr'}}
+  // nontemplate-error at +1 {{pack declaration outside of template}}
+  constexpr auto [x, ...rest, y] = arr;
 }



More information about the cfe-commits mailing list