diff options
-rw-r--r-- | clang/lib/CodeGen/CGVtable.cpp | 21 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/virt.cpp | 14 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vtt-layout.cpp | 26 |
3 files changed, 50 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp index d72c32ac449..67b2b3dcb69 100644 --- a/clang/lib/CodeGen/CGVtable.cpp +++ b/clang/lib/CodeGen/CGVtable.cpp @@ -1314,6 +1314,17 @@ class VTTBuilder { e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers are present for all bases with either + // virtual bases or virtual function declarations overridden along a + // virtual path. + // + // If the base class is not dynamic, we don't want to add it, nor any + // of its base classes. + if (!Base->isDynamicClass()) + continue; + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); @@ -1330,10 +1341,9 @@ class VTTBuilder { const CXXRecordDecl *subVtblClass = VtblClass; if ((Base->getNumVBases() || BaseMorallyVirtual) && !NonVirtualPrimaryBase) { - // FIXME: Slightly too many of these for __ZTT8test8_B2 llvm::Constant *init; - if (BaseMorallyVirtual) - init = BuildVtablePtr(vtbl, VtblClass, RD, Offset); + if (BaseMorallyVirtual || VtblClass == Class) + init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset); else { init = getCtorVtable(BaseSubobject(Base, BaseOffset)); @@ -1351,7 +1361,10 @@ class VTTBuilder { /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the /// currnet object we're working on. void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) { - if (RD->getNumVBases() == 0 && !MorallyVirtual) + // Itanium C++ ABI 2.6.2: + // An array of virtual table addresses, called the VTT, is declared for + // each class type that has indirect or direct virtual base classes. + if (RD->getNumVBases() == 0) return; llvm::Constant *Vtable; diff --git a/clang/test/CodeGenCXX/virt.cpp b/clang/test/CodeGenCXX/virt.cpp index 45780394421..bdb05eadec6 100644 --- a/clang/test/CodeGenCXX/virt.cpp +++ b/clang/test/CodeGenCXX/virt.cpp @@ -375,13 +375,13 @@ class test8_D : test8_B1, test8_B2, test8_B3 { // CHECK-LP64-NEXT: .quad (__ZTV7test8_D) + 32 // CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_8test8_B2) + 32 // CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_9test8_B2a) + 32 -// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_9test8_B2a) + 64 -// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_9test8_B2a) + 96 -// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_8test8_B2) + 72 -// CHECK-LP64-NEXT .quad (__ZTC7test8_D8_8test8_B2) + 104 -// CHECK-LP64-NEXT .quad (__ZTV7test8_D) + 72 -// CHECK-LP64: .quad (__ZTV7test8_D) + 160 -// CHECK-LP64: .quad (__ZTV7test8_D) + 192 +// CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_9test8_B2a) + 64 +// CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_9test8_B2a) + 96 +// CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_8test8_B2) + 72 +// CHECK-LP64-NEXT: .quad (__ZTC7test8_D8_8test8_B2) + 104 +// CHECK-LP64-NEXT: .quad (__ZTV7test8_D) + 72 +// CHECK-LP64-NEXT: .quad (__ZTV7test8_D) + 160 +// CHECK-LP64-NEXT: .quad (__ZTV7test8_D) + 192 struct test9_B3 { virtual void funcB3(); int i; }; diff --git a/clang/test/CodeGenCXX/vtt-layout.cpp b/clang/test/CodeGenCXX/vtt-layout.cpp new file mode 100644 index 00000000000..1e78c9048db --- /dev/null +++ b/clang/test/CodeGenCXX/vtt-layout.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +namespace Test1 { +struct A { }; + +struct B : virtual A { + virtual void f(); +}; + +void B::f() { } +} + +// Test1::B should just have a single entry in its VTT, which points to the vtable. +// CHECK: @_ZTTN5Test11BE = constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN5Test11BE, i64 0, i64 3) to i8*)] + +namespace Test2 { + struct A { }; + + struct B : A { virtual void f(); }; + struct C : virtual B { }; + + C c; +} + +// Check that we don't add a secondary virtual pointer for Test2::A, since Test2::A doesn't have any virtual member functions or bases. +// CHECK: @_ZTTN5Test21CE = weak_odr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)] ; <[2 x i8*]*> [#uses=0] |