https://gcc.gnu.org/g:08bfa32ae92e36a791ebdefd063b4f2616cd6f80
commit r14-11297-g08bfa32ae92e36a791ebdefd063b4f2616cd6f80 Author: Jakub Jelinek <ja...@redhat.com> Date: Fri Feb 7 17:08:39 2025 +0100 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 <ja...@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. (cherry picked from commit ca7c6d1212b8589deed18386427c67851af2b9ad) Diff: --- gcc/cp/parser.cc | 10 ++++ .../g++.dg/cpp26/name-independent-decl10.C | 63 ++++++++++++++++++++++ .../g++.dg/cpp26/name-independent-decl9.C | 49 +++++++++++++++++ 3 files changed, 122 insertions(+) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 5bfbdf85f152..aeb36d1e4831 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -14130,9 +14130,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 000000000000..792c2bd0c6b3 --- /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 000000000000..0a8ef0405970 --- /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 } } + } +}