+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
}
/* 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,
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;
}
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))),
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" } }
--- /dev/null
+// 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;
+}