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, 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 dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
static int make_new_vtable PARAMS ((tree, tree));
-static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
-extern void dump_class_hierarchy PARAMS ((tree));
+static void dump_class_hierarchy_r PARAMS ((FILE *, tree, tree, int));
+extern void dump_class_hierarchy PARAMS ((const char *, tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, splay_tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
+static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
+ tree));
static void set_vindex PARAMS ((tree, tree, int *));
static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vtbl_init_data *));
-static tree dfs_mark_primary_bases PARAMS ((tree, void *));
+static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree));
+static void force_canonical_binfo PARAMS ((tree, tree, tree, tree));
static void mark_primary_bases PARAMS ((tree));
+static tree mark_primary_virtual_base PARAMS ((tree, tree, 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, int, tree *, tree *));
+static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
+static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
static tree get_matching_base PARAMS ((tree, tree));
static tree dfs_get_primary_binfo PARAMS ((tree, void*));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
+
+/* Macros for dfs walking during vtt construction. See
+ dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
+ and dfs_fixup_binfo_vtbls. */
+#define VTT_TOP_LEVEL_P(node) TREE_UNSIGNED(node)
+#define VTT_MARKED_BINFO_P(node) TREE_USED(node)
+
/* Variables shared between class.c and call.c. */
#ifdef GATHER_STATISTICS
}
}
-/* Called via dfs_walk from mark_primary_bases. Sets
- BINFO_PRIMARY_MARKED_P for BINFO, if appropriate. */
+/* Binfo FROM is within a virtual heirarchy which is being reseated to
+ TO. Move primary information from FROM to TO, and recursively traverse
+ into FROM's bases. The heirarchy is dominated by TYPE. MAPPINGS is an
+ assoc list of binfos that have already been reseated. */
-static tree
-dfs_mark_primary_bases (binfo, data)
- tree binfo;
- void *data;
+static void
+force_canonical_binfo_r (to, from, type, mappings)
+ tree to;
+ tree from;
+ tree type;
+ tree mappings;
{
- tree base_binfo;
+ int i, n_baseclasses = BINFO_N_BASETYPES (from);
+
+ BINFO_INDIRECT_PRIMARY_P (to)
+ = BINFO_INDIRECT_PRIMARY_P (from);
+ BINFO_INDIRECT_PRIMARY_P (from) = 0;
+ if (BINFO_PRIMARY_P (from))
+ {
+ tree primary = BINFO_PRIMARY_BASE_OF (from);
+ tree assoc;
+
+ /* We might have just moved the primary base too, see if it's on our
+ mappings. */
+ assoc = purpose_member (primary, mappings);
+ if (assoc)
+ primary = TREE_VALUE (assoc);
+ BINFO_PRIMARY_BASE_OF (to) = primary;
+ BINFO_PRIMARY_BASE_OF (from) = NULL_TREE;
+ }
+ my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)), 20010104);
+ mappings = tree_cons (from, to, mappings);
+ for (i = 0; i != n_baseclasses; i++)
+ {
+ tree from_binfo = BINFO_BASETYPE (from, i);
+ tree to_binfo = BINFO_BASETYPE (to, i);
+
+ if (TREE_VIA_VIRTUAL (from_binfo))
+ {
+ tree shared_binfo = binfo_for_vbase (BINFO_TYPE (from_binfo), type);
+
+ if (shared_binfo == from_binfo)
+ force_canonical_binfo (to_binfo, from_binfo, type, mappings);
+ }
+ else
+ force_canonical_binfo_r (to_binfo, from_binfo, type, mappings);
+ }
+}
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
- return NULL_TREE;
+/* FROM is the canonical binfo for a virtual base. It is being reseated to
+ make TO the canonical binfo, within the heirarchy dominated by TYPE.
+ MAPPINGS is an assoc list of binfos that have already been reseated.
+ Adjust any non-virtual bases within FROM, and also move any virtual bases
+ which are canonical. This complication arises because selecting primary
+ bases walks in inheritance graph order, but we don't share binfos for
+ virtual bases, hence we can fill in the primaries for a virtual base,
+ and then discover that a later base requires the virtual as its
+ primary. */
- base_binfo = get_primary_binfo (binfo);
+static void
+force_canonical_binfo (to, from, type, mappings)
+ tree to;
+ tree from;
+ tree type;
+ tree mappings;
+{
+ tree assoc = purpose_member (BINFO_TYPE (to),
+ CLASSTYPE_VBASECLASSES (type));
+ TREE_VALUE (assoc) = to;
+ force_canonical_binfo_r (to, from, type, mappings);
+}
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- tree shared_binfo;
- tree type;
+/* Make BASE_BINFO the primary virtual base of BINFO within the hierarchy
+ dominated by TYPE. Returns BASE_BINFO, if it can be made so, NULL
+ otherwise (because something else has already made it primary). */
- type = (tree) data;
- shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
+static tree
+mark_primary_virtual_base (binfo, base_binfo, type)
+ tree binfo;
+ tree base_binfo;
+ tree type;
+{
+ tree shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
+ tree delta;
- /* If this virtual base is not already primary somewhere else in
- the hiearchy, then we'll be using this copy. */
- if (!BINFO_PRIMARY_MARKED_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;
- }
- else
- base_binfo = NULL_TREE;
+ if (BINFO_PRIMARY_P (shared_binfo))
+ {
+ /* It's already allocated in the hierarchy. BINFO won't have a
+ primary base in this hierachy, even though the complete object
+ BINFO is for, would do. */
+ BINFO_LOST_PRIMARY_P (binfo) = 1;
+
+ return NULL_TREE;
}
+
+ /* We need to make sure that the assoc list
+ CLASSTYPE_VBASECLASSES of TYPE, indicates this particular
+ primary BINFO for the virtual base, as this is the one
+ that'll really exist. */
+ if (base_binfo != shared_binfo)
+ force_canonical_binfo (base_binfo, shared_binfo, type, NULL);
- if (base_binfo)
- BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
-
- return NULL_TREE;
+ delta = size_diffop (BINFO_OFFSET (binfo), BINFO_OFFSET (base_binfo));
+ if (!integer_zerop (delta))
+ {
+ propagate_binfo_offsets (base_binfo, delta);
+ BINFO_OFFSET (base_binfo) = BINFO_OFFSET (binfo);
+ }
+ return base_binfo;
}
-/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
- dominated by BINFO that are primary bases. */
+/* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
+ dominated by TYPE 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 binfo;
+
+ /* Walk the bases in inheritance graph order. */
+ for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
{
- 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);
+ tree base_binfo;
+
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+ /* Not a dynamic base. */
+ continue;
- if (!TREE_VIA_VIRTUAL (vbases))
- continue;
+ base_binfo = get_primary_binfo (binfo);
- vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
- if (BINFO_PRIMARY_MARKED_P (vbase))
- /* This virtual base was already included in the hierarchy, so
- there's nothing to do here. */
- continue;
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ base_binfo = mark_primary_virtual_base (binfo, base_binfo, type);
- /* Now, walk its bases. */
- dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
- dfs_skip_nonprimary_vbases_unmarkedp, type);
+ if (base_binfo)
+ BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
}
}
if (!TYPE_VFIELD (t))
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
- /* Mark the indirect primary bases. */
+ /* Find the indirect primary bases - those virtual bases which are primary
+ bases of something else in this hierarchy. */
for (vbases = CLASSTYPE_VBASECLASSES (t);
vbases;
vbases = TREE_CHAIN (vbases))
{
- tree binfo = TREE_VALUE (vbases);
+ tree vbase_binfo = TREE_VALUE (vbases);
- /* See if this virtual base is an indirect primary base. If so,
- it must be either a primary base or an indirect primary base
- in one of the direct bases. */
+ /* See if this virtual base is an indirect primary base. To be so,
+ it must be a primary base within the hierarchy of one of our
+ direct bases. */
for (i = 0; i < n_baseclasses; ++i)
{
- tree basetype;
+ tree basetype = TYPE_BINFO_BASETYPE (t, i);
tree v;
- basetype = TYPE_BINFO_BASETYPE (t, i);
for (v = CLASSTYPE_VBASECLASSES (basetype);
v;
v = TREE_CHAIN (v))
{
- tree b = TREE_VALUE (v);
- if ((BINFO_PRIMARY_MARKED_P (b)
- || BINFO_INDIRECT_PRIMARY_P (b))
- && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+ tree base_vbase = TREE_VALUE (v);
+
+ if (BINFO_PRIMARY_P (base_vbase)
+ && same_type_p (BINFO_TYPE (base_vbase),
+ BINFO_TYPE (vbase_binfo)))
{
- BINFO_INDIRECT_PRIMARY_P (binfo) = 1;
+ BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
break;
}
}
/* If we've discovered that this virtual base is an indirect
primary base, then we can move on to the next virtual
base. */
- if (BINFO_INDIRECT_PRIMARY_P (binfo))
+ if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo))
break;
}
}
candidate = base_binfo;
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)
+
+ /* If this is an indirect primary base, it still could be
+ our primary base -- unless we later find there's another
+ nearly-empty virtual base that isn't an indirect
+ primary base. */
+ if (!candidate)
candidate = base_binfo;
}
}
if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
{
base = ffod->declaring_base;
- while (BINFO_PRIMARY_MARKED_P (base))
- {
- BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1;
- base = BINFO_INHERITANCE_CHAIN (base);
- }
- BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1;
break;
}
tree binfo;
void *data;
{
- if (/* There's no need to modify the vtable for a primary base;
- we're not going to use that vtable anyhow. */
- !BINFO_PRIMARY_MARKED_P (binfo)
+ if (/* There's no need to modify the vtable for a non-virtual
+ primary base; we're not going to use that vtable anyhow
+ (virtual primary bases can become non-primary in a
+ class derivation of this one.) */
+ (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
/* Similarly, a base without a vtable needs no modification. */
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
/* Walk through all the subobjects of TYPE (located at OFFSET). Call
F for every subobject, passing it the type, offset, and table of
- OFFSETS. If VBASES_P is non-zero, then even non-virtual primary
+ OFFSETS. If VBASES_P is non-zero, then even virtual non-primary
bases should be traversed; otherwise, they are ignored. If F
returns a non-zero value, the traversal ceases, and that value is
returned. Otherwise, returns zero. */
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
- && !BINFO_PRIMARY_MARKED_P (binfo))
+ && !BINFO_PRIMARY_P (binfo))
continue;
r = walk_subobject_offsets (BINFO_TYPE (binfo),
base class, but a non-primary virtual base is allocated
later, in layout_virtual_bases. */
if (TREE_VIA_VIRTUAL (base_binfo)
- && !BINFO_PRIMARY_MARKED_P (base_binfo))
+ && !BINFO_PRIMARY_P (base_binfo))
continue;
build_base_field (rli, base_binfo, empty_p, &base_align, offsets);
/* If this is a virtual base, make sure it has the same offset as
the shared copy. If it's a primary base, then we know it's
correct. */
- if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
+ if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
{
tree t = (tree) data;
tree vbase;
else
vbase = TREE_VALUE (vbases);
- if (!BINFO_PRIMARY_MARKED_P (vbase))
+ if (!BINFO_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. */
if (!include_virtuals_p
&& TREE_VIA_VIRTUAL (base_binfo)
- && !BINFO_PRIMARY_MARKED_P (base_binfo))
+ && !BINFO_PRIMARY_P (base_binfo))
continue;
offset = size_binop (PLUS_EXPR,
layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals);
+ if (flag_dump_class_layout)
+ dump_class_hierarchy (*flag_dump_class_layout
+ ? flag_dump_class_layout : NULL,
+ t);
+
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
might need to know it for setting up the offsets in the vtable
(or in thunks) below. */
/* 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);
tree primary_base = (tree) data;
if (TREE_VIA_VIRTUAL (binfo)
- && same_type_p (TREE_TYPE (binfo), TREE_TYPE (primary_base)))
+ && same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (primary_base)))
return binfo;
return NULL_TREE;
primary. In particular if the resulting BINFO is a virtual base,
and it occurs elsewhere in the hierarchy, then this occurrence may
not actually be a primary base in the complete object. Check
- BINFO_PRIMARY_MARKED_P to be sure. */
+ BINFO_PRIMARY_P to be sure. */
tree
get_primary_binfo (binfo)
the top level; it is incremented recursively. */
static void
-dump_class_hierarchy_r (t, binfo, indent)
+dump_class_hierarchy_r (stream, t, binfo, indent)
+ FILE *stream;
tree t;
tree binfo;
int indent;
{
int i;
- fprintf (stderr, "%*s0x%lx (%s) ", indent, "",
+ fprintf (stream, "%*s0x%lx (%s) ", indent, "",
(unsigned long) binfo,
type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
- fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
+ if (is_empty_class (BINFO_TYPE (binfo)))
+ fprintf (stream, " empty");
+ else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
+ fprintf (stream, " nearly-empty");
if (TREE_VIA_VIRTUAL (binfo))
- fprintf (stderr, " virtual");
- if (BINFO_PRIMARY_MARKED_P (binfo)
- || (TREE_VIA_VIRTUAL (binfo)
- && BINFO_PRIMARY_MARKED_P (binfo_for_vbase (BINFO_TYPE (binfo),
- t))))
- fprintf (stderr, " primary");
- fprintf (stderr, "\n");
+ {
+ tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t);
+
+ if (canonical == binfo)
+ fprintf (stream, " virtual-canonical");
+ else
+ fprintf (stream, " virtual-non-canonical");
+ }
+ if (BINFO_PRIMARY_P (binfo))
+ fprintf (stream, " primary-for 0x%lx (%s)",
+ (unsigned long)BINFO_PRIMARY_BASE_OF (binfo),
+ type_as_string (BINFO_PRIMARY_BASE_OF (binfo), TFF_PLAIN_IDENTIFIER));
+ if (BINFO_LOST_PRIMARY_P (binfo))
+ fprintf (stream, " lost-primary");
+ fprintf (stream, "\n");
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
- dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+ dump_class_hierarchy_r (stream, t, BINFO_BASETYPE (binfo, i), indent + 2);
}
/* Dump the BINFO hierarchy for T. */
void
-dump_class_hierarchy (t)
+dump_class_hierarchy (name, t)
+ const char *name;
tree t;
{
- dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
+ FILE *stream = stderr;
+
+ if (name)
+ {
+ static int append = 0;
+
+ stream = fopen (name, append++ ? "a" : "w");
+ if (!stream)
+ error ("could not open dump file `%s'", name);
+ return;
+ }
+ fprintf (stream, "%s\n",
+ type_as_string (t, TFF_PLAIN_IDENTIFIER));
+ dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0);
+ fprintf (stream, "\n");
+ if (name)
+ fclose (stream);
}
/* Virtual function table initialization. */
order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
+ tree real_base;
+
if (!TREE_VIA_VIRTUAL (vbase))
continue;
-
- accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
+
+ /* Although we walk in inheritance order, that might not get the
+ canonical base. */
+ real_base = binfo_for_vbase (BINFO_TYPE (vbase), t);
+
+ accumulate_vtbl_inits (real_base, real_base,
+ TYPE_BINFO (t), t, list);
}
if (TYPE_BINFO_VTABLE (t))
DECL_CONTEXT (decl) = context;
}
-/* Build the VTT (virtual table table) for T. */
+/* Build the VTT (virtual table table) for T.
+ A class requires a VTT if it has virtual bases.
+
+ This holds
+ 1 - primary virtual pointer for complete object T
+ 2 - secondary VTTs for each direct non-virtual base of T which requires a VTT
+ 3 - secondary virtual pointers for each direct or indirect base of T which
+ has virtual bases or is reachable via a virtual path from T.
+ 4 - secondary VTTs for each direct or indirect virtual base of T.
+
+ Secondary VTTs look like complete object VTTs without part 4. */
static void
build_vtt (t)
/* Build up the initializers for the VTT. */
inits = NULL_TREE;
index = size_zero_node;
- build_vtt_inits (TYPE_BINFO (t), t, /*virtual_vtts_p=*/1,
- &inits, &index);
+ build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
/* If we didn't need a VTT, we're done. */
if (!inits)
}
/* Recursively build the VTT-initializer for BINFO (which is in the
- hierarchy dominated by T). If VIRTUAL_VTTS_P is non-zero, then
- sub-VTTs for virtual bases are included. INITS points to the end
- of the initializer list to date. INDEX is the VTT index where the
- next element will be placed. */
+ 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
+ replaced. Iff BINFO is the binfo for T, this is the top level VTT (i.e.
+ not a subvtt for some base of T). When that is so, we emit the sub-VTTs
+ for virtual bases of T. When it is not so, we build the constructor
+ vtables for the BINFO-in-T variant. */
static tree *
-build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
+build_vtt_inits (binfo, t, inits, index)
tree binfo;
tree t;
- int virtual_vtts_p;
tree *inits;
tree *index;
{
tree b;
tree init;
tree secondary_vptrs;
- int ctor_vtbl_p;
+ int top_level_p = same_type_p (TREE_TYPE (binfo), t);
/* We only need VTTs for subobjects with virtual bases. */
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
/* 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)
+ if (!top_level_p)
{
build_ctor_vtbl_group (binfo, t);
init = TREE_VALUE (init);
*inits = build_tree_list (NULL_TREE, init);
inits = &TREE_CHAIN (*inits);
- BINFO_VPTR_INDEX (binfo) = *index;
+ if (top_level_p)
+ {
+ my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+ 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. */
b = BINFO_BASETYPE (binfo, i);
if (!TREE_VIA_VIRTUAL (b))
inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t,
- /*virtuals_vtts_p=*/0,
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. */
+ either virtual bases or reachable along a virtual path, except
+ subobjects that are non-virtual primary bases. */
secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo));
TREE_TYPE (secondary_vptrs) = *index;
+ VTT_TOP_LEVEL_P (secondary_vptrs) = top_level_p;
+ VTT_MARKED_BINFO_P (secondary_vptrs) = 0;
+
dfs_walk_real (binfo,
dfs_build_secondary_vptr_vtt_inits,
NULL,
- dfs_unmarked_real_bases_queue_p,
+ dfs_ctor_vtable_bases_queue_p,
secondary_vptrs);
- dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
+ VTT_MARKED_BINFO_P (secondary_vptrs) = 1;
+ dfs_walk (binfo, dfs_unmark, dfs_ctor_vtable_bases_queue_p,
+ secondary_vptrs);
+
*index = TREE_TYPE (secondary_vptrs);
/* The secondary vptrs come back in reverse order. After we reverse
}
/* Add the secondary VTTs for virtual bases. */
- if (virtual_vtts_p)
+ if (top_level_p)
for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
{
tree vbase;
continue;
vbase = binfo_for_vbase (BINFO_TYPE (b), t);
- inits = build_vtt_inits (vbase, t, /*virtual_vtts_p=*/0,
- inits, index);
+ inits = build_vtt_inits (vbase, t, inits, index);
}
- dfs_walk (binfo, dfs_fixup_binfo_vtbls,
- dfs_unmarked_real_bases_queue_p,
- build_tree_list (t, binfo));
+ if (!top_level_p)
+ {
+ tree data = tree_cons (t, binfo, NULL_TREE);
+ VTT_TOP_LEVEL_P (data) = 0;
+ VTT_MARKED_BINFO_P (data) = 0;
+
+ dfs_walk (binfo, dfs_fixup_binfo_vtbls,
+ dfs_ctor_vtable_bases_queue_p,
+ data);
+ }
return inits;
}
-/* Called from build_vtt_inits via dfs_walk. */
+/* Called from build_vtt_inits via dfs_walk. BINFO is the binfo
+ for the base in most derived. DATA is a TREE_LIST who's
+ TREE_CHAIN is the type of the base being
+ constructed whilst this secondary vptr is live. The TREE_UNSIGNED
+ flag of DATA indicates that this is a constructor vtable. The
+ TREE_TOP_LEVEL flag indicates that this is the primary VTT. */
static tree
dfs_build_secondary_vptr_vtt_inits (binfo, data)
tree t;
tree init;
tree index;
+ int top_level_p;
l = (tree) data;
t = TREE_CHAIN (l);
-
+ top_level_p = VTT_TOP_LEVEL_P (l);
+
SET_BINFO_MARKED (binfo);
/* We don't care about bases that don't have vtables. */
return NULL_TREE;
/* We're not interested in non-virtual primary bases. */
- if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+ if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_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. The point is that given:
-
- struct V { virtual void f(); int i; };
- struct C : public virtual V { void f (); };
-
- when we constrct C we need a secondary vptr for V-in-C because we
- don't know what the vcall offset for `f' should be. If `V' ends
- up in a different place in the complete object, then we'll need a
- different vcall offset than that present in the normal V-in-C
- vtable. */
+ /* If BINFO has virtual bases or is reachable via a virtual path
+ from T, it'll have a secondary vptr. */
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
- && !BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (get_matching_base (binfo, t)))
+ && !binfo_via_virtual (binfo, t))
return NULL_TREE;
/* Record the index where this secondary vptr can be found. */
index = TREE_TYPE (l);
- BINFO_VPTR_INDEX (binfo) = index;
+ if (top_level_p)
+ {
+ my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+ 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. */
+ if (top_level_p && TREE_VIA_VIRTUAL (binfo))
+ {
+ /* It's a primary virtual base, and this is not the construction
+ vtable. Find the base this is primary of in the inheritance graph,
+ and use that base's vtable now. */
+ while (BINFO_PRIMARY_BASE_OF (binfo))
+ binfo = BINFO_PRIMARY_BASE_OF (binfo);
+ }
init = BINFO_VTABLE (binfo);
if (TREE_CODE (init) == TREE_LIST)
init = TREE_VALUE (init);
return NULL_TREE;
}
-/* Called from build_vtt_inits via dfs_walk. */
+/* dfs_walk_real predicate for building vtables. DATA is a TREE_LIST,
+ TREE_UNSIGNED indicates that a constructor vtable is being built.
+ TREE_USED indicates whether marked or unmarked bases should be walked.
+ TREE_PURPOSE is the TREE_TYPE that dominates the hierarchy. */
+
+static tree
+dfs_ctor_vtable_bases_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_P (binfo))
+ {
+ tree type = TREE_PURPOSE ((tree) data);
+
+ /* This is a non-primary virtual base, get the shared version. */
+ binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
+ if (VTT_TOP_LEVEL_P ((tree) data) && BINFO_PRIMARY_P (binfo))
+ return NULL_TREE;
+ }
+ if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
+ return NULL_TREE;
+ return binfo;
+}
+
+/* Called from build_vtt_inits via dfs_walk. After building constructor
+ vtables and generating the sub-vtt from them, we need to restore the
+ BINFO_VTABLES that were scribbled on. DATA is a TREE_LIST whose
+ TREE_VALUE is the TREE_TYPE of the base whose sub vtt was generated. */
static tree
dfs_fixup_binfo_vtbls (binfo, data)
if (IDENTIFIER_GLOBAL_VALUE (id))
return;
+ my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124);
/* Build a version of VTBL (with the wrong type) for use in
constructing the addresses of secondary vtables in the
construction vtable group. */
list = build_tree_list (vtbl, NULL_TREE);
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
binfo, t, list);
- for (vbase = TYPE_BINFO (TREE_TYPE (binfo));
+
+ /* Add the vtables for each of our virtual bases using the vbase in T
+ binfo. */
+ for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
vbase;
vbase = TREE_CHAIN (vbase))
{
tree b;
+ tree orig_base;
if (!TREE_VIA_VIRTUAL (vbase))
continue;
-
b = binfo_for_vbase (BINFO_TYPE (vbase), t);
- accumulate_vtbl_inits (b, vbase, binfo, t, list);
+ orig_base = binfo_for_vbase (BINFO_TYPE (vbase), BINFO_TYPE (binfo));
+
+ accumulate_vtbl_inits (b, orig_base, binfo, t, list);
}
-
inits = TREE_VALUE (list);
/* Figure out the type of the construction vtable. */
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. */
+/* Add the vtbl initializers for BINFO (and its bases other than
+ non-virtual primaries) to the list of INITS. BINFO is in the
+ hierarchy dominated by T. RTTI_BINFO is the binfo within T of
+ the constructor the vtbl inits should be accumulated for. (If this
+ is the complete object vtbl then RTTI_BINFO will be TYPE_BINFO (T).)
+ ORIG_BINFO is the binfo for this object within BINFO_TYPE (RTTI_BINFO).
+ BINFO is the active base equivalent of ORIG_BINFO in the inheritance
+ graph of T. Both BINFO and ORIG_BINFO will have the same BINFO_TYPE,
+ but are not necessarily the same in terms of layout. */
static void
accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
tree inits;
{
int i;
- int ctor_vtbl_p;
+ int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
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))
- && !(BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P
- (get_matching_base (binfo, BINFO_TYPE (rtti_binfo)))))
+ && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))
return;
/* Build the initializers for the BINFO-in-T vtable. */
and RTTI_BINFO simultaneously. */
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
{
- tree base_binfo;
-
- base_binfo = BINFO_BASETYPE (binfo, i);
+ tree 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,
+ rtti_binfo, t,
inits);
}
}
-/* Called from finish_vtbls via dfs_walk when using the new ABI.
+/* Called from accumulate_vtbl_inits 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. */
tree l;
{
tree inits = NULL_TREE;
+ tree vtbl = NULL_TREE;
+ int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+
+ if (ctor_vtbl_p
+ && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
+ {
+ /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a primary
+ virtual base. If it is not the same primary in the hierarchy of T,
+ we'll need to generate a ctor vtable for it, to place at its
+ location in T. If it is the same primary, we still need a VTT
+ entry for the vtable, but that must be the base it is a
+ primary for within the sub-hierarchy of RTTI_BINFO. */
+ tree parent;
+ tree best_primary = NULL;
+ tree primary_for;
+
+ my_friendly_assert (BINFO_PRIMARY_P (binfo), 20010131);
- if (BINFO_NEW_VTABLE_MARKED (orig_binfo, t))
+ for (primary_for = BINFO_PRIMARY_BASE_OF (binfo);
+ primary_for;
+ primary_for = BINFO_PRIMARY_BASE_OF (primary_for))
+ {
+ for (parent = primary_for;
+ parent;
+ parent = BINFO_INHERITANCE_CHAIN (parent))
+ {
+ if (parent == rtti_binfo)
+ {
+ best_primary = primary_for;
+ break;
+ }
+ }
+ if (!parent)
+ break;
+ }
+ if (best_primary)
+ {
+ vtbl = BINFO_VTABLE (best_primary);
+ if (TREE_CODE (vtbl) == TREE_LIST)
+ {
+ my_friendly_assert (TREE_PURPOSE (vtbl) == rtti_binfo,
+ 20010126);
+ vtbl = TREE_VALUE (vtbl);
+ }
+ }
+ }
+ else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
+ return inits;
+
+ if (!vtbl)
{
- tree vtbl;
tree index;
int non_fn_entries;
index);
vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
TREE_CONSTANT (vtbl) = 1;
+ }
+ if (!ctor_vtbl_p)
+ {
/* For an ordinary vtable, set BINFO_VTABLE. */
- if (same_type_p (BINFO_TYPE (rtti_binfo), t))
- 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) =
- tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
+ BINFO_VTABLE (binfo) = vtbl;
+ if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+ inits = NULL_TREE;
}
+ else
+ /* 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. */
+ BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, 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,
+ find the actual function pointers to put in the vtable - but they
+ can be overridden on the path to most-derived in the graph that
+ ORIG_BINFO belongs. Otherwise,
ORIG_BINFO should be the same as BINFO. The RTTI_BINFO 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
number of non-function entries in the vtable.
It might seem that this function should never be called with a
- BINFO for which BINFO_PRIMARY_MARKED_P holds, the vtable for such a
+ BINFO for which BINFO_PRIMARY_P holds, the vtable for such a
base is always subsumed by a derived class vtable. However, when
- we are building construction vtables we do build vtables for
+ we are building construction vtables, we do build vtables for
primary bases; we need these while the primary base is being
constructed. */
}
}
-/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
+/* Called from build_vcall_offset_vtbl_entries_r. */
static void
add_vcall_offset_vtbl_entries_1 (binfo, vid)
if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
- /* The FN comes from BASE. So, we must caculate the adjustment
+ /* The FN comes from BASE. So, we must calculate the adjustment
from the virtual base that derived from BINFO to BASE. */
base = DECL_CONTEXT (fn);
base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
/* 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)))
+ while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b))
+ && !BINFO_LOST_PRIMARY_P (b))
{
tree primary_base;
primary_base = get_primary_binfo (b);
- if (!BINFO_PRIMARY_MARKED_P (primary_base))
- break;
+ my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);
b = primary_base;
}
offset = size_diffop (BINFO_OFFSET (rtti_binfo), BINFO_OFFSET (b));