From 9aad8f83a8c33f5af53fa712234677766716659d Mon Sep 17 00:00:00 2001 From: Matt Austern Date: Fri, 3 Jan 2003 19:48:55 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 16 ++++++++++++ gcc/cp/class.c | 38 +++++++++++++++++++++++++--- gcc/cp/cp-tree.h | 13 +++++++--- gcc/cp/decl.c | 9 +++++++ gcc/cp/decl2.c | 65 ++++++++++++++++++++++++------------------------ gcc/cp/pt.c | 3 +++ 6 files changed, 106 insertions(+), 38 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dad9680fe90..344630d722d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2003-01-03 Matt Austern + + * 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 * decl.c (cp_make_fname_decl): Push the decls inside the diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 54dde539911..c278aa5e91b 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 111cc2ff8ca..8f77d10bab7 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 ed200092777..63ec317d7dc 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 8e440e92e97..73e37ad5f1b 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 ae810514cb9..aedc90d2ec6 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; } -- 2.30.2