From: Serge Pavlov Date: Thu, 18 Feb 2016 16:42:09 +0000 (+0000) Subject: Avoid double deletion in Clang driver. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9998e90e3b605c3c711b120a1519198836d5b634;p=clang Avoid double deletion in Clang driver. Llvm module object is shared between CodeGenerator and BackendConsumer, in both classes it is stored as std::unique_ptr, which is not a good design solution and can cause double deletion error. Usually it does not occur because in BackendConsumer::HandleTranslationUnit the ownership of CodeGenerator over the module is taken away. If however this method is not called, the module is deleted twice and compiler crashes. As the module owned by BackendConsumer is always the same as CodeGenerator has, pointer to llvm module can be removed from BackendGenerator. Differential Revision: http://reviews.llvm.org/D15450 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261222 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp index 645663ff7b..3d333c88f9 100644 --- a/lib/CodeGen/CodeGenAction.cpp +++ b/lib/CodeGen/CodeGenAction.cpp @@ -53,7 +53,6 @@ namespace clang { std::unique_ptr Gen; - std::unique_ptr TheModule; SmallVector>, 4> LinkModules; @@ -81,7 +80,10 @@ namespace clang { this->LinkModules.push_back( std::make_pair(I.first, std::unique_ptr(I.second))); } - std::unique_ptr takeModule() { return std::move(TheModule); } + llvm::Module *getModule() const { return Gen->GetModule(); } + std::unique_ptr takeModule() { + return std::unique_ptr(Gen->ReleaseModule()); + } void releaseLinkModules() { for (auto &I : LinkModules) I.second.release(); @@ -101,8 +103,6 @@ namespace clang { Gen->Initialize(Ctx); - TheModule.reset(Gen->GetModule()); - if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -149,25 +149,12 @@ namespace clang { } // Silently ignore if we weren't initialized for some reason. - if (!TheModule) - return; - - // Make sure IR generation is happy with the module. This is released by - // the module provider. - llvm::Module *M = Gen->ReleaseModule(); - if (!M) { - // The module has been released by IR gen on failures, do not double - // free. - TheModule.release(); + if (!getModule()) return; - } - - assert(TheModule.get() == M && - "Unexpected module change during IR generation"); // Install an inline asm handler so that diagnostics get printed through // our diagnostics hooks. - LLVMContext &Ctx = TheModule->getContext(); + LLVMContext &Ctx = getModule()->getContext(); LLVMContext::InlineAsmDiagHandlerTy OldHandler = Ctx.getInlineAsmDiagnosticHandler(); void *OldContext = Ctx.getInlineAsmDiagnosticContext(); @@ -182,13 +169,13 @@ namespace clang { for (auto &I : LinkModules) { unsigned LinkFlags = I.first; CurLinkModule = I.second.get(); - if (Linker::linkModules(*M, std::move(I.second), LinkFlags)) + if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags)) return; } EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, C.getTargetInfo().getDataLayoutString(), - TheModule.get(), Action, AsmOutStream); + getModule(), Action, AsmOutStream); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); diff --git a/unittests/Frontend/CMakeLists.txt b/unittests/Frontend/CMakeLists.txt index 5b5fdc9a54..674f77bd01 100644 --- a/unittests/Frontend/CMakeLists.txt +++ b/unittests/Frontend/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS add_clang_unittest(FrontendTests FrontendActionTest.cpp + CodeGenActionTest.cpp ) target_link_libraries(FrontendTests clangAST @@ -11,4 +12,5 @@ target_link_libraries(FrontendTests clangFrontend clangLex clangSema + clangCodeGen )