On Thu, Dec 11, 2025 at 07:55:38PM +0700, Jason Merrill wrote:
> On 12/11/25 5:17 AM, Marek Polacek wrote:
> > On Fri, Dec 05, 2025 at 10:18:34PM +0530, Jason Merrill wrote:
> > > > +  /* Nope.  Well then, maybe it's a type-id.  */
> > > > +  cp_parser_parse_tentatively (parser);
> > > > +
> > > > +  /* Unfortunately we need to distinguish in
> > > > +     template <typename> struct cls_tmpl {};
> > > > +     template <typename T> using cls_tmpl_alias = const cls_tmpl <T>;
> > > > +
> > > > +     ^^cls_tmpl_alias <int> which is a type alias from
> > > > +     ^^const cls_tmpl_alias <int>
> > > > +     ^^cls_tmpl_alias <int> const
> > > > +     ^^cls_tmpl_alias <int> *
> > > > +     etc. which are just types, not type aliases.  Parse tentatively
> > > > +     type specifiers and check that there is just ds_type_spec 
> > > > specified
> > > > +     and it is a specialization of a template alias, in that case later
> > > > +     on if cp_parser_type_id parses the same tokens don't strip 
> > > > typedefs.  */
> > > > +  if (!talias)
> > > > +    {
> > > > +      cp_decl_specifier_seq type_specifier_seq;
> > > > +
> > > > +      /* Parse the type-specifier-seq.  */
> > > > +      cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
> > > > +                                   /*is_declaration=*/false, false,
> > > > +                                   &type_specifier_seq);
> > > > +      if (is_typedef_decl (type_specifier_seq.type)
> > > > +         && TYPE_ALIAS_TEMPLATE_INFO (TREE_TYPE 
> > > > (type_specifier_seq.type)))
> > > > +       {
> > > > +         int i;
> > > > +         for (i = ds_first; i < ds_last; ++i)
> > > > +           if (i != ds_type_spec && type_specifier_seq.locations[i])
> > > > +             break;
> > > > +         if (i == ds_last)
> > > > +           {
> > > > +             talias = type_specifier_seq.type;
> > > > +             next = cp_lexer_peek_token (parser->lexer);
> > > > +           }
> > > > +       }
> > > > +      cp_parser_abort_tentative_parse (parser);
> > > > +      cp_parser_parse_tentatively (parser);
> > > > +    }
> > > > +
> > > > +  t = cp_parser_type_id (parser);
> > > > +  if (cp_parser_parse_definitely (parser))
> > > > +    {
> > > > +      if (TYPE_P (t))
> > > > +       {
> > > > +         /* With using A = int; ^^A is a type alias but
> > > > +            ^^const A or ^^A & or ^^A const is not.
> > > > +            With template <typename T> using B = C <T>;
> > > > +            ^^B <int> is a type alias though.  */
> > > > +         if (talias == NULL_TREE
> > > > +             || cp_lexer_peek_token (parser->lexer) != next)
> > > > +           t = strip_typedefs (t);
> > > > +       }
> > > > +      return get_reflection (loc, t);
> > > > +    }
> > > 
> > > I think it would be simpler to handle more of this in cp_parser_type_id_1,
> > > which already handles other special cases, rather than parsing the
> > > type-specifiers twice?
> > 
> > I took a crack at this in
> > <https://forge.sourceware.org/marek/gcc/commit/e2a9ca89a628d54897ffe30054191b0e14dfd1c4>
> > and it seemed to work.
> 
> Looks good, except I think I'd rather call _type_id_1 directly rather than
> add a special-case parameter to _type_id.

Done:
<https://forge.sourceware.org/marek/gcc/commit/90552c882ab38ff7270dc900fab786bab53f5435>

> > > > @@ -3437,9 +3444,24 @@ finish_class_member_access_expr (cp_expr object, 
> > > > tree name, bool template_p,
> > > >         return error_mark_node;
> > > >       }
> > > > +  /* For OBJECT.[:S::fn:] the BASELINK can be inside a SCOPE_REF.
> > > > +     This happens, but, until Reflection, not for a class member 
> > > > access.  */
> > > > +  if (TREE_CODE (name) == SCOPE_REF && BASELINK_P (TREE_OPERAND (name, 
> > > > 1)))
> > > > +    name = TREE_OPERAND (name, 1);
> > > 
> > > Why does this happen?  Why isn't the SCOPE_REF folded into the BASELINK?
> > 
> > Happens in:
> > 
> >    struct S {
> >      void foo () {}
> >    };
> > 
> >    template <typename T>
> >    void qux ()
> >    {
> >      S s {};
> >      s.[:(T) ^^S::foo:] ();
> >    }
> > 
> >    void
> >    corge ()
> >    {
> >      qux <decltype (^^int)> ();
> >    }
> > 
> > In cp_parser_postfix_dot_deref_expression:
> > * cp_parser_splice_expression gives us a SPLICE_EXPR (~it's dependent)
> 
> Yes.
> 
> > * since parser->scope is S, we create a SCOPE_REF in build_qualified_name
> 
> As discussed in _dot_deref, parser->scope shouldn't be set by the time we
> get back there, so I guess fixing that should make this hunk unnecessary.

OK.  I'm going to look at this now.
 
> > * need to tsubst, so tsubst_expr/SCOPE_REF does tsubst_scope + tsubst_name,
> >    then build_qualified_name creates a new SCOPE_REF
> > * tsubst_expr calls finish_class_member_access_expr with that SCOPE_REF

Marek

Reply via email to