aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c94
-rw-r--r--gcc/cp/pt.c29
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/static7.C14
5 files changed, 100 insertions, 49 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 470c9cf..d8bdb2c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3eb8550..21392ce 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c68e25a..744baae 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b26b88a..f2e40b3 100644
--- a/gcc/cp/pt.c
+++ b/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,
- /*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);
+ init = tsubst_expr (DECL_INITIAL (t), args,
+ /*complain=*/1, NULL_TREE);
+ 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);
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/static7.C b/gcc/testsuite/g++.old-deja/g++.pt/static7.C
new file mode 100644
index 0000000..282f78f
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/static7.C
@@ -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;