From eb19fa948173502f47c26357c2ec41aa4be197b4 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 6 Aug 2009 13:41:24 +0000 Subject: [PATCH] Layout virtual bases. Work in progress. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78308 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 27 +++++++++++++++++++++++---- lib/AST/RecordLayoutBuilder.h | 4 +++- lib/CodeGen/CGCXX.cpp | 4 +--- test/CodeGenCXX/virt.cpp | 22 +++++++++++++++++++++- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 833e053e14..5f23a8ca46 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -52,7 +52,7 @@ ASTRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD) { cast(i->getType()->getAs()->getDecl()); // Skip the PrimaryBase here, as it is laid down first. if (Base != PrimaryBase) - LayoutNonVirtualBase(Base); + LayoutBaseNonVirtually(Base); } } } @@ -155,7 +155,22 @@ void ASTRecordLayoutBuilder::SelectPrimaryBase(const CXXRecordDecl *RD) { return; } -void ASTRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *RD) { +void ASTRecordLayoutBuilder::LayoutVirtualBase(const CXXRecordDecl *RD) { + LayoutBaseNonVirtually(RD); +} + +void ASTRecordLayoutBuilder::LayoutVirtualBases(const CXXRecordDecl *RD) { + // FIXME: audit indirect virtual bases + for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), + e = RD->vbases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast(i->getType()->getAs()->getDecl()); + if (Base != PrimaryBase) + LayoutVirtualBase(Base); + } +} + +void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD) { const ASTRecordLayout &BaseInfo = Ctx.getASTRecordLayout(RD); assert(BaseInfo.getDataSize() > 0 && "FIXME: Handle empty classes."); @@ -190,11 +205,12 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { UpdateAlignment(AA->getAlignment()); // If this is a C++ class, lay out the nonvirtual bases. - if (const CXXRecordDecl *RD = dyn_cast(D)) { + const CXXRecordDecl *RD = dyn_cast(D); + if (RD) { LayoutVtable(RD); // PrimaryBase goes first. if (PrimaryBase) - LayoutNonVirtualBase(PrimaryBase); + LayoutBaseNonVirtually(PrimaryBase); LayoutNonVirtualBases(RD); } @@ -203,6 +219,9 @@ void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { NonVirtualSize = Size; NonVirtualAlignment = Alignment; + if (RD) + LayoutVirtualBases(RD); + // Finally, round the size of the total struct up to the alignment of the // struct itself. FinishLayout(); diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index a6c9c5e873..a745c85db4 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -58,7 +58,9 @@ class ASTRecordLayoutBuilder { bool IsNearlyEmpty(const CXXRecordDecl *RD); void LayoutVtable(const CXXRecordDecl *RD); void LayoutNonVirtualBases(const CXXRecordDecl *RD); - void LayoutNonVirtualBase(const CXXRecordDecl *RD); + void LayoutBaseNonVirtually(const CXXRecordDecl *RD); + void LayoutVirtualBase(const CXXRecordDecl *RD); + void LayoutVirtualBases(const CXXRecordDecl *RD); /// FinishLayout - Finalize record layout. Adjust record size based on the /// alignment. diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 0f76266acc..eb8e87d372 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -623,10 +623,8 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { /// base classes and non-static data members belonging to this constructor. void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { const CXXRecordDecl *ClassDecl = cast(CD->getDeclContext()); - assert(ClassDecl->getNumVBases() == 0 - && "FIXME: virtual base initialization unsupported"); + // FIXME: Add vbase initialization llvm::Value *LoadOfThis = 0; - for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), E = CD->init_end(); diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 0d43b80ea7..a90e7228d3 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -30,7 +30,7 @@ struct E { static_assert (sizeof (C) == (sizeof(void *)), "vtable pointer layout"); -class A : public E, public B, public C, /* virtual */ public D { +class A : public E, public B, public C { public: virtual void foo1(); virtual void foo2(); @@ -90,3 +90,23 @@ int main() { // CHECK-LP32: .space 4 // CHECK-LP32: .long __ZN1C4bee1Ev // CHECK-LP32: .long __ZN1C4bee2Ev + +struct D1 { + virtual void bar(); + void *d1; +}; +void D1::bar() { } + +class F : virtual public D1, virtual public D { +public: + virtual void foo(); + void *f; +}; +void F::foo() { } + +void test2() { + F f; + f.f = 0; +} + +static_assert(sizeof(F) == sizeof(void*)*4, "invalid vbase size"); -- 2.40.0