diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index ad752acf78280ae8f5d6384eeba1e6715009fc0f..fa20ae48e4f099fb282adcb7a700762428251642 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/ModuleLoader.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -325,6 +326,7 @@ public: } void resetAndLeakFileManager() { + BuryPointer(FileMgr.getPtr()); FileMgr.resetWithoutRelease(); } @@ -344,6 +346,7 @@ public: } void resetAndLeakSourceManager() { + BuryPointer(SourceMgr.getPtr()); SourceMgr.resetWithoutRelease(); } @@ -363,6 +366,7 @@ public: } void resetAndLeakPreprocessor() { + BuryPointer(PP.getPtr()); PP.resetWithoutRelease(); } @@ -381,6 +385,7 @@ public: } void resetAndLeakASTContext() { + BuryPointer(Context.getPtr()); Context.resetWithoutRelease(); } diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index dff56c3a8a4eb0b43e6071587c882e61beb9be5e..db52d5cf0dda324dd7f80342171e690e677f6124 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -123,6 +123,11 @@ inline int getLastArgIntValue(const llvm::opt::ArgList &Args, return getLastArgIntValue(Args, Id, Default, &Diags); } +// When Clang->getFrontendOpts().DisableFree is set we don't delete some of the +// global objects, but we don't want LeakDetectors to complain, so we bury them +// in a globally visible array. +void BuryPointer(const void *Ptr); + } // end namespace clang #endif diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index f302ef7b37c22e464132889a0a3035e7d6f1ef64..55970cdf842a0abd86df6a85e8851157737f5bdf 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/Utils.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Bitcode/ReaderWriter.h" @@ -117,7 +118,7 @@ public: delete PerModulePasses; delete PerFunctionPasses; if (CodeGenOpts.DisableFree) - TM.take(); + BuryPointer(TM.take()); } llvm::OwningPtr<TargetMachine> TM; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 71e6b74d38b2a480d6b5f7839142e0f7b3dfbc2b..78a88f65f6b0ac023849835a61e8fef6eb289587 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -28,6 +28,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/Support/Atomic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -1827,4 +1828,19 @@ int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default, } return Res; } + +void BuryPointer(const void *Ptr) { + // This function may be called only a small fixed amount of times per each + // invocation, otherwise we do actually have a leak which we want to report. + // If this function is called more than kGraveYardMaxSize times, the pointers + // will not be properly buried and a leak detector will report a leak, which + // is what we want in such case. + static const size_t kGraveYardMaxSize = 16; + static const void *GraveYard[kGraveYardMaxSize]; + static llvm::sys::cas_flag GraveYardSize; + llvm::sys::cas_flag Idx = llvm::sys::AtomicIncrement(&GraveYardSize) - 1; + if (Idx >= kGraveYardMaxSize) + return; + GraveYard[Idx] = Ptr; +} } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 49d01f9d372c7f38fae33720d69b8e3edf152c31..31889f1fff8cfa0142139b59a320560c08022528 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -17,6 +17,7 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/LayoutOverrideSource.h" +#include "clang/Frontend/Utils.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" @@ -403,9 +404,9 @@ void FrontendAction::EndSourceFile() { // // FIXME: There is more per-file stuff we could just drop here? if (CI.getFrontendOpts().DisableFree) { - CI.takeASTConsumer(); + BuryPointer(CI.takeASTConsumer()); if (!isCurrentFileAST()) { - CI.takeSema(); + BuryPointer(CI.takeSema()); CI.resetAndLeakASTContext(); } } else { diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index e22f9ba0523a87b50c47455c9cc608ff6fd6c7f4..e14fb2340e63fed4aa7bee59a77271d87d2f1594 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -21,6 +21,7 @@ #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/Utils.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "llvm/Option/OptTable.h" @@ -236,6 +237,6 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { return false; bool Success = Clang->ExecuteAction(*Act); if (Clang->getFrontendOpts().DisableFree) - Act.take(); + BuryPointer(Act.take()); return Success; } diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp index 5b3b5ad6500bca82c103ab5c201385a0cc1903f7..28ada6944e87ad5ad98f4c5f39a7dff765fe2229 100644 --- a/tools/driver/cc1_main.cpp +++ b/tools/driver/cc1_main.cpp @@ -21,6 +21,7 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Frontend/Utils.h" #include "clang/FrontendTool/Utils.h" #include "llvm/ADT/Statistic.h" #include "llvm/LinkAllPasses.h" @@ -112,7 +113,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd, if (Clang->getFrontendOpts().DisableFree) { if (llvm::AreStatisticsEnabled() || Clang->getFrontendOpts().ShowStats) llvm::PrintStatistics(); - Clang.take(); + BuryPointer(Clang.take()); return !Success; }