aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c2036
1 files changed, 1052 insertions, 984 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 216d7e3cfea..a9f35951375 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -38,12 +38,6 @@ Boston, MA 02111-1307, USA. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-/* This is how we tell when two virtual member functions are really the
- same. */
-#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
-
-extern void set_class_shadows PARAMS ((tree));
-
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -68,6 +62,22 @@ typedef struct class_stack_node {
splay_tree names_used;
}* class_stack_node_t;
+typedef struct vcall_offset_data_s
+{
+ /* The binfo for the most-derived type. */
+ tree derived;
+ /* The binfo for the virtual base for which we're building
+ initializers. */
+ tree vbase;
+ /* The vcall offset initializers built up so far. */
+ tree inits;
+ /* The vtable index of the next vcall or vbase offset. */
+ tree index;
+ /* Nonzero if we are building the initializer for the primary
+ vtable. */
+ int primary_p;
+} vcall_offset_data;
+
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
static int current_class_stack_size;
@@ -80,7 +90,6 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
-static void set_rtti_entry PARAMS ((tree, tree, tree));
static int build_primary_vtable PARAMS ((tree, tree));
static int build_secondary_vtable PARAMS ((tree, tree));
static tree dfs_finish_vtbls PARAMS ((tree, void *));
@@ -109,7 +118,7 @@ static tree fixed_type_or_null PARAMS ((tree, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, tree));
static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
-static tree build_vtbl_initializer PARAMS ((tree, tree));
+static tree build_vtbl_initializer PARAMS ((tree, tree, int *));
static int count_fields PARAMS ((tree));
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
@@ -136,20 +145,17 @@ static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_virtual_bases PARAMS ((tree, varray_type *));
static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
-static tree dfs_build_vbase_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vbase_offset_vtbl_entries PARAMS ((tree, tree));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
-static tree dfs_count_virtuals PARAMS ((tree, void *));
-static void start_vtable PARAMS ((tree, int *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static void layout_vtable_decl PARAMS ((tree, int));
-static int num_vfun_entries PARAMS ((tree));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
static tree dfs_find_base PARAMS ((tree, void *));
static int make_new_vtable PARAMS ((tree, tree));
-extern void dump_class_hierarchy PARAMS ((tree, int));
+static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
+extern void dump_class_hierarchy PARAMS ((tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
@@ -162,6 +168,12 @@ static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree));
+static void set_vindex PARAMS ((tree, tree, int *));
+static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
+static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
+ vcall_offset_data *));
+static tree dfs_mark_primary_bases PARAMS ((tree, void *));
+static void mark_primary_bases PARAMS ((tree));
/* Variables shared between class.c and call.c. */
@@ -243,7 +255,7 @@ build_vbase_pointer_fields (rli, empty_p)
empty_p);
BINFO_VPTR_FIELD (base_binfo) = decl;
TREE_CHAIN (decl) = vbase_decls;
- layout_field (rli, decl);
+ place_field (rli, decl);
vbase_decls = decl;
*empty_p = 0;
@@ -256,236 +268,6 @@ build_vbase_pointer_fields (rli, empty_p)
return vbase_decls;
}
-/* Called from build_vbase_offset_vtbl_entries via dfs_walk. */
-
-static tree
-dfs_build_vbase_offset_vtbl_entries (binfo, data)
- tree binfo;
- void *data;
-{
- tree list = (tree) data;
-
- if (TREE_TYPE (list) == binfo)
- /* The TREE_TYPE of LIST is the base class from which we started
- walking. If that BINFO is virtual it's not a virtual baseclass
- of itself. */
- ;
- 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 (BINFO_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)
- = fold (build (MINUS_EXPR, integer_type_node,
- BINFO_VPTR_FIELD (vbase), integer_one_node));
- }
-
- /* And record the offset at which this virtual base lies in the
- vtable. */
- init = BINFO_OFFSET (binfo);
- 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
- for BINFO (which is part of the class hierarchy dominated by T), in
- reverse order. */
-
-static tree
-build_vbase_offset_vtbl_entries (binfo, t)
- tree binfo;
- tree t;
-{
- tree inits;
- tree init;
- tree list;
-
- /* Under the old ABI, pointers to virtual bases are stored in each
- object. */
- if (!vbase_offsets_in_vtable_p ())
- return NULL_TREE;
-
- /* If there are no virtual baseclasses, then there is nothing to
- do. */
- if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- return NULL_TREE;
-
- inits = NULL_TREE;
-
- /* 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 order. However, the offsets
- we've stored are offsets from the beginning of the complete
- object, and we need offsets from this BINFO. */
- for (init = inits; init; init = TREE_CHAIN (init))
- {
- /* 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)
- = fold (build1 (NOP_EXPR, vtable_entry_type,
- size_diffop (TREE_VALUE (init),
- BINFO_OFFSET (binfo))));
- }
-
- return inits;
-}
-
-typedef struct vcall_offset_data_s
-{
- /* The binfo for the most-derived type. */
- tree derived;
- /* The binfo for the virtual base for which we're building
- initializers. */
- tree vbase;
- /* The vcall offset initializers built up so far. */
- tree inits;
- /* The number of vcall offsets accumulated. */
- int offsets;
-} vcall_offset_data;
-
-/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
-
-static tree
-dfs_vcall_offset_queue_p (binfo, data)
- tree binfo;
- void *data;
-{
- vcall_offset_data* vod = (vcall_offset_data *) data;
-
- return (binfo == vod->vbase) ? binfo : dfs_skip_vbases (binfo, NULL);
-}
-
-/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
-
-static tree
-dfs_build_vcall_offset_vtbl_entries (binfo, data)
- tree binfo;
- void *data;
-{
- vcall_offset_data* vod;
- tree virtuals;
- tree binfo_inits;
-
- /* Primary bases are not interesting; all of the virtual
- function table entries have been overridden. */
- if (BINFO_PRIMARY_MARKED_P (binfo))
- return NULL_TREE;
-
- vod = (vcall_offset_data *) data;
- binfo_inits = NULL_TREE;
-
- /* We chain the offsets on in reverse order. That's correct --
- build_vtbl_initializer will straighten them out. */
- for (virtuals = skip_rtti_stuff (binfo,
- BINFO_TYPE (binfo),
- NULL);
- virtuals;
- virtuals = TREE_CHAIN (virtuals))
- {
- /* Figure out what function we're looking at. */
- tree fn = TREE_VALUE (virtuals);
- tree base = DECL_CONTEXT (fn);
- /* The FN comes from BASE. So, we must caculate the adjustment
- from the virtual base that derived from BINFO to BASE. */
- tree base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
-
- binfo_inits
- = tree_cons (NULL_TREE,
- fold (build1 (NOP_EXPR, vtable_entry_type,
- size_diffop (BINFO_OFFSET (base_binfo),
- BINFO_OFFSET (vod->vbase)))),
- binfo_inits);
- }
-
- /* Now add the initializers we've just created to the list that will
- be returned to our caller. */
- vod->inits = chainon (vod->inits, binfo_inits);
-
- return NULL_TREE;
-}
-
-/* Returns the initializers for the vcall offset entries in the vtable
- for BINFO (which is part of the class hierarchy dominated by T), in
- reverse order. */
-
-static tree
-build_vcall_offset_vtbl_entries (binfo, t)
- tree binfo;
- tree t;
-{
- vcall_offset_data vod;
-
- /* Under the old ABI, the adjustments to the `this' pointer were made
- elsewhere. */
- if (!vcall_offsets_in_vtable_p ())
- return NULL_TREE;
-
- /* We only need these entries if this base is a virtual base. */
- if (!TREE_VIA_VIRTUAL (binfo))
- return NULL_TREE;
-
- /* We need a vcall offset for each of the virtual functions in this
- vtable. For example:
-
- class A { virtual void f (); };
- class B : virtual public A { };
- class C: virtual public A, public B {};
-
- Now imagine:
-
- B* b = new C;
- b->f();
-
- The location of `A' is not at a fixed offset relative to `B'; the
- offset depends on the complete object derived from `B'. So,
- `B' vtable contains an entry for `f' that indicates by what
- amount the `this' pointer for `B' needs to be adjusted to arrive
- at `A'.
-
- We need entries for all the functions in our primary vtable and
- in our non-virtual bases vtables. For each base, the entries
- appear in the same order as in the base; but the bases themselves
- appear in reverse depth-first, left-to-right order. */
- vod.derived = t;
- vod.vbase = binfo;
- vod.inits = NULL_TREE;
- dfs_walk (binfo,
- dfs_build_vcall_offset_vtbl_entries,
- dfs_vcall_offset_queue_p,
- &vod);
-
- return vod.inits;
-}
-
/* Returns a pointer to the virtual base class of EXP that has the
indicated TYPE. EXP is of class type, not a pointer type. */
@@ -504,9 +286,10 @@ build_vbase_pointer (exp, type)
/* 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 = build (PLUS_EXPR,
+ TREE_TYPE (vbase_ptr),
+ vbase_ptr,
+ BINFO_VPTR_FIELD (vbase));
vbase_ptr = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
vbase_ptr);
@@ -678,75 +461,6 @@ build_vbase_path (code, type, expr, path, nonnull)
/* Virtual function things. */
-/* Build an entry in the virtual function table. DELTA is the offset
- for the `this' pointer. VCALL_INDEX is the vtable index containing
- the vcall offset; zero if none. ENTRY is the virtual function
- table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
- but it may not actually be a virtual function table pointer. (For
- example, it might be the address of the RTTI object, under the new
- ABI.) */
-
-static tree
-build_vtable_entry (delta, vcall_index, entry)
- tree delta;
- tree vcall_index;
- tree entry;
-{
- if (flag_vtable_thunks)
- {
- HOST_WIDE_INT idelta;
- HOST_WIDE_INT ivindex;
-
- idelta = tree_low_cst (delta, 0);
- ivindex = tree_low_cst (vcall_index, 0);
- if ((idelta || ivindex)
- && ! DECL_PURE_VIRTUAL_P (TREE_OPERAND (entry, 0)))
- {
- entry = make_thunk (entry, idelta, ivindex);
- entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
- TREE_READONLY (entry) = 1;
- TREE_CONSTANT (entry) = 1;
- }
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
- return entry;
- }
- else
- {
- extern int flag_huge_objects;
- tree elems = tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, integer_zero_node,
- build_tree_list (NULL_TREE, entry)));
- tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
-
- /* We don't use vcall offsets when not using vtable thunks. */
- my_friendly_assert (integer_zerop (vcall_index), 20000125);
-
- /* DELTA used to be constructed by `size_int' and/or size_binop,
- which caused overflow problems when it was negative. That should
- be fixed now. */
-
- if (! int_fits_type_p (delta, delta_type_node))
- {
- if (flag_huge_objects)
- sorry ("object size exceeds built-in limit for virtual function table implementation");
- else
- sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
- }
-
- TREE_CONSTANT (entry) = 1;
- TREE_STATIC (entry) = 1;
- TREE_READONLY (entry) = 1;
-
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
-
- return entry;
- }
-}
-
/* We want to give the assembler the vtable identifier as well as
the offset to the function pointer. So we generate
@@ -761,7 +475,7 @@ build_vtable_entry_ref (basetype, vtbl, idx)
static char asm_stmt[] = ".vtable_entry %c0, %c1";
tree s, i, i2;
- s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
+ s = build_unary_op (ADDR_EXPR, get_vtbl_decl_for_binfo (basetype), 0);
s = build_tree_list (build_string (1, "s"), s);
i = build_array_ref (vtbl, idx);
@@ -832,7 +546,23 @@ build_vtbl_ref (instance, idx)
&& (TREE_CODE (instance) == RESULT_DECL
|| TREE_CODE (instance) == PARM_DECL
|| TREE_CODE (instance) == VAR_DECL))
- vtbl = TYPE_BINFO_VTABLE (basetype);
+ {
+ vtbl = TYPE_BINFO_VTABLE (basetype);
+ /* Knowing the dynamic type of INSTANCE we can easily obtain
+ the correct vtable entry. In the new ABI, we resolve
+ this back to be in terms of the primary vtable. */
+ if (TREE_CODE (vtbl) == PLUS_EXPR)
+ {
+ idx = fold (build (PLUS_EXPR,
+ TREE_TYPE (idx),
+ idx,
+ build (EXACT_DIV_EXPR,
+ TREE_TYPE (idx),
+ TREE_OPERAND (vtbl, 1),
+ TYPE_SIZE_UNIT (vtable_entry_type))));
+ vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
+ }
+ }
else
vtbl = build_vfield_ref (instance, basetype);
}
@@ -912,13 +642,9 @@ tree
get_vfield_offset (binfo)
tree binfo;
{
- tree tmp
- = size_binop (FLOOR_DIV_EXPR,
- bit_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
- bitsize_int (BITS_PER_UNIT));
-
- return size_binop (PLUS_EXPR, convert (sizetype, tmp),
- BINFO_OFFSET (binfo));
+ return
+ size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
+ BINFO_OFFSET (binfo));
}
/* Get the offset to the start of the original binfo that we derived
@@ -949,47 +675,6 @@ get_derived_offset (binfo, type)
return size_binop (MINUS_EXPR, offset1, offset2);
}
-/* Update the rtti info for this class. */
-
-static void
-set_rtti_entry (virtuals, offset, type)
- tree virtuals, offset, type;
-{
- tree decl;
-
- if (CLASSTYPE_COM_INTERFACE (type))
- return;
-
- if (flag_rtti)
- decl = get_tinfo_decl (type);
- else if (!new_abi_rtti_p ())
- /* If someone tries to get RTTI information for a type compiled
- without RTTI, they're out of luck. By calling __pure_virtual
- in this case, we give a small clue as to what went wrong. We
- could consider having a __no_typeinfo function as well, for a
- more specific hint. */
- decl = abort_fndecl;
- else
- /* For the new-abi, we just point to the type_info object. */
- decl = NULL_TREE;
-
- if (flag_vtable_thunks)
- {
- /* The first slot holds the offset. */
- BV_DELTA (virtuals) = offset;
- BV_VCALL_INDEX (virtuals) = integer_zero_node;
-
- /* The next node holds the decl. */
- virtuals = TREE_CHAIN (virtuals);
- offset = integer_zero_node;
- }
-
- /* This slot holds the function to call. */
- BV_DELTA (virtuals) = offset;
- BV_VCALL_INDEX (virtuals) = integer_zero_node;
- BV_FN (virtuals) = decl;
-}
-
/* Create a VAR_DECL for a primary or secondary vtable for
CLASS_TYPE. Use NAME for the name of the vtable, and VTABLE_TYPE
for its type. */
@@ -1071,23 +756,15 @@ build_primary_vtable (binfo, type)
if (binfo)
{
- tree offset;
-
if (BINFO_NEW_VTABLE_MARKED (binfo, type))
/* We have already created a vtable for this base, so there's
no need to do it again. */
return 0;
virtuals = copy_list (BINFO_VIRTUALS (binfo));
- TREE_TYPE (decl) = TREE_TYPE (BINFO_VTABLE (binfo));
- DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
- DECL_SIZE_UNIT (decl)
- = TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo)));
-
- /* Now do rtti stuff. */
- offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
- offset = size_diffop (size_zero_node, offset);
- set_rtti_entry (virtuals, offset, type);
+ TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo));
+ DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
+ DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
}
else
{
@@ -1175,10 +852,6 @@ build_secondary_vtable (binfo, for_type)
else
offset = BINFO_OFFSET (binfo);
- set_rtti_entry (BINFO_VIRTUALS (binfo),
- size_diffop (size_zero_node, offset),
- for_type);
-
/* In the new ABI, secondary vtables are laid out as part of the
same structure as the primary vtable. */
if (merge_primary_and_secondary_vtables_p ())
@@ -1353,42 +1026,52 @@ modify_vtable_entry (t, binfo, fndecl, delta, 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. */
+/* Return the index (in the virtual function table) of the first
+ virtual function. */
+
+int
+first_vfun_index (t)
+ tree t;
+{
+ /* Under the old ABI, the offset-to-top and RTTI entries are at
+ indices zero and one; under the new ABI, the first virtual
+ function is at index zero. */
+ if (!CLASSTYPE_COM_INTERFACE (t) && !flag_new_abi)
+ return flag_vtable_thunks ? 2 : 1;
+
+ return 0;
+}
+
+/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual
+ functions present in the vtable so far. */
static void
-start_vtable (t, has_virtual_p)
+set_vindex (t, decl, vfuns_p)
tree t;
- int *has_virtual_p;
+ tree decl;
+ int *vfuns_p;
{
- if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (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 (flag_vtable_thunks)
- *has_virtual_p = 2;
- else
- *has_virtual_p = 1;
- }
+ int vindex;
+
+ vindex = (*vfuns_p)++;
+ vindex += first_vfun_index (t);
+ DECL_VINDEX (decl) = build_shared_int_cst (vindex);
}
/* 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
know that no other function from another vtable is overridden by X.
- HAS_VIRTUAL keeps track of how many virtuals there are in our main
- vtable for the type, and we build upon the NEW_VIRTUALS list
+ VFUNS_P keeps track of how many virtuals there are in our
+ main vtable for the type, and we build upon the NEW_VIRTUALS list
and return it. */
static void
add_virtual_function (new_virtuals_p, overridden_virtuals_p,
- has_virtual, fndecl, t)
+ vfuns_p, fndecl, t)
tree *new_virtuals_p;
tree *overridden_virtuals_p;
- int *has_virtual;
+ int *vfuns_p;
tree fndecl;
tree t; /* Structure type. */
{
@@ -1413,10 +1096,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
/* We remember that this was the base sub-object for rtti. */
CLASSTYPE_RTTI (t) = t;
- start_vtable (t, has_virtual);
-
/* Now assign virtual dispatch information. */
- DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++);
+ set_vindex (t, fndecl, vfuns_p);
DECL_VIRTUAL_CONTEXT (fndecl) = t;
/* Save the state we've computed on the NEW_VIRTUALS list. */
@@ -1970,13 +1651,104 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
}
}
+/* Called via dfs_walk from mark_primary_bases. Sets
+ BINFO_PRIMARY_MARKED_P for BINFO, if appropriate. */
+
+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_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. */
+
+static void
+mark_primary_bases (type)
+ tree type;
+{
+ tree vbases;
+
+ /* 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 in inheritance graph
+ order. Any that are not already primary will need to be
+ allocated in TYPE, and so we need to mark their primary bases. */
+ for (vbases = TYPE_BINFO (type); vbases; vbases = TREE_CHAIN (vbases))
+ {
+ tree vbase;
+
+ /* Make sure that only BINFOs appear on this list.
+ Historically, the TREE_CHAIN was used for other purposes, and
+ we want to make sure that none of those uses remain. */
+ my_friendly_assert (TREE_CODE (vbases) == TREE_VEC, 20000402);
+
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+
+ vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), type);
+ 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_real (vbase, dfs_mark_primary_bases, NULL,
+ dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+ /* VBASE wasn't really primary. */
+ BINFO_PRIMARY_MARKED_P (vbase) = 0;
+ }
+}
+
/* Make the Ith baseclass of T its primary base. */
static void
-set_primary_base (t, i, has_virtual_p)
+set_primary_base (t, i, vfuns_p)
tree t;
int i;
- int *has_virtual_p;
+ int *vfuns_p;
{
tree basetype;
@@ -1986,15 +1758,15 @@ set_primary_base (t, i, has_virtual_p)
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
- *has_virtual_p = CLASSTYPE_VSIZE (basetype);
+ *vfuns_p = CLASSTYPE_VSIZE (basetype);
}
/* Determine the primary class for T. */
static void
-determine_primary_base (t, has_virtual_p)
+determine_primary_base (t, vfuns_p)
tree t;
- int *has_virtual_p;
+ int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
@@ -2002,7 +1774,7 @@ determine_primary_base (t, has_virtual_p)
if (n_baseclasses == 0)
return;
- *has_virtual_p = 0;
+ *vfuns_p = 0;
for (i = 0; i < n_baseclasses; i++)
{
@@ -2025,7 +1797,7 @@ determine_primary_base (t, has_virtual_p)
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- set_primary_base (t, i, has_virtual_p);
+ set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
@@ -2043,8 +1815,8 @@ determine_primary_base (t, has_virtual_p)
VF_BASETYPE_VALUE (vfields),
CLASSTYPE_VFIELDS (t));
- if (*has_virtual_p == 0)
- set_primary_base (t, i, has_virtual_p);
+ if (!flag_new_abi && *vfuns_p == 0)
+ set_primary_base (t, i, vfuns_p);
}
}
}
@@ -2064,7 +1836,7 @@ determine_primary_base (t, has_virtual_p)
if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
- set_primary_base (t, i, has_virtual_p);
+ set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
break;
}
@@ -2531,6 +2303,7 @@ layout_vtable_decl (binfo, n)
{
tree itype;
tree atype;
+ tree vtable;
itype = size_int (n);
atype = build_cplus_array_type (vtable_entry_type,
@@ -2538,12 +2311,11 @@ layout_vtable_decl (binfo, n)
layout_type (atype);
/* We may have to grow the vtable. */
- if (!same_type_p (TREE_TYPE (BINFO_VTABLE (binfo)), atype))
+ vtable = get_vtbl_decl_for_binfo (binfo);
+ if (!same_type_p (TREE_TYPE (vtable), atype))
{
- tree vtable = BINFO_VTABLE (binfo);
-
TREE_TYPE (vtable) = atype;
- DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = 0;
+ DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = NULL_TREE;
layout_decl (vtable, 0);
/* At one time the vtable info was grabbed 2 words at a time. This
@@ -2553,328 +2325,6 @@ layout_vtable_decl (binfo, n)
}
}
-/* Returns the number of virtual function table entries (excluding
- RTTI information, vbase and vcall offests, etc.) in the vtable for
- BINFO. */
-
-static int
-num_vfun_entries (binfo)
- tree binfo;
-{
- return list_length (skip_rtti_stuff (binfo,
- BINFO_TYPE (binfo),
- NULL));
-}
-
-/* Called from num_extra_vtbl_entries via dfs_walk. */
-
-static tree
-dfs_count_virtuals (binfo, data)
- tree binfo;
- void *data;
-{
- /* Non-primary bases are not interesting; all of the virtual
- function table entries have been overridden. */
- if (!BINFO_PRIMARY_MARKED_P (binfo))
- ((vcall_offset_data *) data)->offsets += num_vfun_entries (binfo);
-
- return NULL_TREE;
-}
-
-/* Returns the number of extra entries (at negative indices) required
- for BINFO's vtable. */
-
-tree
-num_extra_vtbl_entries (binfo)
- tree binfo;
-{
- tree type;
- int entries;
-
- type = BINFO_TYPE (binfo);
- entries = 0;
-
- /* There is an entry for the offset to each virtual base. */
- if (vbase_offsets_in_vtable_p ())
- entries += list_length (CLASSTYPE_VBASECLASSES (type));
-
- /* If this is a virtual base, there are entries for each virtual
- function defined in this class or its bases. */
- if (vcall_offsets_in_vtable_p () && TREE_VIA_VIRTUAL (binfo))
- {
- vcall_offset_data vod;
-
- vod.vbase = binfo;
- vod.offsets = 0;
- dfs_walk (binfo,
- dfs_count_virtuals,
- dfs_vcall_offset_queue_p,
- &vod);
- entries += vod.offsets;
- }
-
- return entries ? size_int (entries) : size_zero_node;
-}
-
-/* Returns the offset (in bytes) from the beginning of BINFO's vtable
- where the vptr should actually point. */
-
-tree
-size_extra_vtbl_entries (binfo)
- tree binfo;
-{
- tree offset = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type),
- num_extra_vtbl_entries (binfo));
- return fold (offset);
-}
-
-/* Construct the initializer for BINFOs virtual function table. BINFO
- is part of the hierarchy dominated by T. The value returned is a
- TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
- DECL_INITIAL for a vtable. */
-
-static tree
-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 that indicate how to adjust the this
- pointer when calling a virtual function in this class. */
- inits = build_vcall_offset_vtbl_entries (binfo, t);
-
- /* Add entries to the vtable for offsets to our virtual bases. */
- inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
- inits);
-
- /* 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
- function, and we can process it just like the other virtual
- function entries. */
- if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks)
- {
- tree offset;
- tree init;
-
- /* The first entry is an offset. */
- offset = TREE_PURPOSE (v);
- my_friendly_assert (TREE_CODE (offset) == INTEGER_CST,
- 19990727);
-
- /* Convert the offset to look like a function pointer, so that
- we can put it in the vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (init) = 1;
- inits = tree_cons (NULL_TREE, init, inits);
-
- v = TREE_CHAIN (v);
-
- if (new_abi_rtti_p ())
- {
- tree decl = TREE_VALUE (v);
-
- if (decl)
- decl = build_unary_op (ADDR_EXPR, decl, 0);
- else
- decl = integer_zero_node;
- decl = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
- TREE_CONSTANT (decl) = 1;
- decl = build_vtable_entry (integer_zero_node, integer_zero_node,
- decl);
- inits = tree_cons (NULL_TREE, decl, inits);
-
- v = TREE_CHAIN (v);
- }
- /* In the old abi the second entry (the tdesc pointer) is
- just an ordinary function, so it can be dealt with like the
- virtual functions. */
- }
-
- /* Go through all the ordinary virtual functions, building up
- initializers. */
- while (v)
- {
- tree delta;
- tree vcall_index;
- tree fn;
- tree pfn;
- tree init;
-
- /* Pull the offset for `this', and the function to call, out of
- the list. */
- delta = BV_DELTA (v);
- vcall_index = BV_VCALL_INDEX (v);
- fn = BV_FN (v);
- my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
- my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
-
- /* You can't call an abstract virtual function; it's abstract.
- So, we replace these functions with __pure_virtual. */
- if (DECL_PURE_VIRTUAL_P (fn))
- fn = abort_fndecl;
-
- /* Take the address of the function, considering it to be of an
- appropriate generic type. */
- pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
- /* The address of a function can't change. */
- TREE_CONSTANT (pfn) = 1;
- /* Enter it in the vtable. */
- init = build_vtable_entry (delta, vcall_index, pfn);
- /* And add it to the chain of initializers. */
- inits = tree_cons (NULL_TREE, init, inits);
-
- /* Keep going. */
- v = TREE_CHAIN (v);
- }
-
- /* The initializers were built up in reverse order; straighten them
- out now. */
- return nreverse (inits);
-}
-
-/* Initialize the vtable for BINFO with the INITS. */
-
-static void
-initialize_vtable (binfo, inits)
- tree binfo;
- tree inits;
-{
- tree context;
- tree decl;
-
- layout_vtable_decl (binfo, list_length (inits));
- decl = BINFO_VTABLE (binfo);
- context = DECL_CONTEXT (decl);
- DECL_CONTEXT (decl) = 0;
- DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
- cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
- DECL_CONTEXT (decl) = context;
-}
-
-/* Called from finish_vtbls via dfs_walk. */
-
-static tree
-dfs_finish_vtbls (binfo, data)
- tree binfo;
- void *data;
-{
- tree t = (tree) data;
-
- if (!BINFO_PRIMARY_MARKED_P (binfo)
- && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
- && BINFO_NEW_VTABLE_MARKED (binfo, t))
- initialize_vtable (binfo,
- build_vtbl_initializer (binfo, t));
-
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
- SET_BINFO_MARKED (binfo);
-
- return NULL_TREE;
-}
-
-/* Called from finish_vtbls via dfs_walk when using the new ABI.
- Accumulates the vtable initializers for all of the vtables into
- TREE_VALUE (DATA). */
-
-static tree
-dfs_accumulate_vtbl_inits (binfo, data)
- tree binfo;
- void *data;
-{
- tree l;
- tree t;
-
- l = (tree) data;
- t = TREE_PURPOSE (l);
-
- if (!BINFO_PRIMARY_MARKED_P (binfo)
- && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
- && BINFO_NEW_VTABLE_MARKED (binfo, t))
- {
-
- /* If this is a secondary vtable, record its location. */
- if (binfo != TYPE_BINFO (t))
- {
- tree vtbl;
-
- vtbl = TYPE_BINFO_VTABLE (t);
- vtbl = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (vtbl)),
- vtbl);
- BINFO_VTABLE (binfo)
- = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
- size_binop (MULT_EXPR,
- TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
- size_int (list_length (TREE_VALUE (l)))));
- }
-
- /* Add the initializers for this vtable to the initializers for
- the other vtables we've already got. */
- TREE_VALUE (l)
- = chainon (TREE_VALUE (l),
- build_vtbl_initializer (binfo, t));
- }
-
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
-
- return NULL_TREE;
-}
-
-/* Add the vtbl initializers for BINFO (and its non-primary,
- non-virtual bases) to the list of INITS. */
-
-static void
-accumulate_vtbl_inits (binfo, inits)
- tree binfo;
- tree inits;
-{
- /* Walk the BINFO and its bases. */
- dfs_walk_real (binfo,
- dfs_accumulate_vtbl_inits,
- NULL,
- dfs_skip_vbases,
- inits);
-}
-
-/* Create all the necessary vtables for T and its base classes. */
-
-static void
-finish_vtbls (t)
- tree t;
-{
- if (merge_primary_and_secondary_vtables_p ())
- {
- tree list;
- tree vbase;
-
- /* Under the new ABI, we lay out the primary and secondary
- vtables in one contiguous vtable. The primary vtable is
- first, followed by the non-virtual secondary vtables in
- inheritance graph order. */
- list = build_tree_list (t, NULL_TREE);
- accumulate_vtbl_inits (TYPE_BINFO (t), list);
- /* Then come the virtual bases, also in inheritance graph
- order. */
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
- accumulate_vtbl_inits (vbase, list);
-
- if (TYPE_BINFO_VTABLE (t))
- initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
- }
- else
- {
- dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
- dfs_unmarked_real_bases_queue_p, t);
- dfs_walk (TYPE_BINFO (t), dfs_unmark,
- dfs_marked_real_bases_queue_p, t);
- }
-}
-
/* True if we should override the given BASE_FNDECL with the given
FNDECL. */
@@ -3053,43 +2503,6 @@ find_final_overrider (t, binfo, fn)
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
}
-/* Return the BINFO_VIRTUALS list for BINFO, without the RTTI stuff at
- the front. If non-NULL, N is set to the number of entries
- skipped. */
-
-tree
-skip_rtti_stuff (binfo, t, n)
- tree binfo;
- tree t;
- HOST_WIDE_INT *n;
-{
- tree virtuals;
-
- if (CLASSTYPE_COM_INTERFACE (t))
- return 0;
-
- if (n)
- *n = 0;
- virtuals = BINFO_VIRTUALS (binfo);
- if (virtuals)
- {
- /* We always reserve a slot for the offset/tdesc entry. */
- if (n)
- ++*n;
- virtuals = TREE_CHAIN (virtuals);
- }
- if (flag_vtable_thunks && virtuals)
- {
- /* The second slot is reserved for the tdesc pointer when thunks
- are used. */
- if (n)
- ++*n;
- virtuals = TREE_CHAIN (virtuals);
- }
-
- return virtuals;
-}
-
/* Called via dfs_walk. Returns BINFO if BINFO has the same type as
DATA (which is really an _TYPE node). */
@@ -3130,10 +2543,8 @@ dfs_modify_vtables (binfo, data)
/* Now, go through each of the virtual functions in the virtual
function table for BINFO. Find the final overrider, and
update the BINFO_VIRTUALS list appropriately. */
- for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL),
- old_virtuals = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (binfo)),
- BINFO_TYPE (binfo),
- NULL);
+ for (virtuals = BINFO_VIRTUALS (binfo),
+ old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
virtuals;
virtuals = TREE_CHAIN (virtuals),
old_virtuals = TREE_CHAIN (old_virtuals))
@@ -3143,17 +2554,16 @@ dfs_modify_vtables (binfo, data)
tree overrider;
tree vindex;
tree delta;
- HOST_WIDE_INT vindex_val, i;
-
+ HOST_WIDE_INT vindex_val;
+ HOST_WIDE_INT i;
/* Find the function which originally caused this vtable
entry to be present. */
fn = BV_FN (old_virtuals);
vindex = DECL_VINDEX (fn);
b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
- fn = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (b)),
- BINFO_TYPE (b),
- &i);
+ fn = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (b)));
+ i = first_vfun_index (BINFO_TYPE (b));
vindex_val = tree_low_cst (vindex, 0);
while (i < vindex_val)
{
@@ -3200,9 +2610,9 @@ dfs_modify_vtables (binfo, data)
which should therefore be appended to the end of the vtable for T. */
static tree
-modify_all_vtables (t, has_virtual_p, overridden_virtuals)
+modify_all_vtables (t, vfuns_p, overridden_virtuals)
tree t;
- int *has_virtual_p;
+ int *vfuns_p;
tree overridden_virtuals;
{
tree binfo;
@@ -3229,11 +2639,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
if (BINFO_VIRTUALS (binfo)
&& !value_member (fn, BINFO_VIRTUALS (binfo)))
{
- /* We know we need a vtable for this class now. */
- start_vtable (t, has_virtual_p);
/* Set the vtable index. */
- DECL_VINDEX (fn)
- = build_shared_int_cst ((*has_virtual_p)++);
+ set_vindex (t, fn, vfuns_p);
/* We don't need to convert to a base class when calling
this function. */
DECL_VIRTUAL_CONTEXT (fn) = t;
@@ -3763,7 +3170,7 @@ check_field_decl (field, t, cant_have_const_ctor,
tree fields;
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- if (TREE_CODE (field) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
+ if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
check_field_decl (fields, t, cant_have_const_ctor,
cant_have_default_ctor, no_const_asn_ref,
any_default_members);
@@ -3927,7 +3334,7 @@ check_field_decls (t, access_decls, empty_p,
/* If we've gotten this far, it's a data member, possibly static,
or an enumerator. */
- DECL_FIELD_CONTEXT (x) = t;
+ DECL_CONTEXT (x) = t;
/* ``A local class cannot have static data members.'' ARM 9.4 */
if (current_function_decl && TREE_STATIC (x))
@@ -3958,8 +3365,6 @@ check_field_decls (t, access_decls, empty_p,
if (type == error_mark_node)
continue;
- DECL_SAVED_INSNS (x) = 0;
-
/* When this goes into scope, it will be a non-local reference. */
DECL_NONLOCAL (x) = 1;
@@ -4115,29 +3520,12 @@ build_vtbl_or_vbase_field (name, assembler_name, type, class_type, fcontext,
DECL_ARTIFICIAL (field) = 1;
DECL_FIELD_CONTEXT (field) = class_type;
DECL_FCONTEXT (field) = fcontext;
- DECL_SAVED_INSNS (field) = 0;
DECL_ALIGN (field) = TYPE_ALIGN (type);
/* Return it. */
return field;
}
-/* Return the BINFO_OFFSET for BINFO as a native integer, not an
- INTEGER_CST. */
-
-static unsigned HOST_WIDE_INT
-get_binfo_offset_as_int (binfo)
- tree binfo;
-{
- tree offset;
-
- offset = BINFO_OFFSET (binfo);
- my_friendly_assert (TREE_CODE (offset) == INTEGER_CST, 20000313);
- my_friendly_assert (TREE_INT_CST_HIGH (offset) == 0, 20000313);
-
- return (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (offset);
-}
-
/* Record the type of BINFO in the slot in DATA (which is really a
`varray_type *') corresponding to the BINFO_OFFSET. */
@@ -4147,7 +3535,7 @@ dfs_record_base_offsets (binfo, data)
void *data;
{
varray_type *v;
- unsigned HOST_WIDE_INT offset = get_binfo_offset_as_int (binfo);
+ unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
v = (varray_type *) data;
while (VARRAY_SIZE (*v) <= offset)
@@ -4184,11 +3572,10 @@ dfs_search_base_offsets (binfo, data)
if (is_empty_class (BINFO_TYPE (binfo)))
{
varray_type v = (varray_type) data;
- unsigned HOST_WIDE_INT offset;
+ /* Find the offset for this BINFO. */
+ unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
tree t;
- /* Find the offset for this BINFO. */
- offset = get_binfo_offset_as_int (binfo);
/* If we haven't yet encountered any objects at offsets that
big, then there's no conflict. */
if (VARRAY_SIZE (v) <= offset)
@@ -4238,16 +3625,17 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
while (1)
{
tree offset;
+ struct record_layout_info old_rli = *rli;
- /* Layout this field. */
- layout_field (rli, decl);
+ /* Place this field. */
+ place_field (rli, decl);
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
- offset = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (decl)),
- BITS_PER_UNIT));
+ offset = byte_position (decl);
if (binfo)
- propagate_binfo_offsets (binfo, offset);
+ propagate_binfo_offsets (binfo,
+ convert (ssizetype, offset));
/* We have to check to see whether or not there is already
something of the same type at the offset we're about to use.
@@ -4267,17 +3655,20 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
{
/* Undo the propogate_binfo_offsets call. */
- offset = convert (sizetype,
- size_diffop (size_zero_node, offset));
- propagate_binfo_offsets (binfo, offset);
-
+ offset = size_diffop (size_zero_node, offset);
+ propagate_binfo_offsets (binfo, convert (ssizetype, offset));
+
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
proper alignment. */
- rli->const_size -= TREE_INT_CST_LOW (DECL_SIZE (decl));
- /* Bump up by th alignment required for the type, without
+ *rli = old_rli;
+
+ /* Bump up by the alignment required for the type, without
virtual base classes. */
- rli->const_size += CLASSTYPE_ALIGN (BINFO_TYPE (binfo));
+ rli->bitpos
+ = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (CLASSTYPE_ALIGN (BINFO_TYPE (binfo))));
+ normalize_rli (rli);
}
else
/* There was no conflict. We're done laying out this field. */
@@ -4286,8 +3677,9 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
- past the end of the class; BINFO_OFFSETS gives the offsets of the
- other bases allocated so far. */
+ past the end of the class, and should be correctly aligned for a
+ class of the type indicated by BINFO; BINFO_OFFSETS gives the
+ offsets of the other bases allocated so far. */
static void
layout_empty_base (binfo, eoc, binfo_offsets)
@@ -4295,16 +3687,12 @@ layout_empty_base (binfo, eoc, binfo_offsets)
tree eoc;
varray_type binfo_offsets;
{
+ tree alignment;
tree basetype = BINFO_TYPE (binfo);
/* This routine should only be used for empty classes. */
my_friendly_assert (is_empty_class (basetype), 20000321);
-
- /* This code assumes that zero-sized classes have one-byte
- alignment. There might someday be a system where that's not
- true. */
- my_friendly_assert (TYPE_ALIGN (basetype) == BITS_PER_UNIT,
- 20000314);
+ alignment = ssize_int (CLASSTYPE_ALIGN (basetype));
/* This is an empty base class. We first try to put it at offset
zero. */
@@ -4312,7 +3700,7 @@ layout_empty_base (binfo, eoc, binfo_offsets)
{
/* That didn't work. Now, we move forward from the next
available spot in the class. */
- propagate_binfo_offsets (binfo, eoc);
+ propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
while (1)
{
if (!layout_conflict_p (binfo, binfo_offsets))
@@ -4320,7 +3708,7 @@ layout_empty_base (binfo, eoc, binfo_offsets)
break;
/* There's overlap here, too. Bump along to the next spot. */
- propagate_binfo_offsets (binfo, size_one_node);
+ propagate_binfo_offsets (binfo, alignment);
}
}
}
@@ -4379,9 +3767,15 @@ build_base_field (rli, binfo, empty_p, base_align, v)
layout_nonempty_base_or_field (rli, decl, binfo, *v);
}
else
- layout_empty_base (binfo,
- size_int (CEIL (rli->const_size, BITS_PER_UNIT)),
- *v);
+ {
+ unsigned HOST_WIDE_INT eoc;
+
+ /* On some platforms (ARM), even empty classes will not be
+ byte-aligned. */
+ eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
+ eoc = CEIL (eoc, DECL_ALIGN (decl)) * DECL_ALIGN (decl);
+ layout_empty_base (binfo, size_int (eoc), *v);
+ }
/* Check for inaccessible base classes. If the same base class
appears more than once in the hierarchy, but isn't virtual, then
@@ -4463,7 +3857,6 @@ check_methods (t)
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue;
- DECL_SAVED_INSNS (x) = 0;
check_for_override (x, t);
if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
cp_error_at ("initializer specified for non-virtual method `%D'", x);
@@ -4617,15 +4010,15 @@ check_bases_and_members (t, empty_p)
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
accordingly. If a new vfield was created (because T doesn't have a
primary base class), then the newly created field is returned. It
- is not added to the TYPE_FIELDS list; it is the callers
+ is not added to the TYPE_FIELDS list; it is the caller's
responsibility to do that. */
static tree
-create_vtable_ptr (t, empty_p, has_virtual_p,
+create_vtable_ptr (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
int *empty_p;
- int *has_virtual_p;
+ int *vfuns_p;
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
@@ -4636,17 +4029,15 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
if (DECL_VINDEX (fn))
add_virtual_function (new_virtuals_p, overridden_virtuals_p,
- has_virtual_p, fn, t);
+ vfuns_p, fn, t);
- /* Even if there weren't any new virtual functions, we might need a
+ /* If we couldn't find an appropriate base class, create a new field
+ here. 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))
+ if (!TYPE_VFIELD (t)
+ && (*vfuns_p
+ || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())))
{
/* We build this decl with vtbl_ptr_type_node, which is a
`vtable_entry_type*'. It might seem more precise to use
@@ -4749,12 +4140,12 @@ dfs_propagate_binfo_offsets (binfo, data)
{
tree offset = (tree) data;
- /* Update the BINFO_OFFSET for this base. */
- BINFO_OFFSET (binfo) = fold (build (PLUS_EXPR,
- sizetype,
- BINFO_OFFSET (binfo),
- offset));
-
+ /* Update the BINFO_OFFSET for this base. Allow for the case where it
+ might be negative. */
+ BINFO_OFFSET (binfo)
+ = convert (sizetype, size_binop (PLUS_EXPR,
+ convert (ssizetype, BINFO_OFFSET (binfo)),
+ offset));
SET_BINFO_MARKED (binfo);
return NULL_TREE;
@@ -4835,7 +4226,7 @@ layout_virtual_bases (t, base_offsets)
tree t;
varray_type *base_offsets;
{
- tree vbase;
+ tree vbases;
unsigned HOST_WIDE_INT dsize;
unsigned HOST_WIDE_INT eoc;
@@ -4855,52 +4246,70 @@ layout_virtual_bases (t, base_offsets)
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
/* Go through the virtual bases, allocating space for each virtual
- base that is not already a primary base class. */
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
- if (!BINFO_VBASE_PRIMARY_P (vbase))
- {
- /* This virtual base is not a primary base of any class in the
- hierarchy, so we have to add space for it. */
- tree basetype;
- unsigned int desired_align;
-
- basetype = BINFO_TYPE (vbase);
-
- /* Under the new ABI, we try to squish empty virtual bases in
- just like ordinary empty bases. */
- if (flag_new_abi && is_empty_class (basetype))
- layout_empty_base (vbase,
- size_int (CEIL (dsize, BITS_PER_UNIT)),
- *base_offsets);
- else
- {
- if (flag_new_abi)
- desired_align = CLASSTYPE_ALIGN (basetype);
- else
- /* Under the old ABI, virtual bases were aligned as for
- the entire base object (including its virtual bases).
- That's wasteful, in general. */
- desired_align = TYPE_ALIGN (basetype);
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
- /* Add padding so that we can put the virtual base class at an
- appropriately aligned offset. */
- dsize = CEIL (dsize, desired_align) * desired_align;
- /* And compute the offset of the virtual base. */
- propagate_binfo_offsets (vbase,
- size_int (CEIL (dsize, BITS_PER_UNIT)));
- /* Every virtual baseclass takes a least a UNIT, so that
- we can take it's address and get something different
- for each base. */
- dsize += MAX (BITS_PER_UNIT,
- tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
- }
+ base that is not already a primary base class. Under the new
+ ABI, these are allocated according to a depth-first left-to-right
+ postorder traversal; in the new ABI, inheritance graph order is
+ used instead. */
+ for (vbases = (flag_new_abi
+ ? TYPE_BINFO (t)
+ : CLASSTYPE_VBASECLASSES (t));
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree vbase;
- /* Keep track of the offsets assigned to this virtual base. */
- record_base_offsets (vbase, base_offsets);
- }
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+
+ if (flag_new_abi)
+ vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), t);
+ else
+ vbase = vbases;
+
+ if (!BINFO_VBASE_PRIMARY_P (vbase))
+ {
+ /* This virtual base is not a primary base of any class in the
+ hierarchy, so we have to add space for it. */
+ tree basetype;
+ unsigned int desired_align;
+
+ basetype = BINFO_TYPE (vbase);
+
+ if (flag_new_abi)
+ desired_align = CLASSTYPE_ALIGN (basetype);
+ else
+ /* Under the old ABI, virtual bases were aligned as for the
+ entire base object (including its virtual bases). That's
+ wasteful, in general. */
+ desired_align = TYPE_ALIGN (basetype);
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
+
+ /* Add padding so that we can put the virtual base class at an
+ appropriately aligned offset. */
+ dsize = CEIL (dsize, desired_align) * desired_align;
+
+ /* Under the new ABI, we try to squish empty virtual bases in
+ just like ordinary empty bases. */
+ if (flag_new_abi && is_empty_class (basetype))
+ layout_empty_base (vbase,
+ size_int (CEIL (dsize, BITS_PER_UNIT)),
+ *base_offsets);
+ else
+ {
+ /* And compute the offset of the virtual base. */
+ propagate_binfo_offsets (vbase,
+ ssize_int (CEIL (dsize, BITS_PER_UNIT)));
+ /* Every virtual baseclass takes a least a UNIT, so that
+ we can take it's address and get something different
+ for each base. */
+ dsize += MAX (BITS_PER_UNIT,
+ tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
+ }
+
+ /* Keep track of the offsets assigned to this virtual base. */
+ record_base_offsets (vbase, base_offsets);
+ }
+ }
/* Make sure that all of the CLASSTYPE_VBASECLASSES have their
BINFO_OFFSET set correctly. Those we just allocated certainly
@@ -4917,10 +4326,10 @@ layout_virtual_bases (t, base_offsets)
in get_base_distance depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
- dfs_walk (vbase, dfs_set_offset_for_unshared_vbases, NULL, t);
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ dfs_walk (vbases, dfs_set_offset_for_unshared_vbases, NULL, t);
/* If we had empty base classes that protruded beyond the end of the
class, we didn't update DSIZE above; we were hoping to overlay
@@ -4934,16 +4343,16 @@ layout_virtual_bases (t, base_offsets)
dsize = CEIL (dsize, TYPE_ALIGN (t)) * TYPE_ALIGN (t);
TYPE_SIZE (t) = bitsize_int (dsize);
TYPE_SIZE_UNIT (t) = convert (sizetype,
- size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (t),
- bitsize_int (BITS_PER_UNIT)));
+ size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
+ bitsize_unit_node));
/* Check for ambiguous virtual bases. */
if (extra_warnings)
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
{
- tree basetype = BINFO_TYPE (vbase);
+ tree basetype = BINFO_TYPE (vbases);
if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
@@ -4991,11 +4400,11 @@ end_of_class (t, include_virtuals_p)
pointer. */
static void
-layout_class_type (t, empty_p, has_virtual_p,
+layout_class_type (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
int *empty_p;
- int *has_virtual_p;
+ int *vfuns_p;
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
@@ -5009,15 +4418,15 @@ layout_class_type (t, empty_p, has_virtual_p,
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
- /* Initialize the layout information. */
- rli = new_record_layout_info (t);
+ /* Start laying out the record. */
+ rli = start_record_layout (t);
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
- determine_primary_base (t, has_virtual_p);
+ determine_primary_base (t, vfuns_p);
/* Create a pointer to our virtual function table. */
- vptr = create_vtable_ptr (t, empty_p, has_virtual_p,
+ vptr = create_vtable_ptr (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p);
/* Under the new ABI, the vptr is always the first thing in the
@@ -5025,7 +4434,7 @@ layout_class_type (t, empty_p, has_virtual_p,
if (flag_new_abi && vptr)
{
TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
- layout_field (rli, vptr);
+ place_field (rli, vptr);
}
/* Add pointers to all of our virtual base-classes. */
@@ -5040,9 +4449,7 @@ layout_class_type (t, empty_p, has_virtual_p,
fixup_inline_methods (t);
/* Layout the non-static data members. */
- for (field = non_static_data_members;
- field;
- field = TREE_CHAIN (field))
+ for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
tree binfo;
tree type;
@@ -5052,7 +4459,7 @@ layout_class_type (t, empty_p, has_virtual_p,
the back-end, in case it wants to do something with them. */
if (TREE_CODE (field) != FIELD_DECL)
{
- layout_field (rli, field);
+ place_field (rli, field);
continue;
}
@@ -5067,9 +4474,9 @@ layout_class_type (t, empty_p, has_virtual_p,
&& ((flag_new_abi
&& INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
|| (!flag_new_abi
- && compare_tree_int (DECL_SIZE (field),
- TYPE_PRECISION
- (long_long_unsigned_type_node)) > 0)))
+ && 0 < compare_tree_int (DECL_SIZE (field),
+ TYPE_PRECISION
+ (long_long_unsigned_type_node)))))
{
integer_type_kind itk;
tree integer_type;
@@ -5087,8 +4494,8 @@ layout_class_type (t, empty_p, has_virtual_p,
field. We have to back up by one to find the largest
type that fits. */
integer_type = integer_types[itk - 1];
- padding = size_diffop (DECL_SIZE (field),
- TYPE_SIZE (integer_type));
+ padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
+ TYPE_SIZE (integer_type));
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
}
@@ -5122,13 +4529,15 @@ layout_class_type (t, empty_p, has_virtual_p,
offset. However, now we need to make sure that RLI is big enough
to reflect the entire class. */
eoc = end_of_class (t, /*include_virtuals_p=*/0);
- if (eoc * BITS_PER_UNIT > rli->const_size)
+ if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
+ && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
{
/* We don't handle zero-sized base classes specially under the
old ABI, so if we get here, we had better be operating under
the new ABI rules. */
my_friendly_assert (flag_new_abi, 20000321);
- rli->const_size = (eoc + 1) * BITS_PER_UNIT;
+ rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc + 1));
+ rli->bitpos = bitsize_zero_node;
}
/* We make all structures have at least one element, so that they
@@ -5141,7 +4550,7 @@ layout_class_type (t, empty_p, has_virtual_p,
tree padding;
padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
- layout_field (rli, padding);
+ place_field (rli, padding);
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
@@ -5151,7 +4560,7 @@ layout_class_type (t, empty_p, has_virtual_p,
class. */
if (!flag_new_abi && vptr)
{
- layout_field (rli, vptr);
+ place_field (rli, vptr);
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vptr);
}
@@ -5170,7 +4579,7 @@ layout_class_type (t, empty_p, has_virtual_p,
the virtual bases. */
if (*empty_p && flag_new_abi)
{
- CLASSTYPE_SIZE (t) = bitsize_int (0);
+ CLASSTYPE_SIZE (t) = bitsize_zero_node;
CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
}
else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t)
@@ -5201,7 +4610,7 @@ layout_class_type (t, empty_p, has_virtual_p,
/* Clean up. */
VARRAY_FREE (v);
}
-
+
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
@@ -5234,7 +4643,7 @@ finish_struct_1 (t)
tree t;
{
tree x;
- int has_virtual;
+ int vfuns;
/* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is
a FUNCTION_DECL. Each of these functions is a virtual function
declared in T that does not override any virtual function from a
@@ -5265,7 +4674,7 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_VFIELD_PARENT (t) = -1;
- has_virtual = 0;
+ vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE;
/* Do end-of-class semantic processing: checking the validity of the
@@ -5273,7 +4682,7 @@ finish_struct_1 (t)
check_bases_and_members (t, &empty);
/* Layout the class itself. */
- layout_class_type (t, &empty, &has_virtual,
+ layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals);
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
@@ -5284,22 +4693,20 @@ finish_struct_1 (t)
&& DECL_FIELD_CONTEXT (vfield) != t)
{
tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
- tree offset = convert (bitsizetype, BINFO_OFFSET (binfo));
vfield = copy_node (vfield);
copy_lang_decl (vfield);
- if (! integer_zerop (offset))
- offset = size_binop (MULT_EXPR, offset, bitsize_int (BITS_PER_UNIT));
-
DECL_FIELD_CONTEXT (vfield) = t;
- DECL_FIELD_BITPOS (vfield)
- = size_binop (PLUS_EXPR, offset, bit_position (vfield));
+ DECL_FIELD_OFFSET (vfield)
+ = size_binop (PLUS_EXPR,
+ BINFO_OFFSET (binfo),
+ DECL_FIELD_OFFSET (vfield));
TYPE_VFIELD (t) = vfield;
}
overridden_virtuals
- = modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals));
+ = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
/* If necessary, create the primary vtable for this class. */
if (new_virtuals
@@ -5309,22 +4716,7 @@ finish_struct_1 (t)
new_virtuals = nreverse (new_virtuals);
/* We must enter these virtuals into the table. */
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- if (! CLASSTYPE_COM_INTERFACE (t))
- {
- /* The second slot is for the tdesc pointer when thunks
- are used. */
- if (flag_vtable_thunks)
- new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
-
- /* The first slot is for the rtti offset. */
- new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
-
- set_rtti_entry (new_virtuals,
- convert (ssizetype, integer_zero_node), t);
- }
- build_primary_vtable (NULL_TREE, t);
- }
+ build_primary_vtable (NULL_TREE, t);
else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
@@ -5367,7 +4759,7 @@ finish_struct_1 (t)
my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
20000116);
- CLASSTYPE_VSIZE (t) = has_virtual;
+ CLASSTYPE_VSIZE (t) = vfuns;
/* Entries for virtual functions defined in the primary base are
followed by entries for new functions unique to this class. */
TYPE_BINFO_VIRTUALS (t)
@@ -5380,7 +4772,7 @@ finish_struct_1 (t)
/* If we created a new vtbl pointer for this class, add it to the
list. */
- if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1)
+ if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
CLASSTYPE_VFIELDS (t)
= chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
@@ -5437,7 +4829,7 @@ finish_struct_1 (t)
the base types we marked. */
finish_vtbls (t);
- if (CLASSTYPE_VSIZE (t) != 0)
+ if (TYPE_VFIELD (t))
{
/* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
@@ -5511,7 +4903,7 @@ finish_struct (t, attributes)
if (processing_template_decl)
{
finish_struct_methods (t);
- TYPE_SIZE (t) = integer_zero_node;
+ TYPE_SIZE (t) = bitsize_zero_node;
}
else
finish_struct_1 (t);
@@ -5676,13 +5068,13 @@ init_class_processing ()
* sizeof (struct class_stack_node));
access_default_node = build_int_2 (0, 0);
- access_public_node = build_int_2 (1, 0);
- access_protected_node = build_int_2 (2, 0);
- access_private_node = build_int_2 (3, 0);
+ access_public_node = build_int_2 (ak_public, 0);
+ access_protected_node = build_int_2 (ak_protected, 0);
+ access_private_node = build_int_2 (ak_private, 0);
access_default_virtual_node = build_int_2 (4, 0);
- access_public_virtual_node = build_int_2 (5, 0);
- access_protected_virtual_node = build_int_2 (6, 0);
- access_private_virtual_node = build_int_2 (7, 0);
+ access_public_virtual_node = build_int_2 (4 | ak_public, 0);
+ access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
+ access_private_virtual_node = build_int_2 (4 | ak_private, 0);
}
/* Set current scope to NAME. CODE tells us if this is a
@@ -6693,12 +6085,36 @@ note_name_declared_in_class (name, decl)
}
}
-/* Dump the offsets of all the bases rooted at BINFO to stderr.
- INDENT should be zero when called from the top level; it is
- incremented recursively. */
+/* Returns the VAR_DECL for the complete vtable associated with
+ BINFO. (Under the new ABI, secondary vtables are merged with
+ primary vtables; this function will return the VAR_DECL for the
+ primary vtable.) */
-void
-dump_class_hierarchy (binfo, indent)
+tree
+get_vtbl_decl_for_binfo (binfo)
+ tree binfo;
+{
+ tree decl;
+
+ decl = BINFO_VTABLE (binfo);
+ if (decl && TREE_CODE (decl) == PLUS_EXPR)
+ {
+ my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
+ 2000403);
+ decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
+ }
+ if (decl)
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+ return decl;
+}
+
+/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
+ dominated by T) to stderr. INDENT should be zero when called from
+ the top level; it is incremented recursively. */
+
+static void
+dump_class_hierarchy_r (t, binfo, indent)
+ tree t;
tree binfo;
int indent;
{
@@ -6709,9 +6125,661 @@ dump_class_hierarchy (binfo, indent)
type_as_string (binfo, TS_PLAIN));
fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
- fprintf (stderr, " %s\n",
- BINFO_PRIMARY_MARKED_P (binfo) ? "primary" : "");
+ if (TREE_VIA_VIRTUAL (binfo))
+ fprintf (stderr, " virtual");
+ if (BINFO_PRIMARY_MARKED_P (binfo)
+ || (TREE_VIA_VIRTUAL (binfo)
+ && BINFO_VBASE_PRIMARY_P (BINFO_FOR_VBASE (BINFO_TYPE (binfo),
+ t))))
+ fprintf (stderr, " primary");
+ fprintf (stderr, "\n");
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
- dump_class_hierarchy (BINFO_BASETYPE (binfo, i), indent + 2);
+ dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+}
+
+/* Dump the BINFO hierarchy for T. */
+
+void
+dump_class_hierarchy (t)
+ tree t;
+{
+ tree vbase;
+
+ dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
+ fprintf (stderr, "virtual bases\n");
+ for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; vbase = TREE_CHAIN (vbase))
+ dump_class_hierarchy_r (t, vbase, 0);
+}
+
+/* Virtual function table initialization. */
+
+/* Create all the necessary vtables for T and its base classes. */
+
+static void
+finish_vtbls (t)
+ tree t;
+{
+ if (merge_primary_and_secondary_vtables_p ())
+ {
+ tree list;
+ tree vbase;
+
+ /* Under the new ABI, we lay out the primary and secondary
+ vtables in one contiguous vtable. The primary vtable is
+ first, followed by the non-virtual secondary vtables in
+ inheritance graph order. */
+ list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
+ TREE_TYPE (list) = t;
+ accumulate_vtbl_inits (TYPE_BINFO (t), list);
+ /* Then come the virtual bases, also in inheritance graph
+ order. */
+ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
+ {
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+ accumulate_vtbl_inits (BINFO_FOR_VBASE (BINFO_TYPE (vbase), t),
+ list);
+ }
+
+ if (TYPE_BINFO_VTABLE (t))
+ initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
+ }
+ else
+ {
+ dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
+ dfs_unmarked_real_bases_queue_p, t);
+ dfs_walk (TYPE_BINFO (t), dfs_unmark,
+ dfs_marked_real_bases_queue_p, t);
+ }
+}
+
+/* Called from finish_vtbls via dfs_walk. */
+
+static tree
+dfs_finish_vtbls (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree t = (tree) data;
+
+ if (!BINFO_PRIMARY_MARKED_P (binfo)
+ && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
+ && BINFO_NEW_VTABLE_MARKED (binfo, t))
+ initialize_vtable (binfo,
+ build_vtbl_initializer (binfo, t, NULL));
+
+ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
+ SET_BINFO_MARKED (binfo);
+
+ return NULL_TREE;
+}
+
+/* Initialize the vtable for BINFO with the INITS. */
+
+static void
+initialize_vtable (binfo, inits)
+ tree binfo;
+ tree inits;
+{
+ tree context;
+ tree decl;
+
+ layout_vtable_decl (binfo, list_length (inits));
+ decl = get_vtbl_decl_for_binfo (binfo);
+ context = DECL_CONTEXT (decl);
+ DECL_CONTEXT (decl) = 0;
+ DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
+ cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
+ DECL_CONTEXT (decl) = context;
+}
+
+/* Add the vtbl initializers for BINFO (and its non-primary,
+ non-virtual bases) to the list of INITS. */
+
+static void
+accumulate_vtbl_inits (binfo, inits)
+ tree binfo;
+ tree inits;
+{
+ /* Walk the BINFO and its bases. We walk in preorder so that as we
+ initialize each vtable we can figure out at what offset the
+ secondary vtable lies from the primary vtable. */
+ dfs_walk_real (binfo,
+ dfs_accumulate_vtbl_inits,
+ NULL,
+ dfs_skip_vbases,
+ inits);
+}
+
+/* Called from finish_vtbls via dfs_walk when using the new ABI.
+ Accumulates the vtable initializers for all of the vtables into
+ TREE_VALUE (DATA). */
+
+static tree
+dfs_accumulate_vtbl_inits (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree l;
+ tree t;
+
+ l = (tree) data;
+ t = TREE_TYPE (l);
+
+ if (!BINFO_PRIMARY_MARKED_P (binfo)
+ && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
+ && BINFO_NEW_VTABLE_MARKED (binfo, t))
+ {
+ tree inits;
+ tree vtbl;
+ tree index;
+ int non_fn_entries;
+
+ /* Compute the initializer for this vtable. */
+ inits = build_vtbl_initializer (binfo, t, &non_fn_entries);
+
+ /* Set BINFO_VTABLE to the address where the VPTR should point. */
+ vtbl = TREE_PURPOSE (l);
+ vtbl = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (vtbl)),
+ vtbl);
+ index = size_binop (PLUS_EXPR,
+ size_int (non_fn_entries),
+ size_int (list_length (TREE_VALUE (l))));
+ BINFO_VTABLE (binfo)
+ = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
+ size_binop (MULT_EXPR,
+ TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
+ index));
+
+ /* Add the initializers for this vtable to the initializers for
+ the other vtables we've already got. */
+ TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
+ }
+
+ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
+
+ return NULL_TREE;
+}
+
+/* Construct the initializer for BINFOs virtual function table. BINFO
+ is part of the hierarchy dominated by T. The value returned is a
+ TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
+ DECL_INITIAL for a vtable. If NON_FN_ENTRIES_P is not NULL,
+ *NON_FN_ENTRIES_P is set to the number of non-function entries in
+ the vtable. */
+
+static tree
+build_vtbl_initializer (binfo, t, non_fn_entries_p)
+ tree binfo;
+ tree t;
+ int *non_fn_entries_p;
+{
+ tree v = BINFO_VIRTUALS (binfo);
+ tree inits = NULL_TREE;
+ tree vfun_inits;
+ tree vbase;
+ vcall_offset_data vod;
+
+ /* Initialize those parts of VOD that matter. */
+ vod.derived = t;
+ vod.inits = NULL_TREE;
+ vod.primary_p = (binfo == TYPE_BINFO (t));
+ /* The first vbase or vcall offset is at index -3 in the vtable. */
+ vod.index = build_int_2 (-3, -1);
+
+ /* Add the vcall and vbase offset entries. */
+ build_vcall_and_vbase_vtbl_entries (binfo, &vod);
+ inits = vod.inits;
+ /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+ build_vbase_offset_vtbl_entries. */
+ for (vbase = CLASSTYPE_VBASECLASSES (t);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ CLEAR_BINFO_VTABLE_PATH_MARKED (vbase);
+
+ /* Add entries to the vtable for RTTI. */
+ inits = chainon (inits, build_rtti_vtbl_entries (binfo, t));
+
+ if (non_fn_entries_p)
+ *non_fn_entries_p = list_length (inits);
+
+ /* Go through all the ordinary virtual functions, building up
+ initializers. */
+ vfun_inits = NULL_TREE;
+ while (v)
+ {
+ tree delta;
+ tree vcall_index;
+ tree fn;
+ tree pfn;
+ tree init;
+
+ /* Pull the offset for `this', and the function to call, out of
+ the list. */
+ delta = BV_DELTA (v);
+ vcall_index = BV_VCALL_INDEX (v);
+ fn = BV_FN (v);
+ my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
+
+ /* You can't call an abstract virtual function; it's abstract.
+ So, we replace these functions with __pure_virtual. */
+ if (DECL_PURE_VIRTUAL_P (fn))
+ fn = abort_fndecl;
+
+ /* Take the address of the function, considering it to be of an
+ appropriate generic type. */
+ pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+ /* The address of a function can't change. */
+ TREE_CONSTANT (pfn) = 1;
+ /* Enter it in the vtable. */
+ init = build_vtable_entry (delta, vcall_index, pfn);
+ /* And add it to the chain of initializers. */
+ vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+
+ /* Keep going. */
+ v = TREE_CHAIN (v);
+ }
+
+ /* The initializers for virtual functions were built up in reverse
+ order; straighten them out now. */
+ vfun_inits = nreverse (vfun_inits);
+
+ /* The complete initializer is the INITS, followed by the
+ VFUN_INITS. */
+ return chainon (inits, vfun_inits);
+}
+
+/* Sets vod->inits to be the initializers for the vbase and vcall
+ offsets in BINFO, which is in the hierarchy dominated by T. */
+
+static void
+build_vcall_and_vbase_vtbl_entries (binfo, vod)
+ tree binfo;
+ vcall_offset_data *vod;
+{
+ tree b;
+ tree inits;
+
+ /* If this is a derived class, we must first create entries
+ corresponding to the base class. These entries must go closer to
+ the vptr, so we save them up and add them to the end of the list
+ later. */
+ inits = vod->inits;
+ vod->inits = NULL_TREE;
+ b = BINFO_PRIMARY_BINFO (binfo);
+ if (b)
+ build_vcall_and_vbase_vtbl_entries (b, vod);
+
+ /* Add the vbase entries for this base. */
+ build_vbase_offset_vtbl_entries (binfo, vod);
+ /* Add the vcall entries for this base. */
+ build_vcall_offset_vtbl_entries (binfo, vod);
+
+ vod->inits = chainon (vod->inits, inits);
+}
+
+/* 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. VBASE_OFFSET_INDEX gives the vtable index
+ where the next vbase offset will go. */
+
+static void
+build_vbase_offset_vtbl_entries (binfo, vod)
+ tree binfo;
+ vcall_offset_data *vod;
+{
+ tree vbase;
+ tree t;
+
+ /* Under the old ABI, pointers to virtual bases are stored in each
+ object. */
+ if (!vbase_offsets_in_vtable_p ())
+ return;
+
+ /* If there are no virtual baseclasses, then there is nothing to
+ do. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ return;
+
+ t = vod->derived;
+
+ /* Go through the virtual bases, adding the offsets. */
+ for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree b;
+ tree delta;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+
+ /* Find the instance of this virtual base in the complete
+ object. */
+ b = BINFO_FOR_VBASE (BINFO_TYPE (vbase), t);
+
+ /* If we've already got an offset for this virtual base, we
+ don't need another one. */
+ if (BINFO_VTABLE_PATH_MARKED (b))
+ continue;
+ SET_BINFO_VTABLE_PATH_MARKED (b);
+
+ /* Figure out where we can find this vbase offset. */
+ delta = size_binop (MULT_EXPR,
+ convert (ssizetype, vod->index),
+ convert (ssizetype,
+ TYPE_SIZE_UNIT (vtable_entry_type)));
+ if (vod->primary_p)
+ BINFO_VPTR_FIELD (b) = delta;
+
+ if (binfo != TYPE_BINFO (t))
+ {
+ tree orig_vbase;
+
+ /* Find the instance of this virtual base in the type of BINFO. */
+ orig_vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbase),
+ BINFO_TYPE (binfo));
+
+ /* The vbase offset had better be the same. */
+ if (!tree_int_cst_equal (delta,
+ BINFO_VPTR_FIELD (orig_vbase)))
+ my_friendly_abort (20000403);
+ }
+
+ /* The next vbase will come at a more negative offset. */
+ vod->index = fold (build (MINUS_EXPR, integer_type_node,
+ vod->index, integer_one_node));
+
+ /* The initializer is the delta from BINFO to this virtual base.
+ The vbase offsets go in reverse inheritance-graph order, and
+ we are walking in inheritance graph order so these end up in
+ the right order. */
+ delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
+ vod->inits = tree_cons (NULL_TREE,
+ fold (build1 (NOP_EXPR,
+ vtable_entry_type,
+ delta)),
+ vod->inits);
+ }
+}
+
+/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
+
+static tree
+dfs_vcall_offset_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ vcall_offset_data* vod = (vcall_offset_data *) data;
+
+ return (binfo == vod->vbase) ? binfo : dfs_skip_vbases (binfo, NULL);
+}
+
+/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
+
+static tree
+dfs_build_vcall_offset_vtbl_entries (binfo, data)
+ tree binfo;
+ void *data;
+{
+ vcall_offset_data* vod;
+ tree virtuals;
+ tree binfo_inits;
+ tree b;
+ int i;
+
+ vod = (vcall_offset_data *) data;
+ binfo_inits = NULL_TREE;
+
+ /* Skip virtuals that we have already handled in a primary base
+ class. */
+ virtuals = BINFO_VIRTUALS (binfo);
+ b = BINFO_PRIMARY_BINFO (binfo);
+ if (b)
+ for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
+ virtuals = TREE_CHAIN (virtuals);
+
+ /* Make entries for the rest of the virtuals. */
+ while (virtuals)
+ {
+ /* Figure out what function we're looking at. */
+ tree fn = TREE_VALUE (virtuals);
+ tree base = DECL_CONTEXT (fn);
+ /* The FN comes from BASE. So, we must caculate the adjustment
+ from the virtual base that derived from BINFO to BASE. */
+ tree base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
+
+ binfo_inits
+ = tree_cons (NULL_TREE,
+ fold (build1 (NOP_EXPR, vtable_entry_type,
+ size_diffop (BINFO_OFFSET (base_binfo),
+ BINFO_OFFSET (vod->vbase)))),
+ binfo_inits);
+ vod->index = fold (build (MINUS_EXPR, integer_type_node,
+ vod->index, integer_one_node));
+ virtuals = TREE_CHAIN (virtuals);
+ }
+
+ /* The offests are built up in reverse order, so we straighten them
+ here. We simultaneously add them to VOD->INITS; we're walking
+ the bases in inheritance graph order, and the initializers are
+ supposed to appear in reverse inheritance order, so that's
+ correct. */
+ while (binfo_inits)
+ {
+ tree next;
+
+ next = TREE_CHAIN (binfo_inits);
+ TREE_CHAIN (binfo_inits) = vod->inits;
+ vod->inits = binfo_inits;
+ binfo_inits = next;
+ }
+
+ return NULL_TREE;
+}
+
+/* Adds the initializers for the vcall offset entries in the vtable
+ for BINFO (which is part of the class hierarchy dominated by T) to
+ VOD->INITS. */
+
+static void
+build_vcall_offset_vtbl_entries (binfo, vod)
+ tree binfo;
+ vcall_offset_data *vod;
+{
+ tree inits;
+
+ /* Under the old ABI, the adjustments to the `this' pointer were made
+ elsewhere. */
+ if (!vcall_offsets_in_vtable_p ())
+ return;
+
+ /* We only need these entries if this base is a virtual base. */
+ if (!TREE_VIA_VIRTUAL (binfo))
+ return;
+
+ /* We need a vcall offset for each of the virtual functions in this
+ vtable. For example:
+
+ class A { virtual void f (); };
+ class B : virtual public A { };
+ class C: virtual public A, public B {};
+
+ Now imagine:
+
+ B* b = new C;
+ b->f();
+
+ The location of `A' is not at a fixed offset relative to `B'; the
+ offset depends on the complete object derived from `B'. So,
+ `B' vtable contains an entry for `f' that indicates by what
+ amount the `this' pointer for `B' needs to be adjusted to arrive
+ at `A'.
+
+ We need entries for all the functions in our primary vtable and
+ in our non-virtual bases vtables. For each base, the entries
+ appear in the same order as in the base; but the bases themselves
+ appear in reverse depth-first, left-to-right order. */
+ vod->vbase = binfo;
+ inits = vod->inits;
+ vod->inits = NULL_TREE;
+ dfs_walk_real (binfo,
+ dfs_build_vcall_offset_vtbl_entries,
+ NULL,
+ dfs_vcall_offset_queue_p,
+ vod);
+ vod->inits = chainon (vod->inits, inits);
+}
+
+/* Return vtbl initializers for the RTTI entries coresponding to the
+ BINFO's vtable. BINFO is a part of the hierarchy dominated by
+ T. */
+
+static tree
+build_rtti_vtbl_entries (binfo, t)
+ tree binfo;
+ tree t;
+{
+ tree b;
+ tree basetype;
+ tree offset;
+ tree decl;
+ tree init;
+ tree inits;
+
+ basetype = BINFO_TYPE (binfo);
+ inits = NULL_TREE;
+
+ /* For a COM object there is no RTTI entry. */
+ if (CLASSTYPE_COM_INTERFACE (basetype))
+ return inits;
+
+ /* To find the complete object, we will first convert to our most
+ primary base, and then add the offset in the vtbl to that value. */
+ b = binfo;
+ while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
+ {
+ tree primary_base;
+
+ primary_base = BINFO_PRIMARY_BINFO (b);
+ if (!BINFO_PRIMARY_MARKED_P (primary_base))
+ break;
+ b = primary_base;
+ }
+ offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
+
+ /* The second entry is, in the case of the new ABI, the address of
+ the typeinfo object, or, in the case of the old ABI, a function
+ which returns a typeinfo object. */
+ if (new_abi_rtti_p ())
+ {
+ if (flag_rtti)
+ decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+ else
+ decl = integer_zero_node;
+
+ /* Convert the declaration to a type that can be stored in the
+ vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
+ TREE_CONSTANT (init) = 1;
+ }
+ else
+ {
+ if (flag_rtti)
+ decl = get_tinfo_decl (t);
+ else
+ decl = abort_fndecl;
+
+ /* Convert the declaration to a type that can be stored in the
+ vtable. */
+ init = build1 (ADDR_EXPR, vfunc_ptr_type_node, decl);
+ TREE_CONSTANT (init) = 1;
+ init = build_vtable_entry (offset, integer_zero_node, init);
+ }
+ inits = tree_cons (NULL_TREE, init, inits);
+
+ /* Add the offset-to-top entry. It comes earlier in the vtable that
+ the the typeinfo entry. */
+ if (flag_vtable_thunks)
+ {
+ /* Convert the offset to look like a function pointer, so that
+ we can put it in the vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+ TREE_CONSTANT (init) = 1;
+ inits = tree_cons (NULL_TREE, init, inits);
+ }
+
+ return inits;
+}
+
+/* Build an entry in the virtual function table. DELTA is the offset
+ for the `this' pointer. VCALL_INDEX is the vtable index containing
+ the vcall offset; zero if none. ENTRY is the virtual function
+ table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
+ but it may not actually be a virtual function table pointer. (For
+ example, it might be the address of the RTTI object, under the new
+ ABI.) */
+
+static tree
+build_vtable_entry (delta, vcall_index, entry)
+ tree delta;
+ tree vcall_index;
+ tree entry;
+{
+ if (flag_vtable_thunks)
+ {
+ HOST_WIDE_INT idelta;
+ HOST_WIDE_INT ivindex;
+
+ idelta = tree_low_cst (delta, 0);
+ ivindex = tree_low_cst (vcall_index, 0);
+ if ((idelta || ivindex)
+ && ! DECL_PURE_VIRTUAL_P (TREE_OPERAND (entry, 0)))
+ {
+ entry = make_thunk (entry, idelta, ivindex);
+ entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
+ TREE_READONLY (entry) = 1;
+ TREE_CONSTANT (entry) = 1;
+ }
+#ifdef GATHER_STATISTICS
+ n_vtable_entries += 1;
+#endif
+ return entry;
+ }
+ else
+ {
+ extern int flag_huge_objects;
+ tree elems = tree_cons (NULL_TREE, delta,
+ tree_cons (NULL_TREE, integer_zero_node,
+ build_tree_list (NULL_TREE, entry)));
+ tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
+
+ /* We don't use vcall offsets when not using vtable thunks. */
+ my_friendly_assert (integer_zerop (vcall_index), 20000125);
+
+ /* DELTA used to be constructed by `size_int' and/or size_binop,
+ which caused overflow problems when it was negative. That should
+ be fixed now. */
+
+ if (! int_fits_type_p (delta, delta_type_node))
+ {
+ if (flag_huge_objects)
+ sorry ("object size exceeds built-in limit for virtual function table implementation");
+ else
+ sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
+ }
+
+ TREE_CONSTANT (entry) = 1;
+ TREE_STATIC (entry) = 1;
+ TREE_READONLY (entry) = 1;
+
+#ifdef GATHER_STATISTICS
+ n_vtable_entries += 1;
+#endif
+
+ return entry;
+ }
}