diff options
author | Jakub Jelinek <jakub@redhat.com> | 2025-08-11 09:02:38 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-08-11 09:05:45 +0200 |
commit | b7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4 (patch) | |
tree | 919ac6c1c1c093ffcfd0df25c6ad1a8f7ddfced8 | |
parent | 5274f490fa72830aafd278bc752145f1225b08e0 (diff) | |
download | gcc-b7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4.zip gcc-b7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4.tar.gz gcc-b7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4.tar.bz2 |
c++: Fix up handling of name independent structured binding packs [PR117783]
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.
2025-08-11 Jakub Jelinek <jakub@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.
-rw-r--r-- | gcc/cp/decl.cc | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C | 129 |
2 files changed, 146 insertions, 7 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 693cf65..5aa8203 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -9870,17 +9870,27 @@ cp_maybe_mangle_decomp (tree decl, cp_decomp *decomp) } } -/* 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)) + /* Only "_" names are treated as name independent, "_#0" etc. is not and + because we pushdecl the individual decl elements of structured binding + pack, we could get redeclaration errors if there are 2 or more name + independent structured binding packs in the same scope. */ + 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 diff --git a/gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C b/gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C new file mode 100644 index 0000000..643b1db --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C @@ -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> (); +} |