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:
Mark Mitchell 2000-04-04 18:13:22 +00:00 committed by Mark Mitchell
parent f2d33f1321
commit c35cce41da
14 changed files with 972 additions and 579 deletions

View File

@ -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.

File diff suppressed because it is too large Load Diff

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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. */

View File

@ -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);

View File

@ -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");

View 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) */

View File

@ -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;

View 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) */

View File

@ -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;
}