diff options
author | Mike Stump <mrs@apple.com> | 2010-01-22 06:45:05 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2010-01-22 06:45:05 +0000 |
commit | 9eb76d47f248ea89b4b3c8af7f255a9a6b34ba64 (patch) | |
tree | 606e086f1657133f16f2618631cbca7b4167590a | |
parent | 5264fce147345f3de0b3dddb5a23d3d60103f265 (diff) | |
download | bcm5719-llvm-9eb76d47f248ea89b4b3c8af7f255a9a6b34ba64.tar.gz bcm5719-llvm-9eb76d47f248ea89b4b3c8af7f255a9a6b34ba64.zip |
Ensure we output all non-virtual base vtables. Fixes PR5890.
llvm-svn: 94163
-rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 67 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/virt.cpp | 14 |
2 files changed, 52 insertions, 29 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index d4b4c65c2bb..3cb699d0e5b 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -431,12 +431,11 @@ public: continue; const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); - if (Base != PrimaryBase || PrimaryBaseWasVirtual) { - uint64_t o = Offset + Layout.getBaseClassOffset(Base); - StartNewTable(); - GenerateVtableForBase(Base, o, MorallyVirtual, false, - CurrentVBaseOffset, Path); - } + uint64_t o = Offset + Layout.getBaseClassOffset(Base); + StartNewTable(); + GenerateVtableForBase(Base, o, MorallyVirtual, false, + true, Base == PrimaryBase && !PrimaryBaseWasVirtual, + CurrentVBaseOffset, Path); } Path->pop_back(); } @@ -493,6 +492,7 @@ public: void FinishGenerateVtable(const CXXRecordDecl *RD, const ASTRecordLayout &Layout, const CXXRecordDecl *PrimaryBase, + bool ForNPNVBases, bool WasPrimaryBase, bool PrimaryBaseWasVirtual, bool MorallyVirtual, int64_t Offset, bool ForVirtualBase, int64_t CurrentVBaseOffset, @@ -505,23 +505,27 @@ public: StartNewTable(); extra = 0; - bool DeferVCalls = MorallyVirtual || ForVirtualBase; - int VCallInsertionPoint = VtableComponents.size(); - if (!DeferVCalls) { - insertVCalls(VCallInsertionPoint); - } else - // FIXME: just for extra, or for all uses of VCalls.size post this? - extra = -VCalls.size(); + Index_t AddressPoint = 0; + int VCallInsertionPoint = 0; + if (!ForNPNVBases || !WasPrimaryBase) { + bool DeferVCalls = MorallyVirtual || ForVirtualBase; + VCallInsertionPoint = VtableComponents.size(); + if (!DeferVCalls) { + insertVCalls(VCallInsertionPoint); + } else + // FIXME: just for extra, or for all uses of VCalls.size post this? + extra = -VCalls.size(); - // Add the offset to top. - VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0); + // Add the offset to top. + VtableComponents.push_back(BuildVtable ? wrap(-((Offset-LayoutOffset)/8)) : 0); - // Add the RTTI information. - VtableComponents.push_back(rtti); + // Add the RTTI information. + VtableComponents.push_back(rtti); - Index_t AddressPoint = VtableComponents.size(); + AddressPoint = VtableComponents.size(); - AppendMethodsToVtable(); + AppendMethodsToVtable(); + } // and then the non-virtual bases. NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, @@ -539,7 +543,8 @@ public: insertVCalls(VCallInsertionPoint); } - AddAddressPoints(RD, Offset, AddressPoint); + if (!ForNPNVBases || !WasPrimaryBase) + AddAddressPoints(RD, Offset, AddressPoint); if (alloc) { delete Path; @@ -611,6 +616,8 @@ public: void GenerateVtableForBase(const CXXRecordDecl *RD, int64_t Offset = 0, bool MorallyVirtual = false, bool ForVirtualBase = false, + bool ForNPNVBases = false, + bool WasPrimaryBase = true, int CurrentVBaseOffset = 0, Path_t *Path = 0) { if (!RD->isDynamicClass()) @@ -633,15 +640,17 @@ public: if (ForVirtualBase) extra = VCalls.size(); - VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, ForVirtualBase, - CurrentVBaseOffset, true); + if (!ForNPNVBases || !WasPrimaryBase) { + VBPrimaries(RD, MorallyVirtual, Offset, !ForVirtualBase, 0, + ForVirtualBase, CurrentVBaseOffset, true); - if (Path) - OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset); + if (Path) + OverrideMethods(Path, MorallyVirtual, Offset, CurrentVBaseOffset); + } - FinishGenerateVtable(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, - MorallyVirtual, Offset, ForVirtualBase, - CurrentVBaseOffset, Path); + FinishGenerateVtable(RD, Layout, PrimaryBase, ForNPNVBases, WasPrimaryBase, + PrimaryBaseWasVirtual, MorallyVirtual, Offset, + ForVirtualBase, CurrentVBaseOffset, Path); } void GenerateVtableForVBases(const CXXRecordDecl *RD, @@ -668,8 +677,8 @@ public: int64_t CurrentVBaseOffset = BaseOffset; D1(printf("vtable %s virtual base %s\n", MostDerivedClass->getNameAsCString(), Base->getNameAsCString())); - GenerateVtableForBase(Base, BaseOffset, true, true, CurrentVBaseOffset, - Path); + GenerateVtableForBase(Base, BaseOffset, true, true, false, + true, CurrentVBaseOffset, Path); } int64_t BaseOffset; if (i->isVirtual()) diff --git a/clang/test/CodeGenCXX/virt.cpp b/clang/test/CodeGenCXX/virt.cpp index 20ea1d5301a..2717d6cf94e 100644 --- a/clang/test/CodeGenCXX/virt.cpp +++ b/clang/test/CodeGenCXX/virt.cpp @@ -1077,7 +1077,21 @@ class test21_D : public test21_B, public test21_B1 { // CHECK-LP64-NEXT .quad (__ZTV8test21_D) + 80 +struct test22_s1 { virtual void dtor() { } }; +struct test22_s2 { virtual void dtor() { } }; +struct test22_s3 : test22_s1, test22_s2 { virtual void dtor() { } }; +struct test22_D : test22_s3 { virtual void dtor() { } }; +// CHECK-LP64: __ZTV8test22_D: +// CHECK-LP64-NEXT: .quad 0 +// CHECK-LP64-NEXT: .quad __ZTI8test22_D +// CHECK-LP64-NEXT: .quad __ZN8test22_D4dtorEv +// CHECK-LP64-NEXT: .quad 18446744073709551608 +// CHECK-LP64-NEXT: .quad __ZTI8test22_D +// CHECK-LP64-NEXT: .quad __ZThn8_N8test22_D4dtorEv + + +test22_D d22; test21_D d21; test20_D d20; test19_D d19; |