diff options
author | Mark Mitchell <mark@codesourcery.com> | 2000-03-22 21:43:45 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2000-03-22 21:43:45 +0000 |
commit | 3c9d63596fc5b0245704c8f66715c5d03dc4c91a (patch) | |
tree | 6d0f3bdb88c1291bb8d71766a4c9bdec7640952d | |
parent | 26356fee5ba5a558889329f911024af9e77351ec (diff) | |
download | gcc-3c9d63596fc5b0245704c8f66715c5d03dc4c91a.zip gcc-3c9d63596fc5b0245704c8f66715c5d03dc4c91a.tar.gz gcc-3c9d63596fc5b0245704c8f66715c5d03dc4c91a.tar.bz2 |
cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
* cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
(CANONICAL_BINFO): New macro.
(BINFO_NEW_VTABLE_MARKED): Use it.
(SET_BINFO_NEW_VTABLE_MARKED): Likewise.
(CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise.
* class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE,
not TREE_TYPE.
(build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(build_secondary_vtable): Likewise.
(dfs_finish_vtbls): Likewise.
(dfs_accumulate_vtbl_inits): Likewise.
(accumulate_vtbl_inits): New function.
(finish_vtbls): Make sure that virtual bases come after
non-virtual bases in the vtable group.
(record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL.
(finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED.
* search.c (struct vbase_info): Move definition.
(marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(unmarked_new_vtable_p): Likewise.
(dfs_mark_vtable_path): Remove.
(dfs_mark_new_vtable): Remove.
(dfs_unmark_new_vtable): Likewise.
(dfs_clear_search_slot): Likewise.
(dfs_find_vbases): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(dfs_clear_vbase_slots): Likewise.
(init_vbase_pointers): LIkewise.
From-SVN: r32689
-rw-r--r-- | gcc/cp/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/cp/class.c | 91 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 24 | ||||
-rw-r--r-- | gcc/cp/search.c | 59 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.abi/vtable.C | 82 |
5 files changed, 209 insertions, 76 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index de6a2eb..33d688f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,32 @@ +2000-03-22 Mark Mitchell <mark@codesourcery.com> + + * cp-tree.h (BINFO_FOR_VBASE): Adjust documentation. + (CANONICAL_BINFO): New macro. + (BINFO_NEW_VTABLE_MARKED): Use it. + (SET_BINFO_NEW_VTABLE_MARKED): Likewise. + (CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise. + * class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE, + not TREE_TYPE. + (build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED. + (build_secondary_vtable): Likewise. + (dfs_finish_vtbls): Likewise. + (dfs_accumulate_vtbl_inits): Likewise. + (accumulate_vtbl_inits): New function. + (finish_vtbls): Make sure that virtual bases come after + non-virtual bases in the vtable group. + (record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL. + (finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED. + * search.c (struct vbase_info): Move definition. + (marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED. + (unmarked_new_vtable_p): Likewise. + (dfs_mark_vtable_path): Remove. + (dfs_mark_new_vtable): Remove. + (dfs_unmark_new_vtable): Likewise. + (dfs_clear_search_slot): Likewise. + (dfs_find_vbases): Adjust usage of BINFO_NEW_VTABLE_MARKED. + (dfs_clear_vbase_slots): Likewise. + (init_vbase_pointers): LIkewise. + 2000-03-22 Jason Merrill <jason@casey.cygnus.com> * typeck.c (type_after_usual_arithmetic_conversions): Prefer a diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 12095ad..216d7e3 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -161,6 +161,7 @@ static tree dfs_search_base_offsets PARAMS ((tree, void *)); static int layout_conflict_p PARAMS ((tree, varray_type)); static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); static void layout_empty_base PARAMS ((tree, tree, varray_type)); +static void accumulate_vtbl_inits PARAMS ((tree, tree)); /* Variables shared between class.c and call.c. */ @@ -276,7 +277,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data) /* Remember the index to the vbase offset for this virtual base. */ - vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list)); + vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list)); if (!TREE_VALUE (list)) BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0); else @@ -1072,7 +1073,7 @@ build_primary_vtable (binfo, type) { tree offset; - if (BINFO_NEW_VTABLE_MARKED (binfo)) + if (BINFO_NEW_VTABLE_MARKED (binfo, type)) /* We have already created a vtable for this base, so there's no need to do it again. */ return 0; @@ -1106,7 +1107,7 @@ build_primary_vtable (binfo, type) TYPE_BINFO_VIRTUALS (type) = virtuals; binfo = TYPE_BINFO (type); - SET_BINFO_NEW_VTABLE_MARKED (binfo); + SET_BINFO_NEW_VTABLE_MARKED (binfo, type); return 1; } @@ -1147,14 +1148,14 @@ build_secondary_vtable (binfo, for_type) current_class_type), 170); - if (BINFO_NEW_VTABLE_MARKED (binfo)) + if (BINFO_NEW_VTABLE_MARKED (binfo, current_class_type)) /* We already created a vtable for this base. There's no need to do it again. */ return 0; /* Remember that we've created a vtable for this BINFO, so that we don't try to do so again. */ - SET_BINFO_NEW_VTABLE_MARKED (binfo); + SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type); /* Make fresh virtual list, so we can smash it later. */ BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo)); @@ -2760,13 +2761,15 @@ dfs_finish_vtbls (binfo, data) tree binfo; void *data; { + tree t = (tree) data; + if (!BINFO_PRIMARY_MARKED_P (binfo) && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)) - && BINFO_NEW_VTABLE_MARKED (binfo)) + && BINFO_NEW_VTABLE_MARKED (binfo, t)) initialize_vtable (binfo, - build_vtbl_initializer (binfo, (tree) data)); + build_vtbl_initializer (binfo, t)); - CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); + CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t); SET_BINFO_MARKED (binfo); return NULL_TREE; @@ -2781,15 +2784,16 @@ dfs_accumulate_vtbl_inits (binfo, data) tree binfo; void *data; { + tree l; + tree t; + + l = (tree) data; + t = TREE_PURPOSE (l); + if (!BINFO_PRIMARY_MARKED_P (binfo) && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)) - && BINFO_NEW_VTABLE_MARKED (binfo)) + && BINFO_NEW_VTABLE_MARKED (binfo, t)) { - tree l; - tree t; - - l = (tree) data; - t = TREE_PURPOSE (l); /* If this is a secondary vtable, record its location. */ if (binfo != TYPE_BINFO (t)) @@ -2807,19 +2811,34 @@ dfs_accumulate_vtbl_inits (binfo, data) size_int (list_length (TREE_VALUE (l))))); } - /* Add the initializers for this vtable to the initailizers for + /* Add the initializers for this vtable to the initializers for the other vtables we've already got. */ TREE_VALUE (l) = chainon (TREE_VALUE (l), build_vtbl_initializer (binfo, t)); } - CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); - SET_BINFO_MARKED (binfo); + CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t); return NULL_TREE; } +/* Add the vtbl initializers for BINFO (and its non-primary, + non-virtual bases) to the list of INITS. */ + +static void +accumulate_vtbl_inits (binfo, inits) + tree binfo; + tree inits; +{ + /* Walk the BINFO and its bases. */ + dfs_walk_real (binfo, + dfs_accumulate_vtbl_inits, + NULL, + dfs_skip_vbases, + inits); +} + /* Create all the necessary vtables for T and its base classes. */ static void @@ -2829,26 +2848,31 @@ finish_vtbls (t) if (merge_primary_and_secondary_vtables_p ()) { tree list; + tree vbase; /* Under the new ABI, we lay out the primary and secondary vtables in one contiguous vtable. The primary vtable is - first, followed by the secondary vtables as encountered in a - pre-order depth-first left-to-right traversal. */ + first, followed by the non-virtual secondary vtables in + inheritance graph order. */ list = build_tree_list (t, NULL_TREE); - dfs_walk_real (TYPE_BINFO (t), - dfs_accumulate_vtbl_inits, - NULL, - dfs_unmarked_real_bases_queue_p, - list); + accumulate_vtbl_inits (TYPE_BINFO (t), list); + /* Then come the virtual bases, also in inheritance graph + order. */ + for (vbase = CLASSTYPE_VBASECLASSES (t); + vbase; + vbase = TREE_CHAIN (vbase)) + accumulate_vtbl_inits (vbase, list); + if (TYPE_BINFO_VTABLE (t)) initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list)); } else - dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, - dfs_unmarked_real_bases_queue_p, t); - - dfs_walk (TYPE_BINFO (t), dfs_unmark, - dfs_marked_real_bases_queue_p, t); + { + dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, + dfs_unmarked_real_bases_queue_p, t); + dfs_walk (TYPE_BINFO (t), dfs_unmark, + dfs_marked_real_bases_queue_p, t); + } } /* True if we should override the given BASE_FNDECL with the given @@ -4142,17 +4166,10 @@ record_base_offsets (binfo, base_offsets) tree binfo; varray_type *base_offsets; { - int virtual_p; - - /* If BINFO is virtual, we still want to mention its offset in - BASE_OFFSETS. */ - virtual_p = TREE_VIA_VIRTUAL (binfo); - TREE_VIA_VIRTUAL (binfo) = 0; dfs_walk (binfo, dfs_record_base_offsets, dfs_skip_vbases, base_offsets); - TREE_VIA_VIRTUAL (binfo) = virtual_p; } /* Returns non-NULL if there is already an entry in DATA (which is @@ -5308,7 +5325,7 @@ finish_struct_1 (t) } build_primary_vtable (NULL_TREE, t); } - else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t))) + else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), 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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 04fd943..9ccd28a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1566,10 +1566,19 @@ struct lang_type (also distinct from the copies in the TYPE_BINFO hierarchy.) */ #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases) -/* The BINFO (if any) for the virtual baseclass T of the class C. */ +/* The BINFO (if any) for the virtual baseclass T of the class C from + the CLASSTYPE_VBASECLASSES list. */ #define BINFO_FOR_VBASE(T, C) \ (binfo_member (T, CLASSTYPE_VBASECLASSES (C))) +/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the + BINFO_FOR_VBASE. C is the most derived class for the hierarchy + containing BINFO. */ +#define CANONICAL_BINFO(BINFO, C) \ + (TREE_VIA_VIRTUAL (BINFO) \ + ? BINFO_FOR_VBASE (BINFO_TYPE (BINFO), C) \ + : BINFO) + /* Number of direct baseclasses of NODE. */ #define CLASSTYPE_N_BASECLASSES(NODE) \ (BINFO_N_BASETYPES (TYPE_BINFO (NODE))) @@ -1704,11 +1713,14 @@ struct lang_type #define SET_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=1)) #define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=0)) -/* Nonzero means that this class has a new vtable. */ -#define BINFO_NEW_VTABLE_MARKED(NODE) \ - (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):TREE_LANG_FLAG_4(NODE)) -#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1)) -#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0)) +/* Nonzero means B (a BINFO) needs a new vtable. B is part of the + hierarchy dominated by C. */ +#define BINFO_NEW_VTABLE_MARKED(B, C) \ + (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C))) +#define SET_BINFO_NEW_VTABLE_MARKED(B, C) \ + (BINFO_NEW_VTABLE_MARKED (B, C) = 1) +#define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \ + (BINFO_NEW_VTABLE_MARKED (B, C) = 0) /* Nonzero means this class has done dfs_pushdecls. */ #define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 9d75476..314dab9 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -76,6 +76,15 @@ pop_stack_level (stack) #define search_level stack_level static struct search_level *search_stack; +struct vbase_info +{ + /* The class dominating the hierarchy. */ + tree type; + tree decl_ptr; + tree inits; + tree vbase_types; +}; + static tree next_baselink PARAMS ((tree)); static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *)); static tree lookup_field_1 PARAMS ((tree, tree)); @@ -2537,17 +2546,21 @@ unmarked_vtable_pathp (binfo, data) static tree marked_new_vtablep (binfo, data) tree binfo; - void *data ATTRIBUTE_UNUSED; + void *data; { - return BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE; + struct vbase_info *vi = (struct vbase_info *) data; + + return BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE; } static tree unmarked_new_vtablep (binfo, data) tree binfo; - void *data ATTRIBUTE_UNUSED; + void *data; { - return !BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE; + struct vbase_info *vi = (struct vbase_info *) data; + + return !BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE; } static tree @@ -2614,31 +2627,7 @@ dfs_vtable_path_unmark (binfo, data) return NULL_TREE; } -#if 0 -static void -dfs_mark_vtable_path (binfo) tree binfo; -{ SET_BINFO_VTABLE_PATH_MARKED (binfo); } - -static void -dfs_mark_new_vtable (binfo) tree binfo; -{ SET_BINFO_NEW_VTABLE_MARKED (binfo); } - -static void -dfs_unmark_new_vtable (binfo) tree binfo; -{ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); } - -static void -dfs_clear_search_slot (binfo) tree binfo; -{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; } -#endif -struct vbase_info -{ - tree decl_ptr; - tree inits; - tree vbase_types; -}; - /* Attach to the type of the virtual base class, the pointer to the virtual base class. */ @@ -2668,7 +2657,7 @@ dfs_find_vbases (binfo, data) } } SET_BINFO_VTABLE_PATH_MARKED (binfo); - SET_BINFO_NEW_VTABLE_MARKED (binfo); + SET_BINFO_NEW_VTABLE_MARKED (binfo, vi->type); return NULL_TREE; } @@ -2737,12 +2726,14 @@ dfs_init_vbase_pointers (binfo, data) static tree dfs_clear_vbase_slots (binfo, data) tree binfo; - void *data ATTRIBUTE_UNUSED; + void *data; { tree type = BINFO_TYPE (binfo); + struct vbase_info *vi = (struct vbase_info *) data; + CLASSTYPE_SEARCH_SLOT (type) = 0; CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); - CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); + CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, vi->type); return NULL_TREE; } @@ -2760,6 +2751,7 @@ init_vbase_pointers (type, decl_ptr) /* Find all the virtual base classes, marking them for later initialization. */ + vi.type = type; vi.decl_ptr = decl_ptr; vi.vbase_types = CLASSTYPE_VBASECLASSES (type); vi.inits = NULL_TREE; @@ -2773,7 +2765,7 @@ init_vbase_pointers (type, decl_ptr) marked_vtable_pathp, &vi); - dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0); + dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi); flag_this_is_variable = old_flag; return vi.inits; } @@ -3088,12 +3080,13 @@ expand_indirect_vtbls_init (binfo, decl_ptr) { tree vbases = CLASSTYPE_VBASECLASSES (type); struct vbase_info vi; + vi.type = type; vi.decl_ptr = decl_ptr; vi.vbase_types = vbases; dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi); fixup_all_virtual_upcast_offsets (type, vi.decl_ptr); - dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0); + dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi); } } diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C new file mode 100644 index 0000000..aafcad8 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C @@ -0,0 +1,82 @@ +// Test various aspects of vtable layout. +// Special g++ Options: -fno-strict-aliasing +// Origin: Mark Mitchell <mark@codesourcery.com> + +#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 + +struct S0 +{ + virtual void h () + { + } + + int k; +}; + + +struct S1 +{ + virtual void f () + { + } + + int i; +}; + +struct S2 : virtual public S0 +{ + virtual void g () + { + } + + int j; +}; + +struct S3 +{ + virtual void k () + { + } + + int l; +}; + +struct S4 : public virtual S1, public S2, public S3 +{ +}; + +inline void* vtable (void *object) +{ + // The vptr is always the first part of the object. + return * (void **) object; +} + +int main () +{ + // The vtable layout order for S4 should consist of S4's primary + // vtable (shared with S2), followed by the vtable for S3 (because + // it is a non-virtual base). Then, these should be followed by the + // the vtables for S1 and S0, which are virtual. + S4 s4; + S0 *s0 = &s4; + S1 *s1 = &s4; + S2 *s2 = &s4; + S3 *s3 = &s4; + + if (vtable (&s4) != vtable (s2)) + return 1; + if (vtable (s2) >= vtable (s3)) + return 2; + if (vtable (s3) >= vtable (s1)) + return 3; + if (vtable (s1) >= vtable (s0)) + return 4; +} + +#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */ + +int main () +{ +} + +#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */ |