aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-07-08 10:00:26 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-07-08 10:00:26 -0400
commitbf1cb49eb6e49ebcdb52aae5ef91357fe2517d16 (patch)
treeb4a615519d887258689016d13781a8a21c025df0 /gcc
parent02de68e16b0548f4ac9599cdd5dcd0b9703f02fb (diff)
downloadgcc-bf1cb49eb6e49ebcdb52aae5ef91357fe2517d16.zip
gcc-bf1cb49eb6e49ebcdb52aae5ef91357fe2517d16.tar.gz
gcc-bf1cb49eb6e49ebcdb52aae5ef91357fe2517d16.tar.bz2
re PR c++/43120 (Virtual inheritance with covariant return type confuses GCC)
PR c++/43120 * class.c (update_vtable_entry_for_fn): Fix handling of dummy virtual bases for covariant thunks. From-SVN: r161954
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/class.c15
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/abi/covariant1.C9
-rw-r--r--gcc/testsuite/g++.dg/inherit/covariant17.C40
5 files changed, 69 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 983d751..0a3f54a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,7 +1,13 @@
+2010-07-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/43120
+ * class.c (update_vtable_entry_for_fn): Fix handling of dummy
+ virtual bases for covariant thunks.
+
2010-07-08 Manuel López-Ibáñez <manu@gcc.gnu.org>
* cp-tree.h: Do not include toplev.h.
-
+
2010-07-06 Jason Merrill <jason@redhat.com>
PR c++/44703
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3c4830e..20b8c12 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2058,8 +2058,9 @@ get_vcall_index (tree fn, tree type)
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
- dominated by T. FN has been overridden in BINFO; VIRTUALS points to the
- corresponding position in the BINFO_VIRTUALS list. */
+ dominated by T. FN is the old function; VIRTUALS points to the
+ corresponding position in the new BINFO_VIRTUALS list. IX is the index
+ of that entry in the list. */
static void
update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
@@ -2252,9 +2253,11 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
virtual_base = probe;
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. */
+ /* OK, first_defn got this function from a (possibly lost) primary
+ virtual base, so we're going to use the vcall offset for that
+ primary virtual base. But the caller is passing a first_defn*,
+ not a virtual_base*, so the correct delta is the delta between
+ first_defn* and itself, i.e. zero. */
goto virtual_covariant;
}
@@ -2272,12 +2275,12 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
entry in our vtable. Except possibly in a constructor vtable,
if we happen to get our primary back. In that case, the offset
will be zero, as it will be a primary base. */
+ virtual_covariant:
delta = size_zero_node;
else
/* 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_loc (input_location,
convert (ssizetype,
BINFO_OFFSET (TREE_VALUE (overrider))),
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ba11239..7bf8c02 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-07-08 Jason Merrill <jason@redhat.com>
+
+ PR c++/43120
+ * g++.dg/inherit/covariant17.C: New.
+ * g++.dg/abi/covariant1.C: Actually test for the bug.
+
2010-07-08 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/44838
diff --git a/gcc/testsuite/g++.dg/abi/covariant1.C b/gcc/testsuite/g++.dg/abi/covariant1.C
index 203ec2c..42522c1 100644
--- a/gcc/testsuite/g++.dg/abi/covariant1.C
+++ b/gcc/testsuite/g++.dg/abi/covariant1.C
@@ -16,6 +16,11 @@ struct c12 : c11 { };
struct c14 :
virtual c12,
- virtual c11 { virtual c12* f17(); };
+ virtual c11 { virtual void f(); c12* f17(); };
-// { dg-final { scan-assembler-not "\n_ZTch0_v0_n16_N3c143f17Ev\[: \t\n\]" } }
+void c14::f() { }
+
+// { dg-final { scan-assembler "_ZTcv0_n12_v0_n16_N3c143f17Ev" { target ilp32 } } }
+// { dg-final { scan-assembler-not "_ZTch0_v0_n16_N3c143f17Ev" } }
+// { dg-final { scan-assembler "_ZTcv0_n24_v0_n32_N3c143f17Ev" { target lp64 } } }
+// { dg-final { scan-assembler-not "_ZTch0_v0_n32_N3c143f17Ev" } }
diff --git a/gcc/testsuite/g++.dg/inherit/covariant17.C b/gcc/testsuite/g++.dg/inherit/covariant17.C
new file mode 100644
index 0000000..26031d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/covariant17.C
@@ -0,0 +1,40 @@
+// PR c++/43120
+// { dg-do run }
+
+extern "C" void abort ();
+
+struct A {
+ int a;
+
+ A(int a_) : a(a_) {}
+
+ A(const A &other) { }
+
+ virtual void dummy() {}
+};
+
+struct B {
+ virtual B *clone() const = 0;
+};
+
+struct C : public virtual B {
+ virtual B *clone() const = 0;
+};
+
+struct E* ep;
+struct E : public A, public C {
+ E(int a_) : A(a_) { ep = this; }
+
+ virtual E *clone() const {
+ if (this != ep)
+ abort();
+ return new E(*this);
+ }
+};
+
+int main() {
+ E *a = new E(123);
+ B *c = a;
+ B *d = c->clone();
+ return 0;
+}