From efcdb22fe3288fbfa4cd8ba9554b3a561c4d6e08 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 6 Jan 2015 15:44:59 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 3 ++ gcc/cp/parser.c | 40 ++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1y/var-templ20.C | 12 +++++++ 3 files changed, 55 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ20.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e5e54eae6f06..f9322bfd839c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2015-01-06 Jason Merrill + * 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. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 22dff06eb6c7..5c23a36337a4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ20.C b/gcc/testsuite/g++.dg/cpp1y/var-templ20.C new file mode 100644 index 000000000000..38bd3705d115 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ20.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++14 } } + +template struct Sink {}; +template void fn(); +template T var = T(); + +template void f() +{ + Sink::value>(); // { dg-error "function" } + Sink::value>(); // { dg-error "variable" } +} +// { dg-prune-output "template argument" } -- 2.43.5