On Fri, Feb 01, 2019 at 12:02:44PM -0500, Jason Merrill wrote:
> On 2/1/19 11:26 AM, Marek Polacek wrote:
> > On Wed, Jan 30, 2019 at 01:39:11PM -0500, Jason Merrill wrote:
> > > On 1/28/19 9:46 PM, Marek Polacek wrote:
> > > > This patch fixes an ICE-on-invalid (becase out-of-line constructors 
> > > > can't have
> > > > template arguments and also because function templates can't be 
> > > > partially
> > > > specialized) in C++2a: when we're parsing
> > > > 
> > > >     template<typename T> template<typename U> A<T>::A<U> ()
> > > > 
> > > > in the attached test we end up parsing "A<T>::A<U>" as a type name, and 
> > > > first we
> > > > try a class-name.  First we process "A<T>::" as the nested name 
> > > > specifier and then
> > > > we parse "A<U>".  In this test that results in a BASELINK.  Because in 
> > > > this context
> > > > we're supposed to treat it as a typename ([temp.res]/6), we call 
> > > > make_typename_type,
> > > > but that crashes.
> > > 
> > > Hmm.  If we've done an actual lookup (that gave us a BASELINK), we aren't
> > > dealing with a member of an unknown specialization anymore, so we should
> > > just use the result of the lookup rather than speculate about what the 
> > > name
> > > might mean.  Why are we still trying to treat it as a typename?
> > 
> > Good point.  It's because cp_parser_class_name has:
> > 
> > 23095   /* Any name names a type if we're following the `typename' keyword
> > 23096      in a qualified name where the enclosing scope is type-dependent. 
> >  */
> > 23097   typename_p = (typename_keyword_p && scope && TYPE_P (scope)
> > 23098                 && dependent_type_p (scope));
> > 
> > and scope is in this case "A<T>" which is dependent.  Then there's this
> > "identifier, but not template-id" case which only performs name lookup when
> > typename_p is false.  But we're parsing "A<U>" so we call
> > cp_parser_template_id.  It sees CPP_TEMPLATE_ID -- an already parsed
> > template-id, so it just returns it, which is a BASELINK.  So even messing
> > with tag_type wouldn't help.
> > 
> > Does this answer your question?
> 
> Mostly, though I'm still curious how we got the previous parse of the
> template-id and yet continued to try to parse it as a class-name.

So we have
template<typename T> template<typename U>
A<T>::A<U> ()

and we're in cp_parser_single_declaration.  We're trying to parse the
decl-specifier-seq, and that first tries to parse variou RID_* keywords
and if that doesn't work it tries to parse a constructor:

      /* Constructors are a special case.  The `S' in `S()' is not a
         decl-specifier; it is the beginning of the declarator.  */
      constructor_p
        = (!found_decl_spec
           && constructor_possible_p
           && (cp_parser_constructor_declarator_p
               (parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend))));

cp_parser_constructor_declarator_p calls cp_parser_nested_name_specifier_opt
and that's where we parse the two template-ids, A<T> and A<U>.  But
cp_parser_constructor_declarator_p isn't successful so we go to parsing
A<T>::A<U> as a type-specifier, and that's where the above happens.

> The patch is OK.

Thanks.

Marek

Reply via email to