PR c++/54769 - wrong lookup of dependent template-name.

PR c++/81257 - ICE with invalid ::template.
	* parser.c (cp_parser_template_name): Handle dependent object type.
	(cp_parser_nested_name_specifier_opt): Make template_keyword_p a
	parameter.
	(cp_parser_id_expression): Pass it.

From-SVN: r249857
This commit is contained in:
Jason Merrill 2017-06-30 18:20:22 -04:00 committed by Jason Merrill
parent e8c860f780
commit a577c31243
4 changed files with 46 additions and 16 deletions

View File

@ -1,3 +1,12 @@
2017-06-30 Jason Merrill <jason@redhat.com>
PR c++/54769 - wrong lookup of dependent template-name.
PR c++/81257 - ICE with invalid ::template.
* parser.c (cp_parser_template_name): Handle dependent object type.
(cp_parser_nested_name_specifier_opt): Make template_keyword_p a
parameter.
(cp_parser_id_expression): Pass it.
2017-06-29 Jason Merrill <jason@redhat.com>
PR c++/81180 - ICE with C++17 deduction of member class template.

View File

@ -2039,7 +2039,7 @@ static cp_expr cp_parser_id_expression
static cp_expr cp_parser_unqualified_id
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool, bool);
(cp_parser *, bool, bool, bool, bool, bool = false);
static tree cp_parser_nested_name_specifier
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_qualifying_entity
@ -5408,16 +5408,21 @@ cp_parser_id_expression (cp_parser *parser,
/* Look for the optional `::' operator. */
global_scope_p
= (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)
!= NULL_TREE);
= (!template_keyword_p
&& (cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false)
!= NULL_TREE));
/* Look for the optional nested-name-specifier. */
nested_name_specifier_p
= (cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false,
check_dependency_p,
/*type_p=*/false,
declarator_p)
declarator_p,
template_keyword_p)
!= NULL_TREE);
/* If there is a nested-name-specifier, then we are looking at
the first qualified-id production. */
if (nested_name_specifier_p)
@ -5862,7 +5867,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
bool typename_keyword_p,
bool check_dependency_p,
bool type_p,
bool is_declaration)
bool is_declaration,
bool template_keyword_p /* = false */)
{
bool success = false;
cp_token_position start = 0;
@ -5880,7 +5886,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
tree new_scope;
tree old_scope;
tree saved_qualifying_scope;
bool template_keyword_p;
/* Spot cases that cannot be the beginning of a
nested-name-specifier. */
@ -5952,8 +5957,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
first time through the loop. */
if (success)
template_keyword_p = cp_parser_optional_template_keyword (parser);
else
template_keyword_p = false;
/* Save the old scope since the name lookup we are about to do
might destroy it. */
@ -15716,15 +15719,19 @@ cp_parser_template_name (cp_parser* parser,
no point in doing name-lookup, so we just return IDENTIFIER.
But, if the qualifying scope is non-dependent then we can
(and must) do name-lookup normally. */
if (template_keyword_p
&& (!parser->scope
|| (TYPE_P (parser->scope)
&& dependent_type_p (parser->scope))))
if (template_keyword_p)
{
/* We're optimizing away the call to cp_parser_lookup_name, but we
still need to do this. */
parser->context->object_type = NULL_TREE;
return identifier;
tree scope = (parser->scope ? parser->scope
: parser->context->object_type);
if (scope && TYPE_P (scope)
&& (!CLASS_TYPE_P (scope)
|| (check_dependency_p && dependent_type_p (scope))))
{
/* We're optimizing away the call to cp_parser_lookup_name, but
we still need to do this. */
parser->context->object_type = NULL_TREE;
return identifier;
}
}
}

View File

@ -0,0 +1,3 @@
// PR c++/81257
template < typename ::template A < int > >; // { dg-error "" }

View File

@ -0,0 +1,11 @@
// PR c++/81026
namespace std {
template<class> struct extent;
}
using namespace std;
template <class T>
struct S {
void f() { T().template extent<42>(); }
};