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
This commit is contained in:
Jason Merrill 2010-07-08 10:00:26 -04:00 committed by Jason Merrill
parent 02de68e16b
commit bf1cb49eb6
5 changed files with 69 additions and 9 deletions

View File

@ -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

View File

@ -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))),

View File

@ -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

View File

@ -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" } }

View File

@ -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;
}