Hi! 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. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2025-02-06 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. --- gcc/cp/parser.cc.jj 2025-02-04 21:14:50.000000000 +0100 +++ gcc/cp/parser.cc 2025-02-06 11:01:49.018050841 +0100 @@ -14570,9 +14570,19 @@ cp_parser_range_for (cp_parser *parser, 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)); --- gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C.jj 2025-02-06 11:09:15.450816690 +0100 +++ gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C 2025-02-06 11:19:01.704625049 +0100 @@ -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 } } + } +} --- gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C.jj 2025-02-06 11:23:38.787751260 +0100 +++ gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C 2025-02-06 11:29:34.043784569 +0100 @@ -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" } + } +} Jakub