On Thu, Dec 11, 2025 at 11:29:01PM +0700, Jason Merrill wrote:
> > same_type<decltype([: ^^S::i :]), int> s5b;
> > where it seems to be parsing [: ^^S::i :] tentatively, sets
> > parser->scope and parser->qualifying_scope to S during that
> > parsing and then when it is parsing it again sees that.
> > So guess the question is where to clear those 3 (e.g. whether
> > at the start of cp_parser_splice_expression and also at the end
> > of those?)
>
> I think so.
>
> > and/or if there are some spots where it should be temporarily
> > and where it should be reset back.
>
> I don't think so.
Marek is looking at these right now.
> > And then there is also parser->context->object_type, guess for that one
> > we should save it and restore it, so that it can be taken into account
> > for s.[: ^^S::foo :] <int> (); etc. parsing.
> ...
> > The following WIP patch fixes that.
> > The reason for saving/restoring rather than just clearing is so that
> > it can be used for the splice-specialization-specifier case later on
> > if the splice-specifier is non-dependent.
>
> Why is this needed? The template arguments aren't member-qualified, e.g.
> this is properly rejected:
>
> struct A {
> static const int i = 42;
> template <int I> void f();
> };
>
> int main()
> {
> A().f<i>(); // error, no 'i' in scope
> }
I wanted to make it behave similarly to the non-splice parsing and without
that lots of things in member18.C testcase (which I finally got to work
fully a few minutes ago) didn't work.
For A().f<i>(); *dot_deref* sets parser->context->object_type and then
cp_parser_template_id is called, it parses the f IDENTIFIER_NODE and because
parser->context->object_type is set, it looks it up in that type and
creates a BASELINK from that and only with that the rest of
cp_parser_template_id can DTRT and create the right TEMPLATE_ID_EXPR,
everything before finish_class_member_access_expr is called.
Now, for the splice-specialization-specifier case for member access,
we get an OVERLOAD for a function template, but without a BASELINK
cp_parser_template_id with the new expr argument added by Marek where
it doesn't parse the identifier before < but uses the splice expression
it doesn't DTRT.
So, what I'm now using is
https://forge.sourceware.org/marek/gcc/src/commit/ebd656a2ba860bf05e0ef3283acd4efb6621f4dc/gcc/cp/parser.cc#L6155
and add a BASELINK in that case.
The relevant recent commits are
https://forge.sourceware.org/marek/gcc/commit/43b63499a56e507d1e646e5ba732e5db88bcfaa0
https://forge.sourceware.org/marek/gcc/commit/47efb49b8d32cf1fecadf28990f74d2deff0039c
https://forge.sourceware.org/marek/gcc/commit/d9d8a99731e44ca57944b03a30b66ed7450bd622
https://forge.sourceware.org/marek/gcc/commit/99aaea31a7e583946f541f1c09ce7d3daff4062c
https://forge.sourceware.org/marek/gcc/commit/a6a2829e25ec1bd4d57779785248ab9dca6e88ef
https://forge.sourceware.org/marek/gcc/commit/d1dff2d009b72047c768a383b28f748982b5f51a
https://forge.sourceware.org/marek/gcc/commit/33ceee24fb16bc3d4772e298536d31f3a103aed4
https://forge.sourceware.org/marek/gcc/commit/ebd656a2ba860bf05e0ef3283acd4efb6621f4dc
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > @@ -6102,6 +6102,7 @@ cp_parser_next_tokens_can_start_splice_scope_spec_p
> > (cp_parser *parser)
> > static cp_expr
> > cp_parser_splice_specifier (cp_parser *parser, bool template_p = false,
> > + bool member_access_p = false,
> > bool *targs_p = nullptr)
> > {
> > /* Get the location of the '[:'. */
> > @@ -6120,11 +6121,22 @@ cp_parser_splice_specifier (cp_parser *parser, bool
> > template_p = false,
> > return error_mark_node;
> > }
> > + /* For member_access_p, temporarily clear parser->context->object_type.
> > */
>
> Why conditional on member_access_p?
It could be done for non-member_access_p too, I just think it will
never be non-NULL otherwise.
Jakub