* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214396
138bc75d-0d04-0410-961f-
82ee72b054a4
+2014-08-23 Jason Merrill <jason@redhat.com>
+
+ 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 <polacek@redhat.com>
PR c++/62199
{
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;
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);
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. */
}
}
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
/* 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
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]
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. */
/* 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);
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);
&& variable_template_p (TREE_OPERAND (decl, 0)))
{
decl = finish_template_variable (decl);
+ mark_used (decl);
}
else if (scope)
{
// 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
{
struct A {};
-void (*A::p)(auto) = 0; // { dg-error "static member|non-template" }
+void (*A::p)(auto) = 0; // { dg-error "static member|template" }
--- /dev/null
+// { dg-do compile { target c++1y } }
+
+template <class T> T var = 0;
+
+int main()
+{
+ var<int> = 42;
+}
// { dg-do assemble }
// Origin: Jason Merrill <jason@cygnus.com>
-// { dg-excess-errors "sorry" }
-template <class T> T t; // template declaration of t
+template <class T> T t; // { dg-error "" "" { target { ! c++1y } } } template declaration of t