cp-tree.h (finish_static_data_member_decl): New function.
* cp-tree.h (finish_static_data_member_decl): New function. * decl2.c (finish_static_data_member_decl): Split out from ... (grokfield): Here. * pt.c (instantiate_class_template): Use it here instead of trying to fake it. (tsubst_decl): Don't set DECL_ASSEMBLER_NAME; finish_static_data_member_decl will do that. Explicit set DECL_EXTERNAL to match non-template processing. From-SVN: r26548
This commit is contained in:
parent
80e9dcb4b2
commit
fa8d6e85a7
|
@ -1,3 +1,14 @@
|
|||
1999-04-19 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (finish_static_data_member_decl): New function.
|
||||
* decl2.c (finish_static_data_member_decl): Split out from ...
|
||||
(grokfield): Here.
|
||||
* pt.c (instantiate_class_template): Use it here instead of
|
||||
trying to fake it.
|
||||
(tsubst_decl): Don't set DECL_ASSEMBLER_NAME;
|
||||
finish_static_data_member_decl will do that. Explicit set
|
||||
DECL_EXTERNAL to match non-template processing.
|
||||
|
||||
1999-04-18 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (finish_class_definition): Add parameter.
|
||||
|
|
|
@ -2947,6 +2947,7 @@ extern void check_default_args PROTO((tree));
|
|||
extern void mark_used PROTO((tree));
|
||||
extern tree handle_class_head PROTO((tree, tree, tree));
|
||||
extern tree lookup_arg_dependent PROTO((tree, tree, tree));
|
||||
extern void finish_static_data_member_decl PROTO((tree, tree, tree, int, int));
|
||||
|
||||
/* in errfn.c */
|
||||
/* The cp_* functions aren't suitable for ATTRIBUTE_PRINTF. */
|
||||
|
|
|
@ -1456,6 +1456,61 @@ check_classfn (ctype, function)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* We have just processed the DECL, which is a static data member.
|
||||
Its initializer, if present, is INIT. The ASMSPEC_TREE, if
|
||||
present, is the assembly-language name for the data member.
|
||||
NEED_POP and FLAGS are as for cp_finish_decl. */
|
||||
|
||||
void
|
||||
finish_static_data_member_decl (decl, init, asmspec_tree, need_pop, flags)
|
||||
tree decl;
|
||||
tree init;
|
||||
tree asmspec_tree;
|
||||
int need_pop;
|
||||
int flags;
|
||||
{
|
||||
char* asmspec = 0;
|
||||
|
||||
if (asmspec_tree)
|
||||
asmspec = TREE_STRING_POINTER (asmspec_tree);
|
||||
|
||||
my_friendly_assert (TREE_PUBLIC (decl), 0);
|
||||
|
||||
/* We cannot call pushdecl here, because that would fill in the
|
||||
decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do
|
||||
the right thing, namely, to put this decl out straight away. */
|
||||
/* current_class_type can be NULL_TREE in case of error. */
|
||||
if (!asmspec && current_class_type)
|
||||
{
|
||||
DECL_INITIAL (decl) = error_mark_node;
|
||||
DECL_ASSEMBLER_NAME (decl)
|
||||
= build_static_name (current_class_type, DECL_NAME (decl));
|
||||
}
|
||||
if (! processing_template_decl)
|
||||
pending_statics = perm_tree_cons (NULL_TREE, decl, pending_statics);
|
||||
|
||||
/* Static consts need not be initialized in the class definition. */
|
||||
if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
|
||||
{
|
||||
static int explanation = 0;
|
||||
|
||||
error ("initializer invalid for static member with constructor");
|
||||
if (explanation++ == 0)
|
||||
error ("(you really want to initialize it separately)");
|
||||
init = 0;
|
||||
}
|
||||
/* Force the compiler to know when an uninitialized static const
|
||||
member is being used. */
|
||||
if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0)
|
||||
TREE_USED (decl) = 1;
|
||||
DECL_INITIAL (decl) = init;
|
||||
DECL_IN_AGGR_P (decl) = 1;
|
||||
DECL_CONTEXT (decl) = current_class_type;
|
||||
DECL_CLASS_CONTEXT (decl) = current_class_type;
|
||||
|
||||
cp_finish_decl (decl, init, asmspec_tree, need_pop, flags);
|
||||
}
|
||||
|
||||
/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
|
||||
of a structure component, returning a FIELD_DECL node.
|
||||
QUALS is a list of type qualifiers for this decl (such as for declaring
|
||||
|
@ -1635,43 +1690,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
|
|||
|
||||
if (TREE_CODE (value) == VAR_DECL)
|
||||
{
|
||||
my_friendly_assert (TREE_PUBLIC (value), 0);
|
||||
|
||||
/* We cannot call pushdecl here, because that would
|
||||
fill in the value of our TREE_CHAIN. Instead, we
|
||||
modify cp_finish_decl to do the right thing, namely, to
|
||||
put this decl out straight away. */
|
||||
/* current_class_type can be NULL_TREE in case of error. */
|
||||
if (asmspec == 0 && current_class_type)
|
||||
{
|
||||
TREE_PUBLIC (value) = 1;
|
||||
DECL_INITIAL (value) = error_mark_node;
|
||||
DECL_ASSEMBLER_NAME (value)
|
||||
= build_static_name (current_class_type, DECL_NAME (value));
|
||||
}
|
||||
if (! processing_template_decl)
|
||||
pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics);
|
||||
|
||||
/* Static consts need not be initialized in the class definition. */
|
||||
if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value)))
|
||||
{
|
||||
static int explanation = 0;
|
||||
|
||||
error ("initializer invalid for static member with constructor");
|
||||
if (explanation++ == 0)
|
||||
error ("(you really want to initialize it separately)");
|
||||
init = 0;
|
||||
}
|
||||
/* Force the compiler to know when an uninitialized static
|
||||
const member is being used. */
|
||||
if (CP_TYPE_CONST_P (TREE_TYPE (value)) && init == 0)
|
||||
TREE_USED (value) = 1;
|
||||
DECL_INITIAL (value) = init;
|
||||
DECL_IN_AGGR_P (value) = 1;
|
||||
DECL_CONTEXT (value) = current_class_type;
|
||||
DECL_CLASS_CONTEXT (value) = current_class_type;
|
||||
|
||||
cp_finish_decl (value, init, asmspec_tree, 1, flags);
|
||||
finish_static_data_member_decl (value, init, asmspec_tree,
|
||||
/*need_pop=*/1, flags);
|
||||
return value;
|
||||
}
|
||||
if (TREE_CODE (value) == FIELD_DECL)
|
||||
|
|
27
gcc/cp/pt.c
27
gcc/cp/pt.c
|
@ -4982,16 +4982,19 @@ instantiate_class_template (type)
|
|||
r = tsubst (t, args, /*complain=*/1, NULL_TREE);
|
||||
if (TREE_CODE (r) == VAR_DECL)
|
||||
{
|
||||
pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
|
||||
/* Perhaps we should do more of grokfield here. */
|
||||
tree init;
|
||||
|
||||
if (DECL_DEFINED_IN_CLASS_P (r))
|
||||
/* Set up DECL_INITIAL, since tsubst doesn't. */
|
||||
DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args,
|
||||
init = tsubst_expr (DECL_INITIAL (t), args,
|
||||
/*complain=*/1, NULL_TREE);
|
||||
start_decl_1 (r);
|
||||
DECL_IN_AGGR_P (r) = 1;
|
||||
DECL_EXTERNAL (r) = 1;
|
||||
cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0);
|
||||
else
|
||||
init = NULL_TREE;
|
||||
|
||||
finish_static_data_member_decl (r, init,
|
||||
/*asmspec_tree=*/NULL_TREE,
|
||||
/*need_pop=*/0,
|
||||
/*flags=*/0);
|
||||
|
||||
if (DECL_DEFINED_IN_CLASS_P (r))
|
||||
check_static_variable_definition (r, TREE_TYPE (r));
|
||||
}
|
||||
|
@ -5825,9 +5828,6 @@ tsubst_decl (t, args, type, in_decl)
|
|||
TREE_TYPE (r) = type;
|
||||
c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
|
||||
DECL_CONTEXT (r) = ctx;
|
||||
if (TREE_STATIC (r))
|
||||
DECL_ASSEMBLER_NAME (r)
|
||||
= build_static_name (DECL_CONTEXT (r), DECL_NAME (r));
|
||||
|
||||
/* Don't try to expand the initializer until someone tries to use
|
||||
this variable; otherwise we run into circular dependencies. */
|
||||
|
@ -5837,6 +5837,11 @@ tsubst_decl (t, args, type, in_decl)
|
|||
copy_lang_decl (r);
|
||||
DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
|
||||
|
||||
/* A static data member declaration is always marked external
|
||||
when it is declared in-class, even if an initializer is
|
||||
present. We mimic the non-template processing here. */
|
||||
DECL_EXTERNAL (r) = 1;
|
||||
|
||||
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
|
||||
SET_DECL_IMPLICIT_INSTANTIATION (r);
|
||||
register_specialization (r, gen_tmpl, argvec);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// Build don't link:
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
template <class T>
|
||||
struct S {
|
||||
S() {}
|
||||
|
||||
static S s;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
S<T> S<T>::s;
|
||||
|
||||
S<int> si;
|
Loading…
Reference in New Issue