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
This commit is contained in:
parent
f2d33f1321
commit
c35cce41da
@ -1,3 +1,90 @@
|
||||
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.
|
||||
|
851
gcc/cp/class.c
851
gcc/cp/class.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
||||
|
225
gcc/cp/search.c
225
gcc/cp/search.c
@ -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");
|
||||
|
51
gcc/testsuite/g++.old-deja/g++.abi/layout1.C
Normal file
51
gcc/testsuite/g++.old-deja/g++.abi/layout1.C
Normal file
@ -0,0 +1,51 @@
|
||||
// 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;
|
||||
|
179
gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
Normal file
179
gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
Normal file
@ -0,0 +1,179 @@
|
||||
// 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user