cp-tree.h (finish_static_data_member_decl): New function.
authorMark Mitchell <mark@codesourcery.com>
Mon, 19 Apr 1999 12:23:55 +0000 (12:23 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 19 Apr 1999 12:23:55 +0000 (12:23 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.pt/static7.C [new file with mode: 0644]

index 470c9cfca6c54a08e0790b31a294c62a1a17546d..d8bdb2c35af947e8329cf31aea51b7db88ca7660 100644 (file)
@@ -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.
index 3eb8550697ea28112acce8064120ab9e9a13d1d5..21392cebbba5e8d4172c8f5b4b842aee2687e0ad 100644 (file)
@@ -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. */
index c68e25a76b2a8d2c18934394d6ba80df5d1a3438..744baae1f20c082d9e7373370628f02cb4baf9da 100644 (file)
@@ -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)
index b26b88a4dcccc8b7f25243b1b76b05f04c3e24fa..f2e40b32242ed2f5a27e18146c7275233b0fd862 100644 (file)
@@ -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 (file)
index 0000000..282f78f
--- /dev/null
@@ -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;