class.c (update_vtable_entry_for_fn): Add index parameter.

cp:
	* class.c (update_vtable_entry_for_fn): Add index parameter.
	Generate vcall thunk for covariant overriding from a virtual
	primary base.
	(dfs_modify_vtables): Adjust.
testsuite:
	* g++.dg/abi/covariant1.C: New test.

From-SVN: r61906
This commit is contained in:
Nathan Sidwell 2003-01-27 23:29:50 +00:00 committed by Nathan Sidwell
parent 23af32e6ea
commit a2ddc3977a
4 changed files with 75 additions and 10 deletions

View File

@ -1,3 +1,10 @@
2003-01-27 Nathan Sidwell <nathan@codesourcery.com>
* class.c (update_vtable_entry_for_fn): Add index parameter.
Generate vcall thunk for covariant overriding from a virtual
primary base.
(dfs_modify_vtables): Adjust.
2003-01-25 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9403

View File

@ -190,7 +190,7 @@ static void mark_primary_bases (tree);
static tree mark_primary_virtual_base (tree, tree);
static void clone_constructors_and_destructors (tree);
static tree build_clone (tree, tree);
static void update_vtable_entry_for_fn (tree, tree, tree, tree *);
static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned);
static tree copy_virtuals (tree);
static void build_ctor_vtbl_group (tree, tree);
static void build_vtt (tree);
@ -2395,7 +2395,8 @@ get_vcall_index (tree fn, tree type)
corresponding position in the BINFO_VIRTUALS list. */
static void
update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals)
update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
unsigned ix)
{
tree b;
tree overrider;
@ -2479,7 +2480,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals)
virtual_offset = binfo_for_vbase (BINFO_TYPE (thunk_binfo),
TREE_TYPE (over_return));
offset = size_diffop (offset,
offset = size_binop (MINUS_EXPR, offset,
BINFO_OFFSET (virtual_offset));
}
if (fixed_offset)
@ -2523,6 +2524,38 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals)
virtual_base = b;
}
if (overrider_fn != overrider_target && !virtual_base)
{
/* The ABI specifies that a covariant thunk includes a mangling
for a this pointer adjustment. This-adjusting thunks that
override a function from a virtual base have a vcall
adjustment. When the virtual base in question is a primary
virtual base, we know the adjustments are zero, (and in the
non-covariant case, we would not use the thunk).
Unfortunately we didn't notice this could happen, when
designing the ABI and so never mandated that such a covariant
thunk should be emitted. Because we must use the ABI mandated
name, we must continue searching from the binfo where we
found the most recent definition of the function, towards the
primary binfo which first introduced the function into the
vtable. If that enters a virtual base, we must use a vcall
this-adjusting thunk. Bleah! */
tree probe;
for (probe = first_defn; (probe = get_primary_binfo (probe));)
{
if (TREE_VIA_VIRTUAL (probe))
virtual_base = probe;
if ((unsigned) list_length (BINFO_VIRTUALS (probe)) <= ix)
break;
}
if (virtual_base)
/* Even if we find a virtual base, the correct delta is
between the overrider and the binfo we're building a vtable
for. */
goto virtual_covariant;
}
/* Compute the constant adjustment to the `this' pointer. The
`this' pointer, when this function is called, will point at BINFO
(or one of its primary bases, which are at the same offset). */
@ -2541,6 +2574,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals)
/* The `this' pointer needs to be adjusted from pointing to
BINFO to pointing at the base where the final overrider
appears. */
virtual_covariant:
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
BINFO_OFFSET (binfo));
@ -2564,26 +2598,25 @@ dfs_modify_vtables (tree binfo, void* data)
/* Similarly, a base without a vtable needs no modification. */
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
tree t;
tree t = (tree) data;
tree virtuals;
tree old_virtuals;
t = (tree) data;
unsigned ix;
make_new_vtable (t, binfo);
/* Now, go through each of the virtual functions in the virtual
function table for BINFO. Find the final overrider, and
update the BINFO_VIRTUALS list appropriately. */
for (virtuals = BINFO_VIRTUALS (binfo),
for (ix = 0, virtuals = BINFO_VIRTUALS (binfo),
old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
virtuals;
virtuals = TREE_CHAIN (virtuals),
ix++, virtuals = TREE_CHAIN (virtuals),
old_virtuals = TREE_CHAIN (old_virtuals))
update_vtable_entry_for_fn (t,
binfo,
BV_FN (old_virtuals),
&virtuals);
&virtuals, ix);
}
SET_BINFO_MARKED (binfo);

View File

@ -1,3 +1,7 @@
2003-01-27 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/abi/covariant1.C: New test.
2003-01-25 Ulrich Weigand <uweigand@de.ibm.com>
* gcc.dg/20030123-1.c: New test.

View File

@ -0,0 +1,21 @@
// { dg-do compile }
// { dg-options "-w" }
// We don't want to use a covariant thunk to have a virtual
// primary base
struct c4 {};
struct c6 : c4 { virtual c4* f17(); };
c4* c6::f17() { return 0; }
struct c11 : virtual c6 { int i; };
struct c12 : c11 { };
struct c14 :
virtual c12,
virtual c11 { virtual c12* f17(); };
// { dg-final { scan-assembler-not "\n_ZTch0_v0_n16_N3c143f17Ev\[: \t\n\]" } }