summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog3
-rw-r--r--gcc/cp/ChangeLog23
-rw-r--r--gcc/cp/class.c14
-rw-r--r--gcc/cp/cp-tree.h8
-rw-r--r--gcc/cp/decl.c133
-rw-r--r--gcc/stor-layout.c5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/opt/static2.C13
8 files changed, 117 insertions, 87 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 62631007bb7..abe29ba04a0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e739e2a0a11..1d2470abf47 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 8ce3fc7ab46..ba28e849554 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8b3a256d5b7..1cd7d4add53 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 78f1b14a7f3..383991f0924 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
}
-/* 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);
}
}
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index baf26dddba1..fbf5e4f42ad 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -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);
}
/* Hook for a front-end function that can modify the record layout as needed
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ddd75d41ea8..c71c02ebbe2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..e2ecd13c572
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/static2.C
@@ -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>();
OpenPOWER on IntegriCloud