#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. */
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;
static class_stack_node_t current_class_stack;
+/* An array of all local classes present in this translation unit, in
+ declaration order. */
+varray_type local_classes;
+
static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree));
static tree build_vbase_pointer PARAMS ((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 *));
-static tree dfs_accumulate_vtbl_inits PARAMS ((tree, void *));
+static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
+ tree));
static void finish_vtbls PARAMS ((tree));
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
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, 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));
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 tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
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 initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
tree, tree,
varray_type));
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 accumulate_vtbl_inits PARAMS ((tree, tree, tree, 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));
+static void clone_constructors_and_destructors PARAMS ((tree));
+static tree build_clone PARAMS ((tree, tree));
+static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
+static tree copy_virtuals PARAMS ((tree));
+static void build_ctor_vtbl_group PARAMS ((tree, tree));
+static void build_vtt PARAMS ((tree));
+static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
+static tree dfs_build_vtt_inits PARAMS ((tree, void *));
+static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
+static int indirect_primary_base_p PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
{
tree other_base_binfo = TREE_VEC_ELT (binfos, j);
if (! TREE_VIA_VIRTUAL (other_base_binfo)
- && BINFO_FOR_VBASE (basetype, BINFO_TYPE (other_base_binfo)))
+ && binfo_for_vbase (basetype, BINFO_TYPE (other_base_binfo)))
goto got_it;
}
FORMAT_VBASE_NAME (name, basetype);
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;
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. */
/* Find the shared copy of TYPE; that's where the vtable offset
is recorded. */
- vbase = BINFO_FOR_VBASE (type, TREE_TYPE (exp));
+ 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 = 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);
\f
/* 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
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 (TYPE_BINFO (basetype)),
+ 0);
s = build_tree_list (build_string (1, "s"), s);
i = build_array_ref (vtbl, 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);
}
get_vtable_name (type)
tree type;
{
- tree type_id = build_typename_overload (type);
- char *buf = (char *) alloca (strlen (VTABLE_NAME_PREFIX)
- + IDENTIFIER_LENGTH (type_id) + 2);
- const char *ptr = IDENTIFIER_POINTER (type_id);
- int i;
- for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
-#if 0
- /* We don't take off the numbers; build_secondary_vtable uses the
- DECL_ASSEMBLER_NAME for the type, which includes the number
- in `3foo'. If we were to pull them off here, we'd end up with
- something like `_vt.foo.3bar', instead of a uniform definition. */
- while (ptr[i] >= '0' && ptr[i] <= '9')
- i += 1;
-#endif
- sprintf (buf, "%s%s", VTABLE_NAME_PREFIX, ptr+i);
- return get_identifier (buf);
+ if (flag_new_abi)
+ return mangle_vtbl_for_type (type);
+ else
+ return build_overload_with_type (get_identifier (VTABLE_NAME_PREFIX),
+ type);
+}
+
+/* Return an IDENTIFIER_NODE for the name of the virtual table table
+ for TYPE. */
+
+tree
+get_vtt_name (type)
+ tree type;
+{
+ if (flag_new_abi)
+ return mangle_vtt_for_type (type);
+ else
+ return build_overload_with_type (get_identifier (VTT_NAME_PREFIX),
+ type);
}
/* Return the offset to the main vtable for a given base BINFO. */
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
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. */
+/* 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. */
static tree
build_vtable (class_type, name, vtable_type)
decl = build_vtable (type, name, void_type_node);
decl = pushdecl_top_level (decl);
- SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
+ my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
+ 20000517);
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
return decl;
}
+/* Returns a copy of the BINFO_VIRTUALS list in BINFO. The
+ BV_VCALL_INDEX for each entry is cleared. */
+
+static tree
+copy_virtuals (binfo)
+ tree binfo;
+{
+ tree copies;
+ tree t;
+
+ copies = copy_list (BINFO_VIRTUALS (binfo));
+ for (t = copies; t; t = TREE_CHAIN (t))
+ BV_VCALL_INDEX (t) = NULL_TREE;
+
+ return copies;
+}
+
/* Build the primary virtual function table for TYPE. If BINFO is
non-NULL, build the vtable starting with the initial approximation
that it is the same as the one which is the head of the association
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);
+ virtuals = copy_virtuals (binfo);
+ 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
{
#endif
if (TREE_VIA_VIRTUAL (binfo))
- my_friendly_assert (binfo == BINFO_FOR_VBASE (BINFO_TYPE (binfo),
+ my_friendly_assert (binfo == binfo_for_vbase (BINFO_TYPE (binfo),
current_class_type),
170);
SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type);
/* Make fresh virtual list, so we can smash it later. */
- BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
+ BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
if (TREE_VIA_VIRTUAL (binfo))
{
- tree binfo1 = BINFO_FOR_VBASE (BINFO_TYPE (binfo), for_type);
+ tree binfo1 = binfo_for_vbase (BINFO_TYPE (binfo), for_type);
/* XXX - This should never happen, if it does, the caller should
ensure that the binfo is from for_type's binfos, not from any
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 ())
/* Make *VIRTUALS, an entry on the BINFO_VIRTUALS list for BINFO
(which is in the hierarchy dominated by T) list FNDECL as its
- BV_FN. DELTA is the required adjustment from the `this' pointer
- where the vtable entry appears to the `this' required when the
- function is actually called. */
+ BV_FN. DELTA is the required constant adjustment from the `this'
+ pointer where the vtable entry appears to the `this' required when
+ the function is actually called. */
static void
modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
tree delta;
tree *virtuals;
{
- tree vcall_index;
tree v;
v = *virtuals;
- vcall_index = integer_zero_node;
if (fndecl != BV_FN (v)
- || !tree_int_cst_equal (delta, BV_DELTA (v))
- || !tree_int_cst_equal (vcall_index, BV_VCALL_INDEX (v)))
+ || !tree_int_cst_equal (delta, BV_DELTA (v)))
{
tree base_fndecl;
base_fndecl = BV_FN (v);
BV_DELTA (v) = delta;
- BV_VCALL_INDEX (v) = vcall_index;
+ BV_VCALL_INDEX (v) = NULL_TREE;
BV_FN (v) = fndecl;
/* Now assign virtual dispatch information, if unset. We can
}
}
-/* 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. */
{
/* We've already dealt with this function. */
return;
- new_virtual = build_tree_list (integer_zero_node, fndecl);
- BV_VCALL_INDEX (new_virtual) = integer_zero_node;
+ new_virtual = build_tree_list (NULL_TREE, fndecl);
+ BV_DELTA (new_virtual) = integer_zero_node;
if (DECL_VINDEX (fndecl) == error_mark_node)
{
/* 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. */
method_vec = CLASSTYPE_METHOD_VEC (type);
len = TREE_VEC_LENGTH (method_vec);
- if (DECL_NAME (method) == constructor_name (type))
- /* A new constructor or destructor. Constructors go in
- slot 0; destructors go in slot 1. */
- slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
+ /* Constructors and destructors go in special slots. */
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
+ slot = CLASSTYPE_CONSTRUCTOR_SLOT;
+ else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+ slot = CLASSTYPE_DESTRUCTOR_SLOT;
else
{
/* See if we already have an entry with this name. */
- for (slot = 2; slot < len; ++slot)
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
if (!TREE_VEC_ELT (method_vec, slot)
|| (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
slot)))
tree fdecl;
tree access;
{
- tree elem = purpose_member (t, DECL_ACCESS (fdecl));
+ tree elem;
+
+ if (!DECL_LANG_SPECIFIC (fdecl))
+ retrofit_lang_decl (fdecl);
+
+ elem = purpose_member (t, DECL_ACCESS (fdecl));
if (elem)
{
if (TREE_VALUE (elem) != access)
if (is_overloaded_fn (fdecl))
flist = fdecl;
- else if (! DECL_LANG_SPECIFIC (fdecl))
- my_friendly_abort (20000221);
if (! old_value)
;
}
}
+/* 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;
+ tree type;
+
+ type = (tree) data;
+ shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
+
+ /* 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))
+ {
+ /* Make sure the CLASSTYPE_VBASECLASSES list contains the
+ primary copy; it's the one that really exists. */
+ if (base_binfo != shared_binfo)
+ TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
+ CLASSTYPE_VBASECLASSES (type)))
+ = base_binfo;
+
+ BINFO_VBASE_PRIMARY_P (base_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;
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);
+}
+
+/* Returns true iff BINFO (a direct virtual base of T) is an indirect
+ primary base. */
+
+static int
+indirect_primary_base_p (t, binfo)
+ tree t;
+ tree binfo;
+{
+ int i;
+
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+ {
+ tree type;
+ tree b;
+
+ /* Figure out to which type the Ith base corresponds. */
+ type = TYPE_BINFO_BASETYPE (t, i);
+ /* See if any of the primary bases have the same type as BINFO. */
+ for (b = TYPE_BINFO (type); b; b = TREE_CHAIN (b))
+ /* If this base is primary, and has the same type as BINFO,
+ then BINFO is an indirect primary base. */
+ if (BINFO_PRIMARY_MARKED_P (b)
+ && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+ return 1;
+ }
+
+ return 0;
}
/* 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);
if (n_baseclasses == 0)
return;
- *has_virtual_p = 0;
+ *vfuns_p = 0;
for (i = 0; i < n_baseclasses; i++)
{
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
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);
}
}
}
class as the primary base class if no non-virtual polymorphic
base can be found. */
if (flag_new_abi && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- for (i = 0; i < n_baseclasses; ++i)
- {
- tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
- tree basetype = BINFO_TYPE (base_binfo);
+ {
+ /* If not -1, this is the index in TYPE_BINFO_BASETYPEs of the
+ best primary base candidate we have found so far. */
+ int candidate = -1;
- if (TREE_VIA_VIRTUAL (base_binfo)
- && CLASSTYPE_NEARLY_EMPTY_P (basetype))
- {
- set_primary_base (t, i, has_virtual_p);
- CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
- break;
- }
- }
+ /* Loop over the baseclasses. */
+ for (i = 0; i < n_baseclasses; ++i)
+ {
+ tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
+ tree basetype = BINFO_TYPE (base_binfo);
+
+ if (TREE_VIA_VIRTUAL (base_binfo)
+ && CLASSTYPE_NEARLY_EMPTY_P (basetype))
+ {
+ int indirect_primary_p;
+
+ /* Figure out whether or not this base is an indirect
+ primary base. */
+ indirect_primary_p = indirect_primary_base_p (t, base_binfo);
+
+ /* If this is not an indirect primary base, then it's
+ definitely our primary base. */
+ if (!indirect_primary_p)
+ {
+ candidate = i;
+ break;
+ }
+ /* If this was an indirect primary base, it's still our
+ primary base -- unless there's another nearly-empty
+ virtual base that isn't an indirect primary base. */
+ else if (candidate == -1)
+ candidate = i;
+ }
+ }
+
+ /* If we've got a primary base, use it. */
+ if (candidate != -1)
+ {
+ set_primary_base (t, candidate, vfuns_p);
+ CLASSTYPE_VFIELDS (t)
+ = copy_list (CLASSTYPE_VFIELDS (TYPE_BINFO_BASETYPE (t,
+ candidate)));
+ }
+ }
/* Mark the primary base classes at this point. */
mark_primary_bases (t);
list. That allows them to be quickly deleted, and requires no
extra storage.
- If there are any constructors/destructors, they are moved to the
- front of the list. This makes pushclass more efficient.
-
- @@ The above comment is obsolete. It mostly describes what add_method
- @@ and add_implicitly_declared_members do.
-
- Sort methods that are not special (i.e., constructors, destructors, and
- type conversion operators) so that we can find them faster in search. */
+ Sort methods that are not special (i.e., constructors, destructors,
+ and type conversion operators) so that we can find them faster in
+ search. */
static void
finish_struct_methods (t)
{
tree fn_fields;
tree method_vec;
- tree ctor_name = constructor_name (t);
int slot, len;
if (!TYPE_METHODS (t))
and the next few with type conversion operators (if any). */
for (fn_fields = TYPE_METHODS (t); fn_fields;
fn_fields = TREE_CHAIN (fn_fields))
- {
- tree fn_name = DECL_NAME (fn_fields);
-
- /* Clear out this flag.
-
- @@ Doug may figure out how to break
- @@ this with nested classes and friends. */
- DECL_IN_AGGR_P (fn_fields) = 0;
-
- /* Note here that a copy ctor is private, so we don't dare generate
- a default copy constructor for a class that has a member
- of this type without making sure they have access to it. */
- if (fn_name == ctor_name)
- {
- tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields);
- tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t)
- {
- if (TREE_CHAIN (parmtypes) == NULL_TREE
- || TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
- {
- if (TREE_PROTECTED (fn_fields))
- TYPE_HAS_NONPUBLIC_CTOR (t) = 1;
- else if (TREE_PRIVATE (fn_fields))
- TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
- }
- }
- }
- else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
- {
- tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
-
- if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields)))
- {
- if (TREE_PROTECTED (fn_fields))
- TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1;
- else if (TREE_PRIVATE (fn_fields))
- TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2;
- }
- }
- }
+ /* Clear out this flag. */
+ DECL_IN_AGGR_P (fn_fields) = 0;
- if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
+ if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t))
/* We thought there was a destructor, but there wasn't. Some
parse errors cause this anomalous situation. */
TYPE_HAS_DESTRUCTOR (t) = 0;
{
tree itype;
tree atype;
+ tree vtable;
itype = size_int (n);
atype = build_cplus_array_type (vtable_entry_type,
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
}
}
-/* Returns the number of virtual function table entries (excluding
- RTTI information, vbase and vcall offests, etc.) in the vtable for
- BINFO. */
+/* True if we should override the given BASE_FNDECL with the given
+ FNDECL. */
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;
+overrides (fndecl, base_fndecl)
+ tree fndecl, base_fndecl;
{
- 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));
+ /* One destructor overrides another if they are the same kind of
+ destructor. */
+ if (DECL_DESTRUCTOR_P (base_fndecl) && DECL_DESTRUCTOR_P (fndecl)
+ && special_function_p (base_fndecl) == special_function_p (fndecl))
+ return 1;
+ /* But a non-destructor never overrides a destructor, nor vice
+ versa, nor do different kinds of destructors override
+ one-another. For example, a complete object destructor does not
+ override a deleting destructor. */
+ if (DECL_DESTRUCTOR_P (base_fndecl) || DECL_DESTRUCTOR_P (fndecl))
+ return 0;
- /* 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))
+ if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
{
- 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;
+ tree types, base_types;
+ types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
+ if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types)))
+ == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types))))
+ && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
+ return 1;
}
-
- return entries ? size_int (entries) : size_zero_node;
+ return 0;
}
-/* 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);
-}
+typedef struct find_final_overrider_data_s {
+ /* The function for which we are trying to find a final overrider. */
+ tree fn;
+ /* The base class in which the function was declared. */
+ tree declaring_base;
+ /* The most derived class in the hierarchy. */
+ tree most_derived_type;
+ /* The final overriding function. */
+ tree overriding_fn;
+ /* The BINFO for the class in which the final overriding function
+ appears. */
+ tree overriding_base;
+} find_final_overrider_data;
-/* 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. */
+/* Called from find_final_overrider via dfs_walk. */
static tree
-build_vtbl_initializer (binfo, t)
+dfs_find_final_overrider (binfo, data)
tree binfo;
- tree t;
+ void *data;
{
- 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);
+ find_final_overrider_data *ffod = (find_final_overrider_data *) data;
- /* 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)
+ if (same_type_p (BINFO_TYPE (binfo),
+ BINFO_TYPE (ffod->declaring_base))
+ && tree_int_cst_equal (BINFO_OFFSET (binfo),
+ BINFO_OFFSET (ffod->declaring_base)))
{
- 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. */
- }
+ tree path;
+ tree method;
- /* Go through all the ordinary virtual functions, building up
- initializers. */
- while (v)
- {
- tree delta;
- tree vcall_index;
- tree fn;
- tree pfn;
- tree init;
+ /* We've found a path to the declaring base. Walk down the path
+ looking for an overrider for FN. */
+ for (path = reverse_path (binfo);
+ path;
+ path = TREE_CHAIN (path))
+ {
+ for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
+ method;
+ method = TREE_CHAIN (method))
+ if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn))
+ break;
- /* 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. */
-
-static int
-overrides (fndecl, base_fndecl)
- tree fndecl, base_fndecl;
-{
- /* Destructors have special names. */
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
- && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
- return 1;
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
- || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
- return 0;
- if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
- {
- tree types, base_types;
-#if 0
- retypes = TREE_TYPE (TREE_TYPE (fndecl));
- base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl));
-#endif
- types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
- if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types)))
- == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types))))
- && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
- return 1;
- }
- return 0;
-}
-
-typedef struct find_final_overrider_data_s {
- /* The function for which we are trying to find a final overrider. */
- tree fn;
- /* The base class in which the function was declared. */
- tree declaring_base;
- /* The most derived class in the hierarchy. */
- tree most_derived_type;
- /* The final overriding function. */
- tree overriding_fn;
- /* The BINFO for the class in which the final overriding function
- appears. */
- tree overriding_base;
-} find_final_overrider_data;
-
-/* Called from find_final_overrider via dfs_walk. */
-
-static tree
-dfs_find_final_overrider (binfo, data)
- tree binfo;
- void *data;
-{
- find_final_overrider_data *ffod = (find_final_overrider_data *) data;
-
- if (same_type_p (BINFO_TYPE (binfo),
- BINFO_TYPE (ffod->declaring_base))
- && tree_int_cst_equal (BINFO_OFFSET (binfo),
- BINFO_OFFSET (ffod->declaring_base)))
- {
- tree path;
- tree method;
-
- /* We've found a path to the declaring base. Walk down the path
- looking for an overrider for FN. */
- for (path = reverse_path (binfo);
- path;
- path = TREE_CHAIN (path))
- {
- for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
- method;
- method = TREE_CHAIN (method))
- if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn))
- break;
-
- if (method)
- break;
- }
+ if (method)
+ break;
+ }
/* If we found an overrider, record the overriding function, and
the base from which it came. */
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). */
? binfo : NULL_TREE);
}
+/* Update a entry in the vtable for BINFO, which is in the hierarchy
+ dominated by T. FN has been overridden in BINFO; VIRTUALS points
+ to the corresponding position in the BINFO_VIRTUALS list. */
+
+static void
+update_vtable_entry_for_fn (t, binfo, fn, virtuals)
+ tree t;
+ tree binfo;
+ tree fn;
+ tree *virtuals;
+{
+ tree b;
+ tree overrider;
+ tree vindex;
+ tree delta;
+ HOST_WIDE_INT vindex_val;
+ HOST_WIDE_INT i;
+
+ /* Find the function which originally caused this vtable
+ entry to be present. */
+ vindex = DECL_VINDEX (fn);
+ b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
+ 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)
+ {
+ fn = TREE_CHAIN (fn);
+ ++i;
+ }
+ fn = BV_FN (fn);
+
+ /* Handle the case of a virtual function defined in BINFO itself. */
+ overrider = find_final_overrider (t, b, fn);
+ if (overrider == error_mark_node)
+ return;
+
+ /* Compute the constant adjustment to the `this' pointer. The
+ `this' pointer, when this function is called, will point at the
+ class whose vtable this is. */
+ delta = size_binop (PLUS_EXPR,
+ get_derived_offset (binfo,
+ DECL_VIRTUAL_CONTEXT (fn)),
+ BINFO_OFFSET (binfo));
+ if (flag_new_abi)
+ {
+ /* Under the new ABI, we only need to adjust as far as the
+ nearest virtual base. Then we use the vcall offset in the
+ virtual bases vtable. */
+ for (b = binfo; b; b = BINFO_INHERITANCE_CHAIN (b))
+ {
+ if (TREE_VIA_VIRTUAL (b))
+ break;
+ if (same_type_p (BINFO_TYPE (b),
+ BINFO_TYPE (TREE_VALUE (overrider))))
+ break;
+ }
+ }
+ else
+ b = NULL_TREE;
+
+ if (b && TREE_VIA_VIRTUAL (b))
+ /* The `this' pointer needs to be adjusted to the nearest virtual
+ base. */
+ delta = size_diffop (BINFO_OFFSET (b), delta);
+ else
+ /* The `this' pointer needs to be adjusted from pointing to
+ BINFO to pointing at the base where the final overrider
+ appears. */
+ delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta);
+
+ modify_vtable_entry (t,
+ binfo,
+ TREE_PURPOSE (overrider),
+ delta,
+ virtuals);
+}
+
/* Called from modify_all_vtables via dfs_walk. */
static tree
/* 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))
- {
- tree b;
- tree fn;
- tree overrider;
- tree vindex;
- tree delta;
- HOST_WIDE_INT vindex_val, 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);
- vindex_val = tree_low_cst (vindex, 0);
- while (i < vindex_val)
- {
- fn = TREE_CHAIN (fn);
- ++i;
- }
- fn = BV_FN (fn);
-
- /* Handle the case of a virtual function defined in BINFO
- itself. */
- overrider = find_final_overrider (t, b, fn);
- if (overrider == error_mark_node)
- continue;
-
- /* The `this' pointer needs to be adjusted from pointing to
- BINFO to pointing at the base where the final overrider
- appears. */
- delta = size_binop (PLUS_EXPR,
- get_derived_offset (binfo,
- DECL_VIRTUAL_CONTEXT (fn)),
- BINFO_OFFSET (binfo));
- delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta);
-
- modify_vtable_entry (t,
- binfo,
- TREE_PURPOSE (overrider),
- delta,
- &virtuals);
- }
+ update_vtable_entry_for_fn (t,
+ binfo,
+ BV_FN (old_virtuals),
+ &virtuals);
}
SET_BINFO_MARKED (binfo);
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;
{
tree fn = TREE_VALUE (*fnsp);
- if (BINFO_VIRTUALS (binfo)
- && !value_member (fn, BINFO_VIRTUALS (binfo)))
+ 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;
/* We don't need to adjust the `this' pointer when
calling this function. */
BV_DELTA (*fnsp) = integer_zero_node;
- BV_VCALL_INDEX (*fnsp) = integer_zero_node;
+ BV_VCALL_INDEX (*fnsp) = NULL_TREE;
/* This is an overridden function not already in our
vtable. Keep it. */
if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
{
tree tmp = get_matching_virtual
- (base_binfo, decl,
- DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
+ (base_binfo, decl, DECL_DESTRUCTOR_P (decl));
if (tmp && !found_overriden_fn)
{
}
}
-extern int interface_only, interface_unknown;
-
/* Create default constructors, assignment operators, and so forth for
the type indicated by T, if they are needed.
CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
- CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class
- cannot have a default constructor, copy constructor taking a const
- reference argument, or an assignment operator, respectively. If a
- virtual destructor is created, its DECL is returned; otherwise the
- return value is NULL_TREE. */
+ CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the
+ class cannot have a default constructor, copy constructor taking a
+ const reference argument, or an assignment operator taking a const
+ reference, respectively. If a virtual destructor is created, its
+ DECL is returned; otherwise the return value is NULL_TREE. */
static tree
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_cctor,
- cant_have_assignment)
+ cant_have_const_assignment)
tree t;
int cant_have_default_ctor;
int cant_have_const_cctor;
- int cant_have_assignment;
+ int cant_have_const_assignment;
{
tree default_fn;
tree implicit_fns = NULL_TREE;
- tree name = TYPE_IDENTIFIER (t);
tree virtual_dtor = NULL_TREE;
tree *f;
/* Destructor. */
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
{
- default_fn = cons_up_default_function (t, name, 0);
+ default_fn = implicitly_declare_fn (sfk_destructor, t, /*const_p=*/0);
check_for_override (default_fn, t);
/* If we couldn't make it work, then pretend we didn't need it. */
/* Default constructor. */
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
{
- default_fn = cons_up_default_function (t, name, 2);
+ default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0);
TREE_CHAIN (default_fn) = implicit_fns;
implicit_fns = default_fn;
}
{
/* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */
- default_fn = cons_up_default_function (t, name,
- 3 + cant_have_const_cctor);
+ default_fn
+ = implicitly_declare_fn (sfk_copy_constructor, t,
+ /*const_p=*/!cant_have_const_cctor);
TREE_CHAIN (default_fn) = implicit_fns;
implicit_fns = default_fn;
}
/* Assignment operator. */
if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
{
- default_fn = cons_up_default_function (t, name,
- 5 + cant_have_assignment);
+ default_fn
+ = implicitly_declare_fn (sfk_assignment_operator, t,
+ /*const_p=*/!cant_have_const_assignment);
TREE_CHAIN (default_fn) = implicit_fns;
implicit_fns = default_fn;
}
/* detect invalid field size. */
if (TREE_CODE (w) == CONST_DECL)
w = DECL_INITIAL (w);
- else if (TREE_READONLY_DECL_P (w))
+ else
w = decl_constant_value (w);
if (TREE_CODE (w) != INTEGER_CST)
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);
/* 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))
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;
|= CLASSTYPE_READONLY_FIELDS_NEED_INIT (type);
}
+ /* Core issue 80: A nonstatic data member is required to have a
+ different name from the class iff the class has a
+ user-defined constructor. */
+ if (DECL_NAME (x) == constructor_name (t)
+ && TYPE_HAS_CONSTRUCTOR (t))
+ cp_pedwarn_at ("field `%#D' with same name as class", x);
+
/* We set DECL_C_BIT_FIELD in grokbitfield.
If the type and width are valid, we'll also set DECL_BIT_FIELD. */
if (DECL_C_BIT_FIELD (x))
*empty_p = 0;
/* Build the FIELD_DECL. */
- field = build_lang_decl (FIELD_DECL, name, type);
+ field = build_decl (FIELD_DECL, name, type);
DECL_ASSEMBLER_NAME (field) = assembler_name;
DECL_VIRTUAL_P (field) = 1;
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. */
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)
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)
while (1)
{
tree offset;
+ struct record_layout_info_s 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.
a data member. */
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);
-
+ /* Undo the propagate_binfo_offsets call. */
+ 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. */
}
/* 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)
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_UNIT (basetype));
/* This is an empty base class. We first try to put it at offset
zero. */
{
/* 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))
break;
/* There's overlap here, too. Bump along to the next spot. */
- propagate_binfo_offsets (binfo, size_one_node);
+ propagate_binfo_offsets (binfo, alignment);
}
}
}
/* Build a FIELD_DECL for the base given by BINFO in the class
- *indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
+ indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
*BASE_ALIGN is a running maximum of the alignments of any base
- *class. */
+ class. */
static void
build_base_field (rli, binfo, empty_p, base_align, v)
location information. */
return;
- decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
+ decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = rli->t;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
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
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);
}
}
-/* Remove all zero-width bit-fields from T. */
+/* FN is a constructor or destructor. Clone the declaration to create
+ a specialized in-charge or not-in-charge version, as indicated by
+ NAME. */
-static void
-remove_zero_width_bit_fields (t)
- tree t;
-{
+static tree
+build_clone (fn, name)
+ tree fn;
+ tree name;
+{
+ tree parms;
+ tree clone;
+
+ /* Copy the function. */
+ clone = copy_decl (fn);
+ /* Remember where this function came from. */
+ DECL_CLONED_FUNCTION (clone) = fn;
+ /* Reset the function name. */
+ DECL_NAME (clone) = name;
+ DECL_ASSEMBLER_NAME (clone) = DECL_NAME (clone);
+ /* There's no pending inline data for this function. */
+ DECL_PENDING_INLINE_INFO (clone) = NULL;
+ DECL_PENDING_INLINE_P (clone) = 0;
+ /* And it hasn't yet been deferred. */
+ DECL_DEFERRED_FN (clone) = 0;
+ /* There's no magic VTT parameter in the clone. */
+ DECL_VTT_PARM (clone) = NULL_TREE;
+
+ /* The base-class destructor is not virtual. */
+ if (name == base_dtor_identifier)
+ {
+ DECL_VIRTUAL_P (clone) = 0;
+ if (TREE_CODE (clone) != TEMPLATE_DECL)
+ DECL_VINDEX (clone) = NULL_TREE;
+ }
+
+ /* If there was an in-charge parameter, drop it from the function
+ type. */
+ if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+ {
+ tree basetype;
+ tree parmtypes;
+ tree exceptions;
+
+ exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
+ parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone));
+ /* Skip the `this' parameter. */
+ parmtypes = TREE_CHAIN (parmtypes);
+ /* Skip the in-charge parameter. */
+ parmtypes = TREE_CHAIN (parmtypes);
+ /* If this is subobject constructor or destructor, add the vtt
+ parameter. */
+ if (DECL_NEEDS_VTT_PARM_P (clone))
+ parmtypes = hash_tree_chain (vtt_parm_type, parmtypes);
+ TREE_TYPE (clone)
+ = build_cplus_method_type (basetype,
+ TREE_TYPE (TREE_TYPE (clone)),
+ parmtypes);
+ if (exceptions)
+ TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
+ exceptions);
+ }
+
+ /* Copy the function parameters. But, DECL_ARGUMENTS aren't
+ function parameters; instead, those are the template parameters. */
+ if (TREE_CODE (clone) != TEMPLATE_DECL)
+ {
+ DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone));
+ /* Remove the in-charge parameter. */
+ if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+ {
+ TREE_CHAIN (DECL_ARGUMENTS (clone))
+ = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
+ DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
+ }
+
+ /* Add the VTT parameter. */
+ if (DECL_NEEDS_VTT_PARM_P (clone))
+ {
+ tree parm;
+
+ parm = build_artificial_parm (vtt_parm_identifier,
+ vtt_parm_type);
+ TREE_CHAIN (parm) = TREE_CHAIN (DECL_ARGUMENTS (clone));
+ TREE_CHAIN (DECL_ARGUMENTS (clone)) = parm;
+ }
+
+ for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
+ {
+ DECL_CONTEXT (parms) = clone;
+ copy_lang_decl (parms);
+ }
+ }
+
+ /* Mangle the function name. */
+ set_mangled_name_for_decl (clone);
+
+ /* Create the RTL for this function. */
+ DECL_RTL (clone) = NULL_RTX;
+ rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
+
+ /* Make it easy to find the CLONE given the FN. */
+ TREE_CHAIN (clone) = TREE_CHAIN (fn);
+ TREE_CHAIN (fn) = clone;
+
+ /* If this is a template, handle the DECL_TEMPLATE_RESULT as well. */
+ if (TREE_CODE (clone) == TEMPLATE_DECL)
+ {
+ tree result;
+
+ DECL_TEMPLATE_RESULT (clone)
+ = build_clone (DECL_TEMPLATE_RESULT (clone), name);
+ result = DECL_TEMPLATE_RESULT (clone);
+ DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
+ DECL_TI_TEMPLATE (result) = clone;
+ }
+ else if (DECL_DEFERRED_FN (fn))
+ defer_fn (clone);
+
+ return clone;
+}
+
+/* Produce declarations for all appropriate clones of FN. If
+ UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
+ CLASTYPE_METHOD_VEC as well. */
+
+void
+clone_function_decl (fn, update_method_vec_p)
+ tree fn;
+ int update_method_vec_p;
+{
+ tree clone;
+
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
+ {
+ /* For each constructor, we need two variants: an in-charge version
+ and a not-in-charge version. */
+ clone = build_clone (fn, complete_ctor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), NULL, clone);
+ clone = build_clone (fn, base_ctor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), NULL, clone);
+ }
+ else
+ {
+ my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
+
+ /* For each destructor, we need three variants: an in-charge
+ version, a not-in-charge version, and an in-charge deleting
+ version. We clone the deleting version first because that
+ means it will go second on the TYPE_METHODS list -- and that
+ corresponds to the correct layout order in the virtual
+ function table. */
+ clone = build_clone (fn, deleting_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), NULL, clone);
+ clone = build_clone (fn, complete_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), NULL, clone);
+ clone = build_clone (fn, base_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), NULL, clone);
+ }
+}
+
+/* For each of the constructors and destructors in T, create an
+ in-charge and not-in-charge variant. */
+
+static void
+clone_constructors_and_destructors (t)
+ tree t;
+{
+ tree fns;
+
+ /* We only clone constructors and destructors under the new ABI. */
+ if (!flag_new_abi)
+ return;
+
+ /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
+ out now. */
+ if (!CLASSTYPE_METHOD_VEC (t))
+ return;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+ for (fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+}
+
+/* Remove all zero-width bit-fields from T. */
+
+static void
+remove_zero_width_bit_fields (t)
+ tree t;
+{
tree *fieldsp;
fieldsp = &TYPE_FIELDS (t);
cant_have_const_ctor,
no_const_asn_ref);
+ /* Create the in-charge and not-in-charge variants of constructors
+ and destructors. */
+ clone_constructors_and_destructors (t);
+
/* Process the using-declarations. */
for (; access_decls; access_decls = TREE_CHAIN (access_decls))
handle_using_decl (TREE_VALUE (access_decls), t);
/* 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;
{
/* Loop over the virtual functions, adding them to our various
vtables. */
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
- if (DECL_VINDEX (fn))
+ if (DECL_VINDEX (fn)
+ && !(flag_new_abi && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (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
{
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;
/* Update the shared copy. */
tree shared_binfo;
- shared_binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), (tree) data);
+ shared_binfo = binfo_for_vbase (BINFO_TYPE (binfo), (tree) data);
BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
}
tree vbase;
tree offset;
- vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), t);
+ vbase = binfo_for_vbase (BINFO_TYPE (binfo), t);
offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
propagate_binfo_offsets (binfo, offset);
}
tree t;
varray_type *base_offsets;
{
- tree vbase;
+ tree vbases;
unsigned HOST_WIDE_INT dsize;
unsigned HOST_WIDE_INT eoc;
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 (flag_new_abi)
+ {
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+ vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
+ }
+ else
+ vbase = TREE_VALUE (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
+ {
+ tree offset;
+
+ offset = ssize_int (CEIL (dsize, BITS_PER_UNIT));
+ offset = size_diffop (offset,
+ convert (ssizetype,
+ BINFO_OFFSET (vbase)));
+
+ /* And compute the offset of the virtual base. */
+ propagate_binfo_offsets (vbase, offset);
+ /* 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
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);
/* 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
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 (TREE_VALUE (vbases));
if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
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;
{
/* 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
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. */
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;
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;
}
&& ((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;
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);
}
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
{
tree padding;
- padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
- layout_field (rli, padding);
+ padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
+ place_field (rli, padding);
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, padding, TYPE_NONCOPIED_PARTS (t));
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
class. */
if (!flag_new_abi && vptr)
{
- layout_field (rli, vptr);
+ place_field (rli, vptr);
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vptr);
}
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)
/* Clean up. */
VARRAY_FREE (v);
}
-
+
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
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
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
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
&& 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));
+ vfield = copy_decl (vfield);
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 we created a new vtbl pointer for this class, add it to the
+ list. */
+ if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ CLASSTYPE_VFIELDS (t)
+ = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
/* If necessary, create the primary vtable for this class. */
if (new_virtuals
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. */
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)
= chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
}
- /* If we created a new vtbl pointer for this class, add it to the
- list. */
- if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1)
- CLASSTYPE_VFIELDS (t)
- = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
-
finish_struct_bits (t);
/* Complete the rtl for any static member objects of the type we're
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
finish_vtbls (t);
+ /* Build the VTT for T. */
+ build_vtt (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
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);
return 0;
if (POINTER_TYPE_P (t))
t = TREE_TYPE (t);
- return same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed));
+ return same_type_ignoring_top_level_qualifiers_p (t, fixed);
}
\f
current_class_stack
= (class_stack_node_t) xmalloc (current_class_stack_size
* sizeof (struct class_stack_node));
+ VARRAY_TREE_INIT (local_classes, 8, "local_classes");
+ ggc_add_tree_varray_root (&local_classes, 1);
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
&& (TREE_CODE (TREE_TYPE (target_type))
== METHOD_TYPE)), 0);
+ if (TREE_CODE (overload) == COMPONENT_REF)
+ overload = TREE_OPERAND (overload, 1);
+
/* Check that the TARGET_TYPE is reasonable. */
if (TYPE_PTRFN_P (target_type))
/* This is OK. */
{
int complain = (flags & 1);
int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
+ tree r;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
case COMPONENT_REF:
{
- tree r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+ r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+ comp:
if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)
&& complain && !flag_ms_extensions)
{
/* Fall through. */
case TEMPLATE_ID_EXPR:
- return
- resolve_address_of_overloaded_function (lhstype,
- TREE_OPERAND (rhs, 0),
- complain,
- /*template_only=*/1,
- TREE_OPERAND (rhs, 1));
+ {
+ tree fns = TREE_OPERAND (rhs, 0);
+ tree args = TREE_OPERAND (rhs, 1);
+
+ r =
+ resolve_address_of_overloaded_function (lhstype,
+ fns,
+ complain,
+ /*template_only=*/1,
+ args);
+ if (TREE_CODE (fns) == COMPONENT_REF)
+ {
+ rhs = fns;
+ goto comp;
+ }
+ return r;
+ }
case OVERLOAD:
return
}
}
-/* 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;
{
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_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+}
+
+/* Dump the BINFO hierarchy for T. */
+
+void
+dump_class_hierarchy (t)
+ tree t;
+{
+ dump_class_hierarchy_r (t, TYPE_BINFO (t), 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);
+ accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
+ TYPE_BINFO (t), 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 (vbase, vbase, TYPE_BINFO (t), 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_NEW_VTABLE_MARKED (binfo, t))
+ initialize_vtable (binfo,
+ build_vtbl_initializer (binfo, binfo, t,
+ TYPE_BINFO (t), NULL));
+
+ 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 decl;
+
+ layout_vtable_decl (binfo, list_length (inits));
+ decl = get_vtbl_decl_for_binfo (binfo);
+ initialize_array (decl, inits);
+}
+
+/* Initialize DECL (a declaration for a namespace-scope array) with
+ the INITS. */
+
+static void
+initialize_array (decl, inits)
+ tree decl;
+ tree inits;
+{
+ tree context;
+
+ context = DECL_CONTEXT (decl);
+ DECL_CONTEXT (decl) = NULL_TREE;
+ DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
+ cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
+ DECL_CONTEXT (decl) = context;
+}
+
+/* Build the VTT (virtual table table) for T. */
+
+static void
+build_vtt (t)
+ tree t;
+{
+ tree inits;
+ tree type;
+ tree vtt;
+ tree index;
+
+ /* Under the old ABI, we don't use VTTs. */
+ if (!flag_new_abi)
+ return;
+
+ /* Build up the initializers for the VTT. */
+ inits = NULL_TREE;
+ index = size_zero_node;
+ build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
+
+ /* If we didn't need a VTT, we're done. */
+ if (!inits)
+ return;
+
+ /* Figure out the type of the VTT. */
+ type = build_index_type (size_int (list_length (inits)));
+ type = build_cplus_array_type (const_ptr_type_node, type);
+
+ /* Now, build the VTT object itself. */
+ vtt = build_vtable (t, get_vtt_name (t), type);
+ pushdecl_top_level (vtt);
+ initialize_array (vtt, inits);
+}
+
+/* Recursively build the VTT-initializer for BINFO (which is in the
+ hierarchy dominated by T). INITS points to the end of the
+ initializer list to date. INDEX is the VTT index where the next
+ element will be placed. */
+
+static tree *
+build_vtt_inits (binfo, t, inits, index)
+ tree binfo;
+ tree t;
+ tree *inits;
+ tree *index;
+{
+ int i;
+ tree b;
+ tree init;
+ tree secondary_vptrs;
+ int ctor_vtbl_p;
+
+ /* We only need VTTs for subobjects with virtual bases. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ return inits;
+
+ /* We need to use a construction vtable if this is not the primary
+ VTT. */
+ ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
+ if (ctor_vtbl_p)
+ {
+ build_ctor_vtbl_group (binfo, t);
+
+ /* Record the offset in the VTT where this sub-VTT can be found. */
+ BINFO_SUBVTT_INDEX (binfo) = *index;
+ }
+
+ /* Add the address of the primary vtable for the complete object. */
+ init = BINFO_VTABLE (binfo);
+ if (TREE_CODE (init) == TREE_LIST)
+ init = TREE_PURPOSE (init);
+ *inits = build_tree_list (NULL_TREE, init);
+ inits = &TREE_CHAIN (*inits);
+ BINFO_VPTR_INDEX (binfo) = *index;
+ *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
+
+ /* Recursively add the secondary VTTs for non-virtual bases. */
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
- dump_class_hierarchy (BINFO_BASETYPE (binfo, i), indent + 2);
+ {
+ b = BINFO_BASETYPE (binfo, i);
+ if (!TREE_VIA_VIRTUAL (b))
+ inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits,
+ index);
+ }
+
+ /* Add secondary virtual pointers for all subobjects of BINFO with
+ either virtual bases or virtual functions overridden along a
+ virtual path between the declaration and D, except subobjects
+ that are non-virtual primary bases. */
+ secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
+ TREE_TYPE (secondary_vptrs) = *index;
+ dfs_walk_real (binfo,
+ dfs_build_vtt_inits,
+ NULL,
+ dfs_unmarked_real_bases_queue_p,
+ secondary_vptrs);
+ dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
+ BINFO_TYPE (binfo));
+ *index = TREE_TYPE (secondary_vptrs);
+
+ /* The secondary vptrs come back in reverse order. After we reverse
+ them, and add the INITS, the last init will be the first element
+ of the chain. */
+ secondary_vptrs = TREE_VALUE (secondary_vptrs);
+ if (secondary_vptrs)
+ {
+ *inits = nreverse (secondary_vptrs);
+ inits = &TREE_CHAIN (secondary_vptrs);
+ my_friendly_assert (*inits == NULL_TREE, 20000517);
+ }
+
+ /* Add the secondary VTTs for virtual bases. */
+ for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
+ {
+ tree vbase;
+
+ if (!TREE_VIA_VIRTUAL (b))
+ continue;
+
+ vbase = binfo_for_vbase (BINFO_TYPE (b), t);
+ inits = build_vtt_inits (vbase, t, inits, index);
+ }
+
+ return inits;
+}
+
+/* Called from build_vtt_inits via dfs_walk. */
+
+static tree
+dfs_build_vtt_inits (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree l;
+ tree t;
+ tree init;
+ tree index;
+
+ l = (tree) data;
+ t = TREE_PURPOSE (l);
+
+ SET_BINFO_MARKED (binfo);
+
+ /* We don't care about bases that don't have vtables. */
+ if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
+ return NULL_TREE;
+
+ /* We're only interested in proper subobjects of T. */
+ if (same_type_p (BINFO_TYPE (binfo), t))
+ return NULL_TREE;
+
+ /* We're not interested in non-virtual primary bases. */
+ if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+ return NULL_TREE;
+
+ /* If BINFO doesn't have virtual bases, then we have to look to see
+ whether or not any virtual functions were overidden along a
+ virtual path between the declaration and T. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ /* FIXME: Implement this. */
+ ;
+
+ /* Record the index where this secondary vptr can be found. */
+ index = TREE_TYPE (l);
+ BINFO_VPTR_INDEX (binfo) = index;
+ TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
+ TYPE_SIZE_UNIT (ptr_type_node));
+
+ /* Add the initializer for the secondary vptr itself. */
+ init = BINFO_VTABLE (binfo);
+ if (TREE_CODE (init) == TREE_LIST)
+ init = TREE_PURPOSE (init);
+ TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
+
+ return NULL_TREE;
+}
+
+/* Called from build_vtt_inits via dfs_walk. */
+
+static tree
+dfs_fixup_binfo_vtbls (binfo, data)
+ tree binfo;
+ void *data ATTRIBUTE_UNUSED;
+{
+ CLEAR_BINFO_MARKED (binfo);
+
+ /* We don't care about bases that don't have vtables. */
+ if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
+ return NULL_TREE;
+
+ /* If we scribbled the construction vtable vptr into BINFO, clear it
+ out now. */
+ if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST)
+ BINFO_VTABLE (binfo) = TREE_VALUE (BINFO_VTABLE (binfo));
+
+ return NULL_TREE;
+}
+
+/* Build the construction vtable group for BINFO which is in the
+ hierarchy dominated by T. */
+
+static void
+build_ctor_vtbl_group (binfo, t)
+ tree binfo;
+ tree t;
+{
+ tree list;
+ tree type;
+ tree vtbl;
+ tree inits;
+ tree id;
+
+ /* See if we've already create this construction vtable group. */
+ if (flag_new_abi)
+ id = mangle_ctor_vtbl_for_type (t, binfo);
+ else
+ id = get_ctor_vtbl_name (t, binfo);
+ if (IDENTIFIER_GLOBAL_VALUE (id))
+ return;
+
+ /* Build a version of VTBL (with the wrong type) for use in
+ constructing the addresses of secondary vtables in the
+ construction vtable group. */
+ vtbl = build_vtable (BINFO_TYPE (binfo), id, ptr_type_node);
+ list = build_tree_list (vtbl, NULL_TREE);
+ accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
+ binfo, t, list);
+ inits = TREE_VALUE (list);
+
+ /* Figure out the type of the construction vtable. */
+ type = build_index_type (size_int (list_length (inits)));
+ type = build_cplus_array_type (vtable_entry_type, type);
+ TREE_TYPE (vtbl) = type;
+
+ /* Initialize the construction vtable. */
+ pushdecl_top_level (vtbl);
+ initialize_array (vtbl, inits);
+}
+
+/* Add the vtbl initializers for BINFO (and its non-primary,
+ non-virtual bases) to the list of INITS. BINFO is in the hierarchy
+ dominated by T. ORIG_BINFO must have the same type as BINFO, but
+ may be different from BINFO if we are building a construction
+ vtable. RTTI_BINFO gives the object that should be used as the
+ complete object for BINFO. */
+
+static void
+accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
+ tree binfo;
+ tree orig_binfo;
+ tree rtti_binfo;
+ tree t;
+ tree inits;
+{
+ int i;
+ int ctor_vtbl_p;
+
+ my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
+ BINFO_TYPE (orig_binfo)),
+ 20000517);
+
+ /* This is a construction vtable if the RTTI type is not the most
+ derived type in the hierarchy. */
+ ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+
+ /* If we're building a construction vtable, we're not interested in
+ subobjects that don't require construction vtables. */
+ if (ctor_vtbl_p
+ && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ return;
+
+ /* Build the initializers for the BINFO-in-T vtable. */
+ TREE_VALUE (inits)
+ = chainon (TREE_VALUE (inits),
+ dfs_accumulate_vtbl_inits (binfo, orig_binfo,
+ rtti_binfo, t, 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. We can't use
+ dfs_walk here because we need to iterate through bases of BINFO
+ and RTTI_BINFO simultaneously. */
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ {
+ tree base_binfo;
+
+ base_binfo = BINFO_BASETYPE (binfo, i);
+ /* Skip virtual bases. */
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+ accumulate_vtbl_inits (base_binfo,
+ BINFO_BASETYPE (orig_binfo, i),
+ rtti_binfo,
+ t,
+ 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). Returns the initializers for the BINFO vtable. */
+
+static tree
+dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
+ tree binfo;
+ tree orig_binfo;
+ tree rtti_binfo;
+ tree t;
+ tree l;
+{
+ tree inits = NULL_TREE;
+ int ctor_vtbl_p;
+
+ /* This is a construction vtable if the RTTI type is not the most
+ derived type in the hierarchy. */
+ ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+
+ if (BINFO_NEW_VTABLE_MARKED (binfo, t)
+ /* We need a new vtable, even for a primary base, when we're
+ building a construction vtable. */
+ || (ctor_vtbl_p && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
+ {
+ tree vtbl;
+ tree index;
+ int non_fn_entries;
+
+ /* Compute the initializer for this vtable. */
+ inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
+ &non_fn_entries);
+
+ /* Figure out the position to which the VPTR should point. */
+ vtbl = TREE_PURPOSE (l);
+ vtbl = build1 (ADDR_EXPR,
+ vtbl_ptr_type_node,
+ vtbl);
+ index = size_binop (PLUS_EXPR,
+ size_int (non_fn_entries),
+ size_int (list_length (TREE_VALUE (l))));
+ index = size_binop (MULT_EXPR,
+ TYPE_SIZE_UNIT (vtable_entry_type),
+ index);
+ vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+ TREE_CONSTANT (vtbl) = 1;
+
+ /* For an ordinary vtable, set BINFO_VTABLE. */
+ if (!ctor_vtbl_p)
+ BINFO_VTABLE (binfo) = vtbl;
+ /* For a construction vtable, we can't overwrite BINFO_VTABLE.
+ So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
+ straighten this out. */
+ else
+ BINFO_VTABLE (binfo) = build_tree_list (vtbl,
+ BINFO_VTABLE (binfo));
+ }
+
+ return inits;
+}
+
+/* Construct the initializer for BINFOs virtual function table. BINFO
+ is part of the hierarchy dominated by T. If we're building a
+ construction vtable, the ORIG_BINFO is the binfo we should use to
+ find the actual function pointers to put in the vtable. Otherwise,
+ ORIG_BINFO should be the same as BINFO. The RTTI_DOMINATOR is the
+ BINFO that should be indicated by the RTTI information in the
+ vtable; it will be a base class of T, rather than T itself, if we
+ are building a construction vtable.
+
+ 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, orig_binfo, t, rtti_binfo, non_fn_entries_p)
+ tree binfo;
+ tree orig_binfo;
+ tree t;
+ tree rtti_binfo;
+ int *non_fn_entries_p;
+{
+ tree v;
+ tree inits;
+ 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 (TREE_VALUE (vbase));
+
+ /* Add entries to the vtable for RTTI. */
+ inits = chainon (inits, build_rtti_vtbl_entries (binfo, rtti_binfo));
+
+ 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;
+ for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (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);
+ }
+
+ /* 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_build_vcall_offset_vtbl_entries (binfo, data)
+ tree binfo;
+ void *data;
+{
+ vcall_offset_data* vod;
+ tree derived_virtuals;
+ tree base_virtuals;
+ tree binfo_inits;
+ tree non_primary_binfo;
+ tree b;
+ int i;
+
+ vod = (vcall_offset_data *) data;
+ binfo_inits = NULL_TREE;
+
+ /* We might be a primary base class. Go up the inheritance
+ hierarchy until we find the class of which we are a primary base:
+ it is the BINFO_VIRTUALS there that we need to consider. */
+ non_primary_binfo = binfo;
+ while (BINFO_PRIMARY_MARKED_P (non_primary_binfo))
+ non_primary_binfo = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+
+ /* Skip virtuals that we have already handled in a primary base
+ class. */
+ base_virtuals = BINFO_VIRTUALS (binfo);
+ derived_virtuals = BINFO_VIRTUALS (non_primary_binfo);
+ b = BINFO_PRIMARY_BINFO (binfo);
+ if (b)
+ for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
+ {
+ base_virtuals = TREE_CHAIN (base_virtuals);
+ derived_virtuals = TREE_CHAIN (derived_virtuals);
+ }
+
+ /* Make entries for the rest of the virtuals. */
+ while (base_virtuals)
+ {
+ /* Figure out what function we're looking at. */
+ tree fn = TREE_VALUE (derived_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);
+
+ /* Compute the vcall offset. */
+ 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);
+
+ /* If there is already a vcall index, then we are processing a
+ construction vtable. The index should be the same as it was
+ when we processed the vtable for the base class. */
+ if (BV_VCALL_INDEX (derived_virtuals))
+ my_friendly_assert (tree_int_cst_equal (BV_VCALL_INDEX
+ (derived_virtuals),
+ vod->index),
+ 20000516);
+ /* Keep track of the vtable index where this vcall offset can be
+ found. */
+ else
+ BV_VCALL_INDEX (derived_virtuals) = vod->index;
+
+ /* The next vcall offset will be found at a more negative
+ offset. */
+ vod->index = fold (build (MINUS_EXPR, integer_type_node,
+ vod->index, integer_one_node));
+
+ /* Go to the next entries in the list. */
+ derived_virtuals = TREE_CHAIN (derived_virtuals);
+ base_virtuals = TREE_CHAIN (base_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_skip_vbases,
+ vod);
+ vod->inits = chainon (vod->inits, inits);
+}
+
+/* Return vtbl initializers for the RTTI entries coresponding to the
+ BINFO's vtable. The RTTI entries should indicate the object given
+ by RTTI_BINFO. */
+
+static tree
+build_rtti_vtbl_entries (binfo, rtti_binfo)
+ tree binfo;
+ tree rtti_binfo;
+{
+ tree b;
+ tree t;
+ tree basetype;
+ tree offset;
+ tree decl;
+ tree init;
+ tree inits;
+
+ basetype = BINFO_TYPE (binfo);
+ inits = NULL_TREE;
+ t = BINFO_TYPE (rtti_binfo);
+
+ /* 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 (BINFO_OFFSET (rtti_binfo), 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 (!vcall_index)
+ vcall_index = integer_zero_node;
+
+ if (flag_vtable_thunks)
+ {
+ HOST_WIDE_INT idelta;
+ HOST_WIDE_INT ivindex;
+ tree fn;
+
+ idelta = tree_low_cst (delta, 0);
+ ivindex = tree_low_cst (vcall_index, 0);
+ fn = TREE_OPERAND (entry, 0);
+ if ((idelta || ivindex)
+ && fn != abort_fndecl
+ && !DECL_TINFO_FN_P (fn))
+ {
+ 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
+ {
+ 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;
+ }
}