{
/* The binfo for the most-derived type. */
tree derived;
+ /* The negative-index vtable initializers built up so far. These
+ are in order from least negative index to most negative index. */
+ tree inits;
+ /* The last (i.e., most negative entry in INITS. */
+ tree* last_init;
/* 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 functions in vbase for which we have already provided vcall
+ offsets. */
+ varray_type fns;
/* The vtable index of the next vcall or vbase offset. */
tree index;
/* Nonzero if we are building the initializer for the primary
static void finish_struct_bits PARAMS ((tree));
static int alter_access PARAMS ((tree, tree, tree));
static void handle_using_decl PARAMS ((tree, tree));
-static int overrides PARAMS ((tree, tree));
+static int same_signature_p PARAMS ((tree, tree));
static int strictly_overrides PARAMS ((tree, tree));
static void mark_overriders PARAMS ((tree, tree));
static void check_for_override PARAMS ((tree, tree));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
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_rtti_vtbl_entries PARAMS ((tree, tree, vcall_offset_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vcall_offset_data *));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
}
}
-/* True if we should override the given BASE_FNDECL with the given
- FNDECL. */
+/* True iff FNDECL and BASE_FNDECL (both non-static member functions)
+ have the same signature. */
static int
-overrides (fndecl, base_fndecl)
+same_signature_p (fndecl, base_fndecl)
tree fndecl, base_fndecl;
{
/* One destructor overrides another if they are the same kind of
for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
method;
method = TREE_CHAIN (method))
- if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn))
+ if (DECL_VIRTUAL_P (method)
+ && same_signature_p (method, ffod->fn))
break;
if (method)
tree fndecl, base_fndecls;
{
for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
- {
- if (overrides (fndecl, TREE_VALUE (base_fndecls)))
- TREE_PURPOSE (base_fndecls) = fndecl;
- }
+ if (same_signature_p (fndecl, TREE_VALUE (base_fndecls)))
+ TREE_PURPOSE (base_fndecls) = fndecl;
}
/* If this declaration supersedes the declaration of
/* Now give a warning for all base functions without overriders,
as they are hidden. */
for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
- {
- if (! overrides (TREE_PURPOSE (base_fndecls),
- TREE_VALUE (base_fndecls)))
- {
- /* Here we know it is a hider, and no overrider exists. */
- cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
- cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls));
- }
- }
+ if (!same_signature_p (TREE_PURPOSE (base_fndecls),
+ TREE_VALUE (base_fndecls)))
+ {
+ /* Here we know it is a hider, and no overrider exists. */
+ cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
+ cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls));
+ }
}
}
int *non_fn_entries_p;
{
tree v;
- tree inits;
- tree vfun_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.last_init = &vod.inits;
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 entries to the vtable for RTTI. */
+ build_rtti_vtbl_entries (binfo, rtti_binfo, &vod);
+
/* 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
+ /* 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);
+ *non_fn_entries_p = list_length (vod.inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
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);
+ /* The negative offset initializers are also in reverse order. */
+ vod.inits = nreverse (vod.inits);
+
+ /* Chain the two together. */
+ return chainon (vod.inits, vfun_inits);
}
/* Sets vod->inits to be the initializers for the vbase and vcall
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;
+ corresponding to the primary base class. */
b = BINFO_PRIMARY_BINFO (binfo);
if (b)
build_vcall_and_vbase_vtbl_entries (b, vod);
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
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);
+ *vod->last_init
+ = build_tree_list (NULL_TREE,
+ fold (build1 (NOP_EXPR,
+ vtable_entry_type,
+ delta)));
+ vod->last_init = &TREE_CHAIN (*vod->last_init);
}
}
}
/* Make entries for the rest of the virtuals. */
- while (base_virtuals)
+ for (; base_virtuals;
+ derived_virtuals = TREE_CHAIN (derived_virtuals),
+ base_virtuals = TREE_CHAIN (base_virtuals))
{
/* Figure out what function we're looking at. */
tree fn = TREE_VALUE (derived_virtuals);
- tree base = DECL_CONTEXT (fn);
+ tree base;
+ tree base_binfo;
+ size_t i;
+
+ /* If there is already an entry for a function with the same
+ signature as FN, then we do not need a second vcall offset.
+ Check the list of functions already present in the derived
+ class vtable. */
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (vod->fns); ++i)
+ {
+ tree derived_entry;
+
+ derived_entry = VARRAY_TREE (vod->fns, i);
+ if (same_signature_p (TREE_VALUE (derived_entry), fn))
+ {
+ BV_VCALL_INDEX (derived_virtuals)
+ = BV_VCALL_INDEX (derived_entry);
+ break;
+ }
+ }
+ if (i != VARRAY_ACTIVE_SIZE (vod->fns))
+ continue;
+
/* 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);
+ base = DECL_CONTEXT (fn);
+ 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);
+ *vod->last_init
+ = (build_tree_list
+ (NULL_TREE,
+ fold (build1 (NOP_EXPR, vtable_entry_type,
+ size_diffop (BINFO_OFFSET (base_binfo),
+ BINFO_OFFSET (vod->vbase))))));
+ vod->last_init = &TREE_CHAIN (*vod->last_init);
/* If there is already a vcall index, then we are processing a
construction vtable. The index should be the same as it was
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;
+ /* Keep track of this function. */
+ VARRAY_PUSH_TREE (vod->fns, derived_virtuals);
}
return NULL_TREE;
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 ())
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;
+ VARRAY_TREE_INIT (vod->fns, 32, "fns");
dfs_walk_real (binfo,
dfs_build_vcall_offset_vtbl_entries,
NULL,
dfs_skip_vbases,
vod);
- vod->inits = chainon (vod->inits, inits);
+ VARRAY_FREE (vod->fns);
}
/* 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)
+static void
+build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
tree binfo;
tree rtti_binfo;
+ vcall_offset_data *vod;
{
tree b;
tree t;
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;
+ return;
/* 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. */
TREE_CONSTANT (init) = 1;
init = build_vtable_entry (offset, integer_zero_node, init);
}
- inits = tree_cons (NULL_TREE, init, inits);
+ *vod->last_init = build_tree_list (NULL_TREE, init);
+ vod->last_init = &TREE_CHAIN (*vod->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. */
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);
+ *vod->last_init = build_tree_list (NULL_TREE, init);
+ vod->last_init = &TREE_CHAIN (*vod->last_init);
}
-
- return inits;
}
/* Build an entry in the virtual function table. DELTA is the offset