diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2014-08-09 17:08:06 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2014-08-09 17:08:06 +0000 |
commit | f97c973c2e40400531663a2020e6c3514baaf7b2 (patch) | |
tree | 2c02e2f0df40e390f5d9188ff28b75488c5ae0be | |
parent | 9cf3625742dd8c1ed38e74ca01101dbaaac4e7cf (diff) | |
download | bcm5719-llvm-f97c973c2e40400531663a2020e6c3514baaf7b2.tar.gz bcm5719-llvm-f97c973c2e40400531663a2020e6c3514baaf7b2.zip |
Fix PR20479 -- missing vftable slots in case of virtual inheritance vs return adjusting thunks
Reviewed at http://reviews.llvm.org/D4829
llvm-svn: 215285
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 11 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp | 24 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp | 12 |
3 files changed, 39 insertions, 8 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index fa1127f58f9..42fafde4a5d 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -3174,9 +3174,16 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables, Paths.push_back(new VPtrInfo(RD)); // Recursive case: get all the vbtables from our bases and remove anything - // that shares a virtual base. + // that shares a virtual base. Look at non-virtual bases first so we get + // longer inheritance paths from the derived class to the virtual bases. + llvm::SmallVector<CXXBaseSpecifier, 10> Bases; + std::copy_if(RD->bases_begin(), RD->bases_end(), std::back_inserter(Bases), + [](CXXBaseSpecifier bs) { return !bs.isVirtual(); }); + std::copy_if(RD->bases_begin(), RD->bases_end(), std::back_inserter(Bases), + [](CXXBaseSpecifier bs) { return bs.isVirtual(); }); + llvm::SmallPtrSet<const CXXRecordDecl*, 4> VBasesSeen; - for (const auto &B : RD->bases()) { + for (const auto &B : Bases) { const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl(); if (B.isVirtual() && VBasesSeen.count(Base)) continue; diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp index a4a21106c68..072cb956035 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp @@ -104,3 +104,27 @@ K::K() {} // GLOBALS-LABEL: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant [3 x i8*] } + +namespace pr20479 { +struct A { + virtual A *f(); +}; + +struct B : virtual A { + virtual B *f(); +}; + +struct C : virtual A, B { +// VFTABLES-LABEL: VFTable for 'pr20479::A' in 'pr20479::B' in 'pr20479::C' (2 entries). +// VFTABLES-NEXT: 0 | pr20479::B *pr20479::B::f() +// VFTABLES-NEXT: [return adjustment (to type 'struct pr20479::A *'): vbase #1, 0 non-virtual] +// VFTABLES-NEXT: 1 | pr20479::B *pr20479::B::f() + C(); +}; + +C::C() {} + +// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*] +// GLOBALS: @"\01?f@B@pr20479@@QAEPAUA@2@XZ" +// GLOBALS: @"\01?f@B@pr20479@@UAEPAU12@XZ" +} diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index 4ce4e9c2e17..5f0c5050c03 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -573,6 +573,10 @@ struct Q { // PR19172: Yet another diamond we miscompiled. struct R : virtual Q, X { + // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries). + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] + // CHECK-NEXT: 1 | void vdtors::X::zzz() + // CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry). // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] // CHECK-NEXT: [this adjustment: -8 non-virtual] @@ -580,10 +584,6 @@ struct R : virtual Q, X { // CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry). // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] - // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries). - // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] - // CHECK-NEXT: 1 | void vdtors::X::zzz() - // CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry). // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] virtual ~R(); @@ -694,10 +694,10 @@ struct X : virtual B {}; struct Y : virtual X, B { Y(); - // CHECK-LABEL: VFTable for 'B' in 'pr19066::X' in 'pr19066::Y' (1 entry). + // CHECK-LABEL: VFTable for 'B' in 'pr19066::Y' (1 entry). // CHECK-NEXT: 0 | void B::g() - // CHECK-LABEL: VFTable for 'B' in 'pr19066::Y' (1 entry). + // CHECK-LABEL: VFTable for 'B' in 'pr19066::X' in 'pr19066::Y' (1 entry). // CHECK-NEXT: 0 | void B::g() }; |