On 8/7/25 2:18 PM, Jakub Jelinek wrote:
Hi!
I've realized I haven't added testsuite coverage for name independent
structured binding packs. And the
auto [i, ..._, j] = T {};
auto [k, ..._, l] = T {};
case shows a problem with that. The elements of the structured binding
pack have #i appended to their names, so for the _ case e.g. _#0, _#1
etc. (to print something useful in diagnostics, perhaps debug info later
on). The above is valid though as long as one doesn't use _ (which is
ambiguous), but we were emitting errors on redeclaration of _#0, _#1
etc.
The following patch uses DECL_NAME (decl) = NULL_TREE; for the
name independent decl case so that the false positive redeclaration
errors aren't emitted.
Ok for trunk if it passes bootstrap/regtest?
2025-08-07 Jakub Jelinek <ja...@redhat.com>
PR c++/117783
* decl.cc (set_sb_pack_name): For name independent decls
just clear DECL_NAME instead of appending #i to it.
* g++.dg/cpp26/name-independent-decl11.C: New test.
--- gcc/cp/decl.cc.jj 2025-08-07 15:53:48.167219127 +0200
+++ gcc/cp/decl.cc 2025-08-07 19:33:27.615010627 +0200
@@ -9870,17 +9870,23 @@ cp_maybe_mangle_decomp (tree decl, cp_de
}
}
-/* Append #i to DECL_NAME (decl). */
+/* Append #i to DECL_NAME (decl) or for name independent decls
+ clear DECL_NAME (decl). */
static void
set_sb_pack_name (tree decl, unsigned HOST_WIDE_INT i)
{
- tree name = DECL_NAME (decl);
- size_t len = IDENTIFIER_LENGTH (name) + 22;
- char *n = XALLOCAVEC (char, len);
- snprintf (n, len, "%s#" HOST_WIDE_INT_PRINT_UNSIGNED,
- IDENTIFIER_POINTER (name), i);
- DECL_NAME (decl) = get_identifier (n);
+ if (name_independent_decl_p (decl))
Let's add a comment here about avoiding redeclaration errors. OK with
that added.
+ DECL_NAME (decl) = NULL_TREE;
+ else
+ {
+ tree name = DECL_NAME (decl);
+ size_t len = IDENTIFIER_LENGTH (name) + 22;
+ char *n = XALLOCAVEC (char, len);
+ snprintf (n, len, "%s#" HOST_WIDE_INT_PRINT_UNSIGNED,
+ IDENTIFIER_POINTER (name), i);
+ DECL_NAME (decl) = get_identifier (n);
+ }
}
/* Finish a decomposition declaration. DECL is the underlying declaration
--- gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C.jj 2025-08-07
18:34:12.858562621 +0200
+++ gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C 2025-08-07
20:09:53.557524916 +0200
@@ -0,0 +1,129 @@
+// P2169R4 - A nice placeholder with no name
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+template <typename T>
+void
+foo ()
+{
+ {
+ auto [i, ..._, k] = T {}; // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ ++_...[0]; // { dg-warning "pack indexing only available with"
"" { target c++23_down } }
+ }
+ {
+ auto [_, ..._, k] = T {}; // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+ {
+ auto [i, ..._, _] = T {}; // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+ {
+ auto [i, ..._, j] = T {}; // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ auto [k, ..._, l] = T {}; // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_...[0]; // { dg-error "reference to '_' is ambiguous" }
+ }
+ {
+ static auto [i, ..._, j] = T {};// { dg-warning "structured bindings only available
with" "" { target c++14_down } }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ // { dg-warning "structured binding declaration can be
'static' only in" "" { target c++17_down } .-2 }
+ ++_...[0]; // { dg-warning "pack indexing only available with"
"" { target c++23_down } }
+ }
+ {
+ static auto [_, ..._, j] = T {};// { dg-error "redeclaration of 'auto _'" }
+ // { dg-warning "structured bindings only available with"
"" { target c++14_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ // { dg-warning "structured binding declaration can be
'static' only in" "" { target c++17_down } .-3 }
+ }
+ {
+ static auto [i, ..._, _] = T {};// { dg-error "conflicting declaration 'auto
_'" }
+ // { dg-warning "structured bindings only available with"
"" { target c++14_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ // { dg-warning "structured binding declaration can be
'static' only in" "" { target c++17_down } .-3 }
+ }
+}
+
+template <typename T>
+void
+bar ()
+{
+ T s[4] = {};
+ for (auto [..._, _, a] : s) // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } }
+ // { dg-warning "structured bindings only available with"
"" { target c++14_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ for (auto [a, ..._, b] : s) // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ ++_...[0]; // { dg-warning "pack indexing only available with"
"" { target c++23_down } }
+ for (auto [_, ..._, a] : s) // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } }
+ { // { dg-warning "structured bindings only available with"
"" { target c++14_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+ for (auto [a, ..._, b] : s) // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ { // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ ++_...[0]; // { dg-warning "pack indexing only available with"
"" { target c++23_down } }
+ int _ = ++b; // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+}
+
+template <typename T>
+void
+baz ()
+{
+ T s[4] = {};
+ for (auto [a, ..._, _] : s) // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } }
+ // { dg-warning "structured bindings only available with"
"" { target c++14_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ for (auto [a, b, ..._] : s) // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ ++_...[0]; // { dg-warning "pack indexing only available with"
"" { target c++23_down } }
+ for (auto [a, ..._, _] : s) // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } }
+ { // { dg-warning "structured bindings only available with"
"" { target c++14_down } .-1 }
+ // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-2 }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ ++a;
+ }
+ for (auto [a, b, ..._] : s) // { dg-warning "structured bindings only available with"
"" { target c++14_down } }
+ { // { dg-warning "structured binding packs only available with"
"" { target { c++17 && c++23_down } } .-1 }
+ ++_...[0]; // { dg-warning "pack indexing only available with"
"" { target c++23_down } }
+ int _ = a + b; // { dg-warning "name-independent declarations only available
with" "" { target c++23_down } }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+}
+
+struct A { int a, b, c, d, e; };
+
+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
+qux ()
+{
+ foo <A> ();
+ bar <A> ();
+ baz <A> ();
+ foo <B> ();
+ bar <B> ();
+ baz <B> ();
+}
Jakub