aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2001-02-05 11:45:16 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2001-02-05 11:45:16 +0000
commit9965d119133a5cb80938b829d28fa45777667a0c (patch)
treee552da6fa53e49d793b63acc246a7fe949765502 /gcc
parent36ca672c97a7f1d07e274626eab0dabb5710b49a (diff)
downloadgcc-9965d119133a5cb80938b829d28fa45777667a0c.zip
gcc-9965d119133a5cb80938b829d28fa45777667a0c.tar.gz
gcc-9965d119133a5cb80938b829d28fa45777667a0c.tar.bz2
invoke.texi (-fdump-class-layout): Document.
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. From-SVN: r39455
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/cp/ChangeLog74
-rw-r--r--gcc/cp/class.c624
-rw-r--r--gcc/cp/cp-tree.h22
-rw-r--r--gcc/cp/decl2.c18
-rw-r--r--gcc/cp/init.c17
-rw-r--r--gcc/cp/search.c40
-rw-r--r--gcc/invoke.texi11
-rw-r--r--gcc/testsuite/ChangeLog19
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/primary2.C21
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/primary3.C34
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/primary4.C27
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/primary5.C36
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3.h181
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3a.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3b.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3c.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3d.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3e.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3f.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3g.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3h.C12
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3i.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable3j.C11
-rw-r--r--gcc/testsuite/g++.old-deja/g++.oliva/thunk1.C1
25 files changed, 1011 insertions, 233 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2ce8ac7..0046ae1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2001-02-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ * invoke.texi (-fdump-class-layout): Document.
+ (-fdump-translation-unit): Use `=' as filename separator.
+
2001-02-05 Mark Mitchell <mark@codesourcery.com>
* Makefile.in (s-mlib): Don't build multilibs if
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6011b76..04d64a0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,77 @@
+2001-02-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ 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 <mark@codesourcery.com>
* Makefile.in (g++spec.o): Adjust use of DRIVER_DEFINES.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 423fb32..376260b 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 9077671..d473006 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 2c3dbc7..fff3956 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 7cd6c57..e7d6293 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 c8cf526..1699c32 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 beec0e7..8052be1 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 60daf56..2cec5af 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,22 @@
+2001-02-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ * 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 <jakub@redhat.com>
* 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 0000000..795eb4d
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..ef245ef
--- /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 <nathan@codesourcery.com>
+
+// 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 <void *> (apc) != static_cast <void *> (b1pc))
+ return 1;
+ if (static_cast <void *> (apd) != static_cast <void *> (b1pd))
+ return 2;
+ if (static_cast <void *> (apd) != static_cast <void *> (&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 0000000..d18f242
--- /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 <nathan@codesourcery.com>
+
+// 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 <void *> (ap) != static_cast <void *> (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 0000000..422e66e
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..327d346
--- /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 <nathan@codesourcery.com>
+
+// Check constructor vtables work. This is included from numerous test
+// files, which set the #defines necessary to specify the heirarchy.
+
+#include <typeinfo>
+#include <stdio.h>
+
+// XXX. vcall offsets are still broken, remove this define to re-enable
+// testing when fixed.
+#define NO_VCALL_TEST
+
+int fail;
+
+template <typename BASE, typename DERIVED>
+int Test (DERIVED *d, int expect)
+{
+ BASE *b = static_cast <BASE *> (d);
+ void *full_b = dynamic_cast <void *> (b);
+ void *full_d = dynamic_cast <void *> (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 <DERIVED *> (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 <void *> (b));
+
+ int res = b->Foo (static_cast <void *> (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 <typename T>
+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 <A> (this, 1);
+}
+A::~A ()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 1);
+}
+
+B1::B1()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 2);
+ Test <B1> (this, 2);
+}
+B1::~B1()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 2);
+ Test <B1> (this, 2);
+}
+B2::B2()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 3);
+ Test <B2> (this, 3);
+}
+B2::~B2()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 3);
+ Test <B2> (this, 3);
+}
+C::C()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 4);
+ Test <C> (this, 4);
+}
+C::~C()
+{
+ fprintf (stderr, "%s\n", __PRETTY_FUNCTION__);
+ Test <A> (this, 4);
+ Test <C> (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 0000000..99d3d0b
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..4d4bd99
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..2863ca5
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..a3a2cbc
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..a1c8a9d
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..7bcf40c
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..1ad70bc
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..074bda4
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..d6fc3a3
--- /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 <nathan@codesourcery.com>
+
+// 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 0000000..1af5225
--- /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 <nathan@codesourcery.com>
+
+// 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 5407e9e..225a1f9 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 <d92-foh@nada.kth.se>
// Special g++ Options: -fvtable-thunks
-// execution test - XFAIL *-*-*
#include <cstdlib>