summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-01-27 23:29:50 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-01-27 23:29:50 +0000
commita2ddc3977ab5a1ae4ed182155d403bc899d36f8e (patch)
tree8e39b79228ad7ed3404e2df8d393ba7858475af2
parent23af32e6ea2031cb4bffc1edc8d0368d5e5dfada (diff)
downloadgcc-a2ddc3977ab5a1ae4ed182155d403bc899d36f8e.tar.gz
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
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/class.c53
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/abi/covariant1.C21
4 files changed, 75 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fe8898f28d6..180fccb2fbf 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index efc86e10708..6cdcb9a5b78 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0f62daf09a3..c778bcc6ee3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/abi/covariant1.C b/gcc/testsuite/g++.dg/abi/covariant1.C
new file mode 100644
index 00000000000..203ec2c9fcb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/covariant1.C
@@ -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\]" } }