Commit c35cce41 by Mark Mitchell Committed by Mark Mitchell

Correct many new ABI issues regarding vbase and vcall offset layout.

	Correct many new ABI issues regarding vbase and vcall offset
	layout.
	* cp-tree.h (BINFO_VTABLE): Document.
	(struct lang_type): Tweak formatting.
	(BINFO_PRIMARY_BINFO): Add to documentation.
	(CLASSTYPE_VSIZE): Fix typo in comment.
	(CLASSTYPE_VBASECLASSES): Update documentation.
	(BINFO_VBASE_MARKED): Remove.
	(SET_BINFO_VBASE_MARKED): Likewise.
	(CLEAR_BINFO_VBASE_MARKED): Likewise.
	(BINFO_FIELDS_MARKED): Remove.
	(SET_BINFO_FIELDS_MARKED): Likewise.
	(CLEAR_BINFO_FIELDS_MARKED): Likewise.
	(enum access_kind): New enumeration.
	(num_extra_vtbl_entries): Remove declaration.
	(size_extra_vtbl_entries): Likewise.
	(get_vtbl_decl_for_binfo): New function.
	(dfs_vbase_unmark): Remove declaration.
	(mark_primary_bases): Likewise.
	* class.c (SAME_FN): Remove.
	(struct vcall_offset_data_s): Move definition.
	(build_vbase_pointer): Use `build', not `build_binary_op', to
	access the vbase pointer under the new ABI.
	(build_vtable_entry_ref): Use get_vtbl_decl_for_binfo.
	(build_primary_vtable): Likewise.
	(dfs_mark_primary_bases): Move here from search.c.
	(mark_primary_bases): Likewise.
	(determine_primary_bases): Under the new ABI, don't make a base
	class a primary base just because we don't yet have any virtual
	functions.
	(layout_vtable_decl): Use get_vtbl_decl_for_binfo.
	(num_vfun_entries): Remove.
	(dfs_count_virtuals): Likewise.
	(num_extra_vtbl_entries): Likewise.
	(size_extra_vtbl_entries): Likewise.
	(layout_virtual_bases): Iterate in inheritance graph order under
	the new ABI.
	(finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to
	indicate that a vfield is present.
	(init_class_processing): Initialize access_public_node, etc., from
	ak_public, etc.
	(get_vtbl_decl_for_binfo): New function.
	(dump_class_hierarchy_r): Likewise.
	(dump_class_hierarchy): Use it.
	(finish_vtbls): Build the vtbls in inheritance graph order.
	(dfs_finish_vtbls): Adjust call to build_vtbl_initializer.
	(initialize_vtable): Use get_vtbl_decl_for_binfo.
	(accumulate_vtbl_inits): Add comments explaining why a pre-order
	walk is required.
	(dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location
	where the vptr points, even for primary vtables.
	(build_vtbl_initializer): Adjust handling of vbase and vcall
	offsets.
	(build_vcall_and_vbase_vtable_entries): New function.
	(dfs_build_vbase_offset_vtbl_entries): Remove.
	(build_vbase_offset_vtbl_entries): Reimplement.
	(dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that
	were already handled in a primary base class vtable.
	(build_vcall_offset_vtbl_entries): Adjust.
	(build_rtti_vtbl_entries): Adjust.
	* decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo.
	* init.c (expand_virtual_init): Simplify.
	* repo.c (repo_get_id): Use get_vtbl_decl_for_binfo.
	* rtti.c (create_pseudo_type_info): Adjust calculation of vptr.
	* search.c (BINFO_ACCESS): New macro.
	(SET_BINFO_ACCESS): Likewise.
	(dfs_access_in_type): Manipulate access_kinds, not access nodes.
	(access_in_type): Likewise.
	(dfs_accessible_p): Likewise.
	(protected_accessible_p): Likewise.
	(lookup_fnfields_1): Adjust documentation.
	(dfs_mark_primary_bases): Move to class.c
	(mark_primary_bases): Likewise.
	(dfs_vbase_unmark): Remove.
	(virtual_context): Use BINFO_FOR_VBASE.
	(dfs_get_vbase_types): Simplify.
	(dfs_build_inheritance_graph_order): New function.
	(get_vbase_types): Use it.
	* tree.c (debug_binfo): Use get_vtbl_decl_for_binfo.

	* tinfo.cc (get_vbase_offset): New function.
	(__vmi_class_type_info::do_find_public_src): Use it.
	(__vmi_class_type_info::do_dyncast): Likewise.
	(__vmi_class_type_info::do_upcast): Likewise.

From-SVN: r32905
parent f2d33f13
2000-04-04 Mark Mitchell <mark@codesourcery.com>
Correct many new ABI issues regarding vbase and vcall offset
layout.
* cp-tree.h (BINFO_VTABLE): Document.
(struct lang_type): Tweak formatting.
(BINFO_PRIMARY_BINFO): Add to documentation.
(CLASSTYPE_VSIZE): Fix typo in comment.
(CLASSTYPE_VBASECLASSES): Update documentation.
(BINFO_VBASE_MARKED): Remove.
(SET_BINFO_VBASE_MARKED): Likewise.
(CLEAR_BINFO_VBASE_MARKED): Likewise.
(BINFO_FIELDS_MARKED): Remove.
(SET_BINFO_FIELDS_MARKED): Likewise.
(CLEAR_BINFO_FIELDS_MARKED): Likewise.
(enum access_kind): New enumeration.
(num_extra_vtbl_entries): Remove declaration.
(size_extra_vtbl_entries): Likewise.
(get_vtbl_decl_for_binfo): New function.
(dfs_vbase_unmark): Remove declaration.
(mark_primary_bases): Likewise.
* class.c (SAME_FN): Remove.
(struct vcall_offset_data_s): Move definition.
(build_vbase_pointer): Use `build', not `build_binary_op', to
access the vbase pointer under the new ABI.
(build_vtable_entry_ref): Use get_vtbl_decl_for_binfo.
(build_primary_vtable): Likewise.
(dfs_mark_primary_bases): Move here from search.c.
(mark_primary_bases): Likewise.
(determine_primary_bases): Under the new ABI, don't make a base
class a primary base just because we don't yet have any virtual
functions.
(layout_vtable_decl): Use get_vtbl_decl_for_binfo.
(num_vfun_entries): Remove.
(dfs_count_virtuals): Likewise.
(num_extra_vtbl_entries): Likewise.
(size_extra_vtbl_entries): Likewise.
(layout_virtual_bases): Iterate in inheritance graph order under
the new ABI.
(finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to
indicate that a vfield is present.
(init_class_processing): Initialize access_public_node, etc., from
ak_public, etc.
(get_vtbl_decl_for_binfo): New function.
(dump_class_hierarchy_r): Likewise.
(dump_class_hierarchy): Use it.
(finish_vtbls): Build the vtbls in inheritance graph order.
(dfs_finish_vtbls): Adjust call to build_vtbl_initializer.
(initialize_vtable): Use get_vtbl_decl_for_binfo.
(accumulate_vtbl_inits): Add comments explaining why a pre-order
walk is required.
(dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location
where the vptr points, even for primary vtables.
(build_vtbl_initializer): Adjust handling of vbase and vcall
offsets.
(build_vcall_and_vbase_vtable_entries): New function.
(dfs_build_vbase_offset_vtbl_entries): Remove.
(build_vbase_offset_vtbl_entries): Reimplement.
(dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that
were already handled in a primary base class vtable.
(build_vcall_offset_vtbl_entries): Adjust.
(build_rtti_vtbl_entries): Adjust.
* decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo.
* init.c (expand_virtual_init): Simplify.
* repo.c (repo_get_id): Use get_vtbl_decl_for_binfo.
* rtti.c (create_pseudo_type_info): Adjust calculation of vptr.
* search.c (BINFO_ACCESS): New macro.
(SET_BINFO_ACCESS): Likewise.
(dfs_access_in_type): Manipulate access_kinds, not access nodes.
(access_in_type): Likewise.
(dfs_accessible_p): Likewise.
(protected_accessible_p): Likewise.
(lookup_fnfields_1): Adjust documentation.
(dfs_mark_primary_bases): Move to class.c
(mark_primary_bases): Likewise.
(dfs_vbase_unmark): Remove.
(virtual_context): Use BINFO_FOR_VBASE.
(dfs_get_vbase_types): Simplify.
(dfs_build_inheritance_graph_order): New function.
(get_vbase_types): Use it.
* tree.c (debug_binfo): Use get_vtbl_decl_for_binfo.
* tinfo.cc (get_vbase_offset): New function.
(__vmi_class_type_info::do_find_public_src): Use it.
(__vmi_class_type_info::do_dyncast): Likewise.
(__vmi_class_type_info::do_upcast): Likewise.
2000-04-03 Zack Weinberg <zack@wolery.cumb.org>
* lang-specs.h: Pass -fno-show-column to the preprocessor.
......
......@@ -38,12 +38,6 @@ Boston, MA 02111-1307, USA. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
/* This is how we tell when two virtual member functions are really the
same. */
#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
extern void set_class_shadows PARAMS ((tree));
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
......@@ -68,6 +62,22 @@ typedef struct class_stack_node {
splay_tree names_used;
}* class_stack_node_t;
typedef struct vcall_offset_data_s
{
/* The binfo for the most-derived type. */
tree derived;
/* The binfo for the virtual base for which we're building
initializers. */
tree vbase;
/* The vcall offset initializers built up so far. */
tree inits;
/* The vtable index of the next vcall or vbase offset. */
tree index;
/* Nonzero if we are building the initializer for the primary
vtable. */
int primary_p;
} vcall_offset_data;
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
static int current_class_stack_size;
......@@ -108,7 +118,7 @@ static tree fixed_type_or_null PARAMS ((tree, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, tree));
static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
static tree build_vtbl_initializer PARAMS ((tree, tree));
static tree build_vtbl_initializer PARAMS ((tree, tree, int *));
static int count_fields PARAMS ((tree));
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
......@@ -135,19 +145,17 @@ static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_virtual_bases PARAMS ((tree, varray_type *));
static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static tree dfs_build_vbase_offset_vtbl_entries PARAMS ((tree, void *));
static tree build_vbase_offset_vtbl_entries PARAMS ((tree, tree));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
static tree dfs_count_virtuals PARAMS ((tree, void *));
static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static void layout_vtable_decl PARAMS ((tree, int));
static int num_vfun_entries PARAMS ((tree));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
static tree dfs_find_base PARAMS ((tree, void *));
static int make_new_vtable PARAMS ((tree, tree));
extern void dump_class_hierarchy PARAMS ((tree, int));
static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
extern void dump_class_hierarchy PARAMS ((tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
......@@ -162,6 +170,10 @@ static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vcall_offset_data *));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
static void mark_primary_bases PARAMS ((tree));
/* Variables shared between class.c and call.c. */
......@@ -274,9 +286,10 @@ build_vbase_pointer (exp, type)
/* Find the virtual function table pointer. */
vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
/* Compute the location where the offset will lie. */
vbase_ptr = build_binary_op (PLUS_EXPR,
vbase_ptr,
BINFO_VPTR_FIELD (vbase));
vbase_ptr = build (PLUS_EXPR,
TREE_TYPE (vbase_ptr),
vbase_ptr,
BINFO_VPTR_FIELD (vbase));
vbase_ptr = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
vbase_ptr);
......@@ -462,7 +475,7 @@ build_vtable_entry_ref (basetype, vtbl, idx)
static char asm_stmt[] = ".vtable_entry %c0, %c1";
tree s, i, i2;
s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
s = build_unary_op (ADDR_EXPR, get_vtbl_decl_for_binfo (basetype), 0);
s = build_tree_list (build_string (1, "s"), s);
i = build_array_ref (vtbl, idx);
......@@ -533,7 +546,23 @@ build_vtbl_ref (instance, idx)
&& (TREE_CODE (instance) == RESULT_DECL
|| TREE_CODE (instance) == PARM_DECL
|| TREE_CODE (instance) == VAR_DECL))
vtbl = TYPE_BINFO_VTABLE (basetype);
{
vtbl = TYPE_BINFO_VTABLE (basetype);
/* Knowing the dynamic type of INSTANCE we can easily obtain
the correct vtable entry. In the new ABI, we resolve
this back to be in terms of the primary vtable. */
if (TREE_CODE (vtbl) == PLUS_EXPR)
{
idx = fold (build (PLUS_EXPR,
TREE_TYPE (idx),
idx,
build (EXACT_DIV_EXPR,
TREE_TYPE (idx),
TREE_OPERAND (vtbl, 1),
TYPE_SIZE_UNIT (vtable_entry_type))));
vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
}
}
else
vtbl = build_vfield_ref (instance, basetype);
}
......@@ -733,10 +762,9 @@ build_primary_vtable (binfo, type)
return 0;
virtuals = copy_list (BINFO_VIRTUALS (binfo));
TREE_TYPE (decl) = TREE_TYPE (BINFO_VTABLE (binfo));
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
DECL_SIZE_UNIT (decl)
= TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo)));
TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo));
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
}
else
{
......@@ -1623,6 +1651,97 @@ 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. */
static tree
dfs_mark_primary_bases (binfo, data)
tree binfo;
void *data;
{
int i;
tree base_binfo;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
return NULL_TREE;
i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
base_binfo = BINFO_BASETYPE (binfo, i);
if (!TREE_VIA_VIRTUAL (base_binfo))
/* Non-virtual base classes are easy. */
BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
else
{
tree shared_binfo;
shared_binfo
= BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
/* If this virtual base is not already primary somewhere else in
the hiearchy, then we'll be using this copy. */
if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
{
BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
}
}
return NULL_TREE;
}
/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
dominated by BINFO 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 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);
if (!TREE_VIA_VIRTUAL (vbases))
continue;
vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), type);
if (BINFO_VBASE_PRIMARY_P (vbase))
/* This virtual base was already included in the hierarchy, so
there's nothing to do here. */
continue;
/* Temporarily pretend that VBASE is primary so that its bases
will be walked; this is the real copy of VBASE. */
BINFO_PRIMARY_MARKED_P (vbase) = 1;
/* Now, walk its bases. */
dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
dfs_skip_nonprimary_vbases_unmarkedp, type);
/* VBASE wasn't really primary. */
BINFO_PRIMARY_MARKED_P (vbase) = 0;
}
}
/* Make the Ith baseclass of T its primary base. */
static void
......@@ -1696,7 +1815,7 @@ determine_primary_base (t, vfuns_p)
VF_BASETYPE_VALUE (vfields),
CLASSTYPE_VFIELDS (t));
if (*vfuns_p == 0)
if (!flag_new_abi && *vfuns_p == 0)
set_primary_base (t, i, vfuns_p);
}
}
......@@ -2184,6 +2303,7 @@ layout_vtable_decl (binfo, n)
{
tree itype;
tree atype;
tree vtable;
itype = size_int (n);
atype = build_cplus_array_type (vtable_entry_type,
......@@ -2191,12 +2311,11 @@ layout_vtable_decl (binfo, n)
layout_type (atype);
/* We may have to grow the vtable. */
if (!same_type_p (TREE_TYPE (BINFO_VTABLE (binfo)), atype))
vtable = get_vtbl_decl_for_binfo (binfo);
if (!same_type_p (TREE_TYPE (vtable), atype))
{
tree vtable = BINFO_VTABLE (binfo);
TREE_TYPE (vtable) = atype;
DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = 0;
DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = NULL_TREE;
layout_decl (vtable, 0);
/* At one time the vtable info was grabbed 2 words at a time. This
......@@ -2206,104 +2325,6 @@ layout_vtable_decl (binfo, n)
}
}
/* Returns the number of virtual function table entries (excluding
RTTI information, vbase and vcall offests, etc.) in the vtable for
BINFO. */
static int
num_vfun_entries (binfo)
tree binfo;
{
return list_length (BINFO_VIRTUALS (binfo));
}
typedef struct vcall_offset_data_s
{
/* The binfo for the most-derived type. */
tree derived;
/* The binfo for the virtual base for which we're building
initializers. */
tree vbase;
/* The vcall offset initializers built up so far. */
tree inits;
/* The number of vcall offsets accumulated. */
int offsets;
} vcall_offset_data;
/* Called from num_extra_vtbl_entries via dfs_walk. */
static tree
dfs_count_virtuals (binfo, data)
tree binfo;
void *data;
{
/* Non-primary bases are not interesting; all of the virtual
function table entries have been overridden. */
if (!BINFO_PRIMARY_MARKED_P (binfo))
((vcall_offset_data *) data)->offsets += num_vfun_entries (binfo);
return NULL_TREE;
}
/* Returns the number of extra entries (at negative indices) required
for BINFO's vtable. */
tree
num_extra_vtbl_entries (binfo)
tree binfo;
{
tree type;
int entries;
type = BINFO_TYPE (binfo);
entries = 0;
/* There is an entry for the offset to each virtual base. */
if (vbase_offsets_in_vtable_p ())
entries += list_length (CLASSTYPE_VBASECLASSES (type));
/* If this is a virtual base, there are entries for each virtual
function defined in this class or its bases. */
if (vcall_offsets_in_vtable_p () && TREE_VIA_VIRTUAL (binfo))
{
vcall_offset_data vod;
vod.vbase = binfo;
vod.offsets = 0;
dfs_walk (binfo,
dfs_count_virtuals,
dfs_vcall_offset_queue_p,
&vod);
entries += vod.offsets;
}
/* When laying out COM-compatible classes, there are no RTTI
entries. */
if (CLASSTYPE_COM_INTERFACE (type))
;
/* When using vtable thunks, there are two RTTI entries: the "offset
to top" value and the RTTI entry itself. */
else if (flag_vtable_thunks)
entries += 2;
/* When not using vtable thunks there is only a single entry. */
else
entries += 1;
return size_int (entries);
}
/* Returns the offset (in bytes) from the beginning of BINFO's vtable
where the vptr should actually point. */
tree
size_extra_vtbl_entries (binfo)
tree binfo;
{
tree offset = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type),
num_extra_vtbl_entries (binfo));
return fold (offset);
}
/* True if we should override the given BASE_FNDECL with the given
FNDECL. */
......@@ -3989,7 +4010,7 @@ check_bases_and_members (t, empty_p)
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
accordingly. If a new vfield was created (because T doesn't have a
primary base class), then the newly created field is returned. It
is not added to the TYPE_FIELDS list; it is the callers
is not added to the TYPE_FIELDS list; it is the caller's
responsibility to do that. */
static tree
......@@ -4205,7 +4226,7 @@ layout_virtual_bases (t, base_offsets)
tree t;
varray_type *base_offsets;
{
tree vbase;
tree vbases;
unsigned HOST_WIDE_INT dsize;
unsigned HOST_WIDE_INT eoc;
......@@ -4225,53 +4246,70 @@ layout_virtual_bases (t, base_offsets)
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
if (!BINFO_VBASE_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. */
tree basetype;
unsigned int desired_align;
base that is not already a primary base class. Under the new
ABI, these are allocated according to a depth-first left-to-right
postorder traversal; in the new ABI, inheritance graph order is
used instead. */
for (vbases = (flag_new_abi
? TYPE_BINFO (t)
: CLASSTYPE_VBASECLASSES (t));
vbases;
vbases = TREE_CHAIN (vbases))
{
tree vbase;
if (!TREE_VIA_VIRTUAL (vbases))
continue;
if (flag_new_abi)
vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), t);
else
vbase = vbases;
if (!BINFO_VBASE_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. */
tree basetype;
unsigned int desired_align;
basetype = BINFO_TYPE (vbase);
basetype = BINFO_TYPE (vbase);
if (flag_new_abi)
desired_align = CLASSTYPE_ALIGN (basetype);
else
/* Under the old ABI, virtual bases were aligned as for the
if (flag_new_abi)
desired_align = CLASSTYPE_ALIGN (basetype);
else
/* Under the old ABI, virtual bases were aligned as for the
entire base object (including its virtual bases). That's
wasteful, in general. */
desired_align = TYPE_ALIGN (basetype);
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
/* Add padding so that we can put the virtual base class at an
appropriately aligned offset. */
dsize = CEIL (dsize, desired_align) * desired_align;
/* Under the new ABI, we try to squish empty virtual bases in
just like ordinary empty bases. */
if (flag_new_abi && is_empty_class (basetype))
layout_empty_base (vbase,
size_int (CEIL (dsize, BITS_PER_UNIT)),
*base_offsets);
else
{
/* And compute the offset of the virtual base. */
propagate_binfo_offsets (vbase,
ssize_int (CEIL (dsize, BITS_PER_UNIT)));
/* Every virtual baseclass takes a least a UNIT, so that
we can take it's address and get something different
for each base. */
dsize += MAX (BITS_PER_UNIT,
tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
}
desired_align = TYPE_ALIGN (basetype);
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
/* Add padding so that we can put the virtual base class at an
appropriately aligned offset. */
dsize = CEIL (dsize, desired_align) * desired_align;
/* Under the new ABI, we try to squish empty virtual bases in
just like ordinary empty bases. */
if (flag_new_abi && is_empty_class (basetype))
layout_empty_base (vbase,
size_int (CEIL (dsize, BITS_PER_UNIT)),
*base_offsets);
else
{
/* And compute the offset of the virtual base. */
propagate_binfo_offsets (vbase,
ssize_int (CEIL (dsize, BITS_PER_UNIT)));
/* Every virtual baseclass takes a least a UNIT, so that
we can take it's address and get something different
for each base. */
dsize += MAX (BITS_PER_UNIT,
tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
}
/* Keep track of the offsets assigned to this virtual base. */
record_base_offsets (vbase, base_offsets);
}
/* Keep track of the offsets assigned to this virtual base. */
record_base_offsets (vbase, base_offsets);
}
}
/* Make sure that all of the CLASSTYPE_VBASECLASSES have their
BINFO_OFFSET set correctly. Those we just allocated certainly
......@@ -4288,10 +4326,10 @@ layout_virtual_bases (t, base_offsets)
in get_base_distance depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
dfs_walk (vbase, dfs_set_offset_for_unshared_vbases, NULL, t);
for (vbases = CLASSTYPE_VBASECLASSES (t);
vbases;
vbases = TREE_CHAIN (vbases))
dfs_walk (vbases, dfs_set_offset_for_unshared_vbases, NULL, t);
/* If we had empty base classes that protruded beyond the end of the
class, we didn't update DSIZE above; we were hoping to overlay
......@@ -4310,11 +4348,11 @@ layout_virtual_bases (t, base_offsets)
/* Check for ambiguous virtual bases. */
if (extra_warnings)
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
for (vbases = CLASSTYPE_VBASECLASSES (t);
vbases;
vbases = TREE_CHAIN (vbases))
{
tree basetype = BINFO_TYPE (vbase);
tree basetype = BINFO_TYPE (vbases);
if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
......@@ -4572,7 +4610,7 @@ layout_class_type (t, empty_p, vfuns_p,
/* Clean up. */
VARRAY_FREE (v);
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
......@@ -4791,7 +4829,7 @@ finish_struct_1 (t)
the base types we marked. */
finish_vtbls (t);
if (CLASSTYPE_VSIZE (t) != 0)
if (TYPE_VFIELD (t))
{
/* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
......@@ -5030,13 +5068,13 @@ init_class_processing ()
* sizeof (struct class_stack_node));
access_default_node = build_int_2 (0, 0);
access_public_node = build_int_2 (1, 0);
access_protected_node = build_int_2 (2, 0);
access_private_node = build_int_2 (3, 0);
access_public_node = build_int_2 (ak_public, 0);
access_protected_node = build_int_2 (ak_protected, 0);
access_private_node = build_int_2 (ak_private, 0);
access_default_virtual_node = build_int_2 (4, 0);
access_public_virtual_node = build_int_2 (5, 0);
access_protected_virtual_node = build_int_2 (6, 0);
access_private_virtual_node = build_int_2 (7, 0);
access_public_virtual_node = build_int_2 (4 | ak_public, 0);
access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
access_private_virtual_node = build_int_2 (4 | ak_private, 0);
}
/* Set current scope to NAME. CODE tells us if this is a
......@@ -6047,12 +6085,36 @@ note_name_declared_in_class (name, decl)
}
}
/* Dump the offsets of all the bases rooted at BINFO to stderr.
INDENT should be zero when called from the top level; it is
incremented recursively. */
/* Returns the VAR_DECL for the complete vtable associated with
BINFO. (Under the new ABI, secondary vtables are merged with
primary vtables; this function will return the VAR_DECL for the
primary vtable.) */
void
dump_class_hierarchy (binfo, indent)
tree
get_vtbl_decl_for_binfo (binfo)
tree binfo;
{
tree decl;
decl = BINFO_VTABLE (binfo);
if (decl && TREE_CODE (decl) == PLUS_EXPR)
{
my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
2000403);
decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
}
if (decl)
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
return decl;
}
/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
dominated by T) to stderr. INDENT should be zero when called from
the top level; it is incremented recursively. */
static void
dump_class_hierarchy_r (t, binfo, indent)
tree t;
tree binfo;
int indent;
{
......@@ -6063,11 +6125,31 @@ dump_class_hierarchy (binfo, indent)
type_as_string (binfo, TS_PLAIN));
fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
fprintf (stderr, " %s\n",
BINFO_PRIMARY_MARKED_P (binfo) ? "primary" : "");
if (TREE_VIA_VIRTUAL (binfo))
fprintf (stderr, " virtual");
if (BINFO_PRIMARY_MARKED_P (binfo)
|| (TREE_VIA_VIRTUAL (binfo)
&& BINFO_VBASE_PRIMARY_P (BINFO_FOR_VBASE (BINFO_TYPE (binfo),
t))))
fprintf (stderr, " primary");
fprintf (stderr, "\n");
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
dump_class_hierarchy (BINFO_BASETYPE (binfo, i), indent + 2);
dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
}
/* Dump the BINFO hierarchy for T. */
void
dump_class_hierarchy (t)
tree t;
{
tree vbase;
dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
fprintf (stderr, "virtual bases\n");
for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; vbase = TREE_CHAIN (vbase))
dump_class_hierarchy_r (t, vbase, 0);
}
/* Virtual function table initialization. */
......@@ -6087,14 +6169,18 @@ finish_vtbls (t)
vtables in one contiguous vtable. The primary vtable is
first, followed by the non-virtual secondary vtables in
inheritance graph order. */
list = build_tree_list (t, NULL_TREE);
list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
TREE_TYPE (list) = t;
accumulate_vtbl_inits (TYPE_BINFO (t), list);
/* Then come the virtual bases, also in inheritance graph
order. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
accumulate_vtbl_inits (vbase, list);
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
if (!TREE_VIA_VIRTUAL (vbase))
continue;
accumulate_vtbl_inits (BINFO_FOR_VBASE (BINFO_TYPE (vbase), t),
list);
}
if (TYPE_BINFO_VTABLE (t))
initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
......@@ -6121,7 +6207,7 @@ dfs_finish_vtbls (binfo, data)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
build_vtbl_initializer (binfo, t));
build_vtbl_initializer (binfo, t, NULL));
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
SET_BINFO_MARKED (binfo);
......@@ -6140,7 +6226,7 @@ initialize_vtable (binfo, inits)
tree decl;
layout_vtable_decl (binfo, list_length (inits));
decl = BINFO_VTABLE (binfo);
decl = get_vtbl_decl_for_binfo (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
......@@ -6156,10 +6242,12 @@ accumulate_vtbl_inits (binfo, inits)
tree binfo;
tree inits;
{
/* Walk the BINFO and its bases. */
/* Walk the BINFO and its bases. We walk in preorder so that as we
initialize each vtable we can figure out at what offset the
secondary vtable lies from the primary vtable. */
dfs_walk_real (binfo,
dfs_accumulate_vtbl_inits,
NULL,
NULL,
dfs_skip_vbases,
inits);
}
......@@ -6177,33 +6265,37 @@ dfs_accumulate_vtbl_inits (binfo, data)
tree t;
l = (tree) data;
t = TREE_PURPOSE (l);
t = TREE_TYPE (l);
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo, t))
{
/* If this is a secondary vtable, record its location. */
if (binfo != TYPE_BINFO (t))
{
tree vtbl;
vtbl = TYPE_BINFO_VTABLE (t);
vtbl = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (vtbl)),
vtbl);
BINFO_VTABLE (binfo)
= build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
size_binop (MULT_EXPR,
TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
size_int (list_length (TREE_VALUE (l)))));
}
tree inits;
tree vtbl;
tree index;
int non_fn_entries;
/* Compute the initializer for this vtable. */
inits = build_vtbl_initializer (binfo, t, &non_fn_entries);
/* Set BINFO_VTABLE to the address where the VPTR should point. */
vtbl = TREE_PURPOSE (l);
vtbl = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (vtbl)),
vtbl);
index = size_binop (PLUS_EXPR,
size_int (non_fn_entries),
size_int (list_length (TREE_VALUE (l))));
BINFO_VTABLE (binfo)
= build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
size_binop (MULT_EXPR,
TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
index));
/* Add the initializers for this vtable to the initializers for
the other vtables we've already got. */
TREE_VALUE (l)
= chainon (TREE_VALUE (l),
build_vtbl_initializer (binfo, t));
TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
}
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
......@@ -6214,29 +6306,48 @@ dfs_accumulate_vtbl_inits (binfo, data)
/* Construct the initializer for BINFOs virtual function table. BINFO
is part of the hierarchy dominated by T. The value returned is a
TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
DECL_INITIAL for a vtable. */
DECL_INITIAL for a vtable. If NON_FN_ENTRIES_P is not NULL,
*NON_FN_ENTRIES_P is set to the number of non-function entries in
the vtable. */
static tree
build_vtbl_initializer (binfo, t)
build_vtbl_initializer (binfo, t, non_fn_entries_p)
tree binfo;
tree t;
int *non_fn_entries_p;
{
tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE;
tree vfun_inits;
tree vbase;
vcall_offset_data vod;
/* Add entries to the vtable that indicate how to adjust the this
pointer when calling a virtual function in this class. */
inits = build_vcall_offset_vtbl_entries (binfo, t);
/* Add entries to the vtable for offsets to our virtual bases. */
inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
inits);
/* Initialize those parts of VOD that matter. */
vod.derived = t;
vod.inits = NULL_TREE;
vod.primary_p = (binfo == TYPE_BINFO (t));
/* The first vbase or vcall offset is at index -3 in the vtable. */
vod.index = build_int_2 (-3, -1);
/* Add the vcall and vbase offset entries. */
build_vcall_and_vbase_vtbl_entries (binfo, &vod);
inits = vod.inits;
/* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
CLEAR_BINFO_VTABLE_PATH_MARKED (vbase);
/* Add entries to the vtable for RTTI. */
inits = chainon (build_rtti_vtbl_entries (binfo, t), inits);
inits = chainon (inits, build_rtti_vtbl_entries (binfo, t));
if (non_fn_entries_p)
*non_fn_entries_p = list_length (inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
vfun_inits = NULL_TREE;
while (v)
{
tree delta;
......@@ -6266,118 +6377,133 @@ build_vtbl_initializer (binfo, t)
/* Enter it in the vtable. */
init = build_vtable_entry (delta, vcall_index, pfn);
/* And add it to the chain of initializers. */
inits = tree_cons (NULL_TREE, init, inits);
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
/* Keep going. */
v = TREE_CHAIN (v);
}
/* The initializers were built up in reverse order; straighten them
out now. */
return nreverse (inits);
/* The initializers for virtual functions were built up in reverse
order; straighten them out now. */
vfun_inits = nreverse (vfun_inits);
/* The complete initializer is the INITS, followed by the
VFUN_INITS. */
return chainon (inits, vfun_inits);
}
/* Called from build_vbase_offset_vtbl_entries via dfs_walk. */
/* Sets vod->inits to be the initializers for the vbase and vcall
offsets in BINFO, which is in the hierarchy dominated by T. */
static tree
dfs_build_vbase_offset_vtbl_entries (binfo, data)
static void
build_vcall_and_vbase_vtbl_entries (binfo, vod)
tree binfo;
void *data;
vcall_offset_data *vod;
{
tree list = (tree) data;
if (TREE_TYPE (list) == binfo)
/* The TREE_TYPE of LIST is the base class from which we started
walking. If that BINFO is virtual it's not a virtual baseclass
of itself. */
;
else if (TREE_VIA_VIRTUAL (binfo))
{
tree init;
tree vbase;
/* Remember the index to the vbase offset for this virtual
base. */
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list))
BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0);
else
{
BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
BINFO_VPTR_FIELD (vbase)
= fold (build (MINUS_EXPR, integer_type_node,
BINFO_VPTR_FIELD (vbase), integer_one_node));
}
/* And record the offset at which this virtual base lies in the
vtable. */
init = BINFO_OFFSET (binfo);
TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase),
init, TREE_VALUE (list));
}
tree b;
tree inits;
SET_BINFO_VTABLE_PATH_MARKED (binfo);
return NULL_TREE;
/* If this is a derived class, we must first create entries
corresponding to the base class. These entries must go closer to
the vptr, so we save them up and add them to the end of the list
later. */
inits = vod->inits;
vod->inits = NULL_TREE;
b = BINFO_PRIMARY_BINFO (binfo);
if (b)
build_vcall_and_vbase_vtbl_entries (b, vod);
/* Add the vbase entries for this base. */
build_vbase_offset_vtbl_entries (binfo, vod);
/* Add the vcall entries for this base. */
build_vcall_offset_vtbl_entries (binfo, vod);
vod->inits = chainon (vod->inits, inits);
}
/* Returns the initializers for the vbase offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T), in
reverse order. */
reverse order. VBASE_OFFSET_INDEX gives the vtable index
where the next vbase offset will go. */
static tree
build_vbase_offset_vtbl_entries (binfo, t)
static void
build_vbase_offset_vtbl_entries (binfo, vod)
tree binfo;
tree t;
vcall_offset_data *vod;
{
tree inits;
tree init;
tree list;
tree vbase;
tree t;
/* Under the old ABI, pointers to virtual bases are stored in each
object. */
if (!vbase_offsets_in_vtable_p ())
return NULL_TREE;
return;
/* If there are no virtual baseclasses, then there is nothing to
do. */
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
return NULL_TREE;
return;
inits = NULL_TREE;
t = vod->derived;
/* The offsets are allocated in the reverse order of a
depth-first left-to-right traversal of the hierarchy. We use
BINFO_VTABLE_PATH_MARKED because we are ourselves during a
dfs_walk, and so BINFO_MARKED is already in use. */
list = build_tree_list (t, NULL_TREE);
TREE_TYPE (list) = binfo;
dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries,
unmarked_vtable_pathp,
list);
dfs_walk (binfo,
dfs_vtable_path_unmark,
marked_vtable_pathp,
list);
inits = nreverse (TREE_VALUE (list));
/* We've now got offsets in the right order. However, the offsets
we've stored are offsets from the beginning of the complete
object, and we need offsets from this BINFO. */
for (init = inits; init; init = TREE_CHAIN (init))
{
/* The dfs_build_vbase_offset_vtbl_entries routine uses the
TREE_PURPOSE to scribble in. But, we need to clear it now so
that the values are not perceived as labeled initializers. */
TREE_PURPOSE (init) = NULL_TREE;
TREE_VALUE (init)
= fold (build1 (NOP_EXPR, vtable_entry_type,
size_diffop (TREE_VALUE (init),
BINFO_OFFSET (binfo))));
}
/* Go through the virtual bases, adding the offsets. */
for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
vbase;
vbase = TREE_CHAIN (vbase))
{
tree b;
tree delta;
if (!TREE_VIA_VIRTUAL (vbase))
continue;
return inits;
/* Find the instance of this virtual base in the complete
object. */
b = BINFO_FOR_VBASE (BINFO_TYPE (vbase), t);
/* If we've already got an offset for this virtual base, we
don't need another one. */
if (BINFO_VTABLE_PATH_MARKED (b))
continue;
SET_BINFO_VTABLE_PATH_MARKED (b);
/* Figure out where we can find this vbase offset. */
delta = size_binop (MULT_EXPR,
convert (ssizetype, vod->index),
convert (ssizetype,
TYPE_SIZE_UNIT (vtable_entry_type)));
if (vod->primary_p)
BINFO_VPTR_FIELD (b) = delta;
if (binfo != TYPE_BINFO (t))
{
tree orig_vbase;
/* Find the instance of this virtual base in the type of BINFO. */
orig_vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbase),
BINFO_TYPE (binfo));
/* The vbase offset had better be the same. */
if (!tree_int_cst_equal (delta,
BINFO_VPTR_FIELD (orig_vbase)))
my_friendly_abort (20000403);
}
/* The next vbase will come at a more negative offset. */
vod->index = fold (build (MINUS_EXPR, integer_type_node,
vod->index, integer_one_node));
/* The initializer is the delta from BINFO to this virtual base.
The vbase offsets go in reverse inheritance-graph order, and
we are walking in inheritance graph order so these end up in
the right order. */
delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
vod->inits = tree_cons (NULL_TREE,
fold (build1 (NOP_EXPR,
vtable_entry_type,
delta)),
vod->inits);
}
}
/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
......@@ -6402,20 +6528,22 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
vcall_offset_data* vod;
tree virtuals;
tree binfo_inits;
/* Primary bases are not interesting; all of the virtual
function table entries have been overridden. */
if (BINFO_PRIMARY_MARKED_P (binfo))
return NULL_TREE;
tree b;
int i;
vod = (vcall_offset_data *) data;
binfo_inits = NULL_TREE;
/* Skip virtuals that we have already handled in a primary base
class. */
virtuals = BINFO_VIRTUALS (binfo);
b = BINFO_PRIMARY_BINFO (binfo);
if (b)
for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
virtuals = TREE_CHAIN (virtuals);
/* We chain the offsets on in reverse order. That's correct --
build_vtbl_initializer will straighten them out. */
for (virtuals = BINFO_VIRTUALS (binfo);
virtuals;
virtuals = TREE_CHAIN (virtuals))
/* Make entries for the rest of the virtuals. */
while (virtuals)
{
/* Figure out what function we're looking at. */
tree fn = TREE_VALUE (virtuals);
......@@ -6430,34 +6558,48 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
size_diffop (BINFO_OFFSET (base_binfo),
BINFO_OFFSET (vod->vbase)))),
binfo_inits);
vod->index = fold (build (MINUS_EXPR, integer_type_node,
vod->index, integer_one_node));
virtuals = TREE_CHAIN (virtuals);
}
/* Now add the initializers we've just created to the list that will
be returned to our caller. */
vod->inits = chainon (vod->inits, binfo_inits);
/* The offests are built up in reverse order, so we straighten them
here. We simultaneously add them to VOD->INITS; we're walking
the bases in inheritance graph order, and the initializers are
supposed to appear in reverse inheritance order, so that's
correct. */
while (binfo_inits)
{
tree next;
next = TREE_CHAIN (binfo_inits);
TREE_CHAIN (binfo_inits) = vod->inits;
vod->inits = binfo_inits;
binfo_inits = next;
}
return NULL_TREE;
}
/* Returns the initializers for the vcall offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T), in
reverse order. */
/* Adds the initializers for the vcall offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T) to
VOD->INITS. */
static tree
build_vcall_offset_vtbl_entries (binfo, t)
static void
build_vcall_offset_vtbl_entries (binfo, vod)
tree binfo;
tree t;
vcall_offset_data *vod;
{
vcall_offset_data vod;
tree inits;
/* Under the old ABI, the adjustments to the `this' pointer were made
elsewhere. */
if (!vcall_offsets_in_vtable_p ())
return NULL_TREE;
return;
/* We only need these entries if this base is a virtual base. */
if (!TREE_VIA_VIRTUAL (binfo))
return NULL_TREE;
return;
/* We need a vcall offset for each of the virtual functions in this
vtable. For example:
......@@ -6481,15 +6623,15 @@ build_vcall_offset_vtbl_entries (binfo, t)
in our non-virtual bases vtables. For each base, the entries
appear in the same order as in the base; but the bases themselves
appear in reverse depth-first, left-to-right order. */
vod.derived = t;
vod.vbase = binfo;
vod.inits = NULL_TREE;
dfs_walk (binfo,
dfs_build_vcall_offset_vtbl_entries,
dfs_vcall_offset_queue_p,
&vod);
return vod.inits;
vod->vbase = binfo;
inits = vod->inits;
vod->inits = NULL_TREE;
dfs_walk_real (binfo,
dfs_build_vcall_offset_vtbl_entries,
NULL,
dfs_vcall_offset_queue_p,
vod);
vod->inits = chainon (vod->inits, inits);
}
/* Return vtbl initializers for the RTTI entries coresponding to the
......@@ -6503,10 +6645,10 @@ build_rtti_vtbl_entries (binfo, t)
{
tree b;
tree basetype;
tree inits;
tree offset;
tree decl;
tree init;
tree inits;
basetype = BINFO_TYPE (binfo);
inits = NULL_TREE;
......@@ -6519,19 +6661,15 @@ build_rtti_vtbl_entries (binfo, t)
primary base, and then add the offset in the vtbl to that value. */
b = binfo;
while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
b = BINFO_BASETYPE (b,
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (b)));
offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
/* Add the offset-to-top entry. */
if (flag_vtable_thunks)
{
/* Convert the offset to look like a function pointer, so that
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
inits = tree_cons (NULL_TREE, init, inits);
tree primary_base;
primary_base = BINFO_PRIMARY_BINFO (b);
if (!BINFO_PRIMARY_MARKED_P (primary_base))
break;
b = primary_base;
}
offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
/* The second entry is, in the case of the new ABI, the address of
the typeinfo object, or, in the case of the old ABI, a function
......@@ -6561,10 +6699,19 @@ build_rtti_vtbl_entries (binfo, t)
TREE_CONSTANT (init) = 1;
init = build_vtable_entry (offset, integer_zero_node, init);
}
/* Hook the RTTI declaration onto the list. */
inits = tree_cons (NULL_TREE, init, inits);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. */
if (flag_vtable_thunks)
{
/* Convert the offset to look like a function pointer, so that
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
inits = tree_cons (NULL_TREE, init, inits);
}
return inits;
}
......
......@@ -55,8 +55,6 @@ Boston, MA 02111-1307, USA. */
ICS_ELLIPSIS_FLAG (in _CONV)
STMT_IS_FULL_EXPR_P (in _STMT)
2: IDENTIFIER_OPNAME_P.
BINFO_VBASE_MARKED.
BINFO_FIELDS_MARKED.
TYPE_POLYMORHPIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
STMT_LINENO_FOR_FN_P (in _STMT)
......@@ -130,6 +128,13 @@ Boston, MA 02111-1307, USA. */
this function. (This binfo's BINFO_TYPE will always be the same
as the DECL_CLASS_CONTEXT for the function.)
BINFO_VTABLE
Sometimes this is a VAR_DECL. Under the new ABI, it is instead
an expression with POINTER_TYPE pointing that gives the value
to which the vptr should be initialized. Use get_vtbl_decl_for_binfo
to extract the VAR_DECL for the complete vtable; that macro works
in both ABIs.
DECL_ARGUMENTS
For a VAR_DECL this is DECL_ANON_UNION_ELEMS.
......@@ -1356,24 +1361,17 @@ struct lang_type
int vsize;
int vfield_parent;
union tree_node *vfields;
union tree_node *vbases;
union tree_node *tags;
union tree_node *search_slot;
union tree_node *size;
union tree_node *size_unit;
union tree_node *pure_virtuals;
union tree_node *friend_classes;
union tree_node *rtti;
union tree_node *methods;
union tree_node *template_info;
tree vfields;
tree vbases;
tree tags;
tree search_slot;
tree size;
tree size_unit;
tree pure_virtuals;
tree friend_classes;
tree rtti;
tree methods;
tree template_info;
tree befriending_classes;
};
......@@ -1538,21 +1536,29 @@ struct lang_type
#define CLASSTYPE_PRIMARY_BINFO(NODE) \
(BINFO_PRIMARY_BINFO (TYPE_BINFO (NODE)))
/* If non-NULL, this is the binfo for the primary base of BINFO. */
/* If non-NULL, this is the binfo for the primary base of BINFO. Note
that in a complex hierarchy the resulting BINFO may not actually
*be* 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. */
#define BINFO_PRIMARY_BINFO(NODE) \
(CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (NODE)) \
? BINFO_BASETYPE (NODE, \
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
: NULL_TREE)
/* The number of virtual functions present in this classes virtual
/* The number of virtual functions present in this class' virtual
function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* A chain of BINFOs for the direct and indirect virtual base classes
that this type uses in depth-first left-to-right order. These
BINFOs are distinct from those in the TYPE_BINFO hierarchy. So,
given:
that this type uses in a post-order depth-first left-to-right
order. (In other words, these bases appear in the order that they
should be initialized.)
These BINFOs are distinct from those in the TYPE_BINFO hierarchy.
So, given:
struct A {};
struct B : public A {};
......@@ -1683,9 +1689,7 @@ struct lang_type
We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
inheritance is indicated by the absence of the other two flags, not
by TREE_VIA_PRIVATE, which is unused.
The TREE_CHAIN is for scratch space in search.c. */
by TREE_VIA_PRIVATE, which is unused. */
/* Nonzero means marked by DFS or BFS search, including searches
by `get_binfo' and `get_base_distance'. */
......@@ -1695,18 +1699,6 @@ struct lang_type
#define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1))
#define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0))
/* Nonzero means marked in search through virtual inheritance hierarchy. */
#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
/* Modifier macros */
#define SET_BINFO_VBASE_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
#define CLEAR_BINFO_VBASE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
/* Nonzero means marked in search for members or member functions. */
#define BINFO_FIELDS_MARKED(NODE) \
(TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)):TREE_LANG_FLAG_2(NODE))
#define SET_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=1))
#define CLEAR_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=0))
/* Nonzero means that this class is on a path leading to a new vtable. */
#define BINFO_VTABLE_PATH_MARKED(NODE) \
(TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE))
......@@ -3081,6 +3073,17 @@ typedef enum tmpl_spec_kind {
tsk_expl_inst /* An explicit instantiation. */
} tmpl_spec_kind;
/* The various kinds of access. BINFO_ACCESS depends on these being
two bit quantities. The numerical values are important; they are
used to initialize RTTI data structures, so chaning them changes
the ABI. */
typedef enum access_kind {
ak_none = 0, /* Inaccessible. */
ak_public = 1, /* Accessible, as a `public' thing. */
ak_protected = 2, /* Accessible, as a `protected' thing. */
ak_private = 3 /* Accessible, as a `private' thing. */
} access_kind;
/* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */
extern int strict_prototype;
......@@ -3694,8 +3697,7 @@ extern void unreverse_member_declarations PARAMS ((tree));
extern void invalidate_class_lookup_cache PARAMS ((void));
extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
extern void note_name_declared_in_class PARAMS ((tree, tree));
extern tree num_extra_vtbl_entries PARAMS ((tree));
extern tree size_extra_vtbl_entries PARAMS ((tree));
extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
/* in cvt.c */
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
......@@ -4203,7 +4205,6 @@ extern tree dfs_walk_real PARAMS ((tree,
tree (*) (tree, void *),
void *));
extern tree dfs_unmark PARAMS ((tree, void *));
extern tree dfs_vbase_unmark PARAMS ((tree, void *));
extern tree dfs_vtable_path_unmark PARAMS ((tree, void *));
extern tree markedp PARAMS ((tree, void *));
extern tree unmarkedp PARAMS ((tree, void *));
......@@ -4214,7 +4215,6 @@ extern tree dfs_marked_real_bases_queue_p PARAMS ((tree, void *));
extern tree dfs_skip_vbases PARAMS ((tree, void *));
extern tree marked_vtable_pathp PARAMS ((tree, void *));
extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
extern void mark_primary_bases PARAMS ((tree));
extern tree convert_pointer_to_vbase PARAMS ((tree, tree));
extern tree find_vbase_instance PARAMS ((tree, tree));
......
......@@ -2544,7 +2544,7 @@ output_vtable_inherit (vars)
op[1] = const0_rtx;
else if (parent)
{
parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
}
else
......
......@@ -653,31 +653,23 @@ expand_virtual_init (binfo, decl)
tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo;
tree b;
/* Compute the location of the vtable. */
vtype = DECL_CONTEXT (TYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
b = binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo);
/* Figure out what vtable BINFO's vtable is based on, and mark it as
used. */
vtbl = get_vtbl_decl_for_binfo (b);
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
/* Now compute the address to use when initializing the vptr. */
vtbl = BINFO_VTABLE (b);
if (TREE_CODE (vtbl) == VAR_DECL)
{
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
}
else
/* Under the new ABI, secondary vtables are stored with the
primary vtable. So, the BINFO_VTABLE may be an expression for
computing the secondary vtable, rather than the secondary
vtable itself. */
my_friendly_assert (merge_primary_and_secondary_vtables_p (),
20000220);
/* Under the new ABI, we need to point into the middle of the
vtable. */
if (vbase_offsets_in_vtable_p ())
vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
size_extra_vtbl_entries (binfo));
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
/* Compute the location of the vtpr. */
decl = convert_pointer_to_real (vtype_binfo, decl);
......
......@@ -103,7 +103,7 @@ repo_get_id (t)
if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
my_friendly_abort (981113);
t = TYPE_BINFO_VTABLE (t);
t = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
if (t == NULL_TREE)
return t;
}
......
......@@ -1640,11 +1640,14 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
/* Under the new ABI, we need to point into the middle of the
vtable. */
if (vbase_offsets_in_vtable_p ())
if (flag_new_abi)
{
vtable_decl = build (PLUS_EXPR, TREE_TYPE (vtable_decl),
vtable_decl = build (PLUS_EXPR,
TREE_TYPE (vtable_decl),
vtable_decl,
size_extra_vtbl_entries (TYPE_BINFO (real_type)));
size_binop (MULT_EXPR,
size_int (2),
TYPE_SIZE_UNIT (vtable_entry_type)));
TREE_CONSTANT (vtable_decl) = 1;
}
......
......@@ -143,7 +143,7 @@ static int dependent_base_p PARAMS ((tree));
static tree dfs_accessible_queue_p PARAMS ((tree, void *));
static tree dfs_accessible_p PARAMS ((tree, void *));
static tree dfs_access_in_type PARAMS ((tree, void *));
static tree access_in_type PARAMS ((tree, tree));
static access_kind access_in_type PARAMS ((tree, tree));
static tree dfs_canonical_queue PARAMS ((tree, void *));
static tree dfs_assert_unmarked_p PARAMS ((tree, void *));
static void assert_canonical_unmarked PARAMS ((tree));
......@@ -152,7 +152,6 @@ static int friend_accessible_p PARAMS ((tree, tree, tree));
static void setup_class_bindings PARAMS ((tree, int));
static int template_self_reference_p PARAMS ((tree, tree));
static void fixup_all_virtual_upcast_offsets PARAMS ((tree, tree));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
static tree get_shared_vbase_if_not_primary PARAMS ((tree, void *));
static tree dfs_find_vbase_instance PARAMS ((tree, void *));
static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
......@@ -811,6 +810,18 @@ shared_unmarked_p (binfo, data)
return unmarkedp (binfo, data);
}
/* The accessibility routines use BINFO_ACCESS for scratch space
during the computation of the accssibility of some declaration. */
#define BINFO_ACCESS(NODE) \
((access_kind) ((TREE_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
/* Set the access associated with NODE to ACCESS. */
#define SET_BINFO_ACCESS(NODE, ACCESS) \
((TREE_LANG_FLAG_1 (NODE) = (ACCESS & 2) != 0), \
(TREE_LANG_FLAG_6 (NODE) = (ACCESS & 1) != 0))
/* Called from access_in_type via dfs_walk. Calculate the access to
DATA (which is really a DECL) in BINFO. */
......@@ -821,18 +832,18 @@ dfs_access_in_type (binfo, data)
{
tree decl = (tree) data;
tree type = BINFO_TYPE (binfo);
tree access = NULL_TREE;
access_kind access = ak_none;
if (context_for_name_lookup (decl) == type)
{
/* If we have desceneded to the scope of DECL, just note the
appropriate access. */
if (TREE_PRIVATE (decl))
access = access_private_node;
access = ak_private;
else if (TREE_PROTECTED (decl))
access = access_protected_node;
access = ak_protected;
else
access = access_public_node;
access = ak_public;
}
else
{
......@@ -842,9 +853,10 @@ dfs_access_in_type (binfo, data)
DECL_ACCESS. */
if (DECL_LANG_SPECIFIC (decl))
{
access = purpose_member (type, DECL_ACCESS (decl));
if (access)
access = TREE_VALUE (access);
tree decl_access = purpose_member (type, DECL_ACCESS (decl));
if (decl_access)
access = ((access_kind)
TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
}
if (!access)
......@@ -860,35 +872,36 @@ dfs_access_in_type (binfo, data)
for (i = 0; i < n_baselinks; ++i)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree base_access = TREE_CHAIN (canonical_binfo (base_binfo));
access_kind base_access
= BINFO_ACCESS (canonical_binfo (base_binfo));
if (!base_access || base_access == access_private_node)
if (base_access == ak_none || base_access == ak_private)
/* If it was not accessible in the base, or only
accessible as a private member, we can't access it
all. */
base_access = NULL_TREE;
base_access = ak_none;
else if (TREE_VIA_PROTECTED (base_binfo))
/* Public and protected members in the base are
protected here. */
base_access = access_protected_node;
base_access = ak_protected;
else if (!TREE_VIA_PUBLIC (base_binfo))
/* Public and protected members in the base are
private here. */
base_access = access_private_node;
base_access = ak_private;
/* See if the new access, via this base, gives more
access than our previous best access. */
if (base_access &&
(base_access == access_public_node
|| (base_access == access_protected_node
&& access != access_public_node)
|| (base_access == access_private_node
&& !access)))
if (base_access != ak_none
&& (base_access == ak_public
|| (base_access == ak_protected
&& access != ak_public)
|| (base_access == ak_private
&& access == ak_none)))
{
access = base_access;
/* If the new access is public, we can't do better. */
if (access == access_public_node)
if (access == ak_public)
break;
}
}
......@@ -896,7 +909,7 @@ dfs_access_in_type (binfo, data)
}
/* Note the access to DECL in TYPE. */
TREE_CHAIN (binfo) = access;
SET_BINFO_ACCESS (binfo, access);
/* Mark TYPE as visited so that if we reach it again we do not
duplicate our efforts here. */
......@@ -907,7 +920,7 @@ dfs_access_in_type (binfo, data)
/* Return the access to DECL in TYPE. */
static tree
static access_kind
access_in_type (type, decl)
tree type;
tree decl;
......@@ -929,7 +942,7 @@ access_in_type (type, decl)
dfs_walk (binfo, dfs_unmark, shared_marked_p, 0);
assert_canonical_unmarked (binfo);
return TREE_CHAIN (binfo);
return BINFO_ACCESS (binfo);
}
/* Called from dfs_accessible_p via dfs_walk. */
......@@ -960,17 +973,14 @@ dfs_accessible_p (binfo, data)
void *data;
{
int protected_ok = data != 0;
tree access;
access_kind access;
/* We marked the binfos while computing the access in each type.
So, we unmark as we go now. */
SET_BINFO_MARKED (binfo);
access = TREE_CHAIN (binfo);
if (access == access_public_node
|| (access == access_protected_node && protected_ok))
access = BINFO_ACCESS (binfo);
if (access == ak_public || (access == ak_protected && protected_ok))
return binfo;
else if (access && is_friend (BINFO_TYPE (binfo), current_scope ()))
else if (access != ak_none
&& is_friend (BINFO_TYPE (binfo), current_scope ()))
return binfo;
return NULL_TREE;
......@@ -985,7 +995,7 @@ protected_accessible_p (decl, derived, binfo)
tree derived;
tree binfo;
{
tree access;
access_kind access;
/* We're checking this clause from [class.access.base]
......@@ -1010,7 +1020,7 @@ protected_accessible_p (decl, derived, binfo)
access = access_in_type (derived, decl);
/* If m is inaccessible in DERIVED, then it's not a P. */
if (access == NULL_TREE)
if (access == ak_none)
return 0;
/* [class.protected]
......@@ -1752,12 +1762,11 @@ lookup_fnfields_1 (type, name)
If it ever returns a non-NULL value, that value is immediately
returned and the walk is terminated. At each node FN, is passed a
BINFO indicating the path from the curently visited base-class to
TYPE. The TREE_CHAINs of the BINFOs may be used for scratch space;
they are otherwise unused. Before each base-class is walked QFN is
called. If the value returned is non-zero, the base-class is
walked; otherwise it is not. If QFN is NULL, it is treated as a
function which always returns 1. Both FN and QFN are passed the
DATA whenever they are called. */
TYPE. Before each base-class is walked QFN is called. If the
value returned is non-zero, the base-class is walked; otherwise it
is not. If QFN is NULL, it is treated as a function which always
returns 1. Both FN and QFN are passed the DATA whenever they are
called. */
static tree
bfs_walk (binfo, fn, qfn, data)
......@@ -2194,97 +2203,6 @@ dfs_skip_nonprimary_vbases_markedp (binfo, data)
return markedp (binfo, NULL);
}
/* Called via dfs_walk from mark_primary_bases. */
static tree
dfs_mark_primary_bases (binfo, data)
tree binfo;
void *data;
{
int i;
tree base_binfo;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
return NULL_TREE;
i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
base_binfo = BINFO_BASETYPE (binfo, i);
if (!TREE_VIA_VIRTUAL (base_binfo))
/* Non-virtual base classes are easy. */
BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
else
{
tree shared_binfo;
shared_binfo
= BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
/* If this virtual base is not already primary somewhere else in
the hiearchy, then we'll be using this copy. */
if (!BINFO_VBASE_PRIMARY_P (shared_binfo)
&& !BINFO_VBASE_MARKED (shared_binfo))
{
BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
}
}
return NULL_TREE;
}
/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
dominated by BINFO that are primary bases. */
void
mark_primary_bases (type)
tree type;
{
tree vbase;
/* 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. Any that are not
already primary will need to be allocated in TYPE, and so we need
to mark their primary bases. */
for (vbase = CLASSTYPE_VBASECLASSES (type);
vbase;
vbase = TREE_CHAIN (vbase))
{
if (BINFO_VBASE_PRIMARY_P (vbase))
/* This virtual base was already included in the hierarchy, so
there's nothing to do here. */
continue;
/* Temporarily pretend that VBASE is primary so that its bases
will be walked; this is the real copy of VBASE. */
BINFO_PRIMARY_MARKED_P (vbase) = 1;
/* Now, walk its bases. */
dfs_walk (vbase, dfs_mark_primary_bases,
dfs_skip_nonprimary_vbases_unmarkedp, type);
/* VBASE wasn't really primary. */
BINFO_PRIMARY_MARKED_P (vbase) = 0;
/* And we don't want to allow it to *become* primary if it is a
base of some subsequent base class. */
SET_BINFO_VBASE_MARKED (vbase);
}
/* Clear the VBASE_MARKED bits we set above. */
for (vbase = CLASSTYPE_VBASECLASSES (type);
vbase;
vbase = TREE_CHAIN (vbase))
CLEAR_BINFO_VBASE_MARKED (vbase);
}
/* If BINFO is a non-primary virtual baseclass (in the hierarchy
dominated by TYPE), and no primary copy appears anywhere in the
hierarchy, return the shared copy. If a primary copy appears
......@@ -2577,17 +2495,6 @@ dfs_unmark (binfo, data)
return NULL_TREE;
}
/* Clear both BINFO_MARKED and BINFO_VBASE_MARKED. */
tree
dfs_vbase_unmark (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
{
CLEAR_BINFO_VBASE_MARKED (binfo);
return dfs_unmark (binfo, data);
}
/* Clear BINFO_VTABLE_PATH_MARKED. */
tree
......@@ -2781,7 +2688,7 @@ virtual_context (fndecl, t, vbase)
while (path)
{
if (TREE_VIA_VIRTUAL (path))
return binfo_member (BINFO_TYPE (path), CLASSTYPE_VBASECLASSES (t));
return BINFO_FOR_VBASE (BINFO_TYPE (path), t);
path = BINFO_INHERITANCE_CHAIN (path);
}
return 0;
......@@ -3072,7 +2979,7 @@ dfs_get_vbase_types (binfo, data)
{
tree type = (tree) data;
if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
if (TREE_VIA_VIRTUAL (binfo))
{
tree new_vbase = make_binfo (size_zero_node,
BINFO_TYPE (binfo),
......@@ -3083,24 +2990,50 @@ dfs_get_vbase_types (binfo, data)
BINFO_INHERITANCE_CHAIN (new_vbase) = TYPE_BINFO (type);
TREE_CHAIN (new_vbase) = CLASSTYPE_VBASECLASSES (type);
CLASSTYPE_VBASECLASSES (type) = new_vbase;
SET_BINFO_VBASE_MARKED (binfo);
}
SET_BINFO_MARKED (binfo);
return NULL_TREE;
}
/* Called via dfs_walk from mark_primary_bases. Builds the
inheritance graph order list of BINFOs. */
static tree
dfs_build_inheritance_graph_order (binfo, data)
tree binfo;
void *data;
{
tree *last_binfo = (tree *) data;
if (*last_binfo)
TREE_CHAIN (*last_binfo) = binfo;
*last_binfo = binfo;
SET_BINFO_MARKED (binfo);
return NULL_TREE;
}
/* Set CLASSTYPE_VBASECLASSES for TYPE. */
void
get_vbase_types (type)
tree type;
{
tree last_binfo;
CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
/* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
reverse it so that we get normal dfs ordering. */
CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
dfs_walk (TYPE_BINFO (type), dfs_vbase_unmark, markedp, 0);
dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
/* Thread the BINFOs in inheritance-graph order. */
last_binfo = NULL;
dfs_walk_real (TYPE_BINFO (type),
dfs_build_inheritance_graph_order,
NULL,
unmarkedp,
&last_binfo);
dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
}
/* Called from find_vbase_instance via dfs_walk. */
......
......@@ -590,6 +590,14 @@ adjust_pointer (const void *base, ptrdiff_t offset)
(reinterpret_cast <const char *> (base) + offset);
}
inline ptrdiff_t
get_vbase_offset (const void *object, ptrdiff_t offset)
{
const char *vtable = *reinterpret_cast <const char *const *> (object);
vtable += offset;
return *reinterpret_cast <const ptrdiff_t *> (vtable);
}
// some predicate functions for __class_type_info::sub_kind
inline bool contained_p (__class_type_info::sub_kind access_path)
{
......@@ -718,9 +726,7 @@ do_find_public_src (ptrdiff_t src2dst,
{
if (src2dst == -3)
continue; // Not a virtual base, so can't be here.
const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
offset = vtable[offset];
offset = get_vbase_offset (base, offset);
}
base = adjust_pointer <void> (base, offset);
......@@ -841,9 +847,7 @@ do_dyncast (ptrdiff_t src2dst,
if (base_list[i].is_virtual_p ())
{
base_access = sub_kind (base_access | contained_virtual_mask);
const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
offset = vtable[offset];
offset = get_vbase_offset (base, offset);
}
base = adjust_pointer <void> (base, offset);
......@@ -1041,10 +1045,7 @@ do_upcast (sub_kind access_path,
sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base)
{
const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
offset = vtable[offset];
}
offset = get_vbase_offset (base, offset);
}
if (base)
base = adjust_pointer <void> (base, offset);
......
......@@ -921,7 +921,7 @@ debug_binfo (elem)
debug_tree (BINFO_TYPE (elem));
if (BINFO_VTABLE (elem))
fprintf (stderr, "vtable decl \"%s\"\n",
IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem))));
IDENTIFIER_POINTER (DECL_NAME (get_vtbl_decl_for_binfo (elem))));
else
fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n");
......
// Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
struct R
{
virtual void r ();
};
struct S
{
virtual void f ();
};
struct T : virtual public S
{
virtual void g ();
};
struct U : public R, virtual public T
{
virtual void h ();
};
struct V : public R, virtual public S, virtual public T
{
virtual void v ();
};
struct U1
{
R r;
T t;
};
int main ()
{
if (sizeof (U) != sizeof (U1))
return 1;
if (sizeof (V) != sizeof (U1))
return 2;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
int main ()
{
}
#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
......@@ -65,7 +65,7 @@ int main ()
if (vtable (&s4) != vtable (s2))
return 1;
if (vtable (s2) >= vtable (s3))
if (vtable (s2) >= vtable (s3))
return 2;
if (vtable (s3) >= vtable (s1))
return 3;
......
// Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
#include <stddef.h>
struct S0
{
virtual void s0 ();
};
struct S1 : virtual public S0
{
virtual void s1 ();
};
struct S2 : virtual public S1
{
virtual void s1 ();
virtual void s0 ();
};
struct S3
{
virtual void s3 ();
};
struct S4 : public S3, virtual public S2
{
virtual void s1 ();
};
void S0::s0 ()
{
}
void S1::s1 ()
{
}
void S2::s1 ()
{
}
void S2::s0 ()
{
}
void S3::s3 ()
{
}
void S4::s1 ()
{
}
/* The vtables should look like:
S0 primary vtable
S0 offset to top
S0 RTTI
S0::s0
=================
S1 primary vtable
S0::s0 vcall offset
S0 vbase offset
S1 offset to top
S1 RTTI
S0::s0
S1::s1
=================
S2 primary vtable
S2::s1 vcall offset
S1 vbase offset
S2::s0 vcall offset
S0 vbase offset
S2 offset to top
S2 RTTI
S2::s0
S2::s1
=================
S3 primary vtable
S3 offset to top
S3 RTTI
S3::s3
=================
S4 primary vtable
vbase offset for S0
vbase offset for S1
vbase offset for S2
S4 offset to top
S4 RTTI
S3::s3
S4::s1
S2-in-S4 secondary vtable
S4::s1 vcall offset
S1 vbase offset
S2:s0 vcall offset
S0 vbase offset
S2 offset to top
S4 RTTI
S2::s0
S4::s1
*/
// These are tricks to allow us to get raw function pointers for
// member functions.
extern "C" {
void s3__2S3 ();
void s1__2S4 ();
}
int main ()
{
S4 s4;
ptrdiff_t **vptr;
ptrdiff_t *vtbl;
// Set vtbl to point at the beginning of S4's primary vtable.
vptr = (ptrdiff_t **) &s4;
vtbl = *vptr;
vtbl -= 5;
if (*vtbl++ != ((char*) (S0*) &s4) - (char*) &s4)
return 1;
if (*vtbl++ != ((char*) (S1*) &s4) - (char*) &s4)
return 2;
if (*vtbl++ != ((char*) (S2*) &s4) - (char*) &s4)
return 3;
if (*vtbl++ != 0)
return 4;
// Skip the RTTI entry.
vtbl++;
if (*vtbl++ != (ptrdiff_t) &s3__2S3)
return 5;
if (*vtbl++ != (ptrdiff_t) &s1__2S4)
return 6;
// All the vcall and vbase offsets should be zero.
if (*vtbl++ != 0)
return 7;
if (*vtbl++ != 0)
return 8;
if (*vtbl++ != 0)
return 9;
if (*vtbl++ != 0)
return 10;
// Now we're at the S2 offset to top entry.
if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
return 11;
// Skip the RTTI entry.
vtbl++;
// Skip the remaining virtual functions -- they are thunks.
vtbl++;
vtbl++;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
int main ()
{
}
#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
......@@ -28,5 +28,5 @@ int main ()
ap = (C2*)&e2;
// ap points to base subobject shared by two Bs; fails
if (dynamic_cast <B2*> (ap) != 0)
return 1;
return 2;
}
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