aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Austern <austern@apple.com>2003-01-03 19:48:55 +0000
committerMatt Austern <austern@gcc.gnu.org>2003-01-03 19:48:55 +0000
commit9aad8f83a8c33f5af53fa712234677766716659d (patch)
treefcf7fb52bf769a2736649a456198023537d5a286
parent6cce57b0d073bc545a9a2855885e65a4ca43ce4d (diff)
downloadgcc-9aad8f83a8c33f5af53fa712234677766716659d.zip
gcc-9aad8f83a8c33f5af53fa712234677766716659d.tar.gz
gcc-9aad8f83a8c33f5af53fa712234677766716659d.tar.bz2
cp-tree.h (struct lang_type_class): add field for key method
* cp-tree.h (struct lang_type_class): add field for key method (cp_global_trees): rename dynamic_classes to keyed_classes (key_method): add definition * class.c (finish_struct_1): compute class's key method, and add the class to keyed_classes list if there is no key method. * decl.c (finish_function): add class to keyed_classes list if we see a definition of the class's key method. * pt.c (instantiate_class_template): add template specialization of a dynamic class to keyed_classes list. * decl2.c (key_method): remove (finish_file): iterate only through keyed_classes list when deciding whether to emit vtables, remove class from its list after we do the emission. From-SVN: r60850
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/class.c38
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/decl2.c65
-rw-r--r--gcc/cp/pt.c3
6 files changed, 106 insertions, 38 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index dad9680..344630d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,19 @@
+2003-01-03 Matt Austern <austern@apple.com>
+
+ * cp-tree.h (struct lang_type_class): add field for key method
+ (cp_global_trees): rename dynamic_classes to keyed_classes
+ (key_method): add definition
+ * class.c (finish_struct_1): compute class's key method, and add
+ the class to keyed_classes list if there is no key method.
+ * decl.c (finish_function): add class to keyed_classes list if we
+ see a definition of the class's key method.
+ * pt.c (instantiate_class_template): add template specialization
+ of a dynamic class to keyed_classes list.
+ * decl2.c (key_method): remove
+ (finish_file): iterate only through keyed_classes list when
+ deciding whether to emit vtables, remove class from its list after
+ we do the emission.
+
2003-01-02 Jason Merrill <jason@redhat.com>
* decl.c (cp_make_fname_decl): Push the decls inside the
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 54dde53..c278aa5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5224,6 +5224,30 @@ layout_class_type (tree t, tree *virtuals_p)
splay_tree_delete (empty_base_offsets);
}
+/* Returns the virtual function with which the vtable for TYPE is
+ emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
+
+static tree
+key_method (tree type)
+{
+ tree method;
+
+ if (TYPE_FOR_JAVA (type)
+ || processing_template_decl
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+ || CLASSTYPE_INTERFACE_KNOWN (type))
+ return NULL_TREE;
+
+ for (method = TYPE_METHODS (type); method != NULL_TREE;
+ method = TREE_CHAIN (method))
+ if (DECL_VINDEX (method) != NULL_TREE
+ && ! DECL_DECLARED_INLINE_P (method)
+ && ! DECL_PURE_VIRTUAL_P (method))
+ return method;
+
+ return NULL_TREE;
+}
+
/* Perform processing required when the definition of T (a class type)
is complete. */
@@ -5265,6 +5289,17 @@ finish_struct_1 (t)
bases and members and add implicitly generated methods. */
check_bases_and_members (t);
+ /* Find the key method */
+ if (TYPE_CONTAINS_VPTR_P (t))
+ {
+ CLASSTYPE_KEY_METHOD (t) = key_method (t);
+
+ /* If a polymorphic class has no key method, we may emit the vtable
+ in every translation unit where the class definition appears. */
+ if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
+ keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
+ }
+
/* Layout the class itself. */
layout_class_type (t, &virtuals);
@@ -5342,9 +5377,6 @@ finish_struct_1 (t)
else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
DECL_VINDEX (fndecl) = build_shared_int_cst (vindex);
}
-
- /* Add this class to the list of dynamic classes. */
- dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
}
finish_struct_bits (t);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 111cc2f..8f77d10 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -628,7 +628,7 @@ enum cp_tree_index
CPTI_DSO_HANDLE,
CPTI_DCAST,
- CPTI_DYNAMIC_CLASSES,
+ CPTI_KEYED_CLASSES,
CPTI_MAX
};
@@ -761,9 +761,10 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
-/* A TREE_LIST of all of the dynamic classes in the program. */
+/* A TREE_LIST of the dynamic classes whose vtables may have to be
+ emitted in this translation unit. */
-#define dynamic_classes cp_global_trees[CPTI_DYNAMIC_CLASSES]
+#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES]
/* Global state. */
@@ -1182,6 +1183,7 @@ struct lang_type_class GTY(())
tree pure_virtuals;
tree friend_classes;
tree methods;
+ tree key_method;
tree decl_list;
tree template_info;
tree befriending_classes;
@@ -1302,6 +1304,11 @@ struct lang_type GTY(())
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3 (NODE))
+/* The member function with which the vtable will be emitted:
+ the first noninline non-pure-virtual member function. NULL_TREE
+ if there is no key function or if this is a class template */
+#define CLASSTYPE_KEY_METHOD(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->key_method)
+
/* Vector member functions defined in this class. Each element is
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
functions with the same name end up in the same slot. The first
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ed20009..63ec317 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14360,6 +14360,15 @@ finish_function (flags)
if (fndecl == NULL_TREE)
return error_mark_node;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+ && DECL_VIRTUAL_P (fndecl)
+ && !processing_template_decl)
+ {
+ tree fnclass = DECL_CONTEXT (fndecl);
+ if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
+ keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+ }
+
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8e440e9..73e37ad 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -88,7 +88,6 @@ static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node,
static tree prune_vars_needing_no_initialization (tree);
static void write_out_vars (tree);
static void import_export_class (tree);
-static tree key_method (tree);
static tree get_guard_bits (tree);
/* A list of static class variables. This is needed, because a
@@ -1536,29 +1535,6 @@ maybe_make_one_only (tree decl)
}
}
-/* Returns the virtual function with which the vtable for TYPE is
- emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
-
-static tree
-key_method (tree type)
-{
- tree method;
-
- if (TYPE_FOR_JAVA (type)
- || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
- || CLASSTYPE_INTERFACE_KNOWN (type))
- return NULL_TREE;
-
- for (method = TYPE_METHODS (type); method != NULL_TREE;
- method = TREE_CHAIN (method))
- if (DECL_VINDEX (method) != NULL_TREE
- && ! DECL_DECLARED_INLINE_P (method)
- && ! DECL_PURE_VIRTUAL_P (method))
- return method;
-
- return NULL_TREE;
-}
-
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
based on TYPE and other static flags.
@@ -1589,7 +1565,7 @@ import_export_vtable (tree decl, tree type, int final)
functions in our class, or if we come from a template. */
int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
- || key_method (type));
+ || CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
if (final || ! found)
{
@@ -1648,7 +1624,7 @@ import_export_class (tree ctype)
if (import_export == 0
&& TYPE_POLYMORPHIC_P (ctype))
{
- tree method = key_method (ctype);
+ tree method = CLASSTYPE_KEY_METHOD (ctype);
if (method)
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
@@ -2639,12 +2615,37 @@ finish_file ()
instantiate_pending_templates ();
/* Write out virtual tables as required. Note that writing out
- the virtual table for a template class may cause the
- instantiation of members of that class. */
- for (t = dynamic_classes; t; t = TREE_CHAIN (t))
- if (maybe_emit_vtables (TREE_VALUE (t)))
- reconsider = true;
-
+ the virtual table for a template class may cause the
+ instantiation of members of that class. If we write out
+ vtables then we remove the class from our list so we don't
+ have to look at it again. */
+
+ while (keyed_classes != NULL_TREE
+ && maybe_emit_vtables (TREE_VALUE (keyed_classes)))
+ {
+ reconsider = 1;
+ keyed_classes = TREE_CHAIN (keyed_classes);
+ }
+
+ t = keyed_classes;
+ if (t != NULL_TREE)
+ {
+ tree next = TREE_CHAIN (t);
+
+ while (next)
+ {
+ if (maybe_emit_vtables (TREE_VALUE (next)))
+ {
+ reconsider = 1;
+ TREE_CHAIN (t) = TREE_CHAIN (next);
+ }
+ else
+ t = next;
+
+ next = TREE_CHAIN (t);
+ }
+ }
+
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */
if (walk_globals (unemitted_tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ae81051..aedc90d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5487,6 +5487,9 @@ instantiate_class_template (type)
pop_from_top_level ();
pop_tinst_level ();
+ if (TYPE_CONTAINS_VPTR_P (type))
+ keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+
return type;
}