OSDN Git Service

PR c++/5571
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 7 Apr 2002 06:09:27 +0000 (06:09 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 7 Apr 2002 06:09:27 +0000 (06:09 +0000)
* stor-layout.c (layout_decl): Reset the RTL for the decl.

* class.c (layout_class_type): Remember incomplete static
variables.
(finish_struct_1): Call complete_vars, not
hack_incomplete_structures.
* cp-tree.h (hack_incomplete_structures): Rename to ...
(complete_vars): ... this.
(struct saved_scope): Remove incomplete.
(namespace_scope_incomplete): Remove.
* decl.c (struct binding_level): Remove incomplete.
(incomplete_vars): New variable.
(mark_binding_level): Don't mark incomplete.
(print_binding_level): Don't print it.
(mark_saved_scope): Don't mark incomplete.
(pushdecl): Use maybe_register_incopmlete_var.
(cxx_init_decl_processing): Register incomplete_vars for GC.
(start_decl_1): Clarify error message.
(hack_incomplete_vars): Remove.
(maybe_register_incomplete_var): New function.
(complete_vars): Likewise.

* g++.dg/opt/static2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@51978 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/static2.C [new file with mode: 0644]

index 6263100..abe29ba 100644 (file)
@@ -37,6 +37,9 @@
 
 2002-04-06  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/5571
+       * stor-layout.c (layout_decl): Reset the RTL for the decl.
+
        PR opt/5120
        * sibcall.c (optimize_sibling_and_tail_recursive_call): Clear
        RTX_UNCHANGING_P for the functions arguments when a tail call
index e739e2a..1d2470a 100644 (file)
@@ -1,3 +1,26 @@
+2002-04-06  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/5571
+       * class.c (layout_class_type): Remember incomplete static
+       variables.
+       (finish_struct_1): Call complete_vars, not
+       hack_incomplete_structures.
+       * cp-tree.h (hack_incomplete_structures): Rename to ...
+       (complete_vars): ... this.
+       (struct saved_scope): Remove incomplete.
+       (namespace_scope_incomplete): Remove.
+       * decl.c (struct binding_level): Remove incomplete.
+       (incomplete_vars): New variable.
+       (mark_binding_level): Don't mark incomplete.
+       (print_binding_level): Don't print it.
+       (mark_saved_scope): Don't mark incomplete.
+       (pushdecl): Use maybe_register_incopmlete_var.
+       (cxx_init_decl_processing): Register incomplete_vars for GC.
+       (start_decl_1): Clarify error message.
+       (hack_incomplete_vars): Remove.
+       (maybe_register_incomplete_var): New function.
+       (complete_vars): Likewise.
+
 2002-04-06  Jason Merrill  <jason@redhat.com>
 
        PR c++/4934
index 8ce3fc7..ba28e84 100644 (file)
@@ -4898,6 +4898,18 @@ layout_class_type (t, empty_p, vfuns_p,
       if (TREE_CODE (field) != FIELD_DECL)
        {
          place_field (rli, field);
+         /* If the static data member has incomplete type, keep track
+            of it so that it can be completed later.  (The handling 
+            of pending statics in finish_record_layout is
+            insufficient; consider:
+
+              struct S1;
+              struct S2 { static S1 s1; };
+              
+             At this point, finish_record_layout will be called, but
+            S1 is still incomplete.)  */
+         if (TREE_CODE (field) == VAR_DECL)
+           maybe_register_incomplete_var (field);
          continue;
        }
 
@@ -5240,7 +5252,7 @@ finish_struct_1 (t)
       && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
     warning ("`%#T' has virtual functions but non-virtual destructor", t);
 
-  hack_incomplete_structures (t);
+  complete_vars (t);
 
   if (warn_overloaded_virtual)
     warn_hidden (t);
index 8b3a256..1cd7d4a 100644 (file)
@@ -730,7 +730,6 @@ struct saved_scope
   tree x_previous_class_type;
   tree x_previous_class_values;
   tree x_saved_tree;
-  tree incomplete;
   tree lookups;
   tree last_parms;
 
@@ -795,10 +794,6 @@ struct saved_scope
 
 #define previous_class_values scope_chain->x_previous_class_values
 
-/* A list of the declarations with incomplete type at namespace scope.  */
-
-#define namespace_scope_incomplete scope_chain->incomplete
-
 /* A list of private types mentioned, for deferred access checking.  */
 
 #define type_lookups scope_chain->lookups
@@ -3766,7 +3761,8 @@ extern void finish_function_body          PARAMS ((tree));
 extern tree finish_function                    PARAMS ((int));
 extern tree start_method                       PARAMS ((tree, tree, tree));
 extern tree finish_method                      PARAMS ((tree));
-extern void hack_incomplete_structures         PARAMS ((tree));
+extern void maybe_register_incomplete_var       PARAMS ((tree));
+extern void complete_vars                      PARAMS ((tree));
 extern void finish_stmt                                PARAMS ((void));
 extern void print_other_binding_stack          PARAMS ((struct binding_level *));
 extern void revert_static_member_fn             PARAMS ((tree));
index 78f1b14..383991f 100644 (file)
@@ -398,10 +398,6 @@ struct binding_level
     /* The binding level which this one is contained in (inherits from).  */
     struct binding_level *level_chain;
 
-    /* List of decls in `names' that have incomplete
-       structure or union types.  */
-    tree incomplete;
-
     /* List of VAR_DECLS saved from a previous for statement.
        These would be dead in ISO-conforming code, but might
        be referenced in ARM-era code.  These are stored in a
@@ -484,6 +480,12 @@ static struct binding_level *global_binding_level;
 
 static int keep_next_level_flag;
 
+/* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
+   UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type.  At the
+   time the VAR_DECL was declared, the type was incomplete.  */
+
+static tree incomplete_vars;
+
 #if defined(DEBUG_CP_BINDING_LEVELS)
 static int binding_depth = 0;
 static int is_class_level = 0;
@@ -1957,7 +1959,6 @@ mark_binding_level (arg)
       ggc_mark_tree (lvl->shadowed_labels);
       ggc_mark_tree (lvl->blocks);
       ggc_mark_tree (lvl->this_class);
-      ggc_mark_tree (lvl->incomplete);
       ggc_mark_tree (lvl->dead_vars_from_for);
     }
 }
@@ -1995,8 +1996,6 @@ print_binding_level (lvl)
   int i = 0, len;
   fprintf (stderr, " blocks=");
   fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
-  fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
-          list_length (lvl->incomplete), lvl->parm_flag, lvl->keep);
   if (lvl->tag_transparent)
     fprintf (stderr, " tag-transparent");
   if (lvl->more_cleanups_ok)
@@ -2397,7 +2396,6 @@ mark_saved_scope (arg)
       ggc_mark_tree (t->x_previous_class_type);
       ggc_mark_tree (t->x_previous_class_values);
       ggc_mark_tree (t->x_saved_tree);
-      ggc_mark_tree (t->incomplete);
       ggc_mark_tree (t->lookups);
 
       mark_stmt_tree (&t->x_stmt_tree);
@@ -4242,22 +4240,8 @@ pushdecl (x)
       if (TREE_CODE (x) == FUNCTION_DECL)
        check_default_args (x);
 
-      /* Keep count of variables in this level with incomplete type.  */
-      if (TREE_CODE (x) == VAR_DECL
-         && TREE_TYPE (x) != error_mark_node
-         && ((!COMPLETE_TYPE_P (TREE_TYPE (x))
-              && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
-             /* RTTI TD entries are created while defining the type_info.  */
-             || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
-                 && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
-       {
-         if (namespace_bindings_p ())
-           namespace_scope_incomplete
-             = tree_cons (NULL_TREE, x, namespace_scope_incomplete);
-         else
-           current_binding_level->incomplete
-             = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
-       }
+      if (TREE_CODE (x) == VAR_DECL)
+       maybe_register_incomplete_var (x);
     }
 
   if (need_new_binding)
@@ -6649,6 +6633,7 @@ cxx_init_decl_processing ()
   ggc_add_tree_root (&current_lang_name, 1);
   ggc_add_tree_root (&static_aggregates, 1);
   ggc_add_tree_root (&free_bindings, 1);
+  ggc_add_tree_root (&incomplete_vars, 1);
 }
 
 /* Generate an initializer for a function naming variable from
@@ -7430,7 +7415,7 @@ start_decl_1 (decl)
       if ((! processing_template_decl || ! uses_template_parms (type))
          && !COMPLETE_TYPE_P (complete_type (type)))
        {
-         error ("aggregate `%#D' has incomplete type and cannot be initialized",
+         error ("aggregate `%#D' has incomplete type and cannot be defined",
                 decl);
          /* Change the type so that assemble_variable will give
             DECL an rtl we can live with: (mem (const_int 0)).  */
@@ -14432,72 +14417,60 @@ finish_method (decl)
   return decl;
 }
 \f
-/* Called when a new struct TYPE is defined.
-   If this structure or union completes the type of any previous
-   variable declaration, lay it out and output its rtl.  */
+
+/* VAR is a VAR_DECL.  If its type is incomplete, remember VAR so that
+   we can lay it out later, when and if its type becomes complete.  */
 
 void
-hack_incomplete_structures (type)
-     tree type;
+maybe_register_incomplete_var (var)
+     tree var;
 {
-  tree *list;
-  struct binding_level *level;
+  my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
 
-  if (!type) /* Don't do this for class templates.  */
-    return;
-
-  if (namespace_bindings_p ())
-    {
-      level = 0;
-      list = &namespace_scope_incomplete;
-    }
-  else
+  /* Keep track of variables with incomplete types.  */
+  if (!processing_template_decl && TREE_TYPE (var) != error_mark_node 
+      && DECL_EXTERNAL (var))
     {
-      level = innermost_nonclass_level ();
-      list = &level->incomplete;
+      tree inner_type = TREE_TYPE (var);
+      
+      while (TREE_CODE (inner_type) == ARRAY_TYPE)
+       inner_type = TREE_TYPE (inner_type);
+      inner_type = TYPE_MAIN_VARIANT (inner_type);
+      
+      if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
+         /* RTTI TD entries are created while defining the type_info.  */
+         || (TYPE_LANG_SPECIFIC (inner_type)
+             && TYPE_BEING_DEFINED (inner_type)))
+       incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
     }
+}
 
-  while (1)
-    {
-      while (*list)
-       {
-         tree decl = TREE_VALUE (*list);
-         if ((decl && TREE_TYPE (decl) == type)
-             || (TREE_TYPE (decl)
-                 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-                 && TREE_TYPE (TREE_TYPE (decl)) == type))
-           {
-             int toplevel = toplevel_bindings_p ();
-             if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-                 && TREE_TYPE (TREE_TYPE (decl)) == type)
-               layout_type (TREE_TYPE (decl));
-             layout_decl (decl, 0);
-             rest_of_decl_compilation (decl, NULL, toplevel, 0);
-             if (! toplevel)
-               {
-                 tree cleanup;
-                 expand_decl (decl);
-                 cleanup = cxx_maybe_build_cleanup (decl);
-                 expand_decl_init (decl);
-                 if (! expand_decl_cleanup (decl, cleanup))
-                   error ("parser lost in parsing declaration of `%D'",
-                             decl);
-               }
-             *list = TREE_CHAIN (*list);
-           }
-         else
-           list = &TREE_CHAIN (*list);
-       }
+/* Called when a class type (given by TYPE) is defined.  If there are
+   any existing VAR_DECLs whose type hsa been completed by this
+   declaration, update them now.  */
 
-      /* Keep looking through artificial binding levels generated
-        for local variables.  */
-      if (level && level->keep == 2)
+void
+complete_vars (type)
+     tree type;
+{
+  tree *list = &incomplete_vars;
+
+  my_friendly_assert (CLASS_TYPE_P (type), 20020406);
+  while (*list) 
+    {
+      if (same_type_p (type, TREE_PURPOSE (*list)))
        {
-         level = level->level_chain;
-         list = &level->incomplete;
+         tree var = TREE_VALUE (*list);
+         /* Make sure that the type of the VAR has been laid out.  It
+            might not have been if the type of VAR is an array.  */
+         layout_type (TREE_TYPE (var));
+         /* Lay out the variable itself.  */
+         layout_decl (var, 0);
+         /* Remove this entry from the list.  */
+         *list = TREE_CHAIN (*list);
        }
       else
-       break;
+       list = &TREE_CHAIN (*list);
     }
 }
 
index baf26dd..fbf5e4f 100644 (file)
@@ -461,6 +461,11 @@ layout_decl (decl, known_align)
                               larger_than_size);
        }
     }
+
+  /* If there was already RTL for this DECL, as for a variable with an
+     incomplete type whose type is completed later, update the RTL.  */
+  if (DECL_RTL_SET_P (decl))
+    make_decl_rtl (decl, NULL);
 }
 \f
 /* Hook for a front-end function that can modify the record layout as needed
index ddd75d4..c71c02e 100644 (file)
@@ -1,5 +1,10 @@
 2002-04-06  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/5571
+       * g++.dg/opt/static2.C: New test.
+
+2002-04-06  Mark Mitchell  <mark@codesourcery.com>
+
        PR c/5120
        * gcc.dg/20020406-1.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/opt/static2.C b/gcc/testsuite/g++.dg/opt/static2.C
new file mode 100644 (file)
index 0000000..e2ecd13
--- /dev/null
@@ -0,0 +1,13 @@
+// Origin: reichelt@igpm.rwth-aachen.de
+// PR 5571
+// { dg-options "-O2" }
+
+template <class T> struct A {};
+
+struct B
+{
+    static A<int> a;
+    void f() { a; }
+};
+
+A<int> B::a = A<int>();