https://gcc.gnu.org/g:5274f490fa72830aafd278bc752145f1225b08e0

commit r16-3121-g5274f490fa72830aafd278bc752145f1225b08e0
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Mon Aug 11 08:54:57 2025 +0200

    c++: Implement mangling for structured binding packs [PR117783]
    
    On Wed, Aug 06, 2025 at 11:53:55AM -0700, Jason Merrill wrote:
    > The Clang mangling of the underlying variable seems fine, just mentioning
    > the bound names; we can't get mangling collisions between pack and 
non-pack
    > versions of the same name.
    >
    > But It looks like they use .N discriminators for the individual elements,
    > which is wrong because . is reserved for implementation details.  But I'd
    > think it should be fine to use [<discriminator>] instead.
    
    If you want the whole structured bindings to be mangled normally as if the
    pack isn't a pack and the individual vars of the structured binding pack
    mangled as multiple occurrences of the named entities, the following
    patch does that.
    
    2025-08-11  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/117783
            * decl.cc (cp_finish_decomp): Don't sorry on tuple static
            structured bindings with a pack, instead temporarily reset
            DECL_NAME of the individual vars in the pack to the name
            of the pack for cp_finish_decl time and force mangling.
    
            * g++.dg/cpp26/decomp19.C: Don't expect sorry on tuple static
            structured bindings with a pack.
            * g++.dg/cpp26/decomp26.C: New test.

Diff:
---
 gcc/cp/decl.cc                        | 16 ++++----
 gcc/testsuite/g++.dg/cpp26/decomp19.C |  2 -
 gcc/testsuite/g++.dg/cpp26/decomp26.C | 77 +++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 10 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index ab5b0c974886..693cf65fd012 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -10223,14 +10223,6 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool 
test_p)
                              "pack %qD", v[pack]);
                      goto error_out;
                    }
-                 if (j == 0
-                     && !processing_template_decl
-                     && TREE_STATIC (decl))
-                   {
-                     sorry_at (dloc, "mangling of structured binding pack "
-                                     "elements not implemented yet");
-                     goto error_out;
-                   }
                  maybe_push_decl (t);
                  /* Save the decltype away before reference collapse.  */
                  hash_map_safe_put<hm_ggc> (decomp_type_table, t, eltype);
@@ -10241,8 +10233,16 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool 
test_p)
                  if (!processing_template_decl)
                    {
                      copy_linkage (t, decl);
+                     tree name = DECL_NAME (t);
+                     if (TREE_STATIC (decl))
+                       DECL_NAME (t) = DECL_NAME (v[pack]);
                      cp_finish_decl (t, init, /*constexpr*/false,
                                      /*asm*/NULL_TREE, LOOKUP_NORMAL);
+                     if (TREE_STATIC (decl))
+                       {
+                         DECL_ASSEMBLER_NAME (t);
+                         DECL_NAME (t) = name;
+                       }
                    }
                }
              continue;
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp19.C 
b/gcc/testsuite/g++.dg/cpp26/decomp19.C
index b4d97a154560..3cec3c5d0072 100644
--- a/gcc/testsuite/g++.dg/cpp26/decomp19.C
+++ b/gcc/testsuite/g++.dg/cpp26/decomp19.C
@@ -24,7 +24,6 @@ foo ()
   static auto [ta, ...tb, tc] = t;     // { dg-warning "structured binding 
packs only available with" "" { target { c++17 && c++23_down } } }
                                        // { dg-warning "structured bindings 
only available with" "" { target c++14_down } .-1 }
                                        // { dg-warning "structured binding 
declaration can be 'static' only in" "" { target c++17_down } .-2 }
-                                       // { dg-message "mangling of structured 
binding pack elements not implemented yet" "" { target *-*-* } .-3 }
 }
 
 template <int N>
@@ -35,7 +34,6 @@ bar ()
   thread_local auto [...ta] = t;       // { dg-warning "structured binding 
packs only available with" "" { target { c++17 && c++23_down } } }
                                        // { dg-warning "structured bindings 
only available with" "" { target c++14_down } .-1 }
                                        // { dg-warning "structured binding 
declaration can be 'thread_local' only in" "" { target c++17_down } .-2 }
-                                       // { dg-message "mangling of structured 
binding pack elements not implemented yet" "" { target *-*-* } .-3 }
 }
 
 int
diff --git a/gcc/testsuite/g++.dg/cpp26/decomp26.C 
b/gcc/testsuite/g++.dg/cpp26/decomp26.C
new file mode 100644
index 000000000000..24865ca7e56c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/decomp26.C
@@ -0,0 +1,77 @@
+// P1061R10 - Structured Bindings can introduce a Pack
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1a:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1b:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1c:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1a_0:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1b_0:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1c_0:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivEDC1a1b1cE:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1a_1:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1b_1:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1AEivE1c_1:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1a:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1b:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1c:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1a_0:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1b_0:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1c_0:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivEDC1a1b1cE:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1a_1:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1b_1:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1b_2:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1b_3:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1c_1:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1a_2:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1b_4:" } }
+// { dg-final { scan-assembler "_ZZ3fooI1BEivE1c_2:" } }
+
+template <typename T>
+int
+foo ()
+{
+  static int a = 1, b = 2, c = 3;
+  int d = a++ + b++ + c++;
+  {
+    static int a = 1, b = 2, c = 3;
+    d += a++ + b++ + c++;
+    {
+      static auto [a, ...b, c] = T {}; // { dg-warning "structured binding 
packs only available with" "" { target { c++17 && c++23_down } } }
+                                       // { dg-warning "structured bindings 
only available with" "" { target c++14_down } .-1 }
+                                       // { dg-warning "structured binding 
declaration can be 'static' only in" "" { target c++17_down } .-2 }
+      d += a++ + b...[0]++ + c++;      // { dg-warning "pack indexing only 
available with" "" { target c++23_down } }
+      {
+       static int a = 1, b = 2, c = 3;
+       return d + a++ + b++ + c++;
+      }
+    }
+  }
+}
+
+struct A { int a, b, c, d, e; };
+
+void
+bar ()
+{
+  foo <A> ();
+}
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct B {
+  int a[5];
+  template <int I> int &get () { return a[I]; }
+};
+         
+template<> struct std::tuple_size<B> { static const int value = 5; };
+template<int I> struct std::tuple_element<I,B> { using type = int; };
+
+void
+baz ()
+{
+  foo <B> ();
+}

Reply via email to