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)) + 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