]> granicus.if.org Git - clang/commitdiff
Avoid double deletion in Clang driver.
authorSerge Pavlov <sepavloff@gmail.com>
Thu, 18 Feb 2016 16:42:09 +0000 (16:42 +0000)
committerSerge Pavlov <sepavloff@gmail.com>
Thu, 18 Feb 2016 16:42:09 +0000 (16:42 +0000)
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

lib/CodeGen/CodeGenAction.cpp
unittests/Frontend/CMakeLists.txt

index 645663ff7b7c38d54c48b2bc1e18b6c9a8313342..3d333c88f990fd07c4b15ccaeb4a187355607d94 100644 (file)
@@ -53,7 +53,6 @@ namespace clang {
 
     std::unique_ptr<CodeGenerator> Gen;
 
-    std::unique_ptr<llvm::Module> TheModule;
     SmallVector<std::pair<unsigned, std::unique_ptr<llvm::Module>>, 4>
         LinkModules;
 
@@ -81,7 +80,10 @@ namespace clang {
         this->LinkModules.push_back(
             std::make_pair(I.first, std::unique_ptr<llvm::Module>(I.second)));
     }
-    std::unique_ptr<llvm::Module> takeModule() { return std::move(TheModule); }
+    llvm::Module *getModule() const { return Gen->GetModule(); }
+    std::unique_ptr<llvm::Module> takeModule() {
+      return std::unique_ptr<llvm::Module>(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);
 
index 5b5fdc9a54fee5cbf23fd7f57f786217ae3b776f..674f77bd0135c6bdf9aced6ec0a858a8f61aee3a 100644 (file)
@@ -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
   )