Commit 9aad8f83 by Matt Austern Committed by Matt Austern

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
parent 6cce57b0
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> 2003-01-02 Jason Merrill <jason@redhat.com>
* decl.c (cp_make_fname_decl): Push the decls inside the * decl.c (cp_make_fname_decl): Push the decls inside the
......
...@@ -5224,6 +5224,30 @@ layout_class_type (tree t, tree *virtuals_p) ...@@ -5224,6 +5224,30 @@ layout_class_type (tree t, tree *virtuals_p)
splay_tree_delete (empty_base_offsets); 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) /* Perform processing required when the definition of T (a class type)
is complete. */ is complete. */
...@@ -5265,6 +5289,17 @@ finish_struct_1 (t) ...@@ -5265,6 +5289,17 @@ finish_struct_1 (t)
bases and members and add implicitly generated methods. */ bases and members and add implicitly generated methods. */
check_bases_and_members (t); 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 the class itself. */
layout_class_type (t, &virtuals); layout_class_type (t, &virtuals);
...@@ -5342,9 +5377,6 @@ finish_struct_1 (t) ...@@ -5342,9 +5377,6 @@ finish_struct_1 (t)
else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
DECL_VINDEX (fndecl) = build_shared_int_cst (vindex); 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); finish_struct_bits (t);
......
...@@ -628,7 +628,7 @@ enum cp_tree_index ...@@ -628,7 +628,7 @@ enum cp_tree_index
CPTI_DSO_HANDLE, CPTI_DSO_HANDLE,
CPTI_DCAST, CPTI_DCAST,
CPTI_DYNAMIC_CLASSES, CPTI_KEYED_CLASSES,
CPTI_MAX CPTI_MAX
}; };
...@@ -761,9 +761,10 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; ...@@ -761,9 +761,10 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
destructors. */ destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE] #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. */ /* Global state. */
...@@ -1182,6 +1183,7 @@ struct lang_type_class GTY(()) ...@@ -1182,6 +1183,7 @@ struct lang_type_class GTY(())
tree pure_virtuals; tree pure_virtuals;
tree friend_classes; tree friend_classes;
tree methods; tree methods;
tree key_method;
tree decl_list; tree decl_list;
tree template_info; tree template_info;
tree befriending_classes; tree befriending_classes;
...@@ -1302,6 +1304,11 @@ struct lang_type GTY(()) ...@@ -1302,6 +1304,11 @@ struct lang_type GTY(())
hierarchy, then we can use more efficient search techniques. */ hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3 (NODE)) #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 /* Vector member functions defined in this class. Each element is
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
functions with the same name end up in the same slot. The first functions with the same name end up in the same slot. The first
......
...@@ -14360,6 +14360,15 @@ finish_function (flags) ...@@ -14360,6 +14360,15 @@ finish_function (flags)
if (fndecl == NULL_TREE) if (fndecl == NULL_TREE)
return error_mark_node; 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; nested = function_depth > 1;
fntype = TREE_TYPE (fndecl); fntype = TREE_TYPE (fndecl);
......
...@@ -88,7 +88,6 @@ static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node, ...@@ -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 tree prune_vars_needing_no_initialization (tree);
static void write_out_vars (tree); static void write_out_vars (tree);
static void import_export_class (tree); static void import_export_class (tree);
static tree key_method (tree);
static tree get_guard_bits (tree); static tree get_guard_bits (tree);
/* A list of static class variables. This is needed, because a /* A list of static class variables. This is needed, because a
...@@ -1536,29 +1535,6 @@ maybe_make_one_only (tree decl) ...@@ -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, /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
based on TYPE and other static flags. based on TYPE and other static flags.
...@@ -1589,7 +1565,7 @@ import_export_vtable (tree decl, tree type, int final) ...@@ -1589,7 +1565,7 @@ import_export_vtable (tree decl, tree type, int final)
functions in our class, or if we come from a template. */ functions in our class, or if we come from a template. */
int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type) int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
|| key_method (type)); || CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
if (final || ! found) if (final || ! found)
{ {
...@@ -1648,7 +1624,7 @@ import_export_class (tree ctype) ...@@ -1648,7 +1624,7 @@ import_export_class (tree ctype)
if (import_export == 0 if (import_export == 0
&& TYPE_POLYMORPHIC_P (ctype)) && TYPE_POLYMORPHIC_P (ctype))
{ {
tree method = key_method (ctype); tree method = CLASSTYPE_KEY_METHOD (ctype);
if (method) if (method)
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
} }
...@@ -2639,12 +2615,37 @@ finish_file () ...@@ -2639,12 +2615,37 @@ finish_file ()
instantiate_pending_templates (); instantiate_pending_templates ();
/* Write out virtual tables as required. Note that writing out /* Write out virtual tables as required. Note that writing out
the virtual table for a template class may cause the the virtual table for a template class may cause the
instantiation of members of that class. */ instantiation of members of that class. If we write out
for (t = dynamic_classes; t; t = TREE_CHAIN (t)) vtables then we remove the class from our list so we don't
if (maybe_emit_vtables (TREE_VALUE (t))) have to look at it again. */
reconsider = true;
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 /* Write out needed type info variables. Writing out one variable
might cause others to be needed. */ might cause others to be needed. */
if (walk_globals (unemitted_tinfo_decl_p, emit_tinfo_decl, /*data=*/0)) if (walk_globals (unemitted_tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
......
...@@ -5487,6 +5487,9 @@ instantiate_class_template (type) ...@@ -5487,6 +5487,9 @@ instantiate_class_template (type)
pop_from_top_level (); pop_from_top_level ();
pop_tinst_level (); pop_tinst_level ();
if (TYPE_CONTAINS_VPTR_P (type))
keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
return type; return type;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment