See <https://wg21.link/P2169R4>.
Confirmed.
Created attachment 55725 [details] gcc14-pr110349-wip.patch I've played with this a little bit so far, but am a little bit stuck. When lookup_name reports error on ambiguous _ because 2+ declarations with the _ name are in the same scope (counting function overloads as one obviously), the error is reported too many times, even from tentative parsing. And also unsure if it should return error_mark_node in that case or not, if I return error_mark_node I get some extra error recovery errors as well (though if the error is avoided during tentative parsing, I guess we have to return error_mark_node in that case.
Yeah, we don't want to give errors in lookup_name, pretty much for the reasons you found. cp_parser_lookup_name gives an ambiguity error when lookup_name returns a TREE_LIST, so I think it makes sense to represent the case of multiple _ declarations as a TREE_LIST rather than OVERLOAD. Then I think you don't need PLACEHOLDER_AMBIGUOUS_BINDING_P because you can see that from the binding being a TREE_LIST. I think find_last_decl should return nothing for a name-independent decl, and give up on a TREE_LIST.
Created attachment 55757 [details] gcc14-pr110349-wip.patch Thanks, made some progress with that. I wonder if the paper isn't incomplete though. My understanding of the intent is that say void foo () { auto a = [_ = 1, _ = 2] () {}; } is valid, similarly struct S { int _ = 1; int _ = 2; }; (and it seems the clang implementation allows that), but we still have https://eel.is/c++draft/expr.prim.lambda.capture#2 "Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture." and https://eel.is/c++draft/class.mem#general-5 "A member shall not be declared twice in the member-specification, except that" and nothing mentioning the name-independent exception in either case. Another thing is we have that https://eel.is/c++draft/basic.scope.block#2 spot which has been changed by the paper, so void baz (int _) { int _ = 1; } void qux () { if (int _ = 2) { int _ = 3; } } etc. cases are valid which have been invalid before, but the important question is if ++_; is allowed after 1; and/or 3; https://eel.is/c++draft/basic.scope.scope#6 has the note: "An id-expression that names a unique name-independent declaration is usable until an additional declaration of the same name is introduced in the same scope ([basic.lookup.general])." but does that apply here? https://eel.is/c++draft/basic.scope.block#2 seems to talk about the behavior in the same scope, but aren't the scopes different here? Seems clang rejects the baz case with ++_; added after 1; (and the WIP patch does too), but doesn't reject ++_; added after 3; (while the WIP patch does).
Also, is the structured binding in void corge () { static int a[2]; static auto [_, _] = a; } inhabitating namespace scope (so it is correct to reject it? clang does, the WIP patch does as well).
(In reply to Jakub Jelinek from comment #4) > "A member shall not be declared twice in the member-specification, except > that" > and nothing mentioning the name-independent exception in either case. Agreed, this seems like a missed edit, and we should accept those. > Seems clang rejects the baz case with ++_; added after 1; (and the WIP patch > does too), but doesn't reject ++_; added after 3; (while the WIP patch does). I agree that these should be rejected and the wording needs improvement to specify that. (In reply to Jakub Jelinek from comment #5) > Also, is the structured binding in > void corge () > { > static int a[2]; > static auto [_, _] = a; > } > inhabitating namespace scope (so it is correct to reject it? clang does, > the WIP patch does as well). No, it inhabits block/function scope.
Created attachment 55759 [details] gcc14-pr110349-wip.patch Some further progress, with lambda capture handling fixed so that it doesn't emit the bogus errors and very basic start of non-static data member support. In that area not really sure what to do, because presumably we want to fail _ member lookups if it is ambiguous but there is tons of internal lookups that will likely have to work somehow. And there is the binary search on member_vec vs. linear search on member_vec vs. field search, and anonymous aggregates etc. (In reply to Jason Merrill from comment #6) > No, it inhabits block/function scope. Ok, so should block/function scope static structured binding act allow (multiple) placeholders or should the standard wording be changed even for that case? If I disable the last hunk in parser.cc in this patch, then #c6 works, but void freddy () { static int a[2]; static auto [_, _] = a; static auto [_, _] = a; } fails to assemble as there is _ZNDC1_1_EE emitted twice.