Commit 95675950 by Mark Mitchell Committed by Mark Mitchell

class.c (dfs_find_final_overrider): Adjust so that the most derived object is a…

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
parent 3dfce4e4
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> 2002-11-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/8389 PR c++/8389
......
...@@ -2220,9 +2220,11 @@ dfs_find_final_overrider (binfo, data) ...@@ -2220,9 +2220,11 @@ dfs_find_final_overrider (binfo, data)
method = NULL_TREE; method = NULL_TREE;
/* We've found a path to the declaring base. Walk down the path /* We've found a path to the declaring base. Walk down the path
looking for an overrider for FN. */ looking for an overrider for FN. */
for (path = reverse_path (binfo); path = reverse_path (binfo);
path; while (!same_type_p (BINFO_TYPE (TREE_VALUE (path)),
path = TREE_CHAIN (path)) ffod->most_derived_type))
path = TREE_CHAIN (path);
while (path)
{ {
method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)), method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
ffod->fn); ffod->fn);
...@@ -2231,6 +2233,8 @@ dfs_find_final_overrider (binfo, data) ...@@ -2231,6 +2233,8 @@ dfs_find_final_overrider (binfo, data)
path = TREE_VALUE (path); path = TREE_VALUE (path);
break; break;
} }
path = TREE_CHAIN (path);
} }
/* If we found an overrider, record the overriding function, and /* If we found an overrider, record the overriding function, and
...@@ -2264,12 +2268,12 @@ dfs_find_final_overrider (binfo, data) ...@@ -2264,12 +2268,12 @@ dfs_find_final_overrider (binfo, data)
/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for /* 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 FN and whose TREE_VALUE is the binfo for the base where the
overriding occurs. BINFO (in the hierarchy dominated by T) is the overriding occurs. BINFO (in the hierarchy dominated by the binfo
base object in which FN is declared. */ DERIVED) is the base object in which FN is declared. */
static tree static tree
find_final_overrider (t, binfo, fn) find_final_overrider (derived, binfo, fn)
tree t; tree derived;
tree binfo; tree binfo;
tree fn; tree fn;
{ {
...@@ -2295,10 +2299,10 @@ find_final_overrider (t, binfo, fn) ...@@ -2295,10 +2299,10 @@ find_final_overrider (t, binfo, fn)
different overriders along any two, then there is a problem. */ different overriders along any two, then there is a problem. */
ffod.fn = fn; ffod.fn = fn;
ffod.declaring_base = binfo; ffod.declaring_base = binfo;
ffod.most_derived_type = t; ffod.most_derived_type = BINFO_TYPE (derived);
ffod.candidates = NULL_TREE; ffod.candidates = NULL_TREE;
dfs_walk (TYPE_BINFO (t), dfs_walk (derived,
dfs_find_final_overrider, dfs_find_final_overrider,
NULL, NULL,
&ffod); &ffod);
...@@ -2306,7 +2310,8 @@ find_final_overrider (t, binfo, fn) ...@@ -2306,7 +2310,8 @@ find_final_overrider (t, binfo, fn)
/* If there was no winner, issue an error message. */ /* If there was no winner, issue an error message. */
if (!ffod.candidates || TREE_CHAIN (ffod.candidates)) 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; return error_mark_node;
} }
...@@ -2365,7 +2370,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2365,7 +2370,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
first_defn = b; first_defn = b;
/* Find the final overrider. */ /* 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) if (overrider == error_mark_node)
return; return;
...@@ -7909,14 +7914,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7909,14 +7914,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree binfo; tree binfo;
vtbl_init_data* vid; 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. */ /* Make entries for the rest of the virtuals. */
if (abi_version_at_least (2)) if (abi_version_at_least (2))
{ {
...@@ -7928,7 +7925,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7928,7 +7925,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
orig_fn; orig_fn;
orig_fn = TREE_CHAIN (orig_fn)) orig_fn = TREE_CHAIN (orig_fn))
if (DECL_VINDEX (orig_fn)) if (DECL_VINDEX (orig_fn))
add_vcall_offset (orig_fn, binfo_in_rtti, vid); add_vcall_offset (orig_fn, binfo, vid);
} }
else else
{ {
...@@ -7993,18 +7990,15 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7993,18 +7990,15 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo))) if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
continue; 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 /* Add a vcall offset entry for ORIG_FN to the vtable. */
construction vtable, BINFO_IN_RTTI is the base corresponding to the
vtable base in VID->RTTI_BINFO. */
static void static void
add_vcall_offset (tree orig_fn, tree binfo_in_rtti, add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
vtbl_init_data *vid)
{ {
size_t i; size_t i;
tree vcall_offset; tree vcall_offset;
...@@ -8045,35 +8039,23 @@ add_vcall_offset (tree orig_fn, tree binfo_in_rtti, ...@@ -8045,35 +8039,23 @@ add_vcall_offset (tree orig_fn, tree binfo_in_rtti,
if (vid->generate_vcall_entries) if (vid->generate_vcall_entries)
{ {
tree base; tree base;
tree base_binfo;
tree fn; tree fn;
/* Find the overriding function. */ /* Find the overriding function. */
fn = find_final_overrider (BINFO_TYPE (vid->rtti_binfo), fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
binfo_in_rtti, orig_fn);
if (fn == error_mark_node) if (fn == error_mark_node)
vcall_offset = build1 (NOP_EXPR, vtable_entry_type, vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
integer_zero_node); integer_zero_node);
else else
{ {
fn = TREE_PURPOSE (fn); base = TREE_VALUE (fn);
/* The FN comes from BASE. So, we must calculate the
adjustment from vid->vbase to BASE. We can just look for /* The vbase we're working on is a primary base of
BASE in the complete object because we are converting vid->binfo. But it might be a lost primary, so its
from a virtual base, so if there were multiple copies, BINFO_OFFSET might be wrong, so we just use the
there would not be a unique final overrider and BINFO_OFFSET from vid->binfo. */
vid->derived would be ill-formed. */ vcall_offset = size_diffop (BINFO_OFFSET (base),
base = DECL_CONTEXT (fn); BINFO_OFFSET (vid->binfo));
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);
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
vcall_offset)); vcall_offset));
} }
......
2002-11-14 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/vcall1.C: New test.
2002-11-14 Jakub Jelinek <jakub@redhat.com> 2002-11-14 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20021029-1.c: New test. * gcc.dg/20021029-1.c: New test.
......
// { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment