Skip to content

Commit

Permalink
Avoid double deletion in Clang driver.
Browse files Browse the repository at this point in the history
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

llvm-svn: 261222
  • Loading branch information
spavloff committed Feb 18, 2016
1 parent eb7e5d9 commit 41c1f79
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 21 deletions.
29 changes: 8 additions & 21 deletions clang/lib/CodeGen/CodeGenAction.cpp
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand All @@ -101,8 +103,6 @@ namespace clang {

Gen->Initialize(Ctx);

TheModule.reset(Gen->GetModule());

if (llvm::TimePassesIsEnabled)
LLVMIRGeneration.stopTimer();
}
Expand Down Expand Up @@ -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();
Expand All @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions clang/unittests/Frontend/CMakeLists.txt
Expand Up @@ -4,11 +4,13 @@ set(LLVM_LINK_COMPONENTS

add_clang_unittest(FrontendTests
FrontendActionTest.cpp
CodeGenActionTest.cpp
)
target_link_libraries(FrontendTests
clangAST
clangBasic
clangFrontend
clangLex
clangSema
clangCodeGen
)

0 comments on commit 41c1f79

Please sign in to comment.