commit dff5042c89e83955238c9ec5b43a73fa2d2f3310 Author: jason Date: Tue Jan 6 20:44:51 2015 +0000 PR c++/64455 * pt.c (type_dependent_expression_p): Handle variable templates. * constexpr.c (potential_constant_expression_1): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219268 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index ee796df..4da263e 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3882,7 +3882,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t)) || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)) && !var_in_constexpr_fn (t) - && !dependent_type_p (TREE_TYPE (t))) + && !type_dependent_expression_p (t)) { if (flags & tf_error) non_const_var_error (t); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 15645b9..de2f6a4 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -21369,6 +21369,14 @@ type_dependent_expression_p (tree expression) && DECL_INITIAL (expression)) return true; + /* A variable template specialization is type-dependent if it has any + dependent template arguments. */ + if (VAR_P (expression) + && DECL_LANG_SPECIFIC (expression) + && DECL_TEMPLATE_INFO (expression) + && variable_template_p (DECL_TI_TEMPLATE (expression))) + return any_dependent_template_arguments_p (DECL_TI_ARGS (expression)); + if (TREE_TYPE (expression) == unknown_type_node) { if (TREE_CODE (expression) == ADDR_EXPR) diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ21.C b/gcc/testsuite/g++.dg/cpp1y/var-templ21.C new file mode 100644 index 0000000..a7b0899 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ21.C @@ -0,0 +1,25 @@ +// PR c++/64455 +// { dg-do compile { target c++14 } } + +template +constexpr bool IsType = true; + +template struct Test +{ +}; + +template +struct Test +{ + typedef T type; +}; + +template +struct X { + typedef typename Test,T>::type type; +}; + +int main() +{ + X::type t; +} commit 33dba2339488931a8630a2414be1d9d4604370e8 Author: jason Date: Tue Jan 6 20:44:59 2015 +0000 * parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid template-ids. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219269 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 22dff06..5c23a36 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 0000000..38bd370 --- /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" }