c++: Member template function lookup failure [PR94799]
commitef3479afc5ab415f00a53fc6f6a990df7f6a0747
authorMarek Polacek <polacek@redhat.com>
Wed, 29 Apr 2020 02:30:44 +0000 (28 22:30 -0400)
committerMarek Polacek <polacek@redhat.com>
Tue, 5 May 2020 14:19:09 +0000 (5 10:19 -0400)
treead74c7f5b8dac79c2b0797de6dfecd77b510e74f
parent811b7636cb8c10f1a550a76242b5666c7ae36da2
c++: Member template function lookup failure [PR94799]

Whew, this took a while.  We fail to parse "p->template A<T>::a()"
(where p is of type A<T> *) because since r249752 we treat the RHS of the ->
as dependent and avoid a lookup in the enclosing context: since that rev
cp_parser_template_name checks parser->context->object_type too, which
here is unknown_type_node, signalling a type-dependent object:

 7756   if (dependent_p)
 7757     /* Tell cp_parser_lookup_name that there was an object, even though it's
 7758        type-dependent.  */
 7759     parser->context->object_type = unknown_type_node;

with which cp_parser_template_name returns identifier 'A', cp_parser_class_name
then creates a TEMPLATE_ID_EXPR A<T>, but then

23735       decl = make_typename_type (scope, decl, tag_type, tf_error);

in cp_parser_class_name fails because scope is NULL.  Then we return
error_mark_node and parse errors ensue.

I've tried various approaches, e.g. keeping TEMPLATE_ID_EXPR around
instead of calling make_typename_type, which didn't work, whereupon I
realized that since we don't want to perform name lookup if we've seen
the template keyword and the scope is dependent, we can adjust
parser->context->object_type and use the type of the object expression
as the scope, even if it's type-dependent.  This should be in line with
[basic.lookup.classref]p4.  If the postfix expression doesn't have a type,
use typeof to carry its type.  This typeof will be processed in
tsubst/TYPENAME_TYPE.

PR c++/94799
* parser.c (cp_parser_postfix_dot_deref_expression): If we have
a type-dependent object of class type, stash it to
parser->context->object_type.  If the postfix expression doesn't have
a type, use typeof.
(cp_parser_class_name): Consider object scope too.
(cp_parser_lookup_name): Remove code dealing with the case when
object_type is unknown_type_node.

* g++.dg/lookup/this1.C: Adjust dg-error.
* g++.dg/template/lookup12.C: New test.
* g++.dg/template/lookup13.C: New test.
* g++.dg/template/lookup14.C: New test.
* g++.dg/template/lookup15.C: New test.
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/this1.C
gcc/testsuite/g++.dg/template/lookup12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/lookup13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/lookup14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/lookup15.C [new file with mode: 0644]