cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.

* cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
	(CANONICAL_BINFO): New macro.
	(BINFO_NEW_VTABLE_MARKED): Use it.
	(SET_BINFO_NEW_VTABLE_MARKED): Likewise.
	(CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise.
	* class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE,
	not TREE_TYPE.
	(build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED.
	(build_secondary_vtable): Likewise.
	(dfs_finish_vtbls): Likewise.
	(dfs_accumulate_vtbl_inits): Likewise.
	(accumulate_vtbl_inits): New function.
	(finish_vtbls): Make sure that virtual bases come after
	non-virtual bases in the vtable group.
	(record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL.
	(finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED.
	* search.c (struct vbase_info): Move definition.
	(marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED.
	(unmarked_new_vtable_p): Likewise.
	(dfs_mark_vtable_path): Remove.
	(dfs_mark_new_vtable): Remove.
	(dfs_unmark_new_vtable): Likewise.
	(dfs_clear_search_slot): Likewise.
	(dfs_find_vbases):  Adjust usage of BINFO_NEW_VTABLE_MARKED.
	(dfs_clear_vbase_slots): Likewise.
	(init_vbase_pointers): LIkewise.

From-SVN: r32689
This commit is contained in:
Mark Mitchell 2000-03-22 21:43:45 +00:00 committed by Mark Mitchell
parent 26356fee5b
commit 3c9d63596f
5 changed files with 209 additions and 76 deletions

View File

@ -1,3 +1,32 @@
2000-03-22 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
(CANONICAL_BINFO): New macro.
(BINFO_NEW_VTABLE_MARKED): Use it.
(SET_BINFO_NEW_VTABLE_MARKED): Likewise.
(CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise.
* class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE,
not TREE_TYPE.
(build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(build_secondary_vtable): Likewise.
(dfs_finish_vtbls): Likewise.
(dfs_accumulate_vtbl_inits): Likewise.
(accumulate_vtbl_inits): New function.
(finish_vtbls): Make sure that virtual bases come after
non-virtual bases in the vtable group.
(record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL.
(finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED.
* search.c (struct vbase_info): Move definition.
(marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(unmarked_new_vtable_p): Likewise.
(dfs_mark_vtable_path): Remove.
(dfs_mark_new_vtable): Remove.
(dfs_unmark_new_vtable): Likewise.
(dfs_clear_search_slot): Likewise.
(dfs_find_vbases): Adjust usage of BINFO_NEW_VTABLE_MARKED.
(dfs_clear_vbase_slots): Likewise.
(init_vbase_pointers): LIkewise.
2000-03-22 Jason Merrill <jason@casey.cygnus.com>
* typeck.c (type_after_usual_arithmetic_conversions): Prefer a

View File

@ -161,6 +161,7 @@ static tree dfs_search_base_offsets PARAMS ((tree, void *));
static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
@ -276,7 +277,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
/* Remember the index to the vbase offset for this virtual
base. */
vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list))
BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
else
@ -1072,7 +1073,7 @@ build_primary_vtable (binfo, type)
{
tree offset;
if (BINFO_NEW_VTABLE_MARKED (binfo))
if (BINFO_NEW_VTABLE_MARKED (binfo, type))
/* We have already created a vtable for this base, so there's
no need to do it again. */
return 0;
@ -1106,7 +1107,7 @@ build_primary_vtable (binfo, type)
TYPE_BINFO_VIRTUALS (type) = virtuals;
binfo = TYPE_BINFO (type);
SET_BINFO_NEW_VTABLE_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo, type);
return 1;
}
@ -1147,14 +1148,14 @@ build_secondary_vtable (binfo, for_type)
current_class_type),
170);
if (BINFO_NEW_VTABLE_MARKED (binfo))
if (BINFO_NEW_VTABLE_MARKED (binfo, current_class_type))
/* We already created a vtable for this base. There's no need to
do it again. */
return 0;
/* Remember that we've created a vtable for this BINFO, so that we
don't try to do so again. */
SET_BINFO_NEW_VTABLE_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type);
/* Make fresh virtual list, so we can smash it later. */
BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
@ -2760,13 +2761,15 @@ dfs_finish_vtbls (binfo, data)
tree binfo;
void *data;
{
tree t = (tree) data;
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
build_vtbl_initializer (binfo, (tree) data));
build_vtbl_initializer (binfo, t));
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
SET_BINFO_MARKED (binfo);
return NULL_TREE;
@ -2781,15 +2784,16 @@ dfs_accumulate_vtbl_inits (binfo, data)
tree binfo;
void *data;
{
tree l;
tree t;
l = (tree) data;
t = TREE_PURPOSE (l);
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo, t))
{
tree l;
tree t;
l = (tree) data;
t = TREE_PURPOSE (l);
/* If this is a secondary vtable, record its location. */
if (binfo != TYPE_BINFO (t))
@ -2807,19 +2811,34 @@ dfs_accumulate_vtbl_inits (binfo, data)
size_int (list_length (TREE_VALUE (l)))));
}
/* Add the initializers for this vtable to the initailizers for
/* Add the initializers for this vtable to the initializers for
the other vtables we've already got. */
TREE_VALUE (l)
= chainon (TREE_VALUE (l),
build_vtbl_initializer (binfo, t));
}
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
SET_BINFO_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
return NULL_TREE;
}
/* Add the vtbl initializers for BINFO (and its non-primary,
non-virtual bases) to the list of INITS. */
static void
accumulate_vtbl_inits (binfo, inits)
tree binfo;
tree inits;
{
/* Walk the BINFO and its bases. */
dfs_walk_real (binfo,
dfs_accumulate_vtbl_inits,
NULL,
dfs_skip_vbases,
inits);
}
/* Create all the necessary vtables for T and its base classes. */
static void
@ -2829,26 +2848,31 @@ finish_vtbls (t)
if (merge_primary_and_secondary_vtables_p ())
{
tree list;
tree vbase;
/* Under the new ABI, we lay out the primary and secondary
vtables in one contiguous vtable. The primary vtable is
first, followed by the secondary vtables as encountered in a
pre-order depth-first left-to-right traversal. */
first, followed by the non-virtual secondary vtables in
inheritance graph order. */
list = build_tree_list (t, NULL_TREE);
dfs_walk_real (TYPE_BINFO (t),
dfs_accumulate_vtbl_inits,
NULL,
dfs_unmarked_real_bases_queue_p,
list);
accumulate_vtbl_inits (TYPE_BINFO (t), list);
/* Then come the virtual bases, also in inheritance graph
order. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
accumulate_vtbl_inits (vbase, list);
if (TYPE_BINFO_VTABLE (t))
initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
}
else
dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
dfs_unmarked_real_bases_queue_p, t);
dfs_walk (TYPE_BINFO (t), dfs_unmark,
dfs_marked_real_bases_queue_p, t);
{
dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
dfs_unmarked_real_bases_queue_p, t);
dfs_walk (TYPE_BINFO (t), dfs_unmark,
dfs_marked_real_bases_queue_p, t);
}
}
/* True if we should override the given BASE_FNDECL with the given
@ -4142,17 +4166,10 @@ record_base_offsets (binfo, base_offsets)
tree binfo;
varray_type *base_offsets;
{
int virtual_p;
/* If BINFO is virtual, we still want to mention its offset in
BASE_OFFSETS. */
virtual_p = TREE_VIA_VIRTUAL (binfo);
TREE_VIA_VIRTUAL (binfo) = 0;
dfs_walk (binfo,
dfs_record_base_offsets,
dfs_skip_vbases,
base_offsets);
TREE_VIA_VIRTUAL (binfo) = virtual_p;
}
/* Returns non-NULL if there is already an entry in DATA (which is
@ -5308,7 +5325,7 @@ finish_struct_1 (t)
}
build_primary_vtable (NULL_TREE, t);
}
else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);

View File

@ -1566,10 +1566,19 @@ struct lang_type
(also distinct from the copies in the TYPE_BINFO hierarchy.) */
#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
/* The BINFO (if any) for the virtual baseclass T of the class C. */
/* The BINFO (if any) for the virtual baseclass T of the class C from
the CLASSTYPE_VBASECLASSES list. */
#define BINFO_FOR_VBASE(T, C) \
(binfo_member (T, CLASSTYPE_VBASECLASSES (C)))
/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
BINFO_FOR_VBASE. C is the most derived class for the hierarchy
containing BINFO. */
#define CANONICAL_BINFO(BINFO, C) \
(TREE_VIA_VIRTUAL (BINFO) \
? BINFO_FOR_VBASE (BINFO_TYPE (BINFO), C) \
: BINFO)
/* Number of direct baseclasses of NODE. */
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
@ -1704,11 +1713,14 @@ struct lang_type
#define SET_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=1))
#define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=0))
/* Nonzero means that this class has a new vtable. */
#define BINFO_NEW_VTABLE_MARKED(NODE) \
(TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):TREE_LANG_FLAG_4(NODE))
#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1))
#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0))
/* Nonzero means B (a BINFO) needs a new vtable. B is part of the
hierarchy dominated by C. */
#define BINFO_NEW_VTABLE_MARKED(B, C) \
(TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
#define SET_BINFO_NEW_VTABLE_MARKED(B, C) \
(BINFO_NEW_VTABLE_MARKED (B, C) = 1)
#define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
(BINFO_NEW_VTABLE_MARKED (B, C) = 0)
/* Nonzero means this class has done dfs_pushdecls. */
#define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE)

View File

@ -76,6 +76,15 @@ pop_stack_level (stack)
#define search_level stack_level
static struct search_level *search_stack;
struct vbase_info
{
/* The class dominating the hierarchy. */
tree type;
tree decl_ptr;
tree inits;
tree vbase_types;
};
static tree next_baselink PARAMS ((tree));
static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
static tree lookup_field_1 PARAMS ((tree, tree));
@ -2537,17 +2546,21 @@ unmarked_vtable_pathp (binfo, data)
static tree
marked_new_vtablep (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
void *data;
{
return BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
struct vbase_info *vi = (struct vbase_info *) data;
return BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE;
}
static tree
unmarked_new_vtablep (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
void *data;
{
return !BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
struct vbase_info *vi = (struct vbase_info *) data;
return !BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE;
}
static tree
@ -2614,31 +2627,7 @@ dfs_vtable_path_unmark (binfo, data)
return NULL_TREE;
}
#if 0
static void
dfs_mark_vtable_path (binfo) tree binfo;
{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
static void
dfs_mark_new_vtable (binfo) tree binfo;
{ SET_BINFO_NEW_VTABLE_MARKED (binfo); }
static void
dfs_unmark_new_vtable (binfo) tree binfo;
{ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); }
static void
dfs_clear_search_slot (binfo) tree binfo;
{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
#endif
struct vbase_info
{
tree decl_ptr;
tree inits;
tree vbase_types;
};
/* Attach to the type of the virtual base class, the pointer to the
virtual base class. */
@ -2668,7 +2657,7 @@ dfs_find_vbases (binfo, data)
}
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo);
SET_BINFO_NEW_VTABLE_MARKED (binfo, vi->type);
return NULL_TREE;
}
@ -2737,12 +2726,14 @@ dfs_init_vbase_pointers (binfo, data)
static tree
dfs_clear_vbase_slots (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
void *data;
{
tree type = BINFO_TYPE (binfo);
struct vbase_info *vi = (struct vbase_info *) data;
CLASSTYPE_SEARCH_SLOT (type) = 0;
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, vi->type);
return NULL_TREE;
}
@ -2760,6 +2751,7 @@ init_vbase_pointers (type, decl_ptr)
/* Find all the virtual base classes, marking them for later
initialization. */
vi.type = type;
vi.decl_ptr = decl_ptr;
vi.vbase_types = CLASSTYPE_VBASECLASSES (type);
vi.inits = NULL_TREE;
@ -2773,7 +2765,7 @@ init_vbase_pointers (type, decl_ptr)
marked_vtable_pathp,
&vi);
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi);
flag_this_is_variable = old_flag;
return vi.inits;
}
@ -3088,12 +3080,13 @@ expand_indirect_vtbls_init (binfo, decl_ptr)
{
tree vbases = CLASSTYPE_VBASECLASSES (type);
struct vbase_info vi;
vi.type = type;
vi.decl_ptr = decl_ptr;
vi.vbase_types = vbases;
dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
fixup_all_virtual_upcast_offsets (type, vi.decl_ptr);
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi);
}
}

View File

@ -0,0 +1,82 @@
// Test various aspects of vtable layout.
// Special g++ Options: -fno-strict-aliasing
// Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
struct S0
{
virtual void h ()
{
}
int k;
};
struct S1
{
virtual void f ()
{
}
int i;
};
struct S2 : virtual public S0
{
virtual void g ()
{
}
int j;
};
struct S3
{
virtual void k ()
{
}
int l;
};
struct S4 : public virtual S1, public S2, public S3
{
};
inline void* vtable (void *object)
{
// The vptr is always the first part of the object.
return * (void **) object;
}
int main ()
{
// The vtable layout order for S4 should consist of S4's primary
// vtable (shared with S2), followed by the vtable for S3 (because
// it is a non-virtual base). Then, these should be followed by the
// the vtables for S1 and S0, which are virtual.
S4 s4;
S0 *s0 = &s4;
S1 *s1 = &s4;
S2 *s2 = &s4;
S3 *s3 = &s4;
if (vtable (&s4) != vtable (s2))
return 1;
if (vtable (s2) >= vtable (s3))
return 2;
if (vtable (s3) >= vtable (s1))
return 3;
if (vtable (s1) >= vtable (s0))
return 4;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
int main ()
{
}
#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */