]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Implement mangling for structured binding packs [PR117783]
authorJakub Jelinek <jakub@redhat.com>
Mon, 11 Aug 2025 06:54:57 +0000 (08:54 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 11 Aug 2025 07:05:23 +0000 (09:05 +0200)
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  <jakub@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.

gcc/cp/decl.cc
gcc/testsuite/g++.dg/cpp26/decomp19.C
gcc/testsuite/g++.dg/cpp26/decomp26.C [new file with mode: 0644]

index ab5b0c974886f5b5c7510d8b61ad2ea9a4f7362e..693cf65fd01209e0e359aa580b22f48eabdd1c70 100644 (file)
@@ -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;
index b4d97a1545601898ed00d565530c9a0807df32c7..3cec3c5d0072c695b3b6e0588b519808e3d7ef98 100644 (file)
@@ -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 (file)
index 0000000..24865ca
--- /dev/null
@@ -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> ();
+}