mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-11 17:27:27 +08:00
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:
parent
26356fee5b
commit
3c9d63596f
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
82
gcc/testsuite/g++.old-deja/g++.abi/vtable.C
Normal file
82
gcc/testsuite/g++.old-deja/g++.abi/vtable.C
Normal 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) */
|
Loading…
Reference in New Issue
Block a user