Commit 73ea87d7 by Nathan Sidwell Committed by Nathan Sidwell

Fix ctor vtable vcall offsets.

cp:
	Fix ctor vtable vcall offsets.
	* class.c (struct vtbl_init_data_s): Add rtti_binfo member.
	(build_rtt_vtbl_entries): Lose RTTI_BINFO parameter.
	(get_matching_base): Remove.
	(get_original_base): New function.
	(build_vtbl_initializer): Initialize vid.rtti_binfo.
	Use a virtual thunk for a ctor vtable with an index
	(add_vcall_offset_vtbl_entries_1): Check if binfo has lost a
	primary base within a constructor vtable. Only set
	BV_VCALL_INDEX when not a constructor vtable. Adjust vcall offset
	when primary base has been lost.
	* cp-tree.h (BINFO_VIRTUALS): Remove ambiguity from comment.
testsuite:
	* g++.old-deja/g++.abi/vtable3.h: Check vcall offsets too.

From-SVN: r40090
parent faa7e814
2001-02-27 Nathan Sidwell <nathan@codesourcery.com>
Fix ctor vtable vcall offsets.
* class.c (struct vtbl_init_data_s): Add rtti_binfo member.
(build_rtt_vtbl_entries): Lose RTTI_BINFO parameter.
(get_matching_base): Remove.
(get_original_base): New function.
(build_vtbl_initializer): Initialize vid.rtti_binfo.
Use a virtual thunk for a ctor vtable with an index
(add_vcall_offset_vtbl_entries_1): Check if binfo has lost a
primary base within a constructor vtable. Only set
BV_VCALL_INDEX when not a constructor vtable. Adjust vcall offset
when primary base has been lost.
* cp-tree.h (BINFO_VIRTUALS): Remove ambiguity from comment.
2001-02-26 Jeffrey Oldham <oldham@codesourcery.com> 2001-02-26 Jeffrey Oldham <oldham@codesourcery.com>
* call.c (joust): Ensure more_specialized()'s argument length * call.c (joust): Ensure more_specialized()'s argument length
......
...@@ -66,8 +66,11 @@ typedef struct vtbl_init_data_s ...@@ -66,8 +66,11 @@ typedef struct vtbl_init_data_s
{ {
/* The base for which we're building initializers. */ /* The base for which we're building initializers. */
tree binfo; tree binfo;
/* The binfo for the most-derived type. */ /* The type of the most-derived type. */
tree derived; tree derived;
/* The binfo for the dynamic type. This will be TYPE_BINFO (derived),
unless ctor_vtbl_p is true. */
tree rtti_binfo;
/* The negative-index vtable initializers built up so far. These /* The negative-index vtable initializers built up so far. These
are in order from least negative index to most negative index. */ are in order from least negative index to most negative index. */
tree inits; tree inits;
...@@ -182,7 +185,7 @@ static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); ...@@ -182,7 +185,7 @@ static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
tree)); tree));
static void set_vindex PARAMS ((tree, int *)); static void set_vindex PARAMS ((tree, int *));
static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *)); static void build_rtti_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vtbl_init_data *)); vtbl_init_data *));
static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree)); static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree));
...@@ -199,7 +202,7 @@ static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *)); ...@@ -199,7 +202,7 @@ static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *)); static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data)); static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *)); static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
static tree get_matching_base PARAMS ((tree, tree)); static tree get_original_base PARAMS ((tree, tree));
static tree dfs_get_primary_binfo PARAMS ((tree, void*)); static tree dfs_get_primary_binfo PARAMS ((tree, void*));
static int record_subobject_offset PARAMS ((tree, tree, splay_tree)); static int record_subobject_offset PARAMS ((tree, tree, splay_tree));
static int check_subobject_offset PARAMS ((tree, tree, splay_tree)); static int check_subobject_offset PARAMS ((tree, tree, splay_tree));
...@@ -6830,32 +6833,31 @@ build_vtt (t) ...@@ -6830,32 +6833,31 @@ build_vtt (t)
initialize_array (vtt, inits); initialize_array (vtt, inits);
} }
/* The type corresponding to BINFO is a base class of T, but BINFO is /* The type corresponding to BASE_BINFO is a base of the type of BINFO, but
in the base class hierarchy of a class derived from T. Return the from within some heirarchy which is inherited from the type of BINFO.
base, in T's hierarchy, that corresponds to BINFO. */ Return BASE_BINFO's equivalent binfo from the hierarchy dominated by
BINFO. */
static tree static tree
get_matching_base (binfo, t) get_original_base (base_binfo, binfo)
tree base_binfo;
tree binfo; tree binfo;
tree t;
{ {
tree derived; tree derived;
int i; int ix;
if (same_type_p (BINFO_TYPE (binfo), t)) if (same_type_p (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo)))
return binfo; return binfo;
if (TREE_VIA_VIRTUAL (base_binfo))
if (TREE_VIA_VIRTUAL (binfo)) return binfo_for_vbase (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo));
return binfo_for_vbase (BINFO_TYPE (binfo), t); derived = get_original_base (BINFO_INHERITANCE_CHAIN (base_binfo), binfo);
derived = get_matching_base (BINFO_INHERITANCE_CHAIN (binfo), t); for (ix = 0; ix != BINFO_N_BASETYPES (derived); ix++)
for (i = 0; i < BINFO_N_BASETYPES (derived); ++i) if (same_type_p (BINFO_TYPE (base_binfo),
if (same_type_p (BINFO_TYPE (BINFO_BASETYPE (derived, i)), BINFO_TYPE (BINFO_BASETYPE (derived, ix))))
BINFO_TYPE (binfo))) return BINFO_BASETYPE (derived, ix);
return BINFO_BASETYPE (derived, i); my_friendly_abort (20010223);
return NULL;
my_friendly_abort (20000628);
return NULL_TREE;
} }
/* Recursively build the VTT-initializer for BINFO (which is in the /* Recursively build the VTT-initializer for BINFO (which is in the
...@@ -7347,6 +7349,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7347,6 +7349,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
memset (&vid, 0, sizeof (vid)); memset (&vid, 0, sizeof (vid));
vid.binfo = binfo; vid.binfo = binfo;
vid.derived = t; vid.derived = t;
vid.rtti_binfo = rtti_binfo;
vid.last_init = &vid.inits; vid.last_init = &vid.inits;
vid.primary_vtbl_p = (binfo == TYPE_BINFO (t)); vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t); vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
...@@ -7354,7 +7357,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7354,7 +7357,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vid.index = ssize_int (-3); vid.index = ssize_int (-3);
/* Add entries to the vtable for RTTI. */ /* Add entries to the vtable for RTTI. */
build_rtti_vtbl_entries (binfo, rtti_binfo, &vid); build_rtti_vtbl_entries (binfo, &vid);
/* Create an array for keeping track of the functions we've /* Create an array for keeping track of the functions we've
processed. When we see multiple functions with the same processed. When we see multiple functions with the same
...@@ -7384,7 +7387,8 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7384,7 +7387,8 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree fn; tree fn;
tree pfn; tree pfn;
tree init; tree init;
int generate_with_vtable_p = BV_GENERATE_THUNK_WITH_VTABLE_P (v);
/* Pull the offset for `this', and the function to call, out of /* Pull the offset for `this', and the function to call, out of
the list. */ the list. */
delta = BV_DELTA (v); delta = BV_DELTA (v);
...@@ -7394,8 +7398,17 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7394,8 +7398,17 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vcall_index = BV_VCALL_INDEX (v); vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (vcall_index != NULL_TREE, 20000621); my_friendly_assert (vcall_index != NULL_TREE, 20000621);
} }
else if (vid.ctor_vtbl_p && BV_VCALL_INDEX (v))
{
/* In the original, we did not need to use the vcall index, even
though there was one, but in a ctor vtable things might be
different (a primary virtual base might have moved). Be
conservative and use a vcall adjusting thunk. */
vcall_index = BV_VCALL_INDEX (v);
generate_with_vtable_p = 1;
}
else else
vcall_index = NULL_TREE; vcall_index = NULL_TREE;
fn = BV_FN (v); fn = BV_FN (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727); my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
...@@ -7413,7 +7426,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7413,7 +7426,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
TREE_CONSTANT (pfn) = 1; TREE_CONSTANT (pfn) = 1;
/* Enter it in the vtable. */ /* Enter it in the vtable. */
init = build_vtable_entry (delta, vcall_index, pfn, init = build_vtable_entry (delta, vcall_index, pfn,
BV_GENERATE_THUNK_WITH_VTABLE_P (v)); generate_with_vtable_p);
/* And add it to the chain of initializers. */ /* And add it to the chain of initializers. */
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits); vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
} }
...@@ -7624,6 +7637,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7624,6 +7637,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree base_virtuals; tree base_virtuals;
tree orig_virtuals; tree orig_virtuals;
tree binfo_inits; tree binfo_inits;
int lost_primary = 0;
/* If BINFO is a primary base, this is the least derived class of /* If BINFO is a primary base, this is the least derived class of
BINFO that is not a primary base. */ BINFO that is not a primary base. */
tree non_primary_binfo; tree non_primary_binfo;
...@@ -7645,6 +7659,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7645,6 +7659,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
care about its vtable offsets. */ care about its vtable offsets. */
if (TREE_VIA_VIRTUAL (non_primary_binfo)) if (TREE_VIA_VIRTUAL (non_primary_binfo))
{ {
if (vid->ctor_vtbl_p)
{
tree probe;
for (probe = vid->binfo;
probe != non_primary_binfo;
probe = get_primary_binfo (probe))
{
if (BINFO_LOST_PRIMARY_P (probe))
{
lost_primary = 1;
break;
}
}
}
non_primary_binfo = vid->binfo; non_primary_binfo = vid->binfo;
break; break;
} }
...@@ -7655,6 +7684,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7655,6 +7684,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
non_primary_binfo = b; non_primary_binfo = b;
} }
if (vid->ctor_vtbl_p)
/* For a ctor vtable we need the equivalent binfo within the hierarchy
where rtti_binfo is the most derived type. */
non_primary_binfo = get_original_base
(non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
/* Make entries for the rest of the virtuals. */ /* Make entries for the rest of the virtuals. */
for (base_virtuals = BINFO_VIRTUALS (binfo), for (base_virtuals = BINFO_VIRTUALS (binfo),
derived_virtuals = BINFO_VIRTUALS (non_primary_binfo), derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
...@@ -7669,6 +7704,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7669,6 +7704,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree base; tree base;
tree base_binfo; tree base_binfo;
size_t i; size_t i;
tree vcall_offset;
/* Find the declaration that originally caused this function to /* Find the declaration that originally caused this function to
be present. */ be present. */
...@@ -7699,8 +7735,9 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7699,8 +7735,9 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
|| (DECL_DESTRUCTOR_P (BV_FN (derived_entry)) || (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
&& DECL_DESTRUCTOR_P (fn))) && DECL_DESTRUCTOR_P (fn)))
{ {
BV_VCALL_INDEX (derived_virtuals) if (!vid->ctor_vtbl_p)
= BV_VCALL_INDEX (derived_entry); BV_VCALL_INDEX (derived_virtuals)
= BV_VCALL_INDEX (derived_entry);
break; break;
} }
} }
...@@ -7713,12 +7750,16 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7713,12 +7750,16 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
base_binfo = get_binfo (base, vid->derived, /*protect=*/0); base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
/* Compute the vcall offset. */ /* Compute the vcall offset. */
*vid->last_init vcall_offset = BINFO_OFFSET (vid->vbase);
= (build_tree_list if (lost_primary)
(NULL_TREE, vcall_offset = size_binop (PLUS_EXPR, vcall_offset,
fold (build1 (NOP_EXPR, vtable_entry_type, BINFO_OFFSET (vid->binfo));
size_diffop (BINFO_OFFSET (base_binfo), vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
BINFO_OFFSET (vid->vbase)))))); vcall_offset);
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
vcall_offset));
*vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
vid->last_init = &TREE_CHAIN (*vid->last_init); vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Keep track of the vtable index where this vcall offset can be /* Keep track of the vtable index where this vcall offset can be
...@@ -7738,12 +7779,11 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7738,12 +7779,11 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
/* Return vtbl initializers for the RTTI entries coresponding to the /* Return vtbl initializers for the RTTI entries coresponding to the
BINFO's vtable. The RTTI entries should indicate the object given BINFO's vtable. The RTTI entries should indicate the object given
by RTTI_BINFO. */ by VID->rtti_binfo. */
static void static void
build_rtti_vtbl_entries (binfo, rtti_binfo, vid) build_rtti_vtbl_entries (binfo, vid)
tree binfo; tree binfo;
tree rtti_binfo;
vtbl_init_data *vid; vtbl_init_data *vid;
{ {
tree b; tree b;
...@@ -7754,7 +7794,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid) ...@@ -7754,7 +7794,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
tree init; tree init;
basetype = BINFO_TYPE (binfo); basetype = BINFO_TYPE (binfo);
t = BINFO_TYPE (rtti_binfo); t = BINFO_TYPE (vid->rtti_binfo);
/* For a COM object there is no RTTI entry. */ /* For a COM object there is no RTTI entry. */
if (CLASSTYPE_COM_INTERFACE (basetype)) if (CLASSTYPE_COM_INTERFACE (basetype))
...@@ -7772,7 +7812,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid) ...@@ -7772,7 +7812,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127); my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);
b = primary_base; b = primary_base;
} }
offset = size_diffop (BINFO_OFFSET (rtti_binfo), BINFO_OFFSET (b)); offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b));
/* The second entry is the address of the typeinfo object. */ /* The second entry is the address of the typeinfo object. */
if (flag_rtti) if (flag_rtti)
...@@ -7802,7 +7842,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid) ...@@ -7802,7 +7842,7 @@ build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
/* Build an entry in the virtual function table. DELTA is the offset /* Build an entry in the virtual function table. DELTA is the offset
for the `this' pointer. VCALL_INDEX is the vtable index containing for the `this' pointer. VCALL_INDEX is the vtable index containing
the vcall offset; zero if none. ENTRY is the virtual function the vcall offset; NULL_TREE if none. ENTRY is the virtual function
table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE, table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
but it may not actually be a virtual function table pointer. (For but it may not actually be a virtual function table pointer. (For
example, it might be the address of the RTTI object, under the new example, it might be the address of the RTTI object, under the new
......
...@@ -136,7 +136,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -136,7 +136,7 @@ Boston, MA 02111-1307, USA. */
does not have a BV_FN; it is just an offset. does not have a BV_FN; it is just an offset.
The BV_OVERRIDING_BASE is the binfo for the final overrider for The BV_OVERRIDING_BASE is the binfo for the final overrider for
this function. (This binfo's BINFO_TYPE will always be the same this function. (That binfo's BINFO_TYPE will always be the same
as the DECL_CLASS_CONTEXT for the function.) as the DECL_CLASS_CONTEXT for the function.)
BINFO_VTABLE BINFO_VTABLE
......
2001-02-27 Nathan Sidwell <nathan@codesourcery.com>
* g++.old-deja/g++.abi/vtable3.h: Check vcall offsets too.
2001-02-26 Will Cohen <wcohen@redhat.com> 2001-02-26 Will Cohen <wcohen@redhat.com>
* gcc.c-torture/execute/ieee/20010226-1.c: New test. * gcc.c-torture/execute/ieee/20010226-1.c: New test.
......
...@@ -7,11 +7,8 @@ ...@@ -7,11 +7,8 @@
#include <typeinfo> #include <typeinfo>
#include <stdio.h> #include <stdio.h>
// XXX. vcall offsets are still broken, remove this define to re-enable
// testing when fixed.
#define NO_VCALL_TEST
int fail; int fail;
struct A;
template <typename BASE, typename DERIVED> template <typename BASE, typename DERIVED>
int Test (DERIVED *d, int expect) int Test (DERIVED *d, int expect)
...@@ -19,6 +16,7 @@ int Test (DERIVED *d, int expect) ...@@ -19,6 +16,7 @@ int Test (DERIVED *d, int expect)
BASE *b = static_cast <BASE *> (d); BASE *b = static_cast <BASE *> (d);
void *full_b = dynamic_cast <void *> (b); void *full_b = dynamic_cast <void *> (b);
void *full_d = dynamic_cast <void *> (d); void *full_d = dynamic_cast <void *> (d);
A *ap = static_cast <A *> (b);
if (full_b != full_d) if (full_b != full_d)
{ {
...@@ -37,8 +35,8 @@ int Test (DERIVED *d, int expect) ...@@ -37,8 +35,8 @@ int Test (DERIVED *d, int expect)
typeid (BASE).name (), typeid (DERIVED).name ()); typeid (BASE).name (), typeid (DERIVED).name ());
return 1; return 1;
} }
#ifndef NO_VCALL_TEST
b->Baz (static_cast <void *> (b)); b->Baz (static_cast <void *> (ap));
int res = b->Foo (static_cast <void *> (d)); int res = b->Foo (static_cast <void *> (d));
...@@ -49,7 +47,7 @@ int Test (DERIVED *d, int expect) ...@@ -49,7 +47,7 @@ int Test (DERIVED *d, int expect)
typeid (BASE).name (), res, expect); typeid (BASE).name (), res, expect);
return 1; return 1;
} }
#endif
return 0; return 0;
} }
......
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