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.

The patch is OK.

Jason

Reply via email to