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
This commit is contained in:
parent
a545cacd68
commit
5e0231c231
|
@ -1,3 +1,17 @@
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
12
gcc/cp/pt.c
12
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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// { dg-do compile { target c++1y } }
|
||||
|
||||
template <class T> T var = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
var<int> = 42;
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
// { 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
|
||||
|
|
Loading…
Reference in New Issue