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
This commit is contained in:
Matt Austern 2003-01-03 19:48:55 +00:00 committed by Matt Austern
parent 6cce57b0d0
commit 9aad8f83a8
6 changed files with 106 additions and 38 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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))

View File

@ -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;
}