Fix another bug where we wouldn't generate secondary vtables for construction vtables in some cases.

llvm-svn: 100998
This commit is contained in:
Anders Carlsson 2010-04-11 22:20:36 +00:00
parent 2908a20d86
commit 3383e2ad74
2 changed files with 65 additions and 5 deletions

View File

@ -1247,9 +1247,13 @@ private:
/// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the
/// given base subobject, as well as all its secondary vtables.
///
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
/// or a direct or indirect base of a virtual base.
///
/// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual
/// in the layout class.
void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
bool BaseIsMorallyVirtual,
bool BaseIsVirtualInLayoutClass,
uint64_t OffsetInLayoutClass);
@ -1839,6 +1843,7 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
void VTableBuilder::LayoutVTable() {
LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass, 0),
/*BaseIsMorallyVirtual=*/false,
MostDerivedClassIsVirtual,
MostDerivedClassOffset);
@ -1854,6 +1859,7 @@ void VTableBuilder::LayoutVTable() {
void
VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
bool BaseIsMorallyVirtual,
bool BaseIsVirtualInLayoutClass,
uint64_t OffsetInLayoutClass) {
assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
@ -1924,10 +1930,6 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base,
RD = PrimaryBase;
}
bool BaseIsMorallyVirtual = BaseIsVirtualInLayoutClass;
if (isBuildingConstructorVTable() && Base.getBase() == MostDerivedClass)
BaseIsMorallyVirtual = false;
// Layout secondary vtables.
LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
}
@ -1983,6 +1985,7 @@ void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base,
// Layout the primary vtable (and any secondary vtables) for this base.
LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
BaseIsMorallyVirtual,
/*BaseIsVirtualInLayoutClass=*/false,
BaseOffsetInLayoutClass);
}
@ -2073,7 +2076,8 @@ VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD,
LayoutClassLayout.getVBaseClassOffset(BaseDecl);
LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset),
/*BaseIsVirtual=*/true,
/*BaseIsMorallyVirtual=*/true,
/*BaseIsVirtualInLayoutClass=*/true,
BaseOffsetInLayoutClass);
}

View File

@ -1455,3 +1455,59 @@ struct F : virtual E, A {
void F::f() { }
}
namespace Test34 {
// Test that we lay out the construction vtable for 'Test34::E' in 'Test34:::F' correctly.
struct A {
virtual void a();
};
struct B : virtual A { };
struct C : B, A {
virtual void c();
};
struct D : A, C { };
struct E : virtual D {
virtual void e();
};
// CHECK: Construction vtable for ('Test34::E', 0) in 'Test34::F' (22 entries).
// CHECK-NEXT: 0 | vbase_offset (0)
// CHECK-NEXT: 1 | vbase_offset (8)
// CHECK-NEXT: 2 | vcall_offset (0)
// CHECK-NEXT: 3 | offset_to_top (0)
// CHECK-NEXT: 4 | Test34::E RTTI
// CHECK-NEXT: -- (Test34::A, 0) vtable address --
// CHECK-NEXT: -- (Test34::E, 0) vtable address --
// CHECK-NEXT: 5 | void Test34::A::a()
// CHECK-NEXT: 6 | void Test34::E::e()
// CHECK-NEXT: 7 | vcall_offset (8)
// CHECK-NEXT: 8 | vcall_offset (0)
// CHECK-NEXT: 9 | vbase_offset (-8)
// CHECK-NEXT: 10 | offset_to_top (-8)
// CHECK-NEXT: 11 | Test34::E RTTI
// CHECK-NEXT: -- (Test34::A, 8) vtable address --
// CHECK-NEXT: -- (Test34::D, 8) vtable address --
// CHECK-NEXT: 12 | void Test34::A::a()
// CHECK-NEXT: 13 | vbase_offset (-16)
// CHECK-NEXT: 14 | vcall_offset (-16)
// CHECK-NEXT: 15 | offset_to_top (-16)
// CHECK-NEXT: 16 | Test34::E RTTI
// CHECK-NEXT: -- (Test34::B, 16) vtable address --
// CHECK-NEXT: -- (Test34::C, 16) vtable address --
// CHECK-NEXT: 17 | [unused] void Test34::A::a()
// CHECK-NEXT: 18 | void Test34::C::c()
// CHECK-NEXT: 19 | offset_to_top (-24)
// CHECK-NEXT: 20 | Test34::E RTTI
// CHECK-NEXT: -- (Test34::A, 24) vtable address --
// CHECK-NEXT: 21 | void Test34::A::a()
struct F : E {
virtual void f();
};
void F::f() { }
}