From e7de47efbec4f33a9d5e111e19eca14c5f79c19a Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 22 Jul 2013 13:51:44 +0000 Subject: [ms-cxxabi] Emit linkonce complete dtors in TUs that need them Based on Peter Collingbourne's destructor patches. Prior to this change, clang was considering ?1 to be the complete destructor and the base destructor, which was wrong. This lead to crashes when clang tried to emit two LLVM functions with the same name. In this ABI, TUs with non-inline dtors might not emit a complete destructor. They are emitted as inline thunks in TUs that need them, and they always delegate to the base dtors of the complete class and its virtual bases. This change uses the DeferredDecls machinery to emit complete dtors as needed. Currently in clang try body destructors can catch exceptions thrown by virtual base destructors. In the Microsoft C++ ABI, clang may not have the destructor definition, in which case clang won't wrap the virtual virtual base destructor calls in a try-catch. Diagnosing this in user code is TODO. Finally, for classes that don't use virtual inheritance, MSVC always calls the base destructor (?1) directly. This is a useful code size optimization that avoids emitting lots of extra thunks or aliases. Implementing it also means our existing tests continue to pass, and is consistent with MSVC's output. We can do the same for Itanium by tweaking GetAddrOfCXXDestructor, but it will require further testing. Reviewers: rjmccall CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1066 llvm-svn: 186828 --- clang/lib/CodeGen/CodeGenModule.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 078edebb965..fd884db6ca2 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -513,6 +513,12 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { llvm::GlobalValue::LinkageTypes CodeGenModule::getFunctionLinkage(GlobalDecl GD) { const FunctionDecl *D = cast(GD.getDecl()); + + if (isa(D) && + getCXXABI().useThunkForDtorVariant(cast(D), + GD.getDtorType())) + return llvm::Function::LinkOnceODRLinkage; + GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); if (Linkage == GVA_Internal) @@ -1348,6 +1354,14 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo()); } + // All MSVC dtors other than the base dtor are linkonce_odr and delegate to + // each other bottoming out with the base dtor. Therefore we emit non-base + // dtors on usage, even if there is no dtor definition in the TU. + if (D && isa(D) && + getCXXABI().useThunkForDtorVariant(cast(D), + GD.getDtorType())) + DeferredDeclsToEmit.push_back(GD); + // This function doesn't have a complete type (for example, the return // type is an incomplete struct). Use a fake type instead, and make // sure not to try to set attributes. @@ -2869,7 +2883,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::CXXDestructor: if (cast(D)->isLateTemplateParsed()) return; - EmitCXXDestructors(cast(D)); + getCXXABI().EmitCXXDestructors(cast(D)); break; case Decl::StaticAssert: -- cgit v1.2.3