* 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
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.
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));
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. */
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);
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);
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
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;
}
}
/* 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);
-
- return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
+ if (vbase_offsets_in_vtable_p ())
+ {
+ tree vbase;
+ tree vbase_ptr;
+
+ /* 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.
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
/* 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. */
{
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
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);
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
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))
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;
}
/* 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
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))
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);
}
}
- /* 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. */
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);
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))
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);
#define RECORD_OR_UNION_TYPE_CHECK(NODE) NODE
#endif
+\f
+/* 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)
+
+\f
/* Language-dependent contents of an identifier. */
struct lang_identifier
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
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. */
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. */
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 *));
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. */
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);
{
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))
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));
/* 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)
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;
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
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. */
/* 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.
(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;
if (TREE_VIA_VIRTUAL (binfo))
{
- 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);
+ 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);
+ }
+ 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);
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));
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 *));
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. */
// 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.
#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.
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))
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);
{
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);
// 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"
// 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 };
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));