const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ // Ignore bases that don't have any virtual member functions.
+ if (!BaseDecl->isPolymorphic())
+ continue;
+
uint64_t BaseOffset;
if (I->isVirtual()) {
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ // Ignore bases that don't have any virtual member functions.
+ if (!BaseDecl->isPolymorphic())
+ continue;
+
uint64_t BaseOffset;
if (I->isVirtual()) {
if (!VisitedVirtualBases.insert(BaseDecl)) {
void VtableBuilder::layoutVtable(BaseSubobject Base) {
const CXXRecordDecl *RD = Base.getBase();
-
+
+ assert(RD->isDynamicClass() && "class does not have a vtable!");
+
// First, add the offset to top.
// FIXME: This is not going to be right for construction vtables.
// FIXME: We should not use / 8 here.
E = RD->bases_end(); I != E; ++I) {
const CXXRecordDecl *BaseDecl =
cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
-
+
// Ignore the primary base.
if (BaseDecl == PrimaryBase)
continue;
-
+
+ // Ignore bases that don't have a vtable.
+ if (!BaseDecl->isDynamicClass())
+ continue;
+
assert(!I->isVirtual() && "FIXME: Handle virtual bases");
// Get the base offset of this base.
void D::f() { }
}
+
+namespace Test8 {
+
+// Test that we don't try to layout vtables for classes that don't have
+// virtual bases or virtual member functions.
+
+struct A { };
+
+// CHECK: Vtable for 'Test8::B' (3 entries).
+// CHECK-NEXT: 0 | offset_to_top (0)
+// CHECK-NEXT: 1 | Test8::B RTTI
+// CHECK-NEXT: -- (Test8::B, 0) vtable address --
+// CHECK-NEXT: 2 | void Test8::B::f()
+struct B : A {
+ virtual void f();
+};
+void B::f() { }
+
+}