method = NULL_TREE;
/* 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))
+ path = reverse_path (binfo);
+ while (!same_type_p (BINFO_TYPE (TREE_VALUE (path)),
+ ffod->most_derived_type))
+ path = TREE_CHAIN (path);
+ while (path)
{
method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
ffod->fn);
path = TREE_VALUE (path);
break;
}
+
+ path = TREE_CHAIN (path);
}
/* If we found an overrider, record the overriding function, and
/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
FN and whose TREE_VALUE is the binfo for the base where the
- overriding occurs. BINFO (in the hierarchy dominated by T) is the
- base object in which FN is declared. */
+ overriding occurs. BINFO (in the hierarchy dominated by the binfo
+ DERIVED) is the base object in which FN is declared. */
static tree
-find_final_overrider (t, binfo, fn)
- tree t;
+find_final_overrider (derived, binfo, fn)
+ tree derived;
tree binfo;
tree fn;
{
different overriders along any two, then there is a problem. */
ffod.fn = fn;
ffod.declaring_base = binfo;
- ffod.most_derived_type = t;
+ ffod.most_derived_type = BINFO_TYPE (derived);
ffod.candidates = NULL_TREE;
- dfs_walk (TYPE_BINFO (t),
+ dfs_walk (derived,
dfs_find_final_overrider,
NULL,
&ffod);
/* If there was no winner, issue an error message. */
if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
{
- error ("no unique final overrider for `%D' in `%T'", fn, t);
+ error ("no unique final overrider for `%D' in `%T'", fn,
+ BINFO_TYPE (derived));
return error_mark_node;
}
first_defn = b;
/* Find the final overrider. */
- overrider = find_final_overrider (t, b, fn);
+ overrider = find_final_overrider (TYPE_BINFO (t), b, fn);
if (overrider == error_mark_node)
return;
tree binfo;
vtbl_init_data* vid;
{
- tree binfo_in_rtti;
-
- if (vid->ctor_vtbl_p)
- binfo_in_rtti = (get_original_base
- (binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo))));
- else
- binfo_in_rtti = binfo;
-
/* Make entries for the rest of the virtuals. */
if (abi_version_at_least (2))
{
orig_fn;
orig_fn = TREE_CHAIN (orig_fn))
if (DECL_VINDEX (orig_fn))
- add_vcall_offset (orig_fn, binfo_in_rtti, vid);
+ add_vcall_offset (orig_fn, binfo, vid);
}
else
{
if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
continue;
- add_vcall_offset (orig_fn, binfo_in_rtti, vid);
+ add_vcall_offset (orig_fn, binfo, vid);
}
}
}
-/* Add a vcall offset entry for ORIG_FN to the vtable. In a
- construction vtable, BINFO_IN_RTTI is the base corresponding to the
- vtable base in VID->RTTI_BINFO. */
+/* Add a vcall offset entry for ORIG_FN to the vtable. */
static void
-add_vcall_offset (tree orig_fn, tree binfo_in_rtti,
- vtbl_init_data *vid)
+add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
{
size_t i;
tree vcall_offset;
if (vid->generate_vcall_entries)
{
tree base;
- tree base_binfo;
tree fn;
/* Find the overriding function. */
- fn = find_final_overrider (BINFO_TYPE (vid->rtti_binfo),
- binfo_in_rtti, orig_fn);
+ fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
if (fn == error_mark_node)
vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
integer_zero_node);
else
{
- fn = TREE_PURPOSE (fn);
- /* The FN comes from BASE. So, we must calculate the
- adjustment from vid->vbase to BASE. We can just look for
- BASE in the complete object because we are converting
- from a virtual base, so if there were multiple copies,
- there would not be a unique final overrider and
- vid->derived would be ill-formed. */
- base = DECL_CONTEXT (fn);
- base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
-
- /* Compute the vcall offset. */
- /* As mentioned above, the vbase we're working on is a
- primary base of vid->binfo. But it might be a lost
- primary, so its BINFO_OFFSET might be wrong, so we just
- use the BINFO_OFFSET from vid->binfo. */
- vcall_offset = BINFO_OFFSET (vid->binfo);
- vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
- vcall_offset);
+ base = TREE_VALUE (fn);
+
+ /* The vbase we're working on is a primary base of
+ vid->binfo. But it might be a lost primary, so its
+ BINFO_OFFSET might be wrong, so we just use the
+ BINFO_OFFSET from vid->binfo. */
+ vcall_offset = size_diffop (BINFO_OFFSET (base),
+ BINFO_OFFSET (vid->binfo));
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
vcall_offset));
}