On 12/12/25 12:58 AM, Jakub Jelinek wrote:
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.

Makes sense.

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.

Right, so adding the parm seems unnecessary.

Jason

Reply via email to