aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-02-07 17:08:39 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-02-07 17:08:39 +0100
commitca7c6d1212b8589deed18386427c67851af2b9ad (patch)
tree46191832c830e7cb45e163147fd1fb0a7bc1a33e
parent35d40b56eb6e7ac63c790a799d3b367742d58a5e (diff)
downloadgcc-ca7c6d1212b8589deed18386427c67851af2b9ad.zip
gcc-ca7c6d1212b8589deed18386427c67851af2b9ad.tar.gz
gcc-ca7c6d1212b8589deed18386427c67851af2b9ad.tar.bz2
c++: Fix up name independent decl in structured binding handling in range for [PR115586]
cp_parser_range_for temporarily reverts IDENTIFIER_BINDING changes to hide the decls from the structured bindings from lookup during parsing of the expression after : If there are 2 or more name independent decls, we undo IDENTIFIER_BINDING for the same name multiple times, even when just one has been added (with a TREE_LIST inside of it as decl). The following patch fixes it by handling the _ name at most once, the later loop will DTRT then and just reinstall the temporarily hidden binding with the TREE_LIST in there. 2025-02-07 Jakub Jelinek <jakub@redhat.com> PR c++/115586 * parser.cc (cp_parser_range_for): For name independent decls in structured bindings, only push the name/binding once per structured binding. * g++.dg/cpp26/name-independent-decl9.C: New test. * g++.dg/cpp26/name-independent-decl10.C: New test.
-rw-r--r--gcc/cp/parser.cc10
-rw-r--r--gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C63
-rw-r--r--gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C49
3 files changed, 122 insertions, 0 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9b8be08..bd43f88 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -14570,9 +14570,19 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
decomp = &decomp_d;
decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
decomp->decl = d;
+ bool seen_name_independent_decl = false;
for (unsigned int i = 0; i < decomp->count;
i++, d = DECL_CHAIN (d))
{
+ if (name_independent_decl_p (d))
+ {
+ /* If there is more than one _ decl in
+ the structured binding, just push and move it
+ away once. */
+ if (seen_name_independent_decl)
+ continue;
+ seen_name_independent_decl = true;
+ }
tree name = DECL_NAME (d);
names.safe_push (name);
bindings.safe_push (IDENTIFIER_BINDING (name));
diff --git a/gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C b/gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C
new file mode 100644
index 0000000..792c2bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C
@@ -0,0 +1,63 @@
+// PR c++/115586
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S { int a, b, c; };
+
+void
+foo ()
+{
+ S 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-error "reference to '_' is ambiguous" "" { target *-*-* } .-1 }
+ for (auto _ : s)
+ ++_.b;
+ for (auto [a, _, b] : s) // { dg-warning "structured bindings only available with" "" { target c++14_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-error "reference to '_' is ambiguous" }
+ }
+ for (auto _ : s)
+ {
+ ++_.b;
+ int _ = 2; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+ for (auto [a, _, b] : s) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ {
+ ++_;
+ int _ = ++b; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+}
+
+void
+bar ()
+{
+ S s[4] = {};
+ auto [_, c, _] = s[0]; // { 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-error "reference to '_' is ambiguous" "" { target *-*-* } .-1 }
+ 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-error "reference to '_' is ambiguous" "" { target *-*-* } .-1 }
+ for (auto _ : s)
+ ++_.c;
+ for (auto [a, b, _] : s) // { dg-warning "structured bindings only available with" "" { target c++14_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-error "reference to '_' is ambiguous" }
+ ++a;
+ }
+ for (auto _ : s)
+ int _ = 5; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ for (auto [a, b, _] : s) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ {
+ ++_;
+ int _ = a + b; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ ++_; // { dg-error "reference to '_' is ambiguous" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C b/gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C
new file mode 100644
index 0000000..0a8ef04
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C
@@ -0,0 +1,49 @@
+// PR c++/115586
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wunused-variable -Wunused-but-set-variable -Wunused-parameter -Wshadow" }
+
+struct S { int a, b, c; };
+
+void
+foo ()
+{
+ S s[4] = {};
+ for (auto [_, _, a] : s) // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ ++a; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ for (auto _ : s)
+ ++_.b;
+ for (auto [a, _, b] : s) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ ++a;
+ for (auto [_, _, a] : s) // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ int _ = ++a; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ for (auto _ : s)
+ {
+ int _ = 2; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ }
+ for (auto [a, _, b] : s) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ int _ = ++b; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+}
+
+void
+bar ()
+{
+ S s[4] = {};
+ auto [_, c, _] = s[0]; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ ++c; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ for (auto [a, _, _] : s) // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ ++a; // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ for (auto _ : s)
+ ++_.c;
+ for (auto [a, b, _] : s) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ ++b;
+ 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 }
+ int _ = ++a;
+ }
+ for (auto _ : s)
+ int _ = 5; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ for (auto [a, b, _] : s) // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+ {
+ int _ = a + b; // { dg-warning "name-independent declarations only available with" "" { target c++23_down } }
+ }
+}