diff options
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 28 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-layout.cpp | 35 |
2 files changed, 57 insertions, 6 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 457bfa559c..6e84c959ed 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -828,6 +828,15 @@ class VCallAndVBaseOffsetBuilder { /// vtable. const CXXRecordDecl *MostDerivedClass; + /// MostDerivedClassOffset - If we're building a construction vtable, this + /// holds the offset from the layout class to the most derived class. + const uint64_t MostDerivedClassOffset; + + /// LayoutClass - The class we're using for layout information. Will be + /// different than the most derived class if we're building a construction + /// vtable. + const CXXRecordDecl *LayoutClass; + /// Context - The ASTContext which we will use for layout information. ASTContext &Context; @@ -858,9 +867,12 @@ class VCallAndVBaseOffsetBuilder { public: VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass, + uint64_t MostDerivedClassOffset, + const CXXRecordDecl *LayoutClass, const FinalOverriders *Overriders, BaseSubobject Base, bool BaseIsVirtual) - : MostDerivedClass(MostDerivedClass), + : MostDerivedClass(MostDerivedClass), + MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), Overriders(Overriders) { // Add vcall and vbase offsets. @@ -1016,11 +1028,10 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base, } } - void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, int64_t OffsetToTop) { - const ASTRecordLayout &MostDerivedClassLayout = - Context.getASTRecordLayout(MostDerivedClass); + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); // Add vbase offsets. for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), @@ -1032,8 +1043,11 @@ void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD, if (I->isVirtual() && VisitedVirtualBases.insert(BaseDecl)) { // FIXME: We shouldn't use / 8 here. uint64_t Offset = - OffsetToTop + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl) / 8; + OffsetToTop + LayoutClassLayout.getVBaseClassOffset(BaseDecl) / 8; + // The offset should be relative to the most derived class offset. + Offset -= MostDerivedClassOffset / 8; + Components.push_back(VtableComponent::MakeVBaseOffset(Offset)); } @@ -1409,6 +1423,7 @@ VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD, // We don't have vcall offsets for this virtual base, go ahead and // build them. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, 0, + MostDerivedClass, 0, BaseSubobject(Offset.VirtualBase, 0), /*BaseIsVirtual=*/true); @@ -1673,7 +1688,8 @@ void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base, assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); // Add vcall and vbase offsets for this vtable. - VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, &Overriders, + VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClassOffset, + LayoutClass, &Overriders, Base, BaseIsVirtual); Components.append(Builder.components_begin(), Builder.components_end()); diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 75d4143d77..58ce44fed7 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -833,3 +833,38 @@ class F : virtual D, virtual E { void F::f() { } } + +namespace Test22 { + +// Very simple construction vtable test. +struct V1 { + int v1; +}; + +struct V2 : virtual V1 { + int v2; +}; + +// CHECK: Vtable for 'Test22::C' (8 entries). +// CHECK-NEXT: 0 | vbase_offset (16) +// CHECK-NEXT: 1 | vbase_offset (12) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test22::C RTTI +// CHECK-NEXT: -- (Test22::C, 0) vtable address -- +// CHECK-NEXT: 4 | void Test22::C::f() +// CHECK-NEXT: 5 | vbase_offset (-4) +// CHECK-NEXT: 6 | offset_to_top (-16) +// CHECK-NEXT: 7 | Test22::C RTTI + +// CHECK: Construction vtable for ('Test22::V2', 16) in 'Test22::C' (3 entries). +// CHECK-NEXT: 0 | vbase_offset (-4) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test22::V2 RTTI + +struct C : virtual V1, virtual V2 { + int c; + virtual void f(); +}; +void C::f() { } + +} |