diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 37 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/class.c | 287 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 40 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 100 | ||||
-rw-r--r-- | gcc/cp/search.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/thunk1.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/thunk2.C | 26 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/vtt1.C | 11 |
10 files changed, 291 insertions, 245 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ce94b3a..2fb30a9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,40 @@ +2002-11-03 Mark Mitchell <mark@codesourcery.com> + + * call.c (build_special_member_call): Do not try to lookup VTTs by + name. + * class.c (vtbl_init_data): Add generate_vcall_entries. + (get_vtable_decl): Do not look up virtual tables by name. + (copy_virtuals): Do not use BV_USE_VCALL_INDEX_P. + (set_primary_base): Do not set CLASSTYPE_RTTI. + (determine_primary_base): Likewise. + (get_matching_virtual): Remove. + (get_vcall_index): New function. + (update_vtable_entry_for_fn): Do not try to use virtual thunks + when they are not required. Assign vcall indices at this point. + (finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT. + Do update dynamic_classes. + (build_vtt): Do not add VTTs to the symbol table. + (build_ctor_vtbl_group): Likewise. + (build_vtbl_initializer): Simplify handling of vcall indices. + (build_vcall_offset_vtbl_entries): Pretend to build vcall offsets + for the most derived class. + (add_vcall_offset_vtbl_entries_1): But do not actually add them to + the vtable. + * cp-tree.h (dynamic_classes): New macro. + (lang_type_class): Remove rtti. Add vtables. Add vcall_indices. + (CLASSTYPE_RTTI): Remove. + (CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove. + (CLASSTYPE_VCALL_INDICES): New macro. + (CLASSTYPE_VTABLES): Likewise. + (BV_USE_VCALL_INDEX_P): Remove. + (build_vtable_path): Remove. + * decl2.c (finish_vtable_vardecl): Remove. + (key_method): Remove #if 0'd code. + (finish_vtable_vardecl): Rename to ... + (maybe_emit_vtables): ... this. + (finish_file): Use it. + * search.c (look_for_overrides_here): Update comment. + 2002-11-01 Zack Weinberg <zack@codesourcery.com> PR c/7353 redux diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a347bba..a7f9a91 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4712,7 +4712,7 @@ build_special_member_call (tree instance, tree name, tree args, /* If the current function is a complete object constructor or destructor, then we fetch the VTT directly. Otherwise, we look it up using the VTT we were given. */ - vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type)); + vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type)); vtt = decay_conversion (vtt); vtt = build (COND_EXPR, TREE_TYPE (vtt), build (EQ_EXPR, boolean_type_node, diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d189686..0dffc62 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -87,6 +87,9 @@ typedef struct vtbl_init_data_s /* Nonzero if we are building the initializer for a construction vtable. */ int ctor_vtbl_p; + /* True when adding vcall offset entries to the vtable. False when + merely computing the indices. */ + bool generate_vcall_entries; } vtbl_init_data; /* The type of a function passed to walk_subobject_offsets. */ @@ -209,6 +212,7 @@ static tree dfs_base_derived_from (tree, void *); static bool base_derived_from (tree, tree); static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree); static tree end_of_base (tree); +static tree get_vcall_index (tree, tree); /* Macros for dfs walking during vtt construction. See dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits @@ -540,21 +544,14 @@ get_vtable_decl (type, complete) tree type; int complete; { - tree name = get_vtable_name (type); - tree decl = IDENTIFIER_GLOBAL_VALUE (name); - - if (decl) - { - my_friendly_assert (TREE_CODE (decl) == VAR_DECL - && DECL_VIRTUAL_P (decl), 20000118); - return decl; - } - - decl = build_vtable (type, name, void_type_node); - decl = pushdecl_top_level (decl); - my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl, - 20000517); + tree decl; + + if (CLASSTYPE_VTABLES (type)) + return CLASSTYPE_VTABLES (type); + decl = build_vtable (type, get_vtable_name (type), void_type_node); + CLASSTYPE_VTABLES (type) = decl; + /* At one time the vtable info was grabbed 2 words at a time. This fails on sparc unless you have 8-byte alignment. (tiemann) */ DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node), @@ -581,10 +578,7 @@ copy_virtuals (binfo) copies = copy_list (BINFO_VIRTUALS (binfo)); for (t = copies; t; t = TREE_CHAIN (t)) - { - BV_VCALL_INDEX (t) = NULL_TREE; - BV_USE_VCALL_INDEX_P (t) = 0; - } + BV_VCALL_INDEX (t) = NULL_TREE; return copies; } @@ -1559,7 +1553,6 @@ set_primary_base (t, binfo) TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype); TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); TYPE_VFIELD (t) = TYPE_VFIELD (basetype); - CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype); } /* Determine the primary class for T. */ @@ -1585,12 +1578,6 @@ determine_primary_base (t) if (TYPE_CONTAINS_VPTR_P (basetype)) { - /* Even a virtual baseclass can contain our RTTI - information. But, we prefer a non-virtual polymorphic - baseclass. */ - if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype); - /* We prefer a non-virtual base, although a virtual one will do. */ if (TREE_VIA_VIRTUAL (base_binfo)) @@ -2325,21 +2312,23 @@ find_final_overrider (t, binfo, fn) return ffod.candidates; } -/* Returns the function from the BINFO_VIRTUALS entry in T which matches - the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words, - the function that the slot in T's primary vtable points to. */ +/* Return the index of the vcall offset for FN when TYPE is used as a + virtual base. */ -static tree get_matching_virtual PARAMS ((tree, tree)); static tree -get_matching_virtual (t, fn) - tree t, fn; +get_vcall_index (tree fn, tree type) { - tree f; + tree v; - for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f)) - if (same_signature_p (BV_FN (f), fn)) - return BV_FN (f); - return NULL_TREE; + for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v)) + if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v))) + || same_signature_p (fn, TREE_PURPOSE (v))) + break; + + /* There should always be an appropriate index. */ + my_friendly_assert (v, 20021103); + + return TREE_VALUE (v); } /* Update an entry in the vtable for BINFO, which is in the hierarchy @@ -2407,7 +2396,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) /* Compute the constant adjustment to the `this' pointer. The `this' pointer, when this function is called, will point at BINFO (or one of its primary bases, which are at the same offset). */ - if (virtual_base) /* The `this' pointer needs to be adjusted from the declaration to the nearest virtual base. */ @@ -2420,36 +2408,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) will be zero, as it will be a primary base. */ delta = size_zero_node; else - { - /* The `this' pointer needs to be adjusted from pointing to - BINFO to pointing at the base where the final overrider - appears. */ - delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), - BINFO_OFFSET (binfo)); - - if (! integer_zerop (delta)) - { - /* We'll need a thunk. But if we have a (perhaps formerly) - primary virtual base, we have a vcall slot for this function, - so we can use it rather than create a non-virtual thunk. */ - - b = get_primary_binfo (first_defn); - for (; b; b = get_primary_binfo (b)) - { - tree f = get_matching_virtual (BINFO_TYPE (b), fn); - if (!f) - /* b doesn't have this function; no suitable vbase. */ - break; - if (TREE_VIA_VIRTUAL (b)) - { - /* Found one; we can treat ourselves as a virtual base. */ - virtual_base = binfo; - delta = size_zero_node; - break; - } - } - } - } + /* The `this' pointer needs to be adjusted from pointing to + BINFO to pointing at the base where the final overrider + appears. */ + delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), + BINFO_OFFSET (binfo)); modify_vtable_entry (t, binfo, @@ -2458,7 +2421,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) virtuals); if (virtual_base) - BV_USE_VCALL_INDEX_P (*virtuals) = 1; + BV_VCALL_INDEX (*virtuals) + = get_vcall_index (TREE_PURPOSE (overrider), + BINFO_TYPE (virtual_base)); } /* Called from modify_all_vtables via dfs_walk. */ @@ -5101,32 +5066,8 @@ layout_class_type (tree t, tree *virtuals_p) splay_tree_delete (empty_base_offsets); } -/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration - (or C++ class declaration). - - For C++, we must handle the building of derived classes. - Also, C++ allows static class members. The way that this is - handled is to keep the field name where it is (as the DECL_NAME - of the field), and place the overloaded decl in the bit position - of the field. layout_record and layout_union will know about this. - - More C++ hair: inline functions have text in their - DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into - meaningful tree structure. After the struct has been laid out, set - things up so that this can happen. - - And still more: virtual functions. In the case of single inheritance, - when a new virtual function is seen which redefines a virtual function - from the base class, the new virtual function is placed into - the virtual function table at exactly the same address that - it had in the base class. When this is extended to multiple - inheritance, the same thing happens, except that multiple virtual - function tables must be maintained. The first virtual function - table is treated in exactly the same way as in the case of single - inheritance. Additional virtual function tables have different - DELTAs, which tell how to adjust `this' to point to the right thing. - - ATTRIBUTES is the set of decl attributes to be applied, if any. */ +/* Perform processing required when the definition of T (a class type) + is complete. */ void finish_struct_1 (t) @@ -5153,7 +5094,6 @@ finish_struct_1 (t) TYPE_SIZE (t) = NULL_TREE; CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE; - CLASSTYPE_RTTI (t) = NULL_TREE; fixup_inline_methods (t); @@ -5210,24 +5150,6 @@ finish_struct_1 (t) /* Here we know enough to change the type of our virtual function table, but we will wait until later this function. */ build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t); - - /* If this type has basetypes with constructors, then those - constructors might clobber the virtual function table. But - they don't if the derived class shares the exact vtable of the base - class. */ - CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; - } - /* If we didn't need a new vtable, see if we should copy one from - the base. */ - else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t)) - { - tree binfo = CLASSTYPE_PRIMARY_BINFO (t); - - /* If this class uses a different vtable than its primary base - then when we will need to initialize our vptr after the base - class constructor runs. */ - if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo)) - CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; } if (TYPE_CONTAINS_VPTR_P (t)) @@ -5253,6 +5175,9 @@ finish_struct_1 (t) ? TARGET_VTABLE_USES_DESCRIPTORS : 1)) if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST) DECL_VINDEX (BV_FN (fn)) = 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); @@ -7068,8 +6993,10 @@ build_vtt (t) /* Now, build the VTT object itself. */ vtt = build_vtable (t, get_vtt_name (t), type); - pushdecl_top_level (vtt); initialize_array (vtt, inits); + /* Add the VTT to the vtables list. */ + TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t)); + TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt; dump_vtt (t, vtt); } @@ -7404,7 +7331,7 @@ build_ctor_vtbl_group (binfo, t) TREE_TYPE (vtbl) = type; /* Initialize the construction vtable. */ - pushdecl_top_level (vtbl); + CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl); initialize_array (vtbl, inits); dump_vtable (t, binfo, vtbl); } @@ -7621,6 +7548,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) vid.last_init = &vid.inits; vid.primary_vtbl_p = (binfo == TYPE_BINFO (t)); vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); + vid.generate_vcall_entries = true; /* The first vbase or vcall offset is at index -3 in the vtable. */ vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); @@ -7704,14 +7632,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) /* Pull the offset for `this', and the function to call, out of the list. */ delta = BV_DELTA (v); - - if (BV_USE_VCALL_INDEX_P (v)) - { - vcall_index = BV_VCALL_INDEX (v); - my_friendly_assert (vcall_index != NULL_TREE, 20000621); - } - else - vcall_index = NULL_TREE; + vcall_index = BV_VCALL_INDEX (v); my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727); my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727); @@ -7900,31 +7821,37 @@ build_vcall_offset_vtbl_entries (binfo, vid) tree binfo; vtbl_init_data *vid; { - /* We only need these entries if this base is a virtual base. */ - if (!TREE_VIA_VIRTUAL (binfo)) - return; - - /* We need a vcall offset for each of the virtual functions in this - vtable. For example: + /* We only need these entries if this base is a virtual base. We + compute the indices -- but do not add to the vtable -- when + building the main vtable for a class. */ + if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived)) + { + /* We need a vcall offset for each of the virtual functions in this + vtable. For example: - class A { virtual void f (); }; - class B1 : virtual public A { virtual void f (); }; - class B2 : virtual public A { virtual void f (); }; - class C: public B1, public B2 { virtual void f (); }; + class A { virtual void f (); }; + class B1 : virtual public A { virtual void f (); }; + class B2 : virtual public A { virtual void f (); }; + class C: public B1, public B2 { virtual void f (); }; - A C object has a primary base of B1, which has a primary base of A. A - C also has a secondary base of B2, which no longer has a primary base - of A. So the B2-in-C construction vtable needs a secondary vtable for - A, which will adjust the A* to a B2* to call f. We have no way of - knowing what (or even whether) this offset will be when we define B2, - so we store this "vcall offset" in the A sub-vtable and look it up in - a "virtual thunk" for B2::f. + A C object has a primary base of B1, which has a primary base of A. A + C also has a secondary base of B2, which no longer has a primary base + of A. So the B2-in-C construction vtable needs a secondary vtable for + A, which will adjust the A* to a B2* to call f. We have no way of + knowing what (or even whether) this offset will be when we define B2, + so we store this "vcall offset" in the A sub-vtable and look it up in + a "virtual thunk" for B2::f. - We need entries for all the functions in our primary vtable and - in our non-virtual bases' secondary vtables. */ - vid->vbase = binfo; - /* Now, walk through the non-virtual bases, adding vcall offsets. */ - add_vcall_offset_vtbl_entries_r (binfo, vid); + We need entries for all the functions in our primary vtable and + in our non-virtual bases' secondary vtables. */ + vid->vbase = binfo; + /* If we are just computing the vcall indices -- but do not need + the actual entries -- not that. */ + if (!TREE_VIA_VIRTUAL (binfo)) + vid->generate_vcall_entries = false; + /* Now, walk through the non-virtual bases, adding vcall offsets. */ + add_vcall_offset_vtbl_entries_r (binfo, vid); + } } /* Build vcall offsets, starting with those for BINFO. */ @@ -8025,8 +7952,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) { tree orig_fn; tree fn; - tree base; - tree base_binfo; size_t i; tree vcall_offset; @@ -8057,42 +7982,17 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) even though there are two virtual table entries. */ || (DECL_DESTRUCTOR_P (BV_FN (derived_entry)) && DECL_DESTRUCTOR_P (fn))) - { - if (!vid->ctor_vtbl_p) - BV_VCALL_INDEX (derived_virtuals) - = BV_VCALL_INDEX (derived_entry); - break; - } + break; } if (i != VARRAY_ACTIVE_SIZE (vid->fns)) continue; - /* The FN comes from BASE. So, we must calculate the adjustment from - vid->vbase to BASE. We can just look for BASE in the complete - object because we are converting from a virtual base, so if there - were multiple copies, there would not be a unique final overrider - and vid->derived would be ill-formed. */ - base = DECL_CONTEXT (fn); - base_binfo = lookup_base (vid->derived, base, ba_any, NULL); - - /* Compute the vcall offset. */ - /* As mentioned above, the vbase we're working on is a primary base of - vid->binfo. But it might be a lost primary, so its BINFO_OFFSET - might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */ - vcall_offset = BINFO_OFFSET (vid->binfo); - vcall_offset = size_diffop (BINFO_OFFSET (base_binfo), - vcall_offset); - vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, - vcall_offset)); - - *vid->last_init = build_tree_list (NULL_TREE, vcall_offset); - vid->last_init = &TREE_CHAIN (*vid->last_init); - - /* Keep track of the vtable index where this vcall offset can be - found. For a construction vtable, we already made this - annotation when we built the original vtable. */ - if (!vid->ctor_vtbl_p) - BV_VCALL_INDEX (derived_virtuals) = vid->index; + /* If we are building these vcall offsets as part of building + the vtable for the most derived class, remember the vcall + offset. */ + if (vid->binfo == TYPE_BINFO (vid->derived)) + CLASSTYPE_VCALL_INDICES (vid->derived) + = tree_cons (fn, vid->index, CLASSTYPE_VCALL_INDICES (vid->derived)); /* The next vcall offset will be found at a more negative offset. */ @@ -8101,6 +8001,35 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) /* Keep track of this function. */ VARRAY_PUSH_TREE (vid->fns, derived_virtuals); + + if (vid->generate_vcall_entries) + { + tree base; + tree base_binfo; + + /* The FN comes from BASE. So, we must calculate the + adjustment from vid->vbase to BASE. We can just look for + BASE in the complete object because we are converting + from a virtual base, so if there were multiple copies, + there would not be a unique final overrider and + vid->derived would be ill-formed. */ + base = DECL_CONTEXT (fn); + base_binfo = lookup_base (vid->derived, base, ba_any, NULL); + + /* Compute the vcall offset. */ + /* As mentioned above, the vbase we're working on is a + primary base of vid->binfo. But it might be a lost + primary, so its BINFO_OFFSET might be wrong, so we just + use the BINFO_OFFSET from vid->binfo. */ + vcall_offset = BINFO_OFFSET (vid->binfo); + vcall_offset = size_diffop (BINFO_OFFSET (base_binfo), + vcall_offset); + vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, + vcall_offset)); + + *vid->last_init = build_tree_list (NULL_TREE, vcall_offset); + vid->last_init = &TREE_CHAIN (*vid->last_init); + } } } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index cfe7cc9..ad88103 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -47,7 +47,6 @@ struct diagnostic_context; ICS_USER_FLAG (in _CONV) CLEANUP_P (in TRY_BLOCK) AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR) - BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST) PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF) PARMLIST_ELLIPSIS_P (in PARMLIST) 1: IDENTIFIER_VIRTUAL_P. @@ -133,9 +132,7 @@ struct diagnostic_context; of the base class. The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable - index of the vcall offset for this entry. If - BV_USE_VCALL_INDEX_P then the corresponding vtable entry should - use a virtual thunk, as opposed to an ordinary thunk. + index of the vcall offset for this entry. The BV_FN is the declaration for the virtual function itself. @@ -615,6 +612,8 @@ enum cp_tree_index CPTI_DSO_HANDLE, CPTI_DCAST, + CPTI_DYNAMIC_CLASSES, + CPTI_MAX }; @@ -745,6 +744,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. */ + +#define dynamic_classes cp_global_trees[CPTI_DYNAMIC_CLASSES] + /* Global state. */ struct saved_scope GTY(()) @@ -1153,12 +1156,13 @@ struct lang_type_class GTY(()) tree primary_base; tree vfields; + tree vcall_indices; + tree vtables; tree vbases; tree tags; tree as_base; tree pure_virtuals; tree friend_classes; - tree rtti; tree methods; tree decl_list; tree template_info; @@ -1257,9 +1261,6 @@ struct lang_type GTY(()) convenient, don't reprocess any methods that appear in its redefinition. */ #define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined) -/* The is the basetype that contains NODE's rtti. */ -#define CLASSTYPE_RTTI(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->rtti) - /* Nonzero means that this _CLASSTYPE node overloads operator(). */ #define TYPE_OVERLOADS_CALL_EXPR(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded) @@ -1431,13 +1432,6 @@ struct lang_type GTY(()) /* Nonzero means that this aggr type has been `closed' by a semicolon. */ #define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon) -/* Nonzero means that the main virtual function table pointer needs to be - set because base constructors have placed the wrong value there. - If this is zero, it means that they placed the right value there, - and there is no need to change it. */ -#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \ - (LANG_TYPE_CLASS_CHECK (NODE)->needs_virtual_reinit) - /* Nonzero means that this type has an X() constructor. */ #define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor) @@ -1629,6 +1623,19 @@ struct lang_type GTY(()) /* Used by various search routines. */ #define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE) +/* A TREE_LIST of the vcall indices associated with the class NODE. + The TREE_PURPOSE of each node is a FUNCTION_DECL for a virtual + function. The TREE_VALUE is the index into the virtual table where + the vcall offset for that function is stored, when NODE is a + virtual base. */ +#define CLASSTYPE_VCALL_INDICES(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->vcall_indices) + +/* The various vtables for the class NODE. The primary vtable will be + first, followed by the construction vtables and VTT, if any. */ +#define CLASSTYPE_VTABLES(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->vtables) + /* Accessor macros for the vfield slots in structures. */ /* List of virtual table fields that this type contains (both the primary @@ -1664,8 +1671,6 @@ struct lang_type GTY(()) /* The function to call. */ #define BV_FN(NODE) (TREE_VALUE (NODE)) -/* Nonzero if we should use a virtual thunk for this entry. */ -#define BV_USE_VCALL_INDEX_P(NODE) (TREE_LANG_FLAG_0 (NODE)) /* Nonzero for TREE_LIST node means that this list of things is a list of parameters, as opposed to a list of expressions. */ @@ -3546,7 +3551,6 @@ extern tree perform_implicit_conversion PARAMS ((tree, tree)); /* in class.c */ extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int)); extern tree convert_to_base (tree, tree, bool); -extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int)); extern tree build_vtbl_ref PARAMS ((tree, tree)); extern tree build_vfn_ref PARAMS ((tree, tree)); extern tree get_vtable_decl PARAMS ((tree, int)); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 93b643f7..339aba3 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -60,7 +60,7 @@ typedef struct priority_info_s { static void mark_vtable_entries PARAMS ((tree)); static void grok_function_init PARAMS ((tree, tree)); -static int finish_vtable_vardecl PARAMS ((tree *, void *)); +static int maybe_emit_vtables (tree); static int is_namespace_ancestor PARAMS ((tree, tree)); static void add_using_namespace PARAMS ((tree, tree, int)); static tree ambiguous_decl PARAMS ((tree, tree, tree,int)); @@ -1658,12 +1658,7 @@ key_method (type) method = TREE_CHAIN (method)) if (DECL_VINDEX (method) != NULL_TREE && ! DECL_DECLARED_INLINE_P (method) - && (! DECL_PURE_VIRTUAL_P (method) -#if 0 - /* This would be nice, but we didn't think of it in time. */ - || DECL_DESTRUCTOR_P (method) -#endif - )) + && ! DECL_PURE_VIRTUAL_P (method)) return method; return NULL_TREE; @@ -1805,28 +1800,52 @@ output_vtable_inherit (vars) assemble_vtable_inherit (child_rtx, parent_rtx); } +/* If necessary, write out the vtables for the dynamic class CTYPE. + Returns non-zero if any vtables were emitted. */ + static int -finish_vtable_vardecl (t, data) - tree *t; - void *data ATTRIBUTE_UNUSED; +maybe_emit_vtables (tree ctype) { - tree vars = *t; - tree ctype = DECL_CONTEXT (vars); + tree vtbl; + tree primary_vtbl; + + /* If the vtables for this class have already been emitted there is + nothing more to do. */ + primary_vtbl = CLASSTYPE_VTABLES (ctype); + if (TREE_ASM_WRITTEN (primary_vtbl)) + return 0; + /* Ignore dummy vtables made by get_vtable_decl. */ + if (TREE_TYPE (primary_vtbl) == void_type_node) + return 0; + import_export_class (ctype); - import_export_vtable (vars, ctype, 1); + import_export_vtable (primary_vtbl, ctype, 1); - if (! DECL_EXTERNAL (vars) - && DECL_NEEDED_P (vars) - && ! TREE_ASM_WRITTEN (vars)) + /* See if any of the vtables are needed. */ + for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl)) + if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl)) + break; + + if (!vtbl) + { + /* If the references to this class' vtables are optimized away, + still emit the appropriate debugging information. See + dfs_debug_mark. */ + if (DECL_COMDAT (primary_vtbl) + && CLASSTYPE_DEBUG_REQUESTED (ctype)) + note_debug_info_needed (ctype); + return 0; + } + + /* The ABI requires that we emit all of the vtables if we emit any + of them. */ + for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl)) { - if (TREE_TYPE (vars) == void_type_node) - /* It is a dummy vtable made by get_vtable_decl. Ignore it. */ - return 0; - /* Write it out. */ - mark_vtable_entries (vars); - if (TREE_TYPE (DECL_INITIAL (vars)) == 0) - store_init_value (vars, DECL_INITIAL (vars)); + import_export_vtable (vtbl, ctype, 1); + mark_vtable_entries (vtbl); + if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) + store_init_value (vtbl, DECL_INITIAL (vtbl)); if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG) { @@ -1851,37 +1870,29 @@ finish_vtable_vardecl (t, data) `S' get written (which would solve the problem) but that would require more intrusive changes to the g++ front end. */ - DECL_IGNORED_P (vars) = 1; + DECL_IGNORED_P (vtbl) = 1; } /* Always make vtables weak. */ if (flag_weak) - comdat_linkage (vars); + comdat_linkage (vtbl); - rest_of_decl_compilation (vars, NULL, 1, 1); + rest_of_decl_compilation (vtbl, NULL, 1, 1); if (flag_vtable_gc) - output_vtable_inherit (vars); + output_vtable_inherit (vtbl); /* Because we're only doing syntax-checking, we'll never end up actually marking the variable as written. */ if (flag_syntax_only) - TREE_ASM_WRITTEN (vars) = 1; - - /* Since we're writing out the vtable here, also write the debug - info. */ - note_debug_info_needed (ctype); - - return 1; + TREE_ASM_WRITTEN (vtbl) = 1; } - /* If the references to this class' vtables were optimized away, still - emit the appropriate debugging information. See dfs_debug_mark. */ - if (DECL_COMDAT (vars) - && CLASSTYPE_DEBUG_REQUESTED (ctype)) - note_debug_info_needed (ctype); + /* Since we're writing out the vtable here, also write the debug + info. */ + note_debug_info_needed (ctype); - return 0; + return 1; } /* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an @@ -2755,6 +2766,8 @@ finish_file () do { + tree t; + reconsider = 0; /* If there are templates that we've put off instantiating, do @@ -2764,10 +2777,9 @@ finish_file () /* 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. */ - if (walk_vtables (vtable_decl_p, - finish_vtable_vardecl, - /*data=*/0)) - reconsider = 1; + for (t = dynamic_classes; t; t = TREE_CHAIN (t)) + if (maybe_emit_vtables (TREE_VALUE (t))) + reconsider = 1; /* Write out needed type info variables. Writing out one variable might cause others to be needed. */ diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 3b06a0a..c14287b 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1955,9 +1955,8 @@ look_for_overrides (type, fndecl) return found; } -/* Look in TYPE for virtual functions with the same signature as FNDECL. - This differs from get_matching_virtual in that it will only return - a function from TYPE. */ +/* Look in TYPE for virtual functions with the same signature as + FNDECL. */ tree look_for_overrides_here (type, fndecl) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index be1e602..a2b9f53 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-11-03 Mark Mitchell <mark@codesourcery.com> + + * g++.dg/abi/thunk1.C: New test. + * g++.dg/abi/thunk2.C: Likewise. + * g++.dg/abi/vtt1.C: Likewise. + 2002-11-02 Diego Novillo <dnovillo@redhat.com> PR optimization/8423 diff --git a/gcc/testsuite/g++.dg/abi/thunk1.C b/gcc/testsuite/g++.dg/abi/thunk1.C new file mode 100644 index 0000000..c9ad5b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/thunk1.C @@ -0,0 +1,22 @@ +// { dg-do compile { target i?86-*-* } } + +struct A { + virtual void f (); +}; + +struct B : public virtual A { + virtual void f (); +}; + +struct C { + virtual void g (); +}; + +struct D : public C, public B { + virtual void f (); +}; + +void D::f () {} + +// { dg-final { scan-assembler _ZThn4_N1D1fEv } } +// { dg-final { scan-assembler _ZTv0_n12_N1D1fEv } } diff --git a/gcc/testsuite/g++.dg/abi/thunk2.C b/gcc/testsuite/g++.dg/abi/thunk2.C new file mode 100644 index 0000000..b1c9788 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/thunk2.C @@ -0,0 +1,26 @@ +// { dg-do compile { target i?86-*-* } } +// { dg-options -w } + +struct A { + virtual void f2 (); + virtual void f3 (); +}; + +struct B : virtual public A { + virtual void f3 (); +}; + +struct C : public A, public B { + virtual void f4 (); +}; + +struct D : virtual public B, virtual public C, virtual public A +{ + virtual void f5 (); + virtual void f6 (); + virtual void f3 (); +}; + +void D::f3 () {} + +// { dg-final { scan-assembler _ZTvn4_n20_N1D2f3Ev } } diff --git a/gcc/testsuite/g++.dg/abi/vtt1.C b/gcc/testsuite/g++.dg/abi/vtt1.C new file mode 100644 index 0000000..8235c46 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/vtt1.C @@ -0,0 +1,11 @@ +// { dg-do compile } + +struct A { +}; + +struct B : virtual public A { +}; + +B b; + +// { dg-final { scan-assembler _ZTT1B } } |