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