diff options
author | Anders Carlsson <andersca@mac.com> | 2010-03-29 05:40:50 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-03-29 05:40:50 +0000 |
commit | 67d568aaeba023e42ca74da3dca18e161664f567 (patch) | |
tree | 81357027f652debb9dea1afdd2fb7a11d9b2ee7d /lib/CodeGen/CGVtable.cpp | |
parent | 6f6de731808ffd3664f0a179d1cb694c4e7e5342 (diff) |
Handle pure virtual member functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99807 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 2f725df814..1283c69d97 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -4049,6 +4049,8 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, unsigned NextVTableThunkIndex = 0; + llvm::Constant* PureVirtualFn = 0; + for (unsigned I = 0; I != NumComponents; ++I) { VtableComponent Component = VtableComponent::getFromOpaqueInteger(Components[I]); @@ -4091,22 +4093,37 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, break; } - // Check if we should use a thunk. - if (NextVTableThunkIndex < VTableThunks.size() && - VTableThunks[NextVTableThunkIndex].first == I) { - const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second; - - Init = CGM.GetAddrOfThunk(GD, Thunk); + if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) { + // We have a pure virtual member function. + if (!PureVirtualFn) { + const llvm::FunctionType *Ty = + llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), + /*isVarArg=*/false); + PureVirtualFn = + CGM.CreateRuntimeFunction(Ty, "__cxa_pure_virtual"); + PureVirtualFn = llvm::ConstantExpr::getBitCast(PureVirtualFn, + Int8PtrTy); + } - NextVTableThunkIndex++; + Init = PureVirtualFn; } else { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); - const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD); + // Check if we should use a thunk. + if (NextVTableThunkIndex < VTableThunks.size() && + VTableThunks[NextVTableThunkIndex].first == I) { + const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second; + + Init = CGM.GetAddrOfThunk(GD, Thunk); + + NextVTableThunkIndex++; + } else { + const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); + const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVtable(MD); - Init = CGM.GetAddrOfFunction(GD, Ty); + Init = CGM.GetAddrOfFunction(GD, Ty); + } + + Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); } - - Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); break; } @@ -4137,11 +4154,8 @@ GetGlobalVariable(llvm::Module &Module, llvm::StringRef Name, if (GV) { // Check if the variable has the right type. - if (GV->getType()->getElementType() == Ty) { - // Set the correct linkage. - GV->setLinkage(Linkage); + if (GV->getType()->getElementType() == Ty) return GV; - } assert(GV->isDeclaration() && "Declaration has wrong type!"); @@ -4221,6 +4235,9 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable, CreateVTableInitializer(RD, getVTableComponentsData(RD), getNumVTableComponents(RD), Thunks); VTable->setInitializer(Init); + + // Set the correct linkage. + VTable->setLinkage(Linkage); } llvm::GlobalVariable * |