Commit c35cce41 by Mark Mitchell Committed by Mark Mitchell

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

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

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

From-SVN: r32905
parent f2d33f13
2000-04-04 Mark Mitchell <mark@codesourcery.com>
Correct many new ABI issues regarding vbase and vcall offset
layout.
* cp-tree.h (BINFO_VTABLE): Document.
(struct lang_type): Tweak formatting.
(BINFO_PRIMARY_BINFO): Add to documentation.
(CLASSTYPE_VSIZE): Fix typo in comment.
(CLASSTYPE_VBASECLASSES): Update documentation.
(BINFO_VBASE_MARKED): Remove.
(SET_BINFO_VBASE_MARKED): Likewise.
(CLEAR_BINFO_VBASE_MARKED): Likewise.
(BINFO_FIELDS_MARKED): Remove.
(SET_BINFO_FIELDS_MARKED): Likewise.
(CLEAR_BINFO_FIELDS_MARKED): Likewise.
(enum access_kind): New enumeration.
(num_extra_vtbl_entries): Remove declaration.
(size_extra_vtbl_entries): Likewise.
(get_vtbl_decl_for_binfo): New function.
(dfs_vbase_unmark): Remove declaration.
(mark_primary_bases): Likewise.
* class.c (SAME_FN): Remove.
(struct vcall_offset_data_s): Move definition.
(build_vbase_pointer): Use `build', not `build_binary_op', to
access the vbase pointer under the new ABI.
(build_vtable_entry_ref): Use get_vtbl_decl_for_binfo.
(build_primary_vtable): Likewise.
(dfs_mark_primary_bases): Move here from search.c.
(mark_primary_bases): Likewise.
(determine_primary_bases): Under the new ABI, don't make a base
class a primary base just because we don't yet have any virtual
functions.
(layout_vtable_decl): Use get_vtbl_decl_for_binfo.
(num_vfun_entries): Remove.
(dfs_count_virtuals): Likewise.
(num_extra_vtbl_entries): Likewise.
(size_extra_vtbl_entries): Likewise.
(layout_virtual_bases): Iterate in inheritance graph order under
the new ABI.
(finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to
indicate that a vfield is present.
(init_class_processing): Initialize access_public_node, etc., from
ak_public, etc.
(get_vtbl_decl_for_binfo): New function.
(dump_class_hierarchy_r): Likewise.
(dump_class_hierarchy): Use it.
(finish_vtbls): Build the vtbls in inheritance graph order.
(dfs_finish_vtbls): Adjust call to build_vtbl_initializer.
(initialize_vtable): Use get_vtbl_decl_for_binfo.
(accumulate_vtbl_inits): Add comments explaining why a pre-order
walk is required.
(dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location
where the vptr points, even for primary vtables.
(build_vtbl_initializer): Adjust handling of vbase and vcall
offsets.
(build_vcall_and_vbase_vtable_entries): New function.
(dfs_build_vbase_offset_vtbl_entries): Remove.
(build_vbase_offset_vtbl_entries): Reimplement.
(dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that
were already handled in a primary base class vtable.
(build_vcall_offset_vtbl_entries): Adjust.
(build_rtti_vtbl_entries): Adjust.
* decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo.
* init.c (expand_virtual_init): Simplify.
* repo.c (repo_get_id): Use get_vtbl_decl_for_binfo.
* rtti.c (create_pseudo_type_info): Adjust calculation of vptr.
* search.c (BINFO_ACCESS): New macro.
(SET_BINFO_ACCESS): Likewise.
(dfs_access_in_type): Manipulate access_kinds, not access nodes.
(access_in_type): Likewise.
(dfs_accessible_p): Likewise.
(protected_accessible_p): Likewise.
(lookup_fnfields_1): Adjust documentation.
(dfs_mark_primary_bases): Move to class.c
(mark_primary_bases): Likewise.
(dfs_vbase_unmark): Remove.
(virtual_context): Use BINFO_FOR_VBASE.
(dfs_get_vbase_types): Simplify.
(dfs_build_inheritance_graph_order): New function.
(get_vbase_types): Use it.
* tree.c (debug_binfo): Use get_vtbl_decl_for_binfo.
* tinfo.cc (get_vbase_offset): New function.
(__vmi_class_type_info::do_find_public_src): Use it.
(__vmi_class_type_info::do_dyncast): Likewise.
(__vmi_class_type_info::do_upcast): Likewise.
2000-04-03 Zack Weinberg <zack@wolery.cumb.org> 2000-04-03 Zack Weinberg <zack@wolery.cumb.org>
* lang-specs.h: Pass -fno-show-column to the preprocessor. * lang-specs.h: Pass -fno-show-column to the preprocessor.
......
...@@ -55,8 +55,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -55,8 +55,6 @@ Boston, MA 02111-1307, USA. */
ICS_ELLIPSIS_FLAG (in _CONV) ICS_ELLIPSIS_FLAG (in _CONV)
STMT_IS_FULL_EXPR_P (in _STMT) STMT_IS_FULL_EXPR_P (in _STMT)
2: IDENTIFIER_OPNAME_P. 2: IDENTIFIER_OPNAME_P.
BINFO_VBASE_MARKED.
BINFO_FIELDS_MARKED.
TYPE_POLYMORHPIC_P (in _TYPE) TYPE_POLYMORHPIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV) ICS_THIS_FLAG (in _CONV)
STMT_LINENO_FOR_FN_P (in _STMT) STMT_LINENO_FOR_FN_P (in _STMT)
...@@ -130,6 +128,13 @@ Boston, MA 02111-1307, USA. */ ...@@ -130,6 +128,13 @@ Boston, MA 02111-1307, USA. */
this function. (This binfo's BINFO_TYPE will always be the same this function. (This binfo's BINFO_TYPE will always be the same
as the DECL_CLASS_CONTEXT for the function.) 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 DECL_ARGUMENTS
For a VAR_DECL this is DECL_ANON_UNION_ELEMS. For a VAR_DECL this is DECL_ANON_UNION_ELEMS.
...@@ -1356,24 +1361,17 @@ struct lang_type ...@@ -1356,24 +1361,17 @@ struct lang_type
int vsize; int vsize;
int vfield_parent; int vfield_parent;
union tree_node *vfields; tree vfields;
union tree_node *vbases; tree vbases;
tree tags;
union tree_node *tags; tree search_slot;
tree size;
union tree_node *search_slot; tree size_unit;
tree pure_virtuals;
union tree_node *size; tree friend_classes;
union tree_node *size_unit; tree rtti;
tree methods;
union tree_node *pure_virtuals; tree template_info;
union tree_node *friend_classes;
union tree_node *rtti;
union tree_node *methods;
union tree_node *template_info;
tree befriending_classes; tree befriending_classes;
}; };
...@@ -1538,21 +1536,29 @@ struct lang_type ...@@ -1538,21 +1536,29 @@ struct lang_type
#define CLASSTYPE_PRIMARY_BINFO(NODE) \ #define CLASSTYPE_PRIMARY_BINFO(NODE) \
(BINFO_PRIMARY_BINFO (TYPE_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) \ #define BINFO_PRIMARY_BINFO(NODE) \
(CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (NODE)) \ (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (NODE)) \
? BINFO_BASETYPE (NODE, \ ? BINFO_BASETYPE (NODE, \
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \ CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
: NULL_TREE) : NULL_TREE)
/* The number of virtual functions present in this classes virtual /* The number of virtual functions present in this class' virtual
function table. */ function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* A chain of BINFOs for the direct and indirect virtual base classes /* A chain of BINFOs for the direct and indirect virtual base classes
that this type uses in depth-first left-to-right order. These that this type uses in a post-order depth-first left-to-right
BINFOs are distinct from those in the TYPE_BINFO hierarchy. So, order. (In other words, these bases appear in the order that they
given: should be initialized.)
These BINFOs are distinct from those in the TYPE_BINFO hierarchy.
So, given:
struct A {}; struct A {};
struct B : public A {}; struct B : public A {};
...@@ -1683,9 +1689,7 @@ struct lang_type ...@@ -1683,9 +1689,7 @@ struct lang_type
We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
inheritance is indicated by the absence of the other two flags, not inheritance is indicated by the absence of the other two flags, not
by TREE_VIA_PRIVATE, which is unused. by TREE_VIA_PRIVATE, which is unused. */
The TREE_CHAIN is for scratch space in search.c. */
/* Nonzero means marked by DFS or BFS search, including searches /* Nonzero means marked by DFS or BFS search, including searches
by `get_binfo' and `get_base_distance'. */ by `get_binfo' and `get_base_distance'. */
...@@ -1695,18 +1699,6 @@ struct lang_type ...@@ -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 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)) #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. */ /* Nonzero means that this class is on a path leading to a new vtable. */
#define BINFO_VTABLE_PATH_MARKED(NODE) \ #define BINFO_VTABLE_PATH_MARKED(NODE) \
(TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE)) (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE))
...@@ -3081,6 +3073,17 @@ typedef enum tmpl_spec_kind { ...@@ -3081,6 +3073,17 @@ typedef enum tmpl_spec_kind {
tsk_expl_inst /* An explicit instantiation. */ tsk_expl_inst /* An explicit instantiation. */
} tmpl_spec_kind; } 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). /* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */ Each language context defines how this variable should be set. */
extern int strict_prototype; extern int strict_prototype;
...@@ -3694,8 +3697,7 @@ extern void unreverse_member_declarations PARAMS ((tree)); ...@@ -3694,8 +3697,7 @@ extern void unreverse_member_declarations PARAMS ((tree));
extern void invalidate_class_lookup_cache PARAMS ((void)); extern void invalidate_class_lookup_cache PARAMS ((void));
extern void maybe_note_name_used_in_class PARAMS ((tree, tree)); extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
extern void note_name_declared_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 get_vtbl_decl_for_binfo PARAMS ((tree));
extern tree size_extra_vtbl_entries PARAMS ((tree));
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree)); extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
...@@ -4203,7 +4205,6 @@ extern tree dfs_walk_real PARAMS ((tree, ...@@ -4203,7 +4205,6 @@ extern tree dfs_walk_real PARAMS ((tree,
tree (*) (tree, void *), tree (*) (tree, void *),
void *)); void *));
extern tree dfs_unmark PARAMS ((tree, 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 dfs_vtable_path_unmark PARAMS ((tree, void *));
extern tree markedp PARAMS ((tree, void *)); extern tree markedp PARAMS ((tree, void *));
extern tree unmarkedp PARAMS ((tree, void *)); extern tree unmarkedp PARAMS ((tree, void *));
...@@ -4214,7 +4215,6 @@ extern tree dfs_marked_real_bases_queue_p 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 dfs_skip_vbases PARAMS ((tree, void *));
extern tree marked_vtable_pathp PARAMS ((tree, void *)); extern tree marked_vtable_pathp PARAMS ((tree, void *));
extern tree unmarked_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 convert_pointer_to_vbase PARAMS ((tree, tree));
extern tree find_vbase_instance PARAMS ((tree, tree)); extern tree find_vbase_instance PARAMS ((tree, tree));
......
...@@ -2544,7 +2544,7 @@ output_vtable_inherit (vars) ...@@ -2544,7 +2544,7 @@ output_vtable_inherit (vars)
op[1] = const0_rtx; op[1] = const0_rtx;
else if (parent) 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 */ op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
} }
else else
......
...@@ -653,31 +653,23 @@ expand_virtual_init (binfo, decl) ...@@ -653,31 +653,23 @@ expand_virtual_init (binfo, decl)
tree type = BINFO_TYPE (binfo); tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr; tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo; tree vtype, vtype_binfo;
tree b;
/* Compute the location of the vtable. */ /* Compute the location of the vtable. */
vtype = DECL_CONTEXT (TYPE_VFIELD (type)); vtype = DECL_CONTEXT (TYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0); 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) if (TREE_CODE (vtbl) == VAR_DECL)
{ vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
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));
/* Compute the location of the vtpr. */ /* Compute the location of the vtpr. */
decl = convert_pointer_to_real (vtype_binfo, decl); decl = convert_pointer_to_real (vtype_binfo, decl);
......
...@@ -103,7 +103,7 @@ repo_get_id (t) ...@@ -103,7 +103,7 @@ repo_get_id (t)
if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t)) if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
my_friendly_abort (981113); my_friendly_abort (981113);
t = TYPE_BINFO_VTABLE (t); t = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
if (t == NULL_TREE) if (t == NULL_TREE)
return t; return t;
} }
......
...@@ -1640,11 +1640,14 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...)) ...@@ -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 /* Under the new ABI, we need to point into the middle of the
vtable. */ 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, 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; TREE_CONSTANT (vtable_decl) = 1;
} }
......
...@@ -590,6 +590,14 @@ adjust_pointer (const void *base, ptrdiff_t offset) ...@@ -590,6 +590,14 @@ adjust_pointer (const void *base, ptrdiff_t offset)
(reinterpret_cast <const char *> (base) + 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 // some predicate functions for __class_type_info::sub_kind
inline bool contained_p (__class_type_info::sub_kind access_path) inline bool contained_p (__class_type_info::sub_kind access_path)
{ {
...@@ -718,9 +726,7 @@ do_find_public_src (ptrdiff_t src2dst, ...@@ -718,9 +726,7 @@ do_find_public_src (ptrdiff_t src2dst,
{ {
if (src2dst == -3) if (src2dst == -3)
continue; // Not a virtual base, so can't be here. continue; // Not a virtual base, so can't be here.
const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base); offset = get_vbase_offset (base, offset);
offset = vtable[offset];
} }
base = adjust_pointer <void> (base, offset); base = adjust_pointer <void> (base, offset);
...@@ -841,9 +847,7 @@ do_dyncast (ptrdiff_t src2dst, ...@@ -841,9 +847,7 @@ do_dyncast (ptrdiff_t src2dst,
if (base_list[i].is_virtual_p ()) if (base_list[i].is_virtual_p ())
{ {
base_access = sub_kind (base_access | contained_virtual_mask); base_access = sub_kind (base_access | contained_virtual_mask);
const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base); offset = get_vbase_offset (base, offset);
offset = vtable[offset];
} }
base = adjust_pointer <void> (base, offset); base = adjust_pointer <void> (base, offset);
...@@ -1041,10 +1045,7 @@ do_upcast (sub_kind access_path, ...@@ -1041,10 +1045,7 @@ do_upcast (sub_kind access_path,
sub_access = sub_kind (sub_access | contained_virtual_mask); sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base) if (base)
{ offset = get_vbase_offset (base, offset);
const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
offset = vtable[offset];
}
} }
if (base) if (base)
base = adjust_pointer <void> (base, offset); base = adjust_pointer <void> (base, offset);
......
...@@ -921,7 +921,7 @@ debug_binfo (elem) ...@@ -921,7 +921,7 @@ debug_binfo (elem)
debug_tree (BINFO_TYPE (elem)); debug_tree (BINFO_TYPE (elem));
if (BINFO_VTABLE (elem)) if (BINFO_VTABLE (elem))
fprintf (stderr, "vtable decl \"%s\"\n", fprintf (stderr, "vtable decl \"%s\"\n",
IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem)))); IDENTIFIER_POINTER (DECL_NAME (get_vtbl_decl_for_binfo (elem))));
else else
fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n"); fprintf (stderr, "virtuals:\n");
......
// Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
struct R
{
virtual void r ();
};
struct S
{
virtual void f ();
};
struct T : virtual public S
{
virtual void g ();
};
struct U : public R, virtual public T
{
virtual void h ();
};
struct V : public R, virtual public S, virtual public T
{
virtual void v ();
};
struct U1
{
R r;
T t;
};
int main ()
{
if (sizeof (U) != sizeof (U1))
return 1;
if (sizeof (V) != sizeof (U1))
return 2;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
int main ()
{
}
#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
...@@ -65,7 +65,7 @@ int main () ...@@ -65,7 +65,7 @@ int main ()
if (vtable (&s4) != vtable (s2)) if (vtable (&s4) != vtable (s2))
return 1; return 1;
if (vtable (s2) >= vtable (s3)) if (vtable (s2) >= vtable (s3))
return 2; return 2;
if (vtable (s3) >= vtable (s1)) if (vtable (s3) >= vtable (s1))
return 3; return 3;
......
// Origin: Mark Mitchell <mark@codesourcery.com>
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
#include <stddef.h>
struct S0
{
virtual void s0 ();
};
struct S1 : virtual public S0
{
virtual void s1 ();
};
struct S2 : virtual public S1
{
virtual void s1 ();
virtual void s0 ();
};
struct S3
{
virtual void s3 ();
};
struct S4 : public S3, virtual public S2
{
virtual void s1 ();
};
void S0::s0 ()
{
}
void S1::s1 ()
{
}
void S2::s1 ()
{
}
void S2::s0 ()
{
}
void S3::s3 ()
{
}
void S4::s1 ()
{
}
/* The vtables should look like:
S0 primary vtable
S0 offset to top
S0 RTTI
S0::s0
=================
S1 primary vtable
S0::s0 vcall offset
S0 vbase offset
S1 offset to top
S1 RTTI
S0::s0
S1::s1
=================
S2 primary vtable
S2::s1 vcall offset
S1 vbase offset
S2::s0 vcall offset
S0 vbase offset
S2 offset to top
S2 RTTI
S2::s0
S2::s1
=================
S3 primary vtable
S3 offset to top
S3 RTTI
S3::s3
=================
S4 primary vtable
vbase offset for S0
vbase offset for S1
vbase offset for S2
S4 offset to top
S4 RTTI
S3::s3
S4::s1
S2-in-S4 secondary vtable
S4::s1 vcall offset
S1 vbase offset
S2:s0 vcall offset
S0 vbase offset
S2 offset to top
S4 RTTI
S2::s0
S4::s1
*/
// These are tricks to allow us to get raw function pointers for
// member functions.
extern "C" {
void s3__2S3 ();
void s1__2S4 ();
}
int main ()
{
S4 s4;
ptrdiff_t **vptr;
ptrdiff_t *vtbl;
// Set vtbl to point at the beginning of S4's primary vtable.
vptr = (ptrdiff_t **) &s4;
vtbl = *vptr;
vtbl -= 5;
if (*vtbl++ != ((char*) (S0*) &s4) - (char*) &s4)
return 1;
if (*vtbl++ != ((char*) (S1*) &s4) - (char*) &s4)
return 2;
if (*vtbl++ != ((char*) (S2*) &s4) - (char*) &s4)
return 3;
if (*vtbl++ != 0)
return 4;
// Skip the RTTI entry.
vtbl++;
if (*vtbl++ != (ptrdiff_t) &s3__2S3)
return 5;
if (*vtbl++ != (ptrdiff_t) &s1__2S4)
return 6;
// All the vcall and vbase offsets should be zero.
if (*vtbl++ != 0)
return 7;
if (*vtbl++ != 0)
return 8;
if (*vtbl++ != 0)
return 9;
if (*vtbl++ != 0)
return 10;
// Now we're at the S2 offset to top entry.
if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
return 11;
// Skip the RTTI entry.
vtbl++;
// Skip the remaining virtual functions -- they are thunks.
vtbl++;
vtbl++;
}
#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
int main ()
{
}
#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
...@@ -28,5 +28,5 @@ int main () ...@@ -28,5 +28,5 @@ int main ()
ap = (C2*)&e2; ap = (C2*)&e2;
// ap points to base subobject shared by two Bs; fails // ap points to base subobject shared by two Bs; fails
if (dynamic_cast <B2*> (ap) != 0) if (dynamic_cast <B2*> (ap) != 0)
return 1; return 2;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment