aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-08-11 09:02:38 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-08-11 09:05:45 +0200
commitb7e4b5e862fcb12cfeaa3bee4e8c77098201d5f4 (patch)
tree919ac6c1c1c093ffcfd0df25c6ad1a8f7ddfced8 /gcc
parent5274f490fa72830aafd278bc752145f1225b08e0 (diff)
downloadgcc-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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/decl.cc24
-rw-r--r--gcc/testsuite/g++.dg/cpp26/name-independent-decl11.C129
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> ();
+}