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:
parent
e8c860f780
commit
a577c31243
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// PR c++/81257
|
||||
|
||||
template < typename ::template A < int > >; // { dg-error "" }
|
|
@ -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>(); }
|
||||
};
|
Loading…
Reference in New Issue