parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid template-ids.

* parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid
	template-ids.

From-SVN: r219269
This commit is contained in:
Jason Merrill 2015-01-06 15:44:59 -05:00 committed by Jason Merrill
parent c6a38536f2
commit efcdb22fe3
3 changed files with 55 additions and 0 deletions

View file

@ -1,5 +1,8 @@
2015-01-06 Jason Merrill <jason@redhat.com>
* parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid
template-ids.
PR c++/64455
* pt.c (type_dependent_expression_p): Handle variable templates.
* constexpr.c (potential_constant_expression_1): Use it.

View file

@ -5435,6 +5435,46 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
cp_lexer_consume_token (parser->lexer);
}
if (cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID)
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_SCOPE))
{
/* If we have a non-type template-id followed by ::, it can't
possibly be valid. */
token = cp_lexer_peek_token (parser->lexer);
tree tid = token->u.tree_check_value->value;
if (TREE_CODE (tid) == TEMPLATE_ID_EXPR
&& TREE_CODE (TREE_OPERAND (tid, 0)) != IDENTIFIER_NODE)
{
tree tmpl = NULL_TREE;
if (is_overloaded_fn (tid))
{
tree fns = get_fns (tid);
if (!OVL_CHAIN (fns))
tmpl = OVL_CURRENT (fns);
error_at (token->location, "function template-id %qD "
"in nested-name-specifier", tid);
}
else
{
/* Variable template. */
tmpl = TREE_OPERAND (tid, 0);
gcc_assert (variable_template_p (tmpl));
error_at (token->location, "variable template-id %qD "
"in nested-name-specifier", tid);
}
if (tmpl)
inform (DECL_SOURCE_LOCATION (tmpl),
"%qD declared here", tmpl);
parser->scope = error_mark_node;
error_p = true;
/* As below. */
success = true;
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
}
}
if (cp_parser_uncommitted_to_tentative_parse_p (parser))
break;
/* If the next token is an identifier, and the one after

View file

@ -0,0 +1,12 @@
// { dg-do compile { target c++14 } }
template <bool> struct Sink {};
template <class T> void fn();
template <class T> T var = T();
template <class T> void f()
{
Sink<fn<T>::value>(); // { dg-error "function" }
Sink<var<T>::value>(); // { dg-error "variable" }
}
// { dg-prune-output "template argument" }