Commit 9965d119 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 36ca672c
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
......
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.
......
......@@ -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));
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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);
......
......@@ -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. */
......
......@@ -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
......
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.
......
// 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;
}
// 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;
}
// 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;
}
// 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;
}
// 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;
}
// 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"
// 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"
// 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"
// 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"
// 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"
// 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"
// 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"
// 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"
// 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"
// 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"
......@@ -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>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment