From 95675950657fdaa6e6a4b38b1c519667514b2fb7 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 14 Nov 2002 16:59:23 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 8 ++++ gcc/cp/class.c | 74 ++++++++++++------------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/abi/vcall1.C | 36 +++++++++++++++ 4 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/vcall1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0b5b67089e8..5550411c1bc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2002-11-14 Mark Mitchell + + * 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 PR c++/8389 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 2ca45a67f84..3c2084d2522 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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)); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 968777c4c6e..3caf7d80132 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-11-14 Mark Mitchell + + * g++.dg/abi/vcall1.C: New test. + 2002-11-14 Jakub Jelinek * gcc.dg/20021029-1.c: New test. diff --git a/gcc/testsuite/g++.dg/abi/vcall1.C b/gcc/testsuite/g++.dg/abi/vcall1.C new file mode 100644 index 00000000000..00830cd23d6 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/vcall1.C @@ -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; +} +