From: Mike Stump Date: Wed, 28 Oct 2009 00:35:46 +0000 (+0000) Subject: Finish off pure virtual function handling. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7809e0d165103864ce6063070e093a0b7cd30cd9;p=clang Finish off pure virtual function handling. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85354 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 0b81c2165e..66f48c0e3d 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -72,8 +72,13 @@ public: LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)), CurrentVBaseOffset(0) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); - // FIXME: ___cxa_pure_virtual - cxa_pure = wrap((Index_t)0); + + // Calculate pointer for ___cxa_pure_virtual. + const llvm::FunctionType *FTy; + std::vector ArgTys; + const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); + FTy = llvm::FunctionType::get(ResultType, ArgTys, false); + cxa_pure = wrap(CGM.CreateRuntimeFunction(FTy, "__cxa_pure_virtual")); } llvm::DenseMap &getIndex() { return Index; } @@ -183,6 +188,7 @@ public: bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, bool MorallyVirtual, Index_t OverrideOffset, Index_t Offset) { + const bool isPure = MD->isPure(); typedef CXXMethodDecl::method_iterator meth_iter; // FIXME: Should OverrideOffset's be Offset? @@ -221,7 +227,9 @@ public: } Index[MD] = i; submethods[i] = m; - + if (isPure) + Pures[MD] = 1; + Pures.erase(OMD); Thunks.erase(OMD); if (MorallyVirtual) { Index_t &idx = VCall[OMD]; @@ -243,7 +251,7 @@ public: CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset, ReturnOffset), oret); - else + else if (!isPure) Thunks[MD] = ThisOffset; return true; } @@ -258,7 +266,7 @@ public: CovariantThunks[MD] = std::make_pair(std::make_pair(ThisOffset, ReturnOffset), oret); - else + else if (!isPure) Thunks[MD] = ThisOffset; } return true; @@ -272,6 +280,7 @@ public: for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end(); i != e; ++i) { const CXXMethodDecl *MD = i->first; + assert(!MD->isPure() && "Trying to thunk a pure"); Index_t idx = Index[MD]; Index_t nv_O = i->second.first; Index_t v_O = i->second.second; @@ -282,6 +291,8 @@ public: e = CovariantThunks.end(); i != e; ++i) { const CXXMethodDecl *MD = i->first; + if (MD->isPure()) + continue; Index_t idx = Index[MD]; Index_t nv_t = i->second.first.first.first; Index_t v_t = i->second.first.first.second; @@ -339,6 +350,8 @@ public: // else allocate a new slot. Index[MD] = submethods.size(); submethods.push_back(m); + if (MD->isPure()) + Pures[MD] = 1; if (MorallyVirtual) { VCallOffset[MD] = Offset/8; Index_t &idx = VCall[MD]; diff --git a/test/CodeGenCXX/virt.cpp b/test/CodeGenCXX/virt.cpp index 21fecac11e..ffd87bd967 100644 --- a/test/CodeGenCXX/virt.cpp +++ b/test/CodeGenCXX/virt.cpp @@ -1049,6 +1049,41 @@ struct test16_D : test16_NV1, virtual test16_B2 { // CHECK-LP32-NEXT: .long __ZN10test16_NV28foo_NV2bEv +class test17_B1 { + virtual void foo() = 0; + virtual void bar() { } +}; + +class test17_B2 : public test17_B1 { + void foo() { } + virtual void bar() = 0; +}; + +class test17_D : public test17_B2 { + void bar() { } +} test17_d; + + +// CHECK-LP64:__ZTV8test17_D: +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI8test17_D +// CHECK-LP64-NEXT: .quad __ZN9test17_B23fooEv +// CHECK-LP64-NEXT: .quad __ZN8test17_D3barEv + +// CHECK-LP64:__ZTV9test17_B2: +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI9test17_B2 +// CHECK-LP64-NEXT: .quad __ZN9test17_B23fooEv +// CHECK-LP64-NEXT: .quad ___cxa_pure_virtual + +// CHECK-LP64:__ZTV9test17_B1: +// CHECK-LP64-NEXT: .space 8 +// CHECK-LP64-NEXT: .quad __ZTI9test17_B1 +// CHECK-LP64-NEXT: .quad ___cxa_pure_virtual +// CHECK-LP64-NEXT: .quad __ZN9test17_B13barEv + + + // CHECK-LP64: __ZTV1B: // CHECK-LP64-NEXT: .space 8 // CHECK-LP64-NEXT: .quad __ZTI1B