cp-tree.h (flag_new_abi): Move.

* cp-tree.h (flag_new_abi): Move.
	(flag_use_cxa_atexit): Likewise.
	(flag_honor_std): Likewise.
	(flag_rtti): Likewise.
	(vbase_offsets_in_vtable_p): Define.
	(vptrs_present_everywhere_p): Likewise.
	(TYPE_CONTAINS_VPTR_P): Likewise.
	(dfs_walk_real): Declare.
	* class.c (build_vbase_pointer_fields): Check
	vbase_offsets_in_vtable_p.
	(dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
	BINFO_VPTR_FIELD.
	(build_vbase_offset_vtbl_entries): Simplify.
	(build_vbase_offset_vtbl_entries): Adjust.
	(build_vbase_pointer): Add ability to look up vbase offsets in
	vtable.
	(start_vtable): New function.
	(add_virtual_function): Use it.
	(determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
	(num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
	(build_vtbl_initializer): Take the type of the complete object as
	input.  Use it to correctly calculate vbase offsets.
	(dfs_finish_vtbls): Pass the complete type to
	build_vtbl_initializer.
	(check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
	(create_vtable_ptr): Create a vtable even if there are no
	new virtual functions, under the new ABI.
	(finish_struct_1): Likewise.
	(get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
	* decl.c (exapnd_static_init): Remove call to
	preserve_initializer.
	* decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
	vtables.
	* init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
	(expand_virtual_init): Use vbase_offsets_in_vtable_p.
	(construct_virtual_bases): Don't initialize virtual base pointers
	under the new ABI.
	(build_aggr_init): Clean up comment.
	(expand_aggr_init_1): Likewise.
	* rtti.c (expand_class_desc): Store the virtual function table
	index where the vbase offset lives in the offset field.
	* search.c (dfs_walk_real): Make it global.
	(dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
	* tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.

	* tinfo.h (USItype): Make it signed under the new ABI.
	* tinfo.cc (convert_to_base): New function.  Encapsulate base
	conversion logic here.
	(__class_type_info::do_upcast): Use it.
	(__class_type_info::do_dyncast): Likewise.
	(__class_type_info::do_find_public_subobj): Likewise.

From-SVN: r31452
This commit is contained in:
Mark Mitchell 2000-01-17 04:08:01 +00:00 committed by Mark Mitchell
parent 2a198bc4bf
commit bbd15aac6f
11 changed files with 333 additions and 170 deletions

View File

@ -1,5 +1,57 @@
2000-01-16 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (flag_new_abi): Move.
(flag_use_cxa_atexit): Likewise.
(flag_honor_std): Likewise.
(flag_rtti): Likewise.
(vbase_offsets_in_vtable_p): Define.
(vptrs_present_everywhere_p): Likewise.
(TYPE_CONTAINS_VPTR_P): Likewise.
(dfs_walk_real): Declare.
* class.c (build_vbase_pointer_fields): Check
vbase_offsets_in_vtable_p.
(dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
BINFO_VPTR_FIELD.
(build_vbase_offset_vtbl_entries): Simplify.
(build_vbase_offset_vtbl_entries): Adjust.
(build_vbase_pointer): Add ability to look up vbase offsets in
vtable.
(start_vtable): New function.
(add_virtual_function): Use it.
(determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
(num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
(build_vtbl_initializer): Take the type of the complete object as
input. Use it to correctly calculate vbase offsets.
(dfs_finish_vtbls): Pass the complete type to
build_vtbl_initializer.
(check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
(create_vtable_ptr): Create a vtable even if there are no
new virtual functions, under the new ABI.
(finish_struct_1): Likewise.
(get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
* decl.c (exapnd_static_init): Remove call to
preserve_initializer.
* decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
vtables.
* init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
(expand_virtual_init): Use vbase_offsets_in_vtable_p.
(construct_virtual_bases): Don't initialize virtual base pointers
under the new ABI.
(build_aggr_init): Clean up comment.
(expand_aggr_init_1): Likewise.
* rtti.c (expand_class_desc): Store the virtual function table
index where the vbase offset lives in the offset field.
* search.c (dfs_walk_real): Make it global.
(dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
* tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.
* tinfo.h (USItype): Make it signed under the new ABI.
* tinfo.cc (convert_to_base): New function. Encapsulate base
conversion logic here.
(__class_type_info::do_upcast): Use it.
(__class_type_info::do_dyncast): Likewise.
(__class_type_info::do_find_public_subobj): Likewise.
* init.c (construct_virtual_bases): Don't look up the addresses of
virtual bases at run-time.

View File

@ -115,7 +115,7 @@ static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
int, tree));
static void build_vtable_entry_ref PROTO((tree, tree, tree));
static tree build_vtable_entry_for_fn PROTO((tree, tree));
static tree build_vtbl_initializer PROTO((tree));
static tree build_vtbl_initializer PROTO((tree, tree));
static int count_fields PROTO((tree));
static int add_fields_to_vec PROTO((tree, tree, int));
static void check_bitfield_decl PROTO((tree));
@ -145,7 +145,8 @@ static void remove_base_fields PROTO((tree));
static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *));
static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *));
static tree build_vbase_offset_vtbl_entries PROTO((tree));
static tree build_vbase_offset_vtbl_entries PROTO((tree, tree));
static void start_vtable PROTO((tree, int *));
/* Variables shared between class.c and call.c. */
@ -178,9 +179,12 @@ build_vbase_pointer_fields (rec, empty_p)
tree decl;
int i;
/* Handle basetypes almost like fields, but record their
offsets differently. */
/* Under the new ABI, there are no vbase pointers in the object.
Instead, the offsets are stored in the vtable. */
if (vbase_offsets_in_vtable_p ())
return NULL_TREE;
/* Loop over the baseclasses, adding vbase pointers as needed. */
for (i = 0; i < n_baseclasses; i++)
{
register tree base_binfo = TREE_VEC_ELT (binfos, i);
@ -251,10 +255,27 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
else if (TREE_VIA_VIRTUAL (binfo))
{
tree init;
tree vbase;
/* Remember the index to the vbase offset for this virtual
base. */
vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list))
BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
else
{
BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
BINFO_VPTR_FIELD (vbase) = ssize_binop (MINUS_EXPR,
BINFO_VPTR_FIELD (vbase),
integer_one_node);
}
/* And record the offset at which this virtual base lies in the
vtable. */
init = BINFO_OFFSET (binfo);
init = build1 (NOP_EXPR, vtable_entry_type, init);
TREE_VALUE (list) = tree_cons (NULL_TREE, init, TREE_VALUE (list));
TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase),
init,
TREE_VALUE (list));
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
@ -262,69 +283,46 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
return NULL_TREE;
}
/* Returns the initializers for the vbase offset entries in the
vtable, in reverse order. */
/* Returns the initializers for the vbase offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T), in
reverse order. */
static tree
build_vbase_offset_vtbl_entries (binfo)
build_vbase_offset_vtbl_entries (binfo, t)
tree binfo;
tree t;
{
tree type;
tree inits;
tree init;
tree list;
/* Under the old ABI, pointers to virtual bases are stored in each
object. */
if (!flag_new_abi)
if (!vbase_offsets_in_vtable_p ())
return NULL_TREE;
/* If there are no virtual baseclasses, then there is nothing to
do. */
type = BINFO_TYPE (binfo);
if (!TYPE_USES_VIRTUAL_BASECLASSES (type))
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
return NULL_TREE;
inits = NULL_TREE;
/* Under the new ABI, the vtable contains offsets to all virtual
bases. The ABI specifies different layouts depending on whether
or not *all* of the bases of this type are virtual. */
if (CLASSTYPE_N_BASECLASSES (type)
== list_length (CLASSTYPE_VBASECLASSES (type)))
{
/* In this case, the offsets are allocated from right to left of
the declaration order in which the virtual bases appear. */
int i;
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
{
tree vbase = BINFO_BASETYPE (binfo, i);
init = BINFO_OFFSET (vbase);
init = build1 (NOP_EXPR, vtable_entry_type, init);
inits = tree_cons (NULL_TREE, init, inits);
}
}
else
{
tree list;
/* While in this case, the offsets are allocated in the reverse
order of a depth-first left-to-right traversal of the
hierarchy. We use BINFO_VTABLE_PATH_MARKED because we are
ourselves during a dfs_walk, and so BINFO_MARKED is already
in use. */
list = build_tree_list (type, NULL_TREE);
TREE_TYPE (list) = binfo;
dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries,
dfs_vtable_path_unmarked_real_bases_queue_p,
list);
dfs_walk (binfo,
dfs_vtable_path_unmark,
dfs_vtable_path_marked_real_bases_queue_p,
list);
inits = nreverse (TREE_VALUE (list));
}
/* The offsets are allocated in the reverse order of a
depth-first left-to-right traversal of the hierarchy. We use
BINFO_VTABLE_PATH_MARKED because we are ourselves during a
dfs_walk, and so BINFO_MARKED is already in use. */
list = build_tree_list (t, NULL_TREE);
TREE_TYPE (list) = binfo;
dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries,
dfs_vtable_path_unmarked_real_bases_queue_p,
list);
dfs_walk (binfo,
dfs_vtable_path_unmark,
dfs_vtable_path_marked_real_bases_queue_p,
list);
inits = nreverse (TREE_VALUE (list));
/* We've now got offsets in the right oder. However, the offsets
we've stored are offsets from the beginning of the complete
@ -334,9 +332,13 @@ build_vbase_offset_vtbl_entries (binfo)
tree exp = TREE_VALUE (init);
exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
exp = build1 (NOP_EXPR, vtable_entry_type, TREE_VALUE (init));
exp = build1 (NOP_EXPR, vtable_entry_type, exp);
exp = fold (exp);
TREE_CONSTANT (exp) = 1;
/* The dfs_build_vbase_offset_vtbl_entries routine uses the
TREE_PURPOSE to scribble in. But, we need to clear it now so
that the values are not perceived as labeled initializers. */
TREE_PURPOSE (init) = NULL_TREE;
TREE_VALUE (init) = exp;
}
@ -344,16 +346,41 @@ build_vbase_offset_vtbl_entries (binfo)
}
/* Returns a pointer to the virtual base class of EXP that has the
indicated TYPE. */
indicated TYPE. EXP is of class type, not a pointer type. */
static tree
build_vbase_pointer (exp, type)
tree exp, type;
{
char *name;
FORMAT_VBASE_NAME (name, type);
if (vbase_offsets_in_vtable_p ())
{
tree vbase;
tree vbase_ptr;
return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
/* Find the shared copy of TYPE; that's where the vtable offset
is recorded. */
vbase = BINFO_FOR_VBASE (type, TREE_TYPE (exp));
/* Find the virtual function table pointer. */
vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
/* Compute the location where the offset will lie. */
vbase_ptr = build_binary_op (PLUS_EXPR,
vbase_ptr,
BINFO_VPTR_FIELD (vbase));
vbase_ptr = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
vbase_ptr);
/* Add the contents of this location to EXP. */
return build (PLUS_EXPR,
build_pointer_type (type),
build_unary_op (ADDR_EXPR, exp, /*noconvert=*/0),
build1 (INDIRECT_REF, ptrdiff_type_node, vbase_ptr));
}
else
{
char *name;
FORMAT_VBASE_NAME (name, type);
return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
}
}
/* Build multi-level access to EXPR using hierarchy path PATH.
@ -1100,6 +1127,25 @@ get_vtable_entry_n (virtuals, n)
return virtuals;
}
/* Call this function whenever its known that a vtable for T is going
to be needed. It's safe to call it more than once. *HAS_VIRTUAL_P
is initialized to the number of slots that are reserved at the
beginning of the vtable for RTTI information. */
static void
start_vtable (t, has_virtual_p)
tree t;
int *has_virtual_p;
{
if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t))
{
if (flag_vtable_thunks)
*has_virtual_p = 2;
else
*has_virtual_p = 1;
}
}
/* Add a virtual function to all the appropriate vtables for the class
T. DECL_VINDEX(X) should be error_mark_node, if we want to
allocate a new slot in our table. If it is error_mark_node, we
@ -1139,13 +1185,7 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
/* If we are using thunks, use two slots at the front, one
for the offset pointer, one for the tdesc pointer.
For ARM-style vtables, use the same slot for both. */
if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
{
if (flag_vtable_thunks)
*has_virtual = 2;
else
*has_virtual = 1;
}
start_vtable (t, has_virtual);
/* Build a new INT_CST for this DECL_VINDEX. */
{
@ -1767,7 +1807,7 @@ determine_primary_base (t, has_virtual_p)
tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_POLYMORPHIC_P (basetype))
if (TYPE_CONTAINS_VPTR_P (basetype))
{
/* Even a virtual baseclass can contain our RTTI
information. But, we prefer a non-virtual polymorphic
@ -2287,9 +2327,8 @@ num_extra_vtbl_entries (binfo)
tree type;
int entries;
/* Under the old ABI, there are no entries at negative offsets. */
if (!flag_new_abi)
if (!vbase_offsets_in_vtable_p ())
return size_zero_node;
type = BINFO_TYPE (binfo);
@ -2317,18 +2356,20 @@ size_extra_vtbl_entries (binfo)
return fold (offset);
}
/* Construct the initializer for BINFOs virtual function table. */
/* Construct the initializer for BINFOs virtual function table. BINFO
is part of the hierarchy dominated by T. */
static tree
build_vtbl_initializer (binfo)
build_vtbl_initializer (binfo, t)
tree binfo;
tree t;
{
tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE;
tree type = BINFO_TYPE (binfo);
/* Add entries to the vtable for offsets to our virtual bases. */
inits = build_vbase_offset_vtbl_entries (binfo);
inits = build_vbase_offset_vtbl_entries (binfo, t);
/* Process the RTTI stuff at the head of the list. If we're not
using vtable thunks, then the RTTI entry is just an ordinary
@ -2397,7 +2438,7 @@ build_vtbl_initializer (binfo)
static tree
dfs_finish_vtbls (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
void *data;
{
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
@ -2409,7 +2450,7 @@ dfs_finish_vtbls (binfo, data)
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
DECL_INITIAL (decl) = build_vtbl_initializer (binfo);
DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
@ -4112,9 +4153,9 @@ check_bases_and_members (t, empty_p)
/* Check all the method declarations. */
check_methods (t);
/* A nearly-empty class has to be polymorphic; a nearly empty class
contains a vptr. */
if (!TYPE_POLYMORPHIC_P (t))
/* A nearly-empty class has to be vptr-containing; a nearly empty
class contains just a vptr. */
if (!TYPE_CONTAINS_VPTR_P (t))
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* Do some bookkeeping that will guide the generation of implicitly
@ -4177,6 +4218,12 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
add_virtual_function (pending_virtuals_p, pending_hard_virtuals_p,
has_virtual_p, fn, t);
/* Even if there weren't any new virtual functions, we might need a
new virtual function table if we're supposed to include vptrs in
all classes that need them. */
if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())
start_vtable (t, has_virtual_p);
/* If we couldn't find an appropriate base class, create a new field
here. */
if (*has_virtual_p && !TYPE_VFIELD (t))
@ -4771,7 +4818,7 @@ finish_struct_1 (t)
TYPE_VFIELD (t) = vfield;
}
if (flag_rtti && TYPE_POLYMORPHIC_P (t) && !pending_hard_virtuals)
if (flag_rtti && TYPE_CONTAINS_VPTR_P (t) && !pending_hard_virtuals)
modify_all_vtables (t, NULL_TREE);
for (pending_hard_virtuals = nreverse (pending_hard_virtuals);
@ -4802,9 +4849,9 @@ finish_struct_1 (t)
}
}
/* Under our model of GC, every C++ class gets its own virtual
function table, at least virtually. */
if (pending_virtuals)
/* If necessary, create the vtable for this class. */
if (pending_virtuals
|| (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))
{
pending_virtuals = nreverse (pending_virtuals);
/* We must enter these virtuals into the table. */
@ -4836,6 +4883,8 @@ finish_struct_1 (t)
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
/* If we didn't need a new vtable, see if we should copy one from
the base. */
else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
@ -4855,7 +4904,7 @@ finish_struct_1 (t)
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
if (TYPE_POLYMORPHIC_P (t))
if (TYPE_CONTAINS_VPTR_P (t))
{
CLASSTYPE_VSIZE (t) = has_virtual;
if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
@ -6004,7 +6053,7 @@ get_vfield_name (type)
char *buf;
while (BINFO_BASETYPES (binfo)
&& TYPE_POLYMORPHIC_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
&& TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
&& ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
binfo = BINFO_BASETYPE (binfo, 0);

View File

@ -177,7 +177,44 @@ Boston, MA 02111-1307, USA. */
#define RECORD_OR_UNION_TYPE_CHECK(NODE) NODE
#endif
/* ABI control. */
/* Nonzero to enable experimental ABI changes. */
extern int flag_new_abi;
/* Nonzero to use __cxa_atexit, rather than atexit, to register
destructors for local statics and global objects. */
extern int flag_use_cxa_atexit;
/* Nonzero to not ignore namespace std. */
extern int flag_honor_std;
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
/* Nonzero if virtual base class offsets are stored in the virtual
function table. Zero if, instead, a pointer to the virtual base is
stored in the object itself. */
#define vbase_offsets_in_vtable_p() (flag_new_abi)
/* Nonzero if a derived class that needs a vptr should always get one,
even if a non-primary base class already has one. For example,
given:
struct S { int i; virtual void f(); };
struct T : virtual public S {};
one could either reuse the vptr in `S' for `T', or create a new
vptr for `T'. If this flag is nonzero we choose the latter
alternative; otherwise, we choose the former. */
#define vptrs_present_everywhere_p() (flag_new_abi)
/* Language-dependent contents of an identifier. */
struct lang_identifier
@ -2156,6 +2193,12 @@ struct lang_decl
polymorphic class. */
#define TYPE_POLYMORPHIC_P(NODE) (TREE_LANG_FLAG_2 (NODE))
/* Nonzero if this class has a virtual function table pointer. */
#define TYPE_CONTAINS_VPTR_P(NODE) \
(TYPE_POLYMORPHIC_P (NODE) \
|| (vbase_offsets_in_vtable_p () \
&& TYPE_USES_VIRTUAL_BASECLASSES (NODE)))
extern int flag_new_for_scope;
/* This flag is true of a local VAR_DECL if it was declared in a for
@ -3160,10 +3203,6 @@ extern struct pending_inline *pending_inlines;
extern int flag_this_is_variable;
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
/* Nonzero means do emit exported implementations of functions even if
they can be inlined. */
@ -3187,19 +3226,6 @@ extern int flag_implicit_templates;
extern int flag_weak;
/* Nonzero to enable experimental ABI changes. */
extern int flag_new_abi;
/* Nonzero to use __cxa_atexit, rather than atexit, to register
destructors for local statics and global objects. */
extern int flag_use_cxa_atexit;
/* Nonzero to not ignore namespace std. */
extern int flag_honor_std;
/* Nonzero if we should expand functions calls inline at the tree
level, rather than at the RTL level. */
@ -3961,6 +3987,11 @@ extern tree dfs_walk PROTO((tree,
tree (*)(tree, void *),
tree (*) (tree, void *),
void *));
extern tree dfs_walk_real PROTO ((tree,
tree (*) (tree, void *),
tree (*) (tree, void *),
tree (*) (tree, void *),
void *));
extern tree dfs_unmark PROTO((tree, void *));
extern tree dfs_vbase_unmark PROTO((tree, void *));
extern tree dfs_vtable_path_unmark PROTO((tree, void *));

View File

@ -8201,15 +8201,7 @@ expand_static_init (decl, init)
finish_if_stmt ();
}
else
{
/* This code takes into account memory allocation policy of
`start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not
hold for this object, then we must make permanent the storage
currently in the temporary obstack. */
if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
preserve_initializer ();
static_aggregates = tree_cons (init, decl, static_aggregates);
}
static_aggregates = tree_cons (init, decl, static_aggregates);
}
/* Finish the declaration of a catch-parameter. */

View File

@ -2296,8 +2296,9 @@ mark_vtable_entries (decl)
fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
: FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
if (TREE_CODE (fnaddr) == NOP_EXPR)
/* RTTI offset. */
if (TREE_CODE (fnaddr) != ADDR_EXPR)
/* This entry is an offset: a virtual base class offset, a
virtual call offset, and RTTI offset, etc. */
continue;
fn = TREE_OPERAND (fnaddr, 0);

View File

@ -119,8 +119,12 @@ initialize_vtbl_ptrs (type, addr)
{
tree list = build_tree_list (type, addr);
dfs_walk (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
dfs_unmarked_real_bases_queue_p, list);
/* Walk through the hierarchy, initializing the vptr in each base
class. We do these in pre-order because under the new ABI we
can't find the virtual bases for a class until we've initialized
the vtbl for that class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
NULL, dfs_unmarked_real_bases_queue_p, list);
dfs_walk (TYPE_BINFO (type), dfs_unmark,
dfs_marked_real_bases_queue_p, type);
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
@ -657,7 +661,7 @@ expand_virtual_init (binfo, decl)
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
/* Under the new ABI, we need to point into the middle of the
vtable. */
if (flag_new_abi)
if (vbase_offsets_in_vtable_p ())
vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
size_extra_vtbl_entries (binfo));
@ -720,7 +724,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
/* Construct the virtual base-classes of THIS_REF (whose address is
THIS_PTR). The object has the indicated TYPE. The construction
actually takes place only if FLAG is non-zero. INIT_LIST is list
of initialization for constructor to perform. */
of initializations for constructors to perform. */
static void
construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
@ -731,21 +735,25 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
tree flag;
{
tree vbases;
tree result;
tree if_stmt;
/* If there are no virtual baseclasses, we shouldn't even be here. */
my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
/* First set the pointers in our object that tell us where to find
our virtual baseclasses. */
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, if_stmt);
result = init_vbase_pointers (type, this_ptr);
if (result)
finish_expr_stmt (build_compound_expr (result));
finish_then_clause (if_stmt);
finish_if_stmt ();
if (!vbase_offsets_in_vtable_p ())
{
tree if_stmt;
tree result;
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, if_stmt);
result = init_vbase_pointers (type, this_ptr);
if (result)
finish_expr_stmt (build_compound_expr (result));
finish_then_clause (if_stmt);
finish_if_stmt ();
}
/* Now, run through the baseclasses, initializing each. */
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
@ -1019,11 +1027,6 @@ finish_init_stmts (stmt_expr, compound_stmt)
If `init' is a CONSTRUCTOR, then we emit a warning message,
explaining that such initializations are invalid.
ALIAS_THIS is nonzero iff we are initializing something which is
essentially an alias for current_class_ref. In this case, the base
constructor may move it on us, and we must keep track of such
deviations.
If INIT resolves to a CALL_EXPR which happens to return
something of the type we are looking for, then we know
that we can safely use that call to perform the
@ -1217,8 +1220,6 @@ expand_default_init (binfo, true_exp, exp, init, flags)
from TRUE_EXP. In constructors, we don't know anything about
the value being initialized.
ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
FLAGS is just passes to `build_method_call'. See that function for
its description. */

View File

@ -1,5 +1,5 @@
/* RunTime Type Identification
Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
Copyright (C) 1995, 96-97, 1998, 1999, 2000 Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
@ -811,7 +811,8 @@ expand_class_desc (tdecl, type)
(type_info_type_node,
TYPE_QUAL_CONST)));
fields [1] = build_lang_decl
(FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
(FIELD_DECL, NULL_TREE,
flag_new_abi ? intSI_type_node : unsigned_intSI_type_node);
DECL_BIT_FIELD (fields[1]) = 1;
DECL_FIELD_SIZE (fields[1]) = 29;
@ -839,15 +840,26 @@ expand_class_desc (tdecl, type)
if (TREE_VIA_VIRTUAL (binfo))
{
tree t = BINFO_TYPE (binfo);
const char *name;
tree field;
if (!vbase_offsets_in_vtable_p ())
{
tree t = BINFO_TYPE (binfo);
const char *name;
tree field;
FORMAT_VBASE_NAME (name, t);
field = lookup_field (type, get_identifier (name), 0, 0);
offset = size_binop (FLOOR_DIV_EXPR,
DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
offset = convert (sizetype, offset);
FORMAT_VBASE_NAME (name, t);
field = lookup_field (type, get_identifier (name), 0, 0);
offset = size_binop (FLOOR_DIV_EXPR,
DECL_FIELD_BITPOS (field),
size_int (BITS_PER_UNIT));
offset = convert (sizetype, offset);
}
else
{
/* Under the new ABI, we store the vtable offset at which
the virtual base offset can be found. */
tree vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
offset = convert (sizetype, BINFO_VPTR_FIELD (vbase));
}
}
else
offset = BINFO_OFFSET (binfo);

View File

@ -126,11 +126,6 @@ static tree bfs_walk
void *));
static tree lookup_field_queue_p PROTO((tree, void *));
static tree lookup_field_r PROTO((tree, void *));
static tree dfs_walk_real PROTO ((tree,
tree (*) (tree, void *),
tree (*) (tree, void *),
tree (*) (tree, void *),
void *));
static tree get_virtuals_named_this_r PROTO ((tree, void *));
static tree context_for_name_lookup PROTO ((tree));
static tree canonical_binfo PROTO ((tree));
@ -1773,7 +1768,7 @@ bfs_walk (binfo, fn, qfn, data)
performed, and PREFN is called in preorder, while POSTFN is called
in postorder. */
static tree
tree
dfs_walk_real (binfo, prefn, postfn, qfn, data)
tree binfo;
tree (*prefn) PROTO((tree, void *));
@ -3200,9 +3195,9 @@ maybe_suppress_debug_info (t)
TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
else if (CLASSTYPE_INTERFACE_KNOWN (t))
/* Don't set it. */;
/* If the class has virtual functions, write out the debug info
along with the vtable. */
else if (TYPE_POLYMORPHIC_P (t))
/* If the class has a vtable, write out the debug info along with
the vtable. */
else if (TYPE_CONTAINS_VPTR_P (t))
TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
/* Otherwise, just emit the debug info normally. */

View File

@ -1,5 +1,5 @@
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
// Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation
// Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation
// This file is part of GNU CC.
@ -31,6 +31,34 @@
#include "tinfo.h"
#include "new" // for placement new
namespace
{
// ADDR is a pointer to an object. Convert it to a pointer to a base,
// using OFFSET.
inline void*
convert_to_base (void *addr, bool is_virtual, USItype offset)
{
if (!addr)
return NULL;
if (!is_virtual)
return (char *) addr + offset;
#ifdef __GXX_ABI_VERSION
// Under the new ABI, the offset gives us an index into the vtable,
// which contains an offset to the virtual base. The vptr is always
// the first thing in the object.
std::ptrdiff_t *vtable = *((std::ptrdiff_t **) addr);
return ((char *) addr) + vtable[offset];
#else
// Under the old ABI, the offset gives us the address of a pointer
// to the virtual base.
return *((void **) ((char *) addr + offset));
#endif
}
}
// This file contains the minimal working set necessary to link with code
// that uses virtual functions and -frtti but does not actually use RTTI
// functionality.
@ -254,14 +282,11 @@ do_upcast (sub_kind access_path,
upcast_result result2;
void *p = objptr;
sub_kind sub_access = access_path;
if (p)
p = (char *)p + base_list[i].offset;
p = convert_to_base (p,
base_list[i].is_virtual,
base_list[i].offset);
if (base_list[i].is_virtual)
{
if (p)
p = *(void **)p;
sub_access = sub_kind (sub_access | contained_virtual_mask);
}
sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base_list[i].access != PUBLIC)
sub_access = sub_kind (sub_access & ~contained_public_mask);
if (base_list[i].base->do_upcast (sub_access, target, p, result2))
@ -344,13 +369,13 @@ do_dyncast (int boff, sub_kind access_path,
for (size_t i = n_bases; i--;)
{
dyncast_result result2;
void *p = (char *)objptr + base_list[i].offset;
void *p;
sub_kind sub_access = access_path;
p = convert_to_base (objptr,
base_list[i].is_virtual,
base_list[i].offset);
if (base_list[i].is_virtual)
{
p = *(void **)p;
sub_access = sub_kind (sub_access | contained_virtual_mask);
}
sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base_list[i].access != PUBLIC)
sub_access = sub_kind (sub_access & ~contained_public_mask);
@ -492,13 +517,15 @@ do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *s
{
if (base_list[i].access != PUBLIC)
continue; // Not public, can't be here.
void *p = (char *)objptr + base_list[i].offset;
if (base_list[i].is_virtual)
{
if (boff == -1)
continue; // Not a virtual base, so can't be here.
p = *(void **)p;
}
void *p;
if (base_list[i].is_virtual && boff == -1)
// Not a virtual base, so can't be here.
continue;
p = convert_to_base (objptr,
base_list[i].is_virtual,
base_list[i].offset);
sub_kind base_kind = base_list[i].base->do_find_public_subobj
(boff, subtype, p, subptr);

View File

@ -1,5 +1,5 @@
// RTTI support internals for -*- C++ -*-
// Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation
// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation
#include "typeinfo"
@ -167,7 +167,11 @@ public:
// type_info for a general class.
#ifdef __GXX_ABI_VERSION
typedef int USItype __attribute__ ((mode (SI)));
#else
typedef unsigned int USItype __attribute__ ((mode (SI)));
#endif
struct __class_type_info : public __user_type_info {
enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };

View File

@ -860,7 +860,6 @@ make_binfo (offset, binfo, vtable, virtuals)
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
BINFO_VIRTUALS (new_binfo) = virtuals;
BINFO_VPTR_FIELD (new_binfo) = NULL_TREE;
if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));