diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2002-08-04 13:13:56 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2002-08-04 13:13:56 +0000 |
commit | e6858a844797a41452b08bc0a58791fc4f061e51 (patch) | |
tree | d222251a6da9c3c55f51ebf2147fe5e9d271ffbf /gcc | |
parent | 9cc7dbc4a8c7ede5f071536a48e281779eab0614 (diff) | |
download | gcc-e6858a844797a41452b08bc0a58791fc4f061e51.zip gcc-e6858a844797a41452b08bc0a58791fc4f061e51.tar.gz gcc-e6858a844797a41452b08bc0a58791fc4f061e51.tar.bz2 |
re PR c++/7470 (Vtable: virtual function pointers not in declaration order)
PR 7470.
C++ ABI change - vfunc ordering.
* class.c (add_virtual_function): Remove.
(dfs_modify_all_vtables): Take list of all declared
virtuals. Assign all that are not in primary base.
(check_for_override): Adjust comments.
(create_vtable_ptr): Take single list of virtuals. Build chain
of declared virtuals here.
(layout_class_type): Take single list of virtuals. Adjust.
(finish_struct_1): Keep virtuals on single list. Adjust.
From-SVN: r56021
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/class.c | 177 |
2 files changed, 66 insertions, 124 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 34315e4..6b08e3c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2002-08-03 Nathan Sidwell <nathan@codesourcery.com> + + PR 7470. + C++ ABI change - vfunc ordering. + * class.c (add_virtual_function): Remove. + (dfs_modify_all_vtables): Take list of all declared + virtuals. Assign all that are not in primary base. + (check_for_override): Adjust comments. + (create_vtable_ptr): Take single list of virtuals. Build chain + of declared virtuals here. + (layout_class_type): Take single list of virtuals. Adjust. + (finish_struct_1): Keep virtuals on single list. Adjust. + 2002-08-02 Mark Mitchell <mark@codesourcery.com> * init.c (build_member_call): Use build_new_method_call, not diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d56be69..eabe544 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -112,7 +112,6 @@ static int build_primary_vtable PARAMS ((tree, tree)); static int build_secondary_vtable PARAMS ((tree, tree)); static void finish_vtbls PARAMS ((tree)); static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *)); -static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree)); static tree delete_duplicate_fields_1 PARAMS ((tree, tree)); static void delete_duplicate_fields PARAMS ((tree)); static void finish_struct_bits PARAMS ((tree)); @@ -148,8 +147,8 @@ static void check_methods PARAMS ((tree)); static void remove_zero_width_bit_fields PARAMS ((tree)); static void check_bases PARAMS ((tree, int *, int *, int *)); static void check_bases_and_members PARAMS ((tree, int *)); -static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *)); -static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *)); +static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *)); +static void layout_class_type PARAMS ((tree, int *, int *, tree *)); static void fixup_pending_inline PARAMS ((tree)); static void fixup_inline_methods PARAMS ((tree)); static void set_primary_base PARAMS ((tree, tree, int *)); @@ -754,61 +753,6 @@ set_vindex (decl, vfuns_p) ? TARGET_VTABLE_USES_DESCRIPTORS : 1); DECL_VINDEX (decl) = build_shared_int_cst (vindex); } - -/* Add a virtual function to all the appropriate vtables for the class - T. DECL_VINDEX(X) should be error_mark_node, if we want to - allocate a new slot in our table. If it is error_mark_node, we - know that no other function from another vtable is overridden by X. - VFUNS_P keeps track of how many virtuals there are in our - main vtable for the type, and we build upon the NEW_VIRTUALS list - and return it. */ - -static void -add_virtual_function (new_virtuals_p, overridden_virtuals_p, - vfuns_p, fndecl, t) - tree *new_virtuals_p; - tree *overridden_virtuals_p; - int *vfuns_p; - tree fndecl; - tree t; /* Structure type. */ -{ - tree new_virtual; - - /* If this function doesn't override anything from a base class, we - can just assign it a new DECL_VINDEX now. Otherwise, if it does - override something, we keep it around and assign its DECL_VINDEX - later, in modify_all_vtables. */ - if (TREE_CODE (DECL_VINDEX (fndecl)) == INTEGER_CST) - /* We've already dealt with this function. */ - return; - - new_virtual = make_node (TREE_LIST); - BV_FN (new_virtual) = fndecl; - BV_DELTA (new_virtual) = integer_zero_node; - - if (DECL_VINDEX (fndecl) == error_mark_node) - { - /* FNDECL is a new virtual function; it doesn't override any - virtual function in a base class. */ - - /* We remember that this was the base sub-object for rtti. */ - CLASSTYPE_RTTI (t) = t; - - /* Now assign virtual dispatch information. */ - set_vindex (fndecl, vfuns_p); - DECL_VIRTUAL_CONTEXT (fndecl) = t; - - /* Save the state we've computed on the NEW_VIRTUALS list. */ - TREE_CHAIN (new_virtual) = *new_virtuals_p; - *new_virtuals_p = new_virtual; - } - else - { - /* FNDECL overrides a function from a base class. */ - TREE_CHAIN (new_virtual) = *overridden_virtuals_p; - *overridden_virtuals_p = new_virtual; - } -} /* Add method METHOD to class TYPE. If ERROR_P is true, we are adding the method after the class has already been defined because a @@ -2626,18 +2570,18 @@ dfs_modify_vtables (binfo, data) /* Update all of the primary and secondary vtables for T. Create new vtables as required, and initialize their RTTI information. Each - of the functions in OVERRIDDEN_VIRTUALS overrides a virtual - function from a base class; find and modify the appropriate entries - to point to the overriding functions. Returns a list, in - declaration order, of the functions that are overridden in this - class, but do not appear in the primary base class vtable, and - which should therefore be appended to the end of the vtable for T. */ + of the functions in VIRTUALS is declared in T and may override a + virtual function from a base class; find and modify the appropriate + entries to point to the overriding functions. Returns a list, in + declaration order, of the virtual functions that are declared in T, + but do not appear in the primary base class vtable, and which + should therefore be appended to the end of the vtable for T. */ static tree -modify_all_vtables (t, vfuns_p, overridden_virtuals) +modify_all_vtables (t, vfuns_p, virtuals) tree t; int *vfuns_p; - tree overridden_virtuals; + tree virtuals; { tree binfo = TYPE_BINFO (t); tree *fnsp; @@ -2649,14 +2593,16 @@ modify_all_vtables (t, vfuns_p, overridden_virtuals) t); dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t); - /* Include overriding functions for secondary vtables in our primary - vtable. */ - for (fnsp = &overridden_virtuals; *fnsp; ) + /* Add virtual functions not already in our primary vtable. These + will be both those introduced by this class, and those overridden + from secondary bases. It does not include virtuals merely + inherited from secondary bases. */ + for (fnsp = &virtuals; *fnsp; ) { tree fn = TREE_VALUE (*fnsp); - if (!BINFO_VIRTUALS (binfo) - || !value_member (fn, BINFO_VIRTUALS (binfo))) + if (!value_member (fn, BINFO_VIRTUALS (binfo)) + || DECL_VINDEX (fn) == error_mark_node) { /* Set the vtable index. */ set_vindex (fn, vfuns_p); @@ -2669,8 +2615,7 @@ modify_all_vtables (t, vfuns_p, overridden_virtuals) BV_DELTA (*fnsp) = integer_zero_node; BV_VCALL_INDEX (*fnsp) = NULL_TREE; - /* This is an overridden function not already in our - vtable. Keep it. */ + /* This is a function not already in our vtable. Keep it. */ fnsp = &TREE_CHAIN (*fnsp); } else @@ -2678,7 +2623,7 @@ modify_all_vtables (t, vfuns_p, overridden_virtuals) *fnsp = TREE_CHAIN (*fnsp); } - return overridden_virtuals; + return virtuals; } /* Here, we already know that they match in every respect. @@ -2748,16 +2693,14 @@ check_for_override (decl, ctype) || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))) && look_for_overrides (ctype, decl) && !DECL_STATIC_FUNCTION_P (decl)) - { - /* Set DECL_VINDEX to a value that is neither an - INTEGER_CST nor the error_mark_node so that - add_virtual_function will realize this is an - overriding function. */ - DECL_VINDEX (decl) = decl; - } + /* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor + the error_mark_node so that we know it is an overriding + function. */ + DECL_VINDEX (decl) = decl; + if (DECL_VIRTUAL_P (decl)) { - if (DECL_VINDEX (decl) == NULL_TREE) + if (!DECL_VINDEX (decl)) DECL_VINDEX (decl) = error_mark_node; IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; } @@ -4379,31 +4322,37 @@ check_bases_and_members (t, empty_p) accordingly. If a new vfield was created (because T doesn't have a primary base class), then the newly created field is returned. It is not added to the TYPE_FIELDS list; it is the caller's - responsibility to do that. */ + responsibility to do that. Accumulate declared virtual functions + on VIRTUALS_P. */ static tree -create_vtable_ptr (t, empty_p, vfuns_p, - new_virtuals_p, overridden_virtuals_p) +create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p) tree t; int *empty_p; int *vfuns_p; - tree *new_virtuals_p; - tree *overridden_virtuals_p; + tree *virtuals_p; { tree fn; - /* Loop over the virtual functions, adding them to our various - vtables. */ + /* Collect the virtual functions declared in T. */ for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) - if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)) - add_virtual_function (new_virtuals_p, overridden_virtuals_p, - vfuns_p, fn, t); + if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn) + && TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST) + { + tree new_virtual = make_node (TREE_LIST); + + BV_FN (new_virtual) = fn; + BV_DELTA (new_virtual) = integer_zero_node; + TREE_CHAIN (new_virtual) = *virtuals_p; + *virtuals_p = new_virtual; + } + /* If we couldn't find an appropriate base class, create a new field here. Even if there weren't any new virtual functions, we might need a new virtual function table if we're supposed to include vptrs in all classes that need them. */ - if (!TYPE_VFIELD (t) && (*vfuns_p || TYPE_CONTAINS_VPTR_P (t))) + if (!TYPE_VFIELD (t) && (*virtuals_p || TYPE_CONTAINS_VPTR_P (t))) { /* We build this decl with vtbl_ptr_type_node, which is a `vtable_entry_type*'. It might seem more precise to use @@ -4795,16 +4744,14 @@ splay_tree_compare_integer_csts (k1, k2) /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate BINFO_OFFSETs for all of the base-classes. Position the vtable - pointer. */ + pointer. Accumulate declared virtual functions on VIRTUALS_P. */ static void -layout_class_type (t, empty_p, vfuns_p, - new_virtuals_p, overridden_virtuals_p) +layout_class_type (t, empty_p, vfuns_p, virtuals_p) tree t; int *empty_p; int *vfuns_p; - tree *new_virtuals_p; - tree *overridden_virtuals_p; + tree *virtuals_p; { tree non_static_data_members; tree field; @@ -4826,8 +4773,7 @@ layout_class_type (t, empty_p, vfuns_p, determine_primary_base (t, vfuns_p); /* Create a pointer to our virtual function table. */ - vptr = create_vtable_ptr (t, empty_p, vfuns_p, - new_virtuals_p, overridden_virtuals_p); + vptr = create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p); /* The vptr is always the first thing in the class. */ if (vptr) @@ -5034,15 +4980,8 @@ finish_struct_1 (t) { tree x; int vfuns; - /* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is - a FUNCTION_DECL. Each of these functions is a virtual function - declared in T that does not override any virtual function from a - base class. */ - tree new_virtuals = NULL_TREE; - /* The OVERRIDDEN_VIRTUALS list is like the NEW_VIRTUALS list, - except that each declaration here overrides the declaration from - a base class. */ - tree overridden_virtuals = NULL_TREE; + /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */ + tree virtuals = NULL_TREE; int n_fields = 0; tree vfield; int empty = 1; @@ -5072,8 +5011,7 @@ finish_struct_1 (t) check_bases_and_members (t, &empty); /* Layout the class itself. */ - layout_class_type (t, &empty, &vfuns, - &new_virtuals, &overridden_virtuals); + layout_class_type (t, &empty, &vfuns, &virtuals); /* Make sure that we get our own copy of the vfield FIELD_DECL. */ vfield = TYPE_VFIELD (t); @@ -5097,8 +5035,7 @@ finish_struct_1 (t) else my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726); - overridden_virtuals - = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals)); + virtuals = modify_all_vtables (t, &vfuns, nreverse (virtuals)); /* If we created a new vtbl pointer for this class, add it to the list. */ @@ -5107,9 +5044,8 @@ finish_struct_1 (t) = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t)); /* If necessary, create the primary vtable for this class. */ - if (new_virtuals || overridden_virtuals || TYPE_CONTAINS_VPTR_P (t)) + if (virtuals || TYPE_CONTAINS_VPTR_P (t)) { - new_virtuals = nreverse (new_virtuals); /* We must enter these virtuals into the table. */ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) build_primary_vtable (NULL_TREE, t); @@ -5122,7 +5058,6 @@ finish_struct_1 (t) 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 @@ -5148,14 +5083,8 @@ finish_struct_1 (t) 20000116); CLASSTYPE_VSIZE (t) = vfuns; - /* Entries for virtual functions defined in the primary base are - followed by entries for new functions unique to this class. */ - TYPE_BINFO_VIRTUALS (t) - = chainon (TYPE_BINFO_VIRTUALS (t), new_virtuals); - /* Finally, add entries for functions that override virtuals - from non-primary bases. */ - TYPE_BINFO_VIRTUALS (t) - = chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals); + /* Add entries for virtual functions introduced by this class. */ + TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals); } finish_struct_bits (t); |