On Tue, Dec 09, 2025 at 08:38:26PM +0800, Jason Merrill wrote:
> > > > +          [:^^B::fn:]()  // do not disable virtual dispatch
> > > > +          [:^^B:]::fn()  // disable virtual dispatch
> > > > +
> > > > +        so we check SPLICE_P.  */
> > > > +      if (parser->scope && !splice_p)
> > > >         *idk = CP_ID_KIND_QUALIFIED;
> > > 
> > > Hmm, it seems wrong for parser->scope to still be set in the former case.
> > 
> > So this is tested in reflect/member9.C.  I thought that d.[:^^B::fn:]()
> > should behave just like d.B::fn() which also leaves parser->scope set
> > to B.
> 
> I don't think it should, as above the splice is a separate lookup context.
> 
> I agree with the comments and the testcase, but we should be clearing
> parser->scope after the splice so we don't need any change here.

I've tried:

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 0d59f6ec5a5..bc31eabf474 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6120,6 +6120,15 @@ cp_parser_splice_specifier (cp_parser *parser, bool 
template_p = false,
       return error_mark_node;
     }
 
+if (parser->scope || parser->qualifying_scope || parser->object_scope)
+{
+FILE *f = fopen ("/tmp/splice", "a");
+fprintf (f, "%s %s %d %d %d %d\n",
+main_input_filename ? main_input_filename : "-", current_function_name (),
+2, (int) !!parser->scope, (int) !!parser->qualifying_scope, (int) 
!!parser->object_scope);
+fclose (f);
+}
+
   tree expr = cp_parser_constant_expression (parser,
                                             /*allow_non_constant_p=*/false,
                                             /*non_constant_p=*/nullptr,
@@ -6215,6 +6224,14 @@ cp_parser_splice_expression (cp_parser *parser, bool 
template_p,
   if (member_access_p)
     push_deferring_access_checks (dk_no_check);
 
+if (parser->scope || parser->qualifying_scope || parser->object_scope)
+{
+FILE *f = fopen ("/tmp/splice", "a");
+fprintf (f, "%s %s %d %d %d %d\n",
+main_input_filename ? main_input_filename : "-", current_function_name (),
+member_access_p, (int) !!parser->scope, (int) !!parser->qualifying_scope, 
(int) !!parser->object_scope);
+fclose (f);
+}
   cp_expr expr = cp_parser_splice_specifier (parser, template_p, &targs_p);
 
   if (member_access_p)

and this only triggers on type8.C testcase, reduced to
template<class, class> struct same_type;
template<class T> struct same_type<T, T> {};

struct S {
  static const int &&mem();
  static int i;
  int j;
} s;

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?) and/or if there are some spots where it should be temporarily
and where it should be reset back.

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.

        Jakub

Reply via email to