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 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, int *));
+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));
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,
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);
/* 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. */
static char asm_stmt[] = ".vtable_entry %c0, %c1";
tree s, i, i2;
- s = build_unary_op (ADDR_EXPR, get_vtbl_decl_for_binfo (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);
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. */
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
no need to do it again. */
return 0;
- virtuals = copy_list (BINFO_VIRTUALS (binfo));
+ 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));
#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
base_fndecl = BV_FN (v);
BV_DELTA (v) = delta;
- BV_VCALL_INDEX (v) = integer_zero_node;
+ BV_VCALL_INDEX (v) = NULL_TREE;
BV_FN (v) = fndecl;
/* Now assign virtual dispatch information, if unset. We can
new_virtual = build_tree_list (NULL_TREE, fndecl);
BV_DELTA (new_virtual) = integer_zero_node;
- BV_VCALL_INDEX (new_virtual) = integer_zero_node;
if (DECL_VINDEX (fndecl) == error_mark_node)
{
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)
;
else
{
tree shared_binfo;
+ tree type;
- shared_binfo
- = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
+ 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))
{
- BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
+ /* 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;
}
}
if (!TREE_VIA_VIRTUAL (vbases))
continue;
- vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), type);
+ 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. */
*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
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, vfuns_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);
overrides (fndecl, base_fndecl)
tree fndecl, base_fndecl;
{
- /* Destructors have special names. */
- if (DECL_DESTRUCTOR_P (base_fndecl) && DECL_DESTRUCTOR_P (fndecl))
+ /* 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 (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)))
/* 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. */
|= 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;
while (1)
{
tree offset;
- struct record_layout_info old_rli = *rli;
+ struct record_layout_info_s old_rli = *rli;
/* Place this field. */
place_field (rli, decl);
a data member. */
if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
{
- /* Undo the propogate_binfo_offsets call. */
+ /* Undo the propagate_binfo_offsets call. */
offset = size_diffop (size_zero_node, offset);
propagate_binfo_offsets (binfo, convert (ssizetype, offset));
/* This routine should only be used for empty classes. */
my_friendly_assert (is_empty_class (basetype), 20000321);
- alignment = ssize_int (CLASSTYPE_ALIGN (basetype));
+ alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
/* This is an empty base class. We first try to put it at offset
zero. */
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);
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)
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)),
= 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;
{
my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
- /* For each destructor, we need two variants: an in-charge
+ /* 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
/* 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 vbase;
- if (!TREE_VIA_VIRTUAL (vbases))
- continue;
-
if (flag_new_abi)
- vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), t);
+ {
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+ vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
+ }
else
- vbase = vbases;
+ vbase = TREE_VALUE (vbases);
if (!BINFO_VBASE_PRIMARY_P (vbase))
{
*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,
- ssize_int (CEIL (dsize, BITS_PER_UNIT)));
+ 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. */
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 (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
- dfs_walk (vbases, dfs_set_offset_for_unshared_vbases, NULL, t);
/* If we had empty base classes that protruded beyond the end of the
class, we didn't update DSIZE above; we were hoping to overlay
vbases;
vbases = TREE_CHAIN (vbases))
{
- tree basetype = BINFO_TYPE (vbases);
+ 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);
{
tree padding;
- padding = build_lang_decl (FIELD_DECL, NULL_TREE, char_type_node);
+ 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));
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
|| overridden_virtuals
= 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_HAS_PRIMARY_BASE_P (t))
- 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 (TYPE_VFIELD (t))
{
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 (ak_public, 0);
fprintf (stderr, " virtual");
if (BINFO_PRIMARY_MARKED_P (binfo)
|| (TREE_VIA_VIRTUAL (binfo)
- && BINFO_VBASE_PRIMARY_P (BINFO_FOR_VBASE (BINFO_TYPE (binfo),
+ && BINFO_VBASE_PRIMARY_P (binfo_for_vbase (BINFO_TYPE (binfo),
t))))
fprintf (stderr, " primary");
fprintf (stderr, "\n");
dump_class_hierarchy (t)
tree t;
{
- tree vbase;
-
dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
- fprintf (stderr, "virtual bases\n");
- for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; vbase = TREE_CHAIN (vbase))
- dump_class_hierarchy_r (t, vbase, 0);
}
/* Virtual function table initialization. */
first, followed by the non-virtual secondary vtables in
inheritance graph order. */
list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
- TREE_TYPE (list) = t;
- accumulate_vtbl_inits (TYPE_BINFO (t), list);
+ 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 (BINFO_FOR_VBASE (BINFO_TYPE (vbase), t),
- list);
+
+ accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
}
if (TYPE_BINFO_VTABLE (t))
{
tree t = (tree) data;
- if (!BINFO_PRIMARY_MARKED_P (binfo)
- && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
- && BINFO_NEW_VTABLE_MARKED (binfo, t))
+ if (BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
- build_vtbl_initializer (binfo, t, NULL));
+ build_vtbl_initializer (binfo, binfo, t,
+ TYPE_BINFO (t), NULL));
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
SET_BINFO_MARKED (binfo);
return NULL_TREE;
tree binfo;
tree inits;
{
- tree context;
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) = 0;
+ 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)
+ {
+ 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. */
+ 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, inits)
+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. */
- dfs_walk_real (binfo,
- dfs_accumulate_vtbl_inits,
- NULL,
- dfs_skip_vbases,
- inits);
+ 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). */
+ TREE_VALUE (DATA). Returns the initializers for the BINFO vtable. */
static tree
-dfs_accumulate_vtbl_inits (binfo, data)
+dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
tree binfo;
- void *data;
+ tree orig_binfo;
+ tree rtti_binfo;
+ tree t;
+ tree l;
{
- tree l;
- tree t;
+ tree inits = NULL_TREE;
+ int ctor_vtbl_p;
- l = (tree) data;
- t = TREE_TYPE (l);
+ /* 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_PRIMARY_MARKED_P (binfo)
- && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
- && BINFO_NEW_VTABLE_MARKED (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 inits;
tree vtbl;
tree index;
int non_fn_entries;
/* Compute the initializer for this vtable. */
- inits = build_vtbl_initializer (binfo, t, &non_fn_entries);
+ inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
+ &non_fn_entries);
- /* Set BINFO_VTABLE to the address where the VPTR should point. */
+ /* Figure out the position to which the VPTR should point. */
vtbl = TREE_PURPOSE (l);
vtbl = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (vtbl)),
+ vtbl_ptr_type_node,
vtbl);
index = size_binop (PLUS_EXPR,
size_int (non_fn_entries),
size_int (list_length (TREE_VALUE (l))));
- BINFO_VTABLE (binfo)
- = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
- size_binop (MULT_EXPR,
- TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
- index));
-
- /* Add the initializers for this vtable to the initializers for
- the other vtables we've already got. */
- TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
+ 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));
}
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
-
- return NULL_TREE;
+ return inits;
}
/* Construct the initializer for BINFOs virtual function table. BINFO
- is part of the hierarchy dominated by T. The value returned is a
- TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
- DECL_INITIAL for a vtable. If NON_FN_ENTRIES_P is not NULL,
- *NON_FN_ENTRIES_P is set to the number of non-function entries in
- the vtable. */
+ 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, t, non_fn_entries_p)
+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 = BINFO_VIRTUALS (binfo);
- tree inits = NULL_TREE;
+ tree v;
+ tree inits;
tree vfun_inits;
tree vbase;
vcall_offset_data vod;
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
vbase = TREE_CHAIN (vbase))
- CLEAR_BINFO_VTABLE_PATH_MARKED (vbase);
+ CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
/* Add entries to the vtable for RTTI. */
- inits = chainon (inits, build_rtti_vtbl_entries (binfo, t));
+ 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;
- while (v)
+ for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
{
tree delta;
tree vcall_index;
init = build_vtable_entry (delta, vcall_index, pfn);
/* And add it to the chain of initializers. */
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
-
- /* Keep going. */
- v = TREE_CHAIN (v);
}
/* The initializers for virtual functions were built up in reverse
/* Find the instance of this virtual base in the complete
object. */
- b = BINFO_FOR_VBASE (BINFO_TYPE (vbase), t);
+ 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. */
tree orig_vbase;
/* Find the instance of this virtual base in the type of BINFO. */
- orig_vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbase),
+ orig_vbase = binfo_for_vbase (BINFO_TYPE (vbase),
BINFO_TYPE (binfo));
/* The vbase offset had better be the same. */
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. */
- BV_VCALL_INDEX (derived_virtuals) = vod->index;
+ 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,
}
/* Return vtbl initializers for the RTTI entries coresponding to the
- BINFO's vtable. BINFO is a part of the hierarchy dominated by
- T. */
+ BINFO's vtable. The RTTI entries should indicate the object given
+ by RTTI_BINFO. */
static tree
-build_rtti_vtbl_entries (binfo, t)
+build_rtti_vtbl_entries (binfo, rtti_binfo)
tree binfo;
- tree t;
+ tree rtti_binfo;
{
tree b;
+ tree t;
tree basetype;
tree offset;
tree decl;
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))
break;
b = primary_base;
}
- offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
+ 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
tree vcall_index;
tree entry;
{
+ if (!vcall_index)
+ vcall_index = integer_zero_node;
+
if (flag_vtable_thunks)
{
HOST_WIDE_INT idelta;