mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-25 09:13:59 +08:00
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:
parent
3dfce4e4fc
commit
9567595065
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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.
|
||||
|
36
gcc/testsuite/g++.dg/abi/vcall1.C
Normal file
36
gcc/testsuite/g++.dg/abi/vcall1.C
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user