class.c (dfs_find_final_overrider): Adjust so that the most derived object is a binfo, rather than a class type.

* class.c (dfs_find_final_overrider): Adjust so that the most
	derived object is a binfo, rather than a class type.
	(find_final_overrider): Likewise.
	(add_vcall_offset_vtbl_entries_1): Simplify accordingly.
	(add_vcall_offset): Likewise.

	* g++.dg/abi/vcall1.C: New test.

From-SVN: r59104
This commit is contained in:
Mark Mitchell 2002-11-14 16:59:23 +00:00 committed by Mark Mitchell
parent 3dfce4e4fc
commit 9567595065
4 changed files with 76 additions and 46 deletions

View File

@ -1,3 +1,11 @@
2002-11-14 Mark Mitchell <mark@codesourcery.com>
* class.c (dfs_find_final_overrider): Adjust so that the most
derived object is a binfo, rather than a class type.
(find_final_overrider): Likewise.
(add_vcall_offset_vtbl_entries_1): Simplify accordingly.
(add_vcall_offset): Likewise.
2002-11-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/8389

View File

@ -2220,9 +2220,11 @@ dfs_find_final_overrider (binfo, data)
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);
@ -2231,6 +2233,8 @@ dfs_find_final_overrider (binfo, data)
path = TREE_VALUE (path);
break;
}
path = TREE_CHAIN (path);
}
/* If we found an overrider, record the overriding function, and
@ -2264,12 +2268,12 @@ dfs_find_final_overrider (binfo, data)
/* 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;
{
@ -2295,10 +2299,10 @@ find_final_overrider (t, binfo, 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);
@ -2306,7 +2310,8 @@ find_final_overrider (t, binfo, fn)
/* 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;
}
@ -2365,7 +2370,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
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;
@ -7909,14 +7914,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
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))
{
@ -7928,7 +7925,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
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
{
@ -7993,18 +7990,15 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
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;
@ -8045,35 +8039,23 @@ add_vcall_offset (tree orig_fn, tree binfo_in_rtti,
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);
base = TREE_VALUE (fn);
/* 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);
/* 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));
}

View File

@ -1,3 +1,7 @@
2002-11-14 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/vcall1.C: New test.
2002-11-14 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20021029-1.c: New test.

View File

@ -0,0 +1,36 @@
// { dg-do run }
// { dg-options "-w" }
extern "C" void abort ();
struct B;
B* b;
struct A {
virtual void f () {}
};
struct B : virtual public A {
B () {
b = this;
((A*) this)->f ();
}
virtual void f () {
if (this != b)
abort ();
}
};
struct C : public B {
};
struct D : public C, public B {
virtual void f () {}
};
int main () {
D d;
}