From 5e0231c231404677aa1b90e499b54cc1ff6328a4 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 23 Aug 2014 02:51:58 -0400 Subject: [PATCH] Allow non-constexpr variable templates. * decl2.c (note_variable_template_instantiation): New. * cp-tree.h: Declare it. * pt.c (instantiate_decl): Call it. (push_template_decl_real): Allow non-constexpr variable templates. * semantics.c (finish_id_expression): Mark the variable template instantiation as used. * mangle.c (write_mangled_name): Variable template instantiations are mangled. * parser.c (cp_parser_init_declarator): Complain about non-function implicit templates. From-SVN: r214396 --- gcc/cp/ChangeLog | 14 ++++++++++ gcc/cp/cp-tree.h | 3 +++ gcc/cp/decl2.c | 8 ++++++ gcc/cp/mangle.c | 2 ++ gcc/cp/parser.c | 34 +++++++++++++----------- gcc/cp/pt.c | 12 +++------ gcc/cp/semantics.c | 1 + gcc/testsuite/g++.dg/cpp1y/pr59638.C | 7 +++-- gcc/testsuite/g++.dg/cpp1y/pr60626.C | 2 +- gcc/testsuite/g++.dg/cpp1y/var-templ7.C | 8 ++++++ gcc/testsuite/g++.old-deja/g++.pt/var1.C | 3 +-- 11 files changed, 64 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b71dcba151f..04b0e00b6ca 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2014-08-23 Jason Merrill + + Allow non-constexpr variable templates. + * decl2.c (note_variable_template_instantiation): New. + * cp-tree.h: Declare it. + * pt.c (instantiate_decl): Call it. + (push_template_decl_real): Allow non-constexpr variable templates. + * semantics.c (finish_id_expression): Mark the variable template + instantiation as used. + * mangle.c (write_mangled_name): Variable template instantiations + are mangled. + * parser.c (cp_parser_init_declarator): Complain about + non-function implicit templates. + 2014-08-22 Marek Polacek PR c++/62199 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 81c7fd6b99c..5d4df6ba7db 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5051,6 +5051,8 @@ variable_template_p (tree t) { if (TREE_CODE (t) != TEMPLATE_DECL) return false; + if (!PRIMARY_TEMPLATE_P (t)) + return false; if (tree r = DECL_TEMPLATE_RESULT (t)) return VAR_P (r); return false; @@ -5393,6 +5395,7 @@ extern tree get_tls_wrapper_fn (tree); extern void mark_needed (tree); extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); +extern void note_variable_template_instantiation (tree); extern tree build_artificial_parm (tree, tree); extern bool possibly_inlined_p (tree); extern int parm_index (tree); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 63583a8dc6a..74a10fb74fb 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -787,6 +787,14 @@ note_vague_linkage_fn (tree decl) vec_safe_push (deferred_fns, decl); } +/* As above, but for variable template instantiations. */ + +void +note_variable_template_instantiation (tree decl) +{ + vec_safe_push (pending_statics, decl); +} + /* We have just processed the DECL, which is a static data member. The other parameters are as for cp_finish_decl. */ diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 40508ab0cc3..283983fbe02 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -667,6 +667,8 @@ write_mangled_name (const tree decl, bool top_level) } } else if (VAR_P (decl) + /* Variable template instantiations are mangled. */ + && !(DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) /* The names of non-static global variables aren't mangled. */ && DECL_EXTERNAL_LINKAGE_P (decl) && (CP_DECL_CONTEXT (decl) == global_namespace diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4dc7c33cb33..7d8b7101cd1 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16779,6 +16779,8 @@ cp_parser_init_declarator (cp_parser* parser, /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); + bool bogus_implicit_tmpl = false; + if (function_declarator_p (declarator)) { /* Check to see if the token indicates the start of a @@ -16831,6 +16833,19 @@ cp_parser_init_declarator (cp_parser* parser, return decl; } } + else if (parser->fully_implicit_function_template_p) + { + /* A non-template declaration involving a function parameter list + containing an implicit template parameter will be made into a + template. If the resulting declaration is not going to be an + actual function then finish the template scope here to prevent it. + An error message will be issued once we have a decl to talk about. + + FIXME probably we should do type deduction rather than create an + implicit template, but the standard currently doesn't allow it. */ + bogus_implicit_tmpl = true; + finish_fully_implicit_template (parser, NULL_TREE); + } /* [dcl.dcl] @@ -16996,21 +17011,10 @@ cp_parser_init_declarator (cp_parser* parser, warning (OPT_Wattributes, "attributes after parenthesized initializer ignored"); - /* A non-template declaration involving a function parameter list containing - an implicit template parameter will have been made into a template. If it - turns out that the resulting declaration is not an actual function then - finish the template declaration here. An error message will already have - been issued. */ - if (parser->fully_implicit_function_template_p) - if (!function_declarator_p (declarator)) - { - if (pushed_scope) - { - pop_scope (pushed_scope); - pushed_scope = 0; - } - finish_fully_implicit_template (parser, /*member_decl_opt=*/0); - } + /* And now complain about a non-function implicit template. */ + if (bogus_implicit_tmpl) + error_at (DECL_SOURCE_LOCATION (decl), + "non-function %qD declared as implicit template", decl); /* For an in-class declaration, use `grokfield' to create the declaration. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 41fd424da8f..14b5bfb190a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4777,14 +4777,7 @@ push_template_decl_real (tree decl, bool is_friend) /* alias-declaration */ gcc_assert (!DECL_ARTIFICIAL (decl)); else if (VAR_P (decl)) - { - if (!DECL_DECLARED_CONSTEXPR_P (decl)) - { - sorry ("template declaration of non-constexpr variable %qD", - decl); - return error_mark_node; - } - } + /* C++14 variable template. */; else { error ("template declaration of %q#D", decl); @@ -20106,6 +20099,9 @@ instantiate_decl (tree d, int defer_ok, if (enter_context) pop_nested_class (); + + if (variable_template_p (td)) + note_variable_template_instantiation (d); } else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern)) synthesize_method (d); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 531927e3bca..aed820cdda5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3512,6 +3512,7 @@ finish_id_expression (tree id_expression, && variable_template_p (TREE_OPERAND (decl, 0))) { decl = finish_template_variable (decl); + mark_used (decl); } else if (scope) { diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59638.C b/gcc/testsuite/g++.dg/cpp1y/pr59638.C index a4c63acee76..ce90483ce8c 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr59638.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr59638.C @@ -1,13 +1,12 @@ // PR c++/59638 // { dg-do compile { target c++1y } } // { dg-options "" } -// { dg-excess-errors "sorry" } -void (*a)(auto); // { dg-error "" "" { xfail *-*-* } } +void (*a)(auto); // { dg-error "" } -void (*b)(auto) = 0; // { dg-error "" "" { xfail *-*-* } } +void (*b)(auto) = 0; // { dg-error "" } -typedef void (*f)(auto); // { dg-error "template declaration" } +typedef void (*f)(auto); // { dg-error "" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60626.C b/gcc/testsuite/g++.dg/cpp1y/pr60626.C index 39ea438159a..314d6dacf10 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr60626.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr60626.C @@ -4,4 +4,4 @@ struct A {}; -void (*A::p)(auto) = 0; // { dg-error "static member|non-template" } +void (*A::p)(auto) = 0; // { dg-error "static member|template" } diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ7.C b/gcc/testsuite/g++.dg/cpp1y/var-templ7.C new file mode 100644 index 00000000000..1e59cf42738 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ7.C @@ -0,0 +1,8 @@ +// { dg-do compile { target c++1y } } + +template T var = 0; + +int main() +{ + var = 42; +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/var1.C b/gcc/testsuite/g++.old-deja/g++.pt/var1.C index ec91bc47672..08d65e9a827 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/var1.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/var1.C @@ -1,5 +1,4 @@ // { dg-do assemble } // Origin: Jason Merrill -// { dg-excess-errors "sorry" } -template T t; // template declaration of t +template T t; // { dg-error "" "" { target { ! c++1y } } } template declaration of t