diff options
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 18 | ||||
-rw-r--r-- | test/CodeGenCXX/virt.cpp | 31 |
2 files changed, 37 insertions, 12 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 10295f1883..3131fdb852 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -25,10 +25,14 @@ ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx) : Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0), IsUnion(false), NonVirtualSize(0), NonVirtualAlignment(8) {} +/// LayoutVtable - Lay out the vtable and set PrimaryBase. void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) { // FIXME: audit indirect virtual bases - if (!RD->isPolymorphic() && !RD->getNumVBases()) + if (!RD->isPolymorphic() && !RD->getNumVBases()) { + // There is no primary base in this case. + setPrimaryBase(0); return; + } SelectPrimaryBase(RD); if (PrimaryBase == 0) { @@ -46,7 +50,9 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { if (!i->isVirtual()) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - LayoutNonVirtualBase(Base); + // Skip the PrimaryBase here, as it is laid down first. + if (Base != PrimaryBase) + LayoutNonVirtualBase(Base); } } } @@ -186,12 +192,10 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { // If this is a C++ class, lay out the nonvirtual bases. if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { LayoutVtable(RD); + // PrimaryBase goes first. + if (PrimaryBase) + LayoutNonVirtualBase(PrimaryBase); LayoutNonVirtualBases(RD); - - // FIXME: audit indirect virtual bases - assert (RD->getNumVBases() == 0 - && "FIXME: We don't support virtual bases yet!"); - // FIXME: We need to layout the virtual bases in the complete object layout. } LayoutFields(D); diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 55c9b5d923..0d43b80ea7 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -7,6 +7,7 @@ struct B { virtual void bar1(); virtual void bar2(); + int b; }; void B::bar1() { } void B::bar2() { } @@ -18,22 +19,42 @@ struct C { void C::bee1() { } void C::bee2() { } -static_assert (sizeof (B) == (sizeof(void *)), "vtable pointer layout"); +struct D { + virtual void boo(); +}; +void D::boo() { } + +struct E { + int e; +}; -class A : public B, public C { +static_assert (sizeof (C) == (sizeof(void *)), "vtable pointer layout"); + +class A : public E, public B, public C, /* virtual */ public D { public: virtual void foo1(); virtual void foo2(); A() { } -} *a; + int a; +} *ap; void A::foo1() { } void A::foo2() { } int main() { A a; B b; + ap->e = 1; + ap->b = 2; } +// CHECK-LP32: main: +// CHECK-LP32: movl $1, 8(%eax) +// CHECK-LP32: movl $2, 4(%eax) + +// CHECK-LP64: main: +// CHECK-LP64: movl $1, 12(%rax) +// CHECK-LP64: movl $2, 8(%rax) + // CHECK-LP64: __ZTV1B: // CHECK-LP64: .space 8 // CHECK-LP64: .space 8 @@ -53,7 +74,7 @@ int main() { // CHECK-LP64: .quad __ZN1B4bar2Ev // CHECK-LP64: .quad __ZN1A4foo1Ev // CHECK-LP64: .quad __ZN1A4foo2Ev -// CHECK-LP64: .quad 18446744073709551608 +// CHECK-LP64: .quad 18446744073709551600 // CHECK-LP64: .space 8 // CHECK-LP64: .quad __ZN1C4bee1Ev // CHECK-LP64: .quad __ZN1C4bee2Ev @@ -65,7 +86,7 @@ int main() { // CHECK-LP32: .long __ZN1B4bar2Ev // CHECK-LP32: .long __ZN1A4foo1Ev // CHECK-LP32: .long __ZN1A4foo2Ev -// CHECK-LP32: .long 4294967292 +// CHECK-LP32: .long 4294967284 // CHECK-LP32: .space 4 // CHECK-LP32: .long __ZN1C4bee1Ev // CHECK-LP32: .long __ZN1C4bee2Ev |