From f235209b305d801a01424c5c5a1e3210967df456 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 5 Feb 2001 11:45:16 +0000 Subject: [PATCH] gcc: * invoke.texi (-fdump-class-layout): Document. (-fdump-translation-unit): Use `=' as filename separator. cp: Fix specification and implementation bugs in V3 ABI construction vtables. * cp-tree.h (flag_dump_class_layout): New flag. (BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P): Remove. (BINFO_LOST_PRIMARY_P): New flag. (SET_BINFO_NEW_VTABLE_MARKED): Adjust asserts. (BINFO_PRIMARY_MARKED_P): Rename to ... (BINFO_PRIMARY_P): ... here. (binfo_via_virtual): New prototype. * decl2.c (flag_dump_class_layout): New flag. (cxx_decode_option): Set it. Adjust -fdump-translation-unit to use `=' as a file name separator. * init.c (dfs_initialize_vtbl_ptrs): Walk into virtual primary bases. (build_vtbl_address): If this is a virtual primary base, then get the vtbl of what it is ultimately primary for. * search.c (dfs_skip_nonprimary_vbases_unmarkedp): Adjust for BINFO_PRIMARY_P. (dfs_skip_nonprimary_vbases_markedp): Likewise. (get_shared_vbase_if_not_primary): Likewise. (dfs_get_pure_virtuals): Likewise. (expand_upcast_fixups): Likewise. (fixup_virtual_upcast_offsets): Likewise. (dfs_find_vbase_instance): Likewise. (find_vbase_instance): Likewise. (binfo_from_vbase): Adjust comment to reflect reality. (binfo_via_virtual): New function. * class.c (VTT_TOP_LEVEL_P, VTT_MARKED_BINFO_P): New macros for binfo walking during VTT construction. (dfs_mark_primary_bases): Remove. (force_canonical_binfo_r): New function. (force_canonical_binfo): New function. (mark_primary_virtual_base): New function. (mark_primary_bases): Walk in inheritance graph order, use mark_primary_virtual_base. (determine_primary_base): Use some more intermediate variables. (dfs_find_final_overrider): Don't check for overriding along a virtual path. (dfs_modify_vtables): Walk into primary virtual bases too. (walk_subobject_offsets): Adjust for BINFO_PRIMARY_P. (build_base_fields): Likewise. (dfs_set_offset_for_unshared_vbases): Likewise. (layout_virtual_bases): Likewise. (end_of_class): Likewise. (finish_struct_1): Call dump_class_hierarchy, if requested. (dfs_get_primary_binfo): Use BINFO_TYPE for binfos. (dump_class_hierarchy_r): Add stream parameter. Emit more information. (dump_class_hierarchy): Add file parameter. Append to file, if required. (finish_vtbls): Adjust accumulate_vtbl_inits call. Use canonical base for virtual bases. (build_vtt): Add more comments. Adjust build_vtt_inits call. (build_vtt_inits): Remove VIRTUAL_VTTS_P parm. Only set BINFO_VPTR_INDEX on top level. Use VTT_TOP_LEVEL_P, VTT_MARKED_BINFO_P for binfo walking. Use canonical vbase for virtual VTTs. (dfs_build_secondary_vptr_vtt_inits): Extract VTT_TOP_LEVEL_P from DATA. We want virtual primary bases and all bases via virtual. Only set BINFO_VPTR_INDEX for top level. Look up from a primary virtual base when not a construction vtable. (dfs_ctor_vtable_bases_queue_p): New DFS predicate. (build_ctor_vtbl_group): Adjust accumulate_vtbl_inits call. Use canonical bases when processing virtual bases. (accumulate_vtbl_inits): We're interested in any base via a virtual path. (dfs_accumulate_vtbl_inits): If this is a primary virtual base within a construction vtable, determine what is being overridden. (build_vtbl_initializer): Add more comments (add_vcall_offset_vtbl_entries_1): Adjust comment. (build_rtti_vtbl_entries): Check if the base has lost its primary. testsuite: * g++.old-deja/g++.abi/primary2.C: New test. * g++.old-deja/g++.abi/primary3.C: New test. * g++.old-deja/g++.abi/primary4.C: New test. * g++.old-deja/g++.abi/primary5.C: New test. * g++.old-deja/g++.abi/vtable3.h: New test. * g++.old-deja/g++.abi/vtable3a.C: New test. * g++.old-deja/g++.abi/vtable3b.C: New test. * g++.old-deja/g++.abi/vtable3c.C: New test. * g++.old-deja/g++.abi/vtable3d.C: New test. * g++.old-deja/g++.abi/vtable3e.C: New test. * g++.old-deja/g++.abi/vtable3f.C: New test. * g++.old-deja/g++.abi/vtable3g.C: New test. * g++.old-deja/g++.abi/vtable3h.C: New test. * g++.old-deja/g++.abi/vtable3i.C: New test. * g++.old-deja/g++.abi/vtable3j.C: New test. * g++.old-deja/g++.oliva/thunk1.C: Remove XFAIL. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39455 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 + gcc/cp/ChangeLog | 74 +++ gcc/cp/class.c | 624 +++++++++++++++++--------- gcc/cp/cp-tree.h | 22 +- gcc/cp/decl2.c | 18 +- gcc/cp/init.c | 17 +- gcc/cp/search.c | 40 +- gcc/invoke.texi | 11 +- gcc/testsuite/ChangeLog | 19 + gcc/testsuite/g++.old-deja/g++.abi/primary2.C | 21 + gcc/testsuite/g++.old-deja/g++.abi/primary3.C | 34 ++ gcc/testsuite/g++.old-deja/g++.abi/primary4.C | 27 ++ gcc/testsuite/g++.old-deja/g++.abi/primary5.C | 36 ++ gcc/testsuite/g++.old-deja/g++.abi/vtable3.h | 181 ++++++++ gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C | 12 + gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C | 11 + gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C | 11 + gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C | 11 + gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C | 11 + gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C | 12 + gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C | 12 + gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C | 12 + gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C | 11 + gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C | 11 + gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C | 1 - 25 files changed, 1011 insertions(+), 233 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/primary2.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/primary3.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/primary4.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/primary5.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3.h create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C create mode 100644 gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ce8ac7af92..0046ae185e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2001-02-05 Nathan Sidwell + + * invoke.texi (-fdump-class-layout): Document. + (-fdump-translation-unit): Use `=' as filename separator. + 2001-02-05 Mark Mitchell * Makefile.in (s-mlib): Don't build multilibs if diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6011b76d47b..04d64a0c824 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,77 @@ +2001-02-05 Nathan Sidwell + + Fix specification and implementation bugs in V3 ABI + construction vtables. + * cp-tree.h (flag_dump_class_layout): New flag. + (BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P): Remove. + (BINFO_LOST_PRIMARY_P): New flag. + (SET_BINFO_NEW_VTABLE_MARKED): Adjust asserts. + (BINFO_PRIMARY_MARKED_P): Rename to ... + (BINFO_PRIMARY_P): ... here. + (binfo_via_virtual): New prototype. + * decl2.c (flag_dump_class_layout): New flag. + (cxx_decode_option): Set it. Adjust -fdump-translation-unit to + use `=' as a file name separator. + * init.c (dfs_initialize_vtbl_ptrs): Walk into virtual primary + bases. + (build_vtbl_address): If this is a virtual primary base, then + get the vtbl of what it is ultimately primary for. + * search.c (dfs_skip_nonprimary_vbases_unmarkedp): Adjust + for BINFO_PRIMARY_P. + (dfs_skip_nonprimary_vbases_markedp): Likewise. + (get_shared_vbase_if_not_primary): Likewise. + (dfs_get_pure_virtuals): Likewise. + (expand_upcast_fixups): Likewise. + (fixup_virtual_upcast_offsets): Likewise. + (dfs_find_vbase_instance): Likewise. + (find_vbase_instance): Likewise. + (binfo_from_vbase): Adjust comment to reflect reality. + (binfo_via_virtual): New function. + * class.c (VTT_TOP_LEVEL_P, VTT_MARKED_BINFO_P): New macros + for binfo walking during VTT construction. + (dfs_mark_primary_bases): Remove. + (force_canonical_binfo_r): New function. + (force_canonical_binfo): New function. + (mark_primary_virtual_base): New function. + (mark_primary_bases): Walk in inheritance graph order, use + mark_primary_virtual_base. + (determine_primary_base): Use some more intermediate variables. + (dfs_find_final_overrider): Don't check for overriding along a + virtual path. + (dfs_modify_vtables): Walk into primary virtual bases too. + (walk_subobject_offsets): Adjust for BINFO_PRIMARY_P. + (build_base_fields): Likewise. + (dfs_set_offset_for_unshared_vbases): Likewise. + (layout_virtual_bases): Likewise. + (end_of_class): Likewise. + (finish_struct_1): Call dump_class_hierarchy, if requested. + (dfs_get_primary_binfo): Use BINFO_TYPE for binfos. + (dump_class_hierarchy_r): Add stream parameter. Emit more information. + (dump_class_hierarchy): Add file parameter. Append to file, if + required. + (finish_vtbls): Adjust accumulate_vtbl_inits call. + Use canonical base for virtual bases. + (build_vtt): Add more comments. Adjust build_vtt_inits call. + (build_vtt_inits): Remove VIRTUAL_VTTS_P parm. + Only set BINFO_VPTR_INDEX on top level. Use VTT_TOP_LEVEL_P, + VTT_MARKED_BINFO_P for binfo walking. Use canonical vbase for + virtual VTTs. + (dfs_build_secondary_vptr_vtt_inits): Extract VTT_TOP_LEVEL_P + from DATA. We want virtual primary bases and all bases via virtual. + Only set BINFO_VPTR_INDEX for top level. Look up from a primary + virtual base when not a construction vtable. + (dfs_ctor_vtable_bases_queue_p): New DFS predicate. + (build_ctor_vtbl_group): Adjust accumulate_vtbl_inits call. + Use canonical bases when processing virtual bases. + (accumulate_vtbl_inits): We're interested in any base via a + virtual path. + (dfs_accumulate_vtbl_inits): If this is a primary virtual base + within a construction vtable, determine what is being overridden. + (build_vtbl_initializer): Add more comments + (add_vcall_offset_vtbl_entries_1): Adjust comment. + (build_rtti_vtbl_entries): Check if the base has lost its + primary. + 2001-02-05 Mark Mitchell * Makefile.in (g++spec.o): Adjust use of DRIVER_DEFINES. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 423fb32671d..376260b0d6a 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -111,8 +111,6 @@ static tree get_basefndecls PARAMS ((tree, tree)); static int build_primary_vtable PARAMS ((tree, tree)); static int build_secondary_vtable PARAMS ((tree, tree)); static tree dfs_finish_vtbls PARAMS ((tree, void *)); -static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, 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)); @@ -171,8 +169,8 @@ static void layout_vtable_decl PARAMS ((tree, int)); static tree dfs_find_final_overrider PARAMS ((tree, void *)); static tree find_final_overrider PARAMS ((tree, tree, tree)); static int make_new_vtable PARAMS ((tree, tree)); -static void dump_class_hierarchy_r PARAMS ((tree, tree, int)); -extern void dump_class_hierarchy PARAMS ((tree)); +static void dump_class_hierarchy_r PARAMS ((FILE *, tree, tree, int)); +extern void dump_class_hierarchy PARAMS ((const char *, tree)); static tree build_vtable PARAMS ((tree, tree, tree)); static void initialize_vtable PARAMS ((tree, tree)); static void initialize_array PARAMS ((tree, tree)); @@ -182,20 +180,25 @@ static void layout_nonempty_base_or_field PARAMS ((record_layout_info, static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); static void layout_empty_base PARAMS ((tree, tree, splay_tree)); static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); +static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, + tree)); static void set_vindex PARAMS ((tree, tree, int *)); static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *)); static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, vtbl_init_data *)); -static tree dfs_mark_primary_bases PARAMS ((tree, void *)); +static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree)); +static void force_canonical_binfo PARAMS ((tree, tree, tree, tree)); static void mark_primary_bases PARAMS ((tree)); +static tree mark_primary_virtual_base PARAMS ((tree, tree, tree)); static void clone_constructors_and_destructors PARAMS ((tree)); static tree build_clone PARAMS ((tree, tree)); static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *)); static tree copy_virtuals PARAMS ((tree)); static void build_ctor_vtbl_group PARAMS ((tree, tree)); static void build_vtt PARAMS ((tree)); -static tree *build_vtt_inits PARAMS ((tree, tree, int, tree *, tree *)); +static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *)); static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *)); +static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data)); static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *)); static tree get_matching_base PARAMS ((tree, tree)); static tree dfs_get_primary_binfo PARAMS ((tree, void*)); @@ -208,6 +211,13 @@ static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int)); static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1, splay_tree_key k2)); + +/* Macros for dfs walking during vtt construction. See + dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits + and dfs_fixup_binfo_vtbls. */ +#define VTT_TOP_LEVEL_P(node) TREE_UNSIGNED(node) +#define VTT_MARKED_BINFO_P(node) TREE_USED(node) + /* Variables shared between class.c and call.c. */ #ifdef GATHER_STATISTICS @@ -1719,92 +1729,142 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p, } } -/* Called via dfs_walk from mark_primary_bases. Sets - BINFO_PRIMARY_MARKED_P for BINFO, if appropriate. */ +/* Binfo FROM is within a virtual heirarchy which is being reseated to + TO. Move primary information from FROM to TO, and recursively traverse + into FROM's bases. The heirarchy is dominated by TYPE. MAPPINGS is an + assoc list of binfos that have already been reseated. */ -static tree -dfs_mark_primary_bases (binfo, data) - tree binfo; - void *data; +static void +force_canonical_binfo_r (to, from, type, mappings) + tree to; + tree from; + tree type; + tree mappings; { - tree base_binfo; + int i, n_baseclasses = BINFO_N_BASETYPES (from); + + BINFO_INDIRECT_PRIMARY_P (to) + = BINFO_INDIRECT_PRIMARY_P (from); + BINFO_INDIRECT_PRIMARY_P (from) = 0; + if (BINFO_PRIMARY_P (from)) + { + tree primary = BINFO_PRIMARY_BASE_OF (from); + tree assoc; + + /* We might have just moved the primary base too, see if it's on our + mappings. */ + assoc = purpose_member (primary, mappings); + if (assoc) + primary = TREE_VALUE (assoc); + BINFO_PRIMARY_BASE_OF (to) = primary; + BINFO_PRIMARY_BASE_OF (from) = NULL_TREE; + } + my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)), 20010104); + mappings = tree_cons (from, to, mappings); + for (i = 0; i != n_baseclasses; i++) + { + tree from_binfo = BINFO_BASETYPE (from, i); + tree to_binfo = BINFO_BASETYPE (to, i); + + if (TREE_VIA_VIRTUAL (from_binfo)) + { + tree shared_binfo = binfo_for_vbase (BINFO_TYPE (from_binfo), type); + + if (shared_binfo == from_binfo) + force_canonical_binfo (to_binfo, from_binfo, type, mappings); + } + else + force_canonical_binfo_r (to_binfo, from_binfo, type, mappings); + } +} - if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))) - return NULL_TREE; +/* FROM is the canonical binfo for a virtual base. It is being reseated to + make TO the canonical binfo, within the heirarchy dominated by TYPE. + MAPPINGS is an assoc list of binfos that have already been reseated. + Adjust any non-virtual bases within FROM, and also move any virtual bases + which are canonical. This complication arises because selecting primary + bases walks in inheritance graph order, but we don't share binfos for + virtual bases, hence we can fill in the primaries for a virtual base, + and then discover that a later base requires the virtual as its + primary. */ - base_binfo = get_primary_binfo (binfo); +static void +force_canonical_binfo (to, from, type, mappings) + tree to; + tree from; + tree type; + tree mappings; +{ + tree assoc = purpose_member (BINFO_TYPE (to), + CLASSTYPE_VBASECLASSES (type)); + TREE_VALUE (assoc) = to; + force_canonical_binfo_r (to, from, type, mappings); +} - if (TREE_VIA_VIRTUAL (base_binfo)) - { - tree shared_binfo; - tree type; +/* Make BASE_BINFO the primary virtual base of BINFO within the hierarchy + dominated by TYPE. Returns BASE_BINFO, if it can be made so, NULL + otherwise (because something else has already made it primary). */ - type = (tree) data; - shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type); +static tree +mark_primary_virtual_base (binfo, base_binfo, type) + tree binfo; + tree base_binfo; + tree type; +{ + tree shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type); + tree delta; - /* If this virtual base is not already primary somewhere else in - the hiearchy, then we'll be using this copy. */ - if (!BINFO_PRIMARY_MARKED_P (shared_binfo)) - { - /* Make sure the CLASSTYPE_VBASECLASSES list contains the - primary copy; it's the one that really exists. */ - if (base_binfo != shared_binfo) - TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo), - CLASSTYPE_VBASECLASSES (type))) - = base_binfo; - } - else - base_binfo = NULL_TREE; + if (BINFO_PRIMARY_P (shared_binfo)) + { + /* It's already allocated in the hierarchy. BINFO won't have a + primary base in this hierachy, even though the complete object + BINFO is for, would do. */ + BINFO_LOST_PRIMARY_P (binfo) = 1; + + return NULL_TREE; } + + /* We need to make sure that the assoc list + CLASSTYPE_VBASECLASSES of TYPE, indicates this particular + primary BINFO for the virtual base, as this is the one + that'll really exist. */ + if (base_binfo != shared_binfo) + force_canonical_binfo (base_binfo, shared_binfo, type, NULL); - if (base_binfo) - BINFO_PRIMARY_BASE_OF (base_binfo) = binfo; - - return NULL_TREE; + delta = size_diffop (BINFO_OFFSET (binfo), BINFO_OFFSET (base_binfo)); + if (!integer_zerop (delta)) + { + propagate_binfo_offsets (base_binfo, delta); + BINFO_OFFSET (base_binfo) = BINFO_OFFSET (binfo); + } + return base_binfo; } -/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy - dominated by BINFO that are primary bases. */ +/* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy + dominated by TYPE that are primary bases. */ static void mark_primary_bases (type) tree type; { - tree vbases; - - /* Mark the TYPE_BINFO hierarchy. We need to mark primary bases in - pre-order to deal with primary virtual bases. (The virtual base - would be skipped if it were not marked as primary, and that - requires getting to dfs_mark_primary_bases before - dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the - virtual base.) */ - dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL, - dfs_skip_nonprimary_vbases_unmarkedp, type); - - /* Now go through the virtual base classes in inheritance graph - order. Any that are not already primary will need to be - allocated in TYPE, and so we need to mark their primary bases. */ - for (vbases = TYPE_BINFO (type); vbases; vbases = TREE_CHAIN (vbases)) + tree binfo; + + /* Walk the bases in inheritance graph order. */ + for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo)) { - tree vbase; - - /* Make sure that only BINFOs appear on this list. - Historically, the TREE_CHAIN was used for other purposes, and - we want to make sure that none of those uses remain. */ - my_friendly_assert (TREE_CODE (vbases) == TREE_VEC, 20000402); + tree base_binfo; + + if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))) + /* Not a dynamic base. */ + continue; - if (!TREE_VIA_VIRTUAL (vbases)) - continue; + base_binfo = get_primary_binfo (binfo); - vbase = binfo_for_vbase (BINFO_TYPE (vbases), type); - if (BINFO_PRIMARY_MARKED_P (vbase)) - /* This virtual base was already included in the hierarchy, so - there's nothing to do here. */ - continue; + if (TREE_VIA_VIRTUAL (base_binfo)) + base_binfo = mark_primary_virtual_base (binfo, base_binfo, type); - /* Now, walk its bases. */ - dfs_walk_real (vbase, dfs_mark_primary_bases, NULL, - dfs_skip_nonprimary_vbases_unmarkedp, type); + if (base_binfo) + BINFO_PRIMARY_BASE_OF (base_binfo) = binfo; } } @@ -1892,32 +1952,33 @@ determine_primary_base (t, vfuns_p) if (!TYPE_VFIELD (t)) CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE; - /* Mark the indirect primary bases. */ + /* Find the indirect primary bases - those virtual bases which are primary + bases of something else in this hierarchy. */ for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases)) { - tree binfo = TREE_VALUE (vbases); + tree vbase_binfo = TREE_VALUE (vbases); - /* See if this virtual base is an indirect primary base. If so, - it must be either a primary base or an indirect primary base - in one of the direct bases. */ + /* See if this virtual base is an indirect primary base. To be so, + it must be a primary base within the hierarchy of one of our + direct bases. */ for (i = 0; i < n_baseclasses; ++i) { - tree basetype; + tree basetype = TYPE_BINFO_BASETYPE (t, i); tree v; - basetype = TYPE_BINFO_BASETYPE (t, i); for (v = CLASSTYPE_VBASECLASSES (basetype); v; v = TREE_CHAIN (v)) { - tree b = TREE_VALUE (v); - if ((BINFO_PRIMARY_MARKED_P (b) - || BINFO_INDIRECT_PRIMARY_P (b)) - && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo))) + tree base_vbase = TREE_VALUE (v); + + if (BINFO_PRIMARY_P (base_vbase) + && same_type_p (BINFO_TYPE (base_vbase), + BINFO_TYPE (vbase_binfo))) { - BINFO_INDIRECT_PRIMARY_P (binfo) = 1; + BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1; break; } } @@ -1925,7 +1986,7 @@ determine_primary_base (t, vfuns_p) /* If we've discovered that this virtual base is an indirect primary base, then we can move on to the next virtual base. */ - if (BINFO_INDIRECT_PRIMARY_P (binfo)) + if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo)) break; } } @@ -1957,10 +2018,12 @@ determine_primary_base (t, vfuns_p) candidate = base_binfo; break; } - /* If this was an indirect primary base, it's still our - primary base -- unless there's another nearly-empty - virtual base that isn't an indirect primary base. */ - else if (!candidate) + + /* If this is an indirect primary base, it still could be + our primary base -- unless we later find there's another + nearly-empty virtual base that isn't an indirect + primary base. */ + if (!candidate) candidate = base_binfo; } } @@ -2516,12 +2579,6 @@ dfs_find_final_overrider (binfo, data) if (TREE_VIA_VIRTUAL (TREE_VALUE (base))) { base = ffod->declaring_base; - while (BINFO_PRIMARY_MARKED_P (base)) - { - BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1; - base = BINFO_INHERITANCE_CHAIN (base); - } - BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1; break; } @@ -2748,9 +2805,11 @@ dfs_modify_vtables (binfo, data) tree binfo; void *data; { - if (/* There's no need to modify the vtable for a primary base; - we're not going to use that vtable anyhow. */ - !BINFO_PRIMARY_MARKED_P (binfo) + if (/* There's no need to modify the vtable for a non-virtual + primary base; we're not going to use that vtable anyhow + (virtual primary bases can become non-primary in a + class derivation of this one.) */ + (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo)) /* Similarly, a base without a vtable needs no modification. */ && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) { @@ -3734,7 +3793,7 @@ check_subobject_offset (type, offset, offsets) /* Walk through all the subobjects of TYPE (located at OFFSET). Call F for every subobject, passing it the type, offset, and table of - OFFSETS. If VBASES_P is non-zero, then even non-virtual primary + OFFSETS. If VBASES_P is non-zero, then even virtual non-primary bases should be traversed; otherwise, they are ignored. If F returns a non-zero value, the traversal ceases, and that value is returned. Otherwise, returns zero. */ @@ -3766,7 +3825,7 @@ walk_subobject_offsets (type, f, offset, offsets, vbases_p) if (!vbases_p && TREE_VIA_VIRTUAL (binfo) - && !BINFO_PRIMARY_MARKED_P (binfo)) + && !BINFO_PRIMARY_P (binfo)) continue; r = walk_subobject_offsets (BINFO_TYPE (binfo), @@ -4085,7 +4144,7 @@ build_base_fields (rli, empty_p, offsets) base class, but a non-primary virtual base is allocated later, in layout_virtual_bases. */ if (TREE_VIA_VIRTUAL (base_binfo) - && !BINFO_PRIMARY_MARKED_P (base_binfo)) + && !BINFO_PRIMARY_P (base_binfo)) continue; build_base_field (rli, base_binfo, empty_p, &base_align, offsets); @@ -4649,7 +4708,7 @@ dfs_set_offset_for_unshared_vbases (binfo, data) /* If this is a virtual base, make sure it has the same offset as the shared copy. If it's a primary base, then we know it's correct. */ - if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo)) + if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo)) { tree t = (tree) data; tree vbase; @@ -4713,7 +4772,7 @@ layout_virtual_bases (t, offsets) else vbase = TREE_VALUE (vbases); - if (!BINFO_PRIMARY_MARKED_P (vbase)) + if (!BINFO_PRIMARY_P (vbase)) { /* This virtual base is not a primary base of any class in the hierarchy, so we have to add space for it. */ @@ -4824,7 +4883,7 @@ end_of_class (t, include_virtuals_p) if (!include_virtuals_p && TREE_VIA_VIRTUAL (base_binfo) - && !BINFO_PRIMARY_MARKED_P (base_binfo)) + && !BINFO_PRIMARY_P (base_binfo)) continue; offset = size_binop (PLUS_EXPR, @@ -5143,6 +5202,11 @@ finish_struct_1 (t) layout_class_type (t, &empty, &vfuns, &new_virtuals, &overridden_virtuals); + if (flag_dump_class_layout) + dump_class_hierarchy (*flag_dump_class_layout + ? flag_dump_class_layout : NULL, + t); + /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we might need to know it for setting up the offsets in the vtable (or in thunks) below. */ @@ -5277,6 +5341,7 @@ finish_struct_1 (t) /* Make the rtl for any new vtables we have created, and unmark the base types we marked. */ finish_vtbls (t); + /* Build the VTT for T. */ build_vtt (t); @@ -6587,7 +6652,7 @@ dfs_get_primary_binfo (binfo, data) tree primary_base = (tree) data; if (TREE_VIA_VIRTUAL (binfo) - && same_type_p (TREE_TYPE (binfo), TREE_TYPE (primary_base))) + && same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (primary_base))) return binfo; return NULL_TREE; @@ -6598,7 +6663,7 @@ dfs_get_primary_binfo (binfo, data) primary. In particular if the resulting BINFO is a virtual base, and it occurs elsewhere in the hierarchy, then this occurrence may not actually be a primary base in the complete object. Check - BINFO_PRIMARY_MARKED_P to be sure. */ + BINFO_PRIMARY_P to be sure. */ tree get_primary_binfo (binfo) @@ -6645,38 +6710,68 @@ get_primary_binfo (binfo) the top level; it is incremented recursively. */ static void -dump_class_hierarchy_r (t, binfo, indent) +dump_class_hierarchy_r (stream, t, binfo, indent) + FILE *stream; tree t; tree binfo; int indent; { int i; - fprintf (stderr, "%*s0x%lx (%s) ", indent, "", + fprintf (stream, "%*s0x%lx (%s) ", indent, "", (unsigned long) binfo, type_as_string (binfo, TFF_PLAIN_IDENTIFIER)); - fprintf (stderr, HOST_WIDE_INT_PRINT_DEC, + fprintf (stream, HOST_WIDE_INT_PRINT_DEC, tree_low_cst (BINFO_OFFSET (binfo), 0)); + if (is_empty_class (BINFO_TYPE (binfo))) + fprintf (stream, " empty"); + else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo))) + fprintf (stream, " nearly-empty"); if (TREE_VIA_VIRTUAL (binfo)) - fprintf (stderr, " virtual"); - if (BINFO_PRIMARY_MARKED_P (binfo) - || (TREE_VIA_VIRTUAL (binfo) - && BINFO_PRIMARY_MARKED_P (binfo_for_vbase (BINFO_TYPE (binfo), - t)))) - fprintf (stderr, " primary"); - fprintf (stderr, "\n"); + { + tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t); + + if (canonical == binfo) + fprintf (stream, " virtual-canonical"); + else + fprintf (stream, " virtual-non-canonical"); + } + if (BINFO_PRIMARY_P (binfo)) + fprintf (stream, " primary-for 0x%lx (%s)", + (unsigned long)BINFO_PRIMARY_BASE_OF (binfo), + type_as_string (BINFO_PRIMARY_BASE_OF (binfo), TFF_PLAIN_IDENTIFIER)); + if (BINFO_LOST_PRIMARY_P (binfo)) + fprintf (stream, " lost-primary"); + fprintf (stream, "\n"); for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) - dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2); + dump_class_hierarchy_r (stream, t, BINFO_BASETYPE (binfo, i), indent + 2); } /* Dump the BINFO hierarchy for T. */ void -dump_class_hierarchy (t) +dump_class_hierarchy (name, t) + const char *name; tree t; { - dump_class_hierarchy_r (t, TYPE_BINFO (t), 0); + FILE *stream = stderr; + + if (name) + { + static int append = 0; + + stream = fopen (name, append++ ? "a" : "w"); + if (!stream) + error ("could not open dump file `%s'", name); + return; + } + fprintf (stream, "%s\n", + type_as_string (t, TFF_PLAIN_IDENTIFIER)); + dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0); + fprintf (stream, "\n"); + if (name) + fclose (stream); } /* Virtual function table initialization. */ @@ -6703,10 +6798,17 @@ finish_vtbls (t) order. */ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase)) { + tree real_base; + if (!TREE_VIA_VIRTUAL (vbase)) continue; - - accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list); + + /* Although we walk in inheritance order, that might not get the + canonical base. */ + real_base = binfo_for_vbase (BINFO_TYPE (vbase), t); + + accumulate_vtbl_inits (real_base, real_base, + TYPE_BINFO (t), t, list); } if (TYPE_BINFO_VTABLE (t)) @@ -6771,7 +6873,17 @@ initialize_array (decl, inits) DECL_CONTEXT (decl) = context; } -/* Build the VTT (virtual table table) for T. */ +/* Build the VTT (virtual table table) for T. + A class requires a VTT if it has virtual bases. + + This holds + 1 - primary virtual pointer for complete object T + 2 - secondary VTTs for each direct non-virtual base of T which requires a VTT + 3 - secondary virtual pointers for each direct or indirect base of T which + has virtual bases or is reachable via a virtual path from T. + 4 - secondary VTTs for each direct or indirect virtual base of T. + + Secondary VTTs look like complete object VTTs without part 4. */ static void build_vtt (t) @@ -6789,8 +6901,7 @@ build_vtt (t) /* Build up the initializers for the VTT. */ inits = NULL_TREE; index = size_zero_node; - build_vtt_inits (TYPE_BINFO (t), t, /*virtual_vtts_p=*/1, - &inits, &index); + build_vtt_inits (TYPE_BINFO (t), t, &inits, &index); /* If we didn't need a VTT, we're done. */ if (!inits) @@ -6835,16 +6946,17 @@ get_matching_base (binfo, t) } /* Recursively build the VTT-initializer for BINFO (which is in the - hierarchy dominated by T). If VIRTUAL_VTTS_P is non-zero, then - sub-VTTs for virtual bases are included. INITS points to the end - of the initializer list to date. INDEX is the VTT index where the - next element will be placed. */ + hierarchy dominated by T). INITS points to the end of the initializer + list to date. INDEX is the VTT index where the next element will be + replaced. Iff BINFO is the binfo for T, this is the top level VTT (i.e. + not a subvtt for some base of T). When that is so, we emit the sub-VTTs + for virtual bases of T. When it is not so, we build the constructor + vtables for the BINFO-in-T variant. */ static tree * -build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) +build_vtt_inits (binfo, t, inits, index) tree binfo; tree t; - int virtual_vtts_p; tree *inits; tree *index; { @@ -6852,7 +6964,7 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) tree b; tree init; tree secondary_vptrs; - int ctor_vtbl_p; + int top_level_p = same_type_p (TREE_TYPE (binfo), t); /* We only need VTTs for subobjects with virtual bases. */ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))) @@ -6860,8 +6972,7 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) /* We need to use a construction vtable if this is not the primary VTT. */ - ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t); - if (ctor_vtbl_p) + if (!top_level_p) { build_ctor_vtbl_group (binfo, t); @@ -6875,7 +6986,11 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) init = TREE_VALUE (init); *inits = build_tree_list (NULL_TREE, init); inits = &TREE_CHAIN (*inits); - BINFO_VPTR_INDEX (binfo) = *index; + if (top_level_p) + { + my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129); + BINFO_VPTR_INDEX (binfo) = *index; + } *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node)); /* Recursively add the secondary VTTs for non-virtual bases. */ @@ -6884,22 +6999,26 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) b = BINFO_BASETYPE (binfo, i); if (!TREE_VIA_VIRTUAL (b)) inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, - /*virtuals_vtts_p=*/0, inits, index); } /* Add secondary virtual pointers for all subobjects of BINFO with - either virtual bases or virtual functions overridden along a - virtual path between the declaration and D, except subobjects - that are non-virtual primary bases. */ + either virtual bases or reachable along a virtual path, except + subobjects that are non-virtual primary bases. */ secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo)); TREE_TYPE (secondary_vptrs) = *index; + VTT_TOP_LEVEL_P (secondary_vptrs) = top_level_p; + VTT_MARKED_BINFO_P (secondary_vptrs) = 0; + dfs_walk_real (binfo, dfs_build_secondary_vptr_vtt_inits, NULL, - dfs_unmarked_real_bases_queue_p, + dfs_ctor_vtable_bases_queue_p, secondary_vptrs); - dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t); + VTT_MARKED_BINFO_P (secondary_vptrs) = 1; + dfs_walk (binfo, dfs_unmark, dfs_ctor_vtable_bases_queue_p, + secondary_vptrs); + *index = TREE_TYPE (secondary_vptrs); /* The secondary vptrs come back in reverse order. After we reverse @@ -6914,7 +7033,7 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) } /* Add the secondary VTTs for virtual bases. */ - if (virtual_vtts_p) + if (top_level_p) for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b)) { tree vbase; @@ -6923,18 +7042,29 @@ build_vtt_inits (binfo, t, virtual_vtts_p, inits, index) continue; vbase = binfo_for_vbase (BINFO_TYPE (b), t); - inits = build_vtt_inits (vbase, t, /*virtual_vtts_p=*/0, - inits, index); + inits = build_vtt_inits (vbase, t, inits, index); } - dfs_walk (binfo, dfs_fixup_binfo_vtbls, - dfs_unmarked_real_bases_queue_p, - build_tree_list (t, binfo)); + if (!top_level_p) + { + tree data = tree_cons (t, binfo, NULL_TREE); + VTT_TOP_LEVEL_P (data) = 0; + VTT_MARKED_BINFO_P (data) = 0; + + dfs_walk (binfo, dfs_fixup_binfo_vtbls, + dfs_ctor_vtable_bases_queue_p, + data); + } return inits; } -/* Called from build_vtt_inits via dfs_walk. */ +/* Called from build_vtt_inits via dfs_walk. BINFO is the binfo + for the base in most derived. DATA is a TREE_LIST who's + TREE_CHAIN is the type of the base being + constructed whilst this secondary vptr is live. The TREE_UNSIGNED + flag of DATA indicates that this is a constructor vtable. The + TREE_TOP_LEVEL flag indicates that this is the primary VTT. */ static tree dfs_build_secondary_vptr_vtt_inits (binfo, data) @@ -6945,10 +7075,12 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data) tree t; tree init; tree index; + int top_level_p; l = (tree) data; t = TREE_CHAIN (l); - + top_level_p = VTT_TOP_LEVEL_P (l); + SET_BINFO_MARKED (binfo); /* We don't care about bases that don't have vtables. */ @@ -6960,32 +7092,34 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data) return NULL_TREE; /* We're not interested in non-virtual primary bases. */ - if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo)) + if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo)) return NULL_TREE; - /* If BINFO doesn't have virtual bases, then we have to look to see - whether or not any virtual functions were overidden along a - virtual path. The point is that given: - - struct V { virtual void f(); int i; }; - struct C : public virtual V { void f (); }; - - when we constrct C we need a secondary vptr for V-in-C because we - don't know what the vcall offset for `f' should be. If `V' ends - up in a different place in the complete object, then we'll need a - different vcall offset than that present in the normal V-in-C - vtable. */ + /* If BINFO has virtual bases or is reachable via a virtual path + from T, it'll have a secondary vptr. */ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)) - && !BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (get_matching_base (binfo, t))) + && !binfo_via_virtual (binfo, t)) return NULL_TREE; /* Record the index where this secondary vptr can be found. */ index = TREE_TYPE (l); - BINFO_VPTR_INDEX (binfo) = index; + if (top_level_p) + { + my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129); + BINFO_VPTR_INDEX (binfo) = index; + } TREE_TYPE (l) = size_binop (PLUS_EXPR, index, TYPE_SIZE_UNIT (ptr_type_node)); /* Add the initializer for the secondary vptr itself. */ + if (top_level_p && TREE_VIA_VIRTUAL (binfo)) + { + /* It's a primary virtual base, and this is not the construction + vtable. Find the base this is primary of in the inheritance graph, + and use that base's vtable now. */ + while (BINFO_PRIMARY_BASE_OF (binfo)) + binfo = BINFO_PRIMARY_BASE_OF (binfo); + } init = BINFO_VTABLE (binfo); if (TREE_CODE (init) == TREE_LIST) init = TREE_VALUE (init); @@ -6994,7 +7128,34 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data) return NULL_TREE; } -/* Called from build_vtt_inits via dfs_walk. */ +/* dfs_walk_real predicate for building vtables. DATA is a TREE_LIST, + TREE_UNSIGNED indicates that a constructor vtable is being built. + TREE_USED indicates whether marked or unmarked bases should be walked. + TREE_PURPOSE is the TREE_TYPE that dominates the hierarchy. */ + +static tree +dfs_ctor_vtable_bases_queue_p (binfo, data) + tree binfo; + void *data; +{ + if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo)) + { + tree type = TREE_PURPOSE ((tree) data); + + /* This is a non-primary virtual base, get the shared version. */ + binfo = binfo_for_vbase (BINFO_TYPE (binfo), type); + if (VTT_TOP_LEVEL_P ((tree) data) && BINFO_PRIMARY_P (binfo)) + return NULL_TREE; + } + if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data)) + return NULL_TREE; + return binfo; +} + +/* Called from build_vtt_inits via dfs_walk. After building constructor + vtables and generating the sub-vtt from them, we need to restore the + BINFO_VTABLES that were scribbled on. DATA is a TREE_LIST whose + TREE_VALUE is the TREE_TYPE of the base whose sub vtt was generated. */ static tree dfs_fixup_binfo_vtbls (binfo, data) @@ -7040,6 +7201,7 @@ build_ctor_vtbl_group (binfo, t) if (IDENTIFIER_GLOBAL_VALUE (id)) return; + my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124); /* Build a version of VTBL (with the wrong type) for use in constructing the addresses of secondary vtables in the construction vtable group. */ @@ -7047,19 +7209,23 @@ build_ctor_vtbl_group (binfo, t) list = build_tree_list (vtbl, NULL_TREE); accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)), binfo, t, list); - for (vbase = TYPE_BINFO (TREE_TYPE (binfo)); + + /* Add the vtables for each of our virtual bases using the vbase in T + binfo. */ + for (vbase = TYPE_BINFO (BINFO_TYPE (binfo)); vbase; vbase = TREE_CHAIN (vbase)) { tree b; + tree orig_base; if (!TREE_VIA_VIRTUAL (vbase)) continue; - b = binfo_for_vbase (BINFO_TYPE (vbase), t); - accumulate_vtbl_inits (b, vbase, binfo, t, list); + orig_base = binfo_for_vbase (BINFO_TYPE (vbase), BINFO_TYPE (binfo)); + + accumulate_vtbl_inits (b, orig_base, binfo, t, list); } - inits = TREE_VALUE (list); /* Figure out the type of the construction vtable. */ @@ -7072,12 +7238,15 @@ build_ctor_vtbl_group (binfo, t) initialize_array (vtbl, inits); } -/* Add the vtbl initializers for BINFO (and its non-primary, - non-virtual bases) to the list of INITS. BINFO is in the hierarchy - dominated by T. ORIG_BINFO must have the same type as BINFO, but - may be different from BINFO if we are building a construction - vtable. RTTI_BINFO gives the object that should be used as the - complete object for BINFO. */ +/* Add the vtbl initializers for BINFO (and its bases other than + non-virtual primaries) to the list of INITS. BINFO is in the + hierarchy dominated by T. RTTI_BINFO is the binfo within T of + the constructor the vtbl inits should be accumulated for. (If this + is the complete object vtbl then RTTI_BINFO will be TYPE_BINFO (T).) + ORIG_BINFO is the binfo for this object within BINFO_TYPE (RTTI_BINFO). + BINFO is the active base equivalent of ORIG_BINFO in the inheritance + graph of T. Both BINFO and ORIG_BINFO will have the same BINFO_TYPE, + but are not necessarily the same in terms of layout. */ static void accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits) @@ -7088,22 +7257,17 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits) tree inits; { int i; - int ctor_vtbl_p; + int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); my_friendly_assert (same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (orig_binfo)), 20000517); - /* This is a construction vtable if the RTTI type is not the most - derived type in the hierarchy. */ - ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); - /* If we're building a construction vtable, we're not interested in subobjects that don't require construction vtables. */ if (ctor_vtbl_p && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)) - && !(BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P - (get_matching_base (binfo, BINFO_TYPE (rtti_binfo))))) + && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo))) return; /* Build the initializers for the BINFO-in-T vtable. */ @@ -7119,21 +7283,19 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits) and RTTI_BINFO simultaneously. */ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i) { - tree base_binfo; - - base_binfo = BINFO_BASETYPE (binfo, i); + tree base_binfo = BINFO_BASETYPE (binfo, i); + /* Skip virtual bases. */ if (TREE_VIA_VIRTUAL (base_binfo)) continue; accumulate_vtbl_inits (base_binfo, BINFO_BASETYPE (orig_binfo, i), - rtti_binfo, - t, + rtti_binfo, t, inits); } } -/* Called from finish_vtbls via dfs_walk when using the new ABI. +/* Called from accumulate_vtbl_inits when using the new ABI. Accumulates the vtable initializers for all of the vtables into TREE_VALUE (DATA). Returns the initializers for the BINFO vtable. */ @@ -7146,10 +7308,57 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) tree l; { tree inits = NULL_TREE; + tree vtbl = NULL_TREE; + int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); + + if (ctor_vtbl_p + && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo)) + { + /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary + virtual base. If it is not the same primary in the hierarchy of T, + we'll need to generate a ctor vtable for it, to place at its + location in T. If it is the same primary, we still need a VTT + entry for the vtable, but that must be the base it is a + primary for within the sub-hierarchy of RTTI_BINFO. */ + tree parent; + tree best_primary = NULL; + tree primary_for; + + my_friendly_assert (BINFO_PRIMARY_P (binfo), 20010131); - if (BINFO_NEW_VTABLE_MARKED (orig_binfo, t)) + for (primary_for = BINFO_PRIMARY_BASE_OF (binfo); + primary_for; + primary_for = BINFO_PRIMARY_BASE_OF (primary_for)) + { + for (parent = primary_for; + parent; + parent = BINFO_INHERITANCE_CHAIN (parent)) + { + if (parent == rtti_binfo) + { + best_primary = primary_for; + break; + } + } + if (!parent) + break; + } + if (best_primary) + { + vtbl = BINFO_VTABLE (best_primary); + if (TREE_CODE (vtbl) == TREE_LIST) + { + my_friendly_assert (TREE_PURPOSE (vtbl) == rtti_binfo, + 20010126); + vtbl = TREE_VALUE (vtbl); + } + } + } + else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo))) + return inits; + + if (!vtbl) { - tree vtbl; tree index; int non_fn_entries; @@ -7170,17 +7379,20 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) index); vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index); TREE_CONSTANT (vtbl) = 1; + } + if (!ctor_vtbl_p) + { /* For an ordinary vtable, set BINFO_VTABLE. */ - if (same_type_p (BINFO_TYPE (rtti_binfo), t)) - BINFO_VTABLE (binfo) = vtbl; - /* For a construction vtable, we can't overwrite BINFO_VTABLE. - So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will - straighten this out. */ - else - BINFO_VTABLE (binfo) = - tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo)); + BINFO_VTABLE (binfo) = vtbl; + if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo)) + inits = NULL_TREE; } + else + /* For a construction vtable, we can't overwrite BINFO_VTABLE. + So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will + straighten this out. */ + BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo)); return inits; } @@ -7188,7 +7400,9 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) /* Construct the initializer for BINFOs virtual function table. BINFO is part of the hierarchy dominated by T. If we're building a construction vtable, the ORIG_BINFO is the binfo we should use to - find the actual function pointers to put in the vtable. Otherwise, + find the actual function pointers to put in the vtable - but they + can be overridden on the path to most-derived in the graph that + ORIG_BINFO belongs. Otherwise, ORIG_BINFO should be the same as BINFO. The RTTI_BINFO is the BINFO that should be indicated by the RTTI information in the vtable; it will be a base class of T, rather than T itself, if we @@ -7200,9 +7414,9 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l) number of non-function entries in the vtable. It might seem that this function should never be called with a - BINFO for which BINFO_PRIMARY_MARKED_P holds, the vtable for such a + BINFO for which BINFO_PRIMARY_P holds, the vtable for such a base is always subsumed by a derived class vtable. However, when - we are building construction vtables we do build vtables for + we are building construction vtables, we do build vtables for primary bases; we need these while the primary base is being constructed. */ @@ -7489,7 +7703,7 @@ add_vcall_offset_vtbl_entries_r (binfo, vid) } } -/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */ +/* Called from build_vcall_offset_vtbl_entries_r. */ static void add_vcall_offset_vtbl_entries_1 (binfo, vid) @@ -7579,7 +7793,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) if (i != VARRAY_ACTIVE_SIZE (vid->fns)) continue; - /* The FN comes from BASE. So, we must caculate the adjustment + /* The FN comes from BASE. So, we must calculate the adjustment from the virtual base that derived from BINFO to BASE. */ base = DECL_CONTEXT (fn); base_binfo = get_binfo (base, vid->derived, /*protect=*/0); @@ -7635,13 +7849,13 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid) /* To find the complete object, we will first convert to our most primary base, and then add the offset in the vtbl to that value. */ b = binfo; - while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b))) + while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)) + && !BINFO_LOST_PRIMARY_P (b)) { tree primary_base; primary_base = get_primary_binfo (b); - if (!BINFO_PRIMARY_MARKED_P (primary_base)) - break; + my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127); b = primary_base; } offset = size_diffop (BINFO_OFFSET (rtti_binfo), BINFO_OFFSET (b)); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9077671bb60..d473006f24e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -60,7 +60,7 @@ Boston, MA 02111-1307, USA. */ TYPE_POLYMORHPIC_P (in _TYPE) ICS_THIS_FLAG (in _CONV) BINDING_HAS_LEVEL_P (in CPLUS_BINDING) - BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (in BINFO) + BINFO_LOST_PRIMARY_P (in BINFO) TREE_PARMLIST (in TREE_LIST) 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). BINFO_VTABLE_PATH_MARKED. @@ -1158,6 +1158,10 @@ extern int flag_access_control; extern int flag_check_new; +/* Nonnull if we want to dump class heirarchies. */ + +extern const char *flag_dump_class_layout; + /* C++ language-specific tree codes. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, @@ -1672,11 +1676,11 @@ struct lang_type (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C))) /* Any subobject that needs a new vtable must have a vptr and must not - be a primary base (since it would then use the vtable from a - derived class.) */ + be a non-virtual primary base (since it would then use the vtable from a + derived class and never become non-primary.) */ #define SET_BINFO_NEW_VTABLE_MARKED(B, C) \ (BINFO_NEW_VTABLE_MARKED (B, C) = 1, \ - my_friendly_assert (!BINFO_PRIMARY_MARKED_P (B), 20000517), \ + my_friendly_assert (!BINFO_PRIMARY_P (B) || TREE_VIA_VIRTUAL (B), 20000517), \ my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE, \ 20000517)) @@ -1691,7 +1695,7 @@ struct lang_type class of a non-primary virtual base. This flag is only valid for paths (given by BINFO_INHERITANCE_CHAIN) that really exist in the final object. */ -#define BINFO_PRIMARY_MARKED_P(NODE) \ +#define BINFO_PRIMARY_P(NODE) \ (BINFO_PRIMARY_BASE_OF (NODE) != NULL_TREE) /* The index in the VTT where this subobject's sub-VTT can be found. @@ -1708,9 +1712,10 @@ struct lang_type immediate base.) */ #define BINFO_PRIMARY_BASE_OF(NODE) TREE_VEC_ELT ((NODE), 10) -/* Nonzero if this binfo declares a virtual function which is - overridden along a virtual path. */ -#define BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P(NODE) TREE_LANG_FLAG_2 (NODE) +/* Nonzero if this binfo has lost its primary base binfo (because that + is a nearly-empty virtual base that has been taken by some other + base in the complete heirarchy. */ +#define BINFO_LOST_PRIMARY_P(NODE) TREE_LANG_FLAG_2 (NODE) /* Nonzero if this binfo is an indirect primary base, i.e. a virtual base that is a primary base of some of other class in the @@ -4248,6 +4253,7 @@ extern tree unmarked_vtable_pathp PARAMS ((tree, void *)); extern tree convert_pointer_to_vbase PARAMS ((tree, tree)); extern tree find_vbase_instance PARAMS ((tree, tree)); extern tree binfo_for_vbase PARAMS ((tree, tree)); +extern tree binfo_via_virtual PARAMS ((tree, tree)); extern void fixup_all_virtual_upcast_offsets PARAMS ((tree)); /* in semantics.c */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2c3dbc78daf..fff395670a7 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -403,6 +403,10 @@ int flag_operator_names = 1; int flag_check_new; +/* Nonnull if we want to dump class heirarchies. */ + +const char *flag_dump_class_layout; + /* Nonzero if we want the new ISO rules for pushing a new scope for `for' initialization variables. 0: Old rules, set by -fno-for-scope. @@ -647,13 +651,23 @@ cxx_decode_option (argc, argv) name_mangling_version = read_integral_parameter (option_value, p - 2, name_mangling_version); else if ((option_value - = skip_leading_substring (p, "dump-translation-unit-"))) + = skip_leading_substring (p, "dump-translation-unit="))) { - if (p[22] == '\0') + if (!*option_value) error ("no file specified with -fdump-translation-unit"); else flag_dump_translation_unit = option_value; } + else if ((option_value + = skip_leading_substring (p, "dump-class-layout="))) + { + if (!*option_value) + error ("no file specified with -fdump-class-layout"); + else + flag_dump_class_layout = option_value; + } + else if (!strcmp (p, "dump-class-layout")) + flag_dump_class_layout = ""; /* empty string for stderr */ else { int found = 0; diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7cd6c5739d6..e7d62934d6d 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -137,7 +137,7 @@ dfs_initialize_vtbl_ptrs (binfo, data) tree binfo; void *data; { - if (!BINFO_PRIMARY_MARKED_P (binfo) + if ((!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo)) && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) { tree base_ptr = TREE_VALUE ((tree) data); @@ -802,16 +802,27 @@ static tree build_vtbl_address (binfo) tree binfo; { + tree binfo_for = binfo; tree vtbl; + if (BINFO_VPTR_INDEX (binfo) && TREE_VIA_VIRTUAL (binfo) + && BINFO_PRIMARY_P (binfo)) + /* If this is a virtual primary base, then the vtable we want to store + is that for the base this is being used as the primary base of. We + can't simply skip the initialization, because we may be expanding the + inits of a subobject constructor where the virtual base layout + can be different. */ + while (BINFO_PRIMARY_BASE_OF (binfo_for)) + binfo_for = BINFO_PRIMARY_BASE_OF (binfo_for); + /* Figure out what vtable BINFO's vtable is based on, and mark it as used. */ - vtbl = get_vtbl_decl_for_binfo (binfo); + vtbl = get_vtbl_decl_for_binfo (binfo_for); assemble_external (vtbl); TREE_USED (vtbl) = 1; /* Now compute the address to use when initializing the vptr. */ - vtbl = BINFO_VTABLE (binfo); + vtbl = BINFO_VTABLE (binfo_for); if (TREE_CODE (vtbl) == VAR_DECL) { vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index c8cf526035f..1699c325f66 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2045,7 +2045,7 @@ dfs_skip_nonprimary_vbases_unmarkedp (binfo, data) tree binfo; void *data ATTRIBUTE_UNUSED; { - if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo)) + if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo)) /* This is a non-primary virtual base. Skip it. */ return NULL_TREE; @@ -2060,7 +2060,7 @@ dfs_skip_nonprimary_vbases_markedp (binfo, data) tree binfo; void *data ATTRIBUTE_UNUSED; { - if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo)) + if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo)) /* This is a non-primary virtual base. Skip it. */ return NULL_TREE; @@ -2078,7 +2078,7 @@ get_shared_vbase_if_not_primary (binfo, data) tree binfo; void *data; { - if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo)) + if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo)) { tree type = (tree) data; @@ -2088,7 +2088,7 @@ get_shared_vbase_if_not_primary (binfo, data) /* This is a non-primary virtual base. If there is no primary version, get the shared version. */ binfo = binfo_for_vbase (BINFO_TYPE (binfo), type); - if (BINFO_PRIMARY_MARKED_P (binfo)) + if (BINFO_PRIMARY_P (binfo)) return NULL_TREE; } @@ -2152,7 +2152,7 @@ dfs_get_pure_virtuals (binfo, data) /* We're not interested in primary base classes; the derived class of which they are a primary base will contain the information we need. */ - if (!BINFO_PRIMARY_MARKED_P (binfo)) + if (!BINFO_PRIMARY_P (binfo)) { tree virtuals; @@ -2455,7 +2455,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, tree delta; HOST_WIDE_INT n; - while (BINFO_PRIMARY_MARKED_P (binfo)) + while (BINFO_PRIMARY_P (binfo)) { binfo = BINFO_INHERITANCE_CHAIN (binfo); if (TREE_VIA_VIRTUAL (binfo)) @@ -2593,7 +2593,7 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori tree real_base_binfo = TREE_VEC_ELT (real_binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i); int is_not_base_vtable - = !BINFO_PRIMARY_MARKED_P (real_base_binfo); + = !BINFO_PRIMARY_P (real_base_binfo); if (! TREE_VIA_VIRTUAL (real_base_binfo)) fixup_virtual_upcast_offsets (real_base_binfo, base_binfo, is_not_base_vtable, can_elide, addr, @@ -2737,7 +2737,7 @@ dfs_find_vbase_instance (binfo, data) { tree base = TREE_VALUE ((tree) data); - if (BINFO_PRIMARY_MARKED_P (binfo) + if (BINFO_PRIMARY_P (binfo) && same_type_p (BINFO_TYPE (binfo), base)) return binfo; @@ -2755,7 +2755,7 @@ find_vbase_instance (base, type) tree instance; instance = binfo_for_vbase (base, type); - if (!BINFO_PRIMARY_MARKED_P (instance)) + if (!BINFO_PRIMARY_P (instance)) return instance; return dfs_walk (TYPE_BINFO (type), @@ -3249,8 +3249,8 @@ binfo_for_vtable (var) return main_binfo; } -/* Returns the binfo of the first direct or indirect virtual base from - which BINFO is derived, or NULL if binfo is not via virtual. */ +/* Returns the binfo of the first direct or indirect virtual base derived + from BINFO, or NULL if binfo is not via virtual. */ tree binfo_from_vbase (binfo) @@ -3264,6 +3264,24 @@ binfo_from_vbase (binfo) return NULL_TREE; } +/* Returns the binfo of the first direct or indirect virtual base derived + from BINFO up to the TREE_TYPE, LIMIT, or NULL if binfo is not + via virtual. */ + +tree +binfo_via_virtual (binfo, limit) + tree binfo; + tree limit; +{ + for (; binfo && (!limit || !same_type_p (BINFO_TYPE (binfo), limit)); + binfo = BINFO_INHERITANCE_CHAIN (binfo)) + { + if (TREE_VIA_VIRTUAL (binfo)) + return binfo; + } + return NULL_TREE; +} + /* Returns the BINFO (if any) for the virtual baseclass T of the class C from the CLASSTYPE_VBASECLASSES list. */ diff --git a/gcc/invoke.texi b/gcc/invoke.texi index beec0e767cf..8052be177ec 100644 --- a/gcc/invoke.texi +++ b/gcc/invoke.texi @@ -223,8 +223,8 @@ in the following sections. @item Debugging Options @xref{Debugging Options,,Options for Debugging Your Program or GCC}. @gccoptlist{ --a -ax -d@var{letters} -fdump-unnumbered -fdump-translation-unit-@var{file} @gol --fpretend-float -fprofile-arcs -ftest-coverage @gol +-a -ax -d@var{letters} -fdump-unnumbered -fdump-translation-unit=@var{file} @gol +-fdump-class-layout=@var{file} -fpretend-float -fprofile-arcs -ftest-coverage @gol -g -g@var{level} -gcoff -gdwarf -gdwarf-1 -gdwarf-1+ -gdwarf-2 @gol -ggdb -gstabs -gstabs+ -gxcoff -gxcoff+ @gol -p -pg -print-file-name=@var{library} -print-libgcc-file-name @gol @@ -2679,10 +2679,15 @@ numbers and line number note output. This makes it more feasible to use diff on debugging dumps for compiler invocations with different options, in particular with and without -g. -@item -fdump-translation-unit-@var{file} (C and C++ only) +@item -fdump-translation-unit=@var{file} (C and C++ only) Dump a representation of the tree structure for the entire translation unit to @var{file}. +@item -fdump-class_layout=@var{file} (C++ only) +@item -fdump-class_layout (C++ only) +Dump a representation of each class's heirarchy to @var{file}, or +@code{stderr} if not specified. + @item -fpretend-float When running a cross-compiler, pretend that the target machine uses the same floating point format as the host machine. This causes incorrect diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 60daf568946..2cec5af4511 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2001-02-05 Nathan Sidwell + + * g++.old-deja/g++.abi/primary2.C: New test. + * g++.old-deja/g++.abi/primary3.C: New test. + * g++.old-deja/g++.abi/primary4.C: New test. + * g++.old-deja/g++.abi/primary5.C: New test. + * g++.old-deja/g++.abi/vtable3.h: New test. + * g++.old-deja/g++.abi/vtable3a.C: New test. + * g++.old-deja/g++.abi/vtable3b.C: New test. + * g++.old-deja/g++.abi/vtable3c.C: New test. + * g++.old-deja/g++.abi/vtable3d.C: New test. + * g++.old-deja/g++.abi/vtable3e.C: New test. + * g++.old-deja/g++.abi/vtable3f.C: New test. + * g++.old-deja/g++.abi/vtable3g.C: New test. + * g++.old-deja/g++.abi/vtable3h.C: New test. + * g++.old-deja/g++.abi/vtable3i.C: New test. + * g++.old-deja/g++.abi/vtable3j.C: New test. + * g++.old-deja/g++.oliva/thunk1.C: Remove XFAIL. + 2001-02-03 Jakub Jelinek * g++.old-deja/g++.other/anon6.C: New test. diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary2.C b/gcc/testsuite/g++.old-deja/g++.abi/primary2.C new file mode 100644 index 00000000000..795eb4d61c0 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/primary2.C @@ -0,0 +1,21 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check primary bases are chosen correctly. + +struct A {virtual void Foo () {}}; +struct B : virtual A {}; +struct C : virtual B {}; +struct D : virtual B, virtual C {}; + +int main () +{ + D d; + +#if __GXX_ABI_VERSION >= 100 + if (sizeof (D) != sizeof (A)) + return 1; +#endif + + return 0; +} diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary3.C b/gcc/testsuite/g++.old-deja/g++.abi/primary3.C new file mode 100644 index 00000000000..ef245ef789e --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/primary3.C @@ -0,0 +1,34 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check primary bases are chosen correctly. + +struct A {virtual void Foo () {}}; +struct B1 : virtual A {}; +struct B2 : virtual A {}; +struct C : virtual B1, B2 {}; +struct D : virtual C {}; + +int main () +{ + C c; + D d; + + A *apc = &c; + B1 *b1pc = &c; + B2 *b2pc = &c; + + A *apd = &d; + B1 *b1pd = &d; + B2 *b2pd = &d; + +#if __GXX_ABI_VERSION >= 100 + if (static_cast (apc) != static_cast (b1pc)) + return 1; + if (static_cast (apd) != static_cast (b1pd)) + return 2; + if (static_cast (apd) != static_cast (&d)) + return 3; +#endif + return 0; +} diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary4.C b/gcc/testsuite/g++.old-deja/g++.abi/primary4.C new file mode 100644 index 00000000000..d18f24297d6 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/primary4.C @@ -0,0 +1,27 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check primary bases are chosen correctly. + +struct A { virtual void Foo () {}}; + +struct B1 : virtual A {}; +struct B2 : virtual A {}; + +struct C : virtual B1 {}; + +struct D : virtual B1, B2, C {}; + +int main () +{ + D d; + A *ap = &d; + C *cp = &d; + +#if __GXX_ABI_VERSION >= 100 + if (static_cast (ap) != static_cast (cp)) + return 1; +#endif + + return 0; +} diff --git a/gcc/testsuite/g++.old-deja/g++.abi/primary5.C b/gcc/testsuite/g++.old-deja/g++.abi/primary5.C new file mode 100644 index 00000000000..422e66e11d6 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/primary5.C @@ -0,0 +1,36 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check primary bases are chosen correctly. + +struct A1 +{ + virtual void Foo () {}; +}; + +struct A : A1 +{ +}; + +struct B : A +{ +}; + +struct C : virtual B +{ +}; + +struct D : virtual B, virtual C +{ +}; + +int main() +{ + D d; +#if __GXX_ABI_VERSION >= 100 + if (sizeof (D) != sizeof (A)) + return 1; +#endif + + return 0; +} diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h b/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h new file mode 100644 index 00000000000..327d346db27 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3.h @@ -0,0 +1,181 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. This is included from numerous test +// files, which set the #defines necessary to specify the heirarchy. + +#include +#include + +// XXX. vcall offsets are still broken, remove this define to re-enable +// testing when fixed. +#define NO_VCALL_TEST + +int fail; + +template +int Test (DERIVED *d, int expect) +{ + BASE *b = static_cast (d); + void *full_b = dynamic_cast (b); + void *full_d = dynamic_cast (d); + + if (full_b != full_d) + { + fail++; + fprintf (stderr, "base %s and derived %s have different full objects\n", + typeid (BASE).name (), typeid (DERIVED).name ()); + return 1; + } + + DERIVED *dynamic_d = dynamic_cast (b); + + if (dynamic_d != d) + { + fail++; + fprintf (stderr, "dynamic_cast from %s to %s failed\n", + typeid (BASE).name (), typeid (DERIVED).name ()); + return 1; + } +#ifndef NO_VCALL_TEST + b->Baz (static_cast (b)); + + int res = b->Foo (static_cast (d)); + + if (res != expect) + { + fail++; + fprintf (stderr, "%s::Foo returned %d, expected %d\n", + typeid (BASE).name (), res, expect); + return 1; + } +#endif + return 0; +} + +template +int Test (T *self, void *expected, int result) +{ + if (self != expected) + { + fail++; + fprintf (stderr, "%s::Foo wrong this pointer\n", typeid (T).name ()); + } + return result; +} + +struct A { +#ifndef A_EMPTY + int a_m; +#endif + virtual int Foo (void *p) {return Test (this, p, 1);} + virtual int Baz (void *p) {return Test (this, p, 1);} + A (); + ~A (); +}; + +struct B1: virtual A { +#ifndef B1_EMPTY + int b1_m; +#endif + virtual int Foo (void *p) {return Test (this, p, 2);} + B1(); + ~B1(); +}; + +struct B2: virtual A { +#ifndef B2_EMPTY + int b2_m; +#endif + virtual int Foo (void *p) {return Test (this, p, 3);} + B2(); + ~B2(); +}; + +struct Empty {}; + +struct C : C_PARENTS { +#ifndef C_EMPTY + int c_m; +#endif + virtual int Foo (void *p) {return Test (this, p, 4);} + C(); + ~C(); +}; + +A::A () +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 1); +} +A::~A () +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 1); +} + +B1::B1() +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 2); + Test (this, 2); +} +B1::~B1() +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 2); + Test (this, 2); +} +B2::B2() +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 3); + Test (this, 3); +} +B2::~B2() +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 3); + Test (this, 3); +} +C::C() +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 4); + Test (this, 4); +} +C::~C() +{ + fprintf (stderr, "%s\n", __PRETTY_FUNCTION__); + Test (this, 4); + Test (this, 4); +} + +struct D : C {}; +struct D1 : virtual C {}; +struct D2 : virtual A, virtual C {}; + +int main() +{ + { + fprintf (stderr, "C\n"); + C c; + } + { + fprintf (stderr, "D\n"); + D d; + } + { + fprintf (stderr, "D1\n"); + D1 d1; + } + { + fprintf (stderr, "D2\n"); + D2 d2; + } + if (fail) + fprintf (stderr, "There are %d failings\n", fail); + else + fprintf (stderr, "Passed\n"); + return fail ? 1 : 0; +} diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C new file mode 100644 index 00000000000..99d3d0b9ecd --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C @@ -0,0 +1,12 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C new file mode 100644 index 00000000000..4d4bd998512 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C @@ -0,0 +1,11 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C new file mode 100644 index 00000000000..2863ca5ec5f --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C @@ -0,0 +1,11 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C new file mode 100644 index 00000000000..a3a2cbcb5a9 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C @@ -0,0 +1,11 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B1_EMPTY +#define C_EMPTY +#define C_PARENTS B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C new file mode 100644 index 00000000000..a1c8a9d59e4 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C @@ -0,0 +1,11 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B1_EMPTY +#define B2_EMPTY +#define C_PARENTS B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C new file mode 100644 index 00000000000..7bcf40ccf4b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C @@ -0,0 +1,12 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS B1, virtual B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C new file mode 100644 index 00000000000..1ad70bc3160 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C @@ -0,0 +1,12 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS virtual B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C new file mode 100644 index 00000000000..074bda44c7a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C @@ -0,0 +1,12 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define A_EMPTY +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS virtual B1, virtual B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C new file mode 100644 index 00000000000..d6fc3a3506b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C @@ -0,0 +1,11 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS virtual B1, B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C new file mode 100644 index 00000000000..1af5225c536 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C @@ -0,0 +1,11 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 4 February 2001 + +// Check constructor vtables work. + +#define B1_EMPTY +#define B2_EMPTY +#define C_EMPTY +#define C_PARENTS virtual B1, virtual B2 + +#include "vtable3.h" diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C b/gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C index 5407e9e0583..225a1f98103 100644 --- a/gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C +++ b/gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C @@ -4,7 +4,6 @@ // based on bug report by Fredrik Öhrström // Special g++ Options: -fvtable-thunks -// execution test - XFAIL *-*-* #include -- 2.11.4.GIT