diff options
author | Nico Weber <nicolasweber@gmx.de> | 2014-05-08 04:26:47 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2014-05-08 04:26:47 +0000 |
commit | 824285ec537f78d2e7143c148edc651b7eb78d99 (patch) | |
tree | f599cb28fb5b566b67ee596628ec5aa761705ca6 /clang/lib/Frontend/FrontendAction.cpp | |
parent | 789d3007fb0d84084ffd9c48beb024f8afac7f25 (diff) | |
download | bcm5719-llvm-824285ec537f78d2e7143c148edc651b7eb78d99.tar.gz bcm5719-llvm-824285ec537f78d2e7143c148edc651b7eb78d99.zip |
Let ASTReader optionally delete its ASTDeserializationListener.
Use this to fix the leak of DeserializedDeclsDumper and DeserializedDeclsChecker
in FrontendAction (found by LSan), PR19560.
The "delete this" bool is necessary because both PCHGenerator and ASTUnit
return the same object from both getDeserializationListener() and
getASTMutationListener(), so ASTReader can't just have a unique_ptr.
It's also not possible to just let FrontendAction (or CompilerInstance) own
these listeners due to lifetime issues (see comments on PR19560).
Finally, ASTDeserializationListener can't easily be refcounted, since several of
the current listeners are allocated on the stack.
Having this bool isn't ideal, but it's a pattern that's used in other places in
the codebase too, and it seems better than leaking.
llvm-svn: 208277
Diffstat (limited to 'clang/lib/Frontend/FrontendAction.cpp')
-rw-r--r-- | clang/lib/Frontend/FrontendAction.cpp | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 8b05849f900..77eb1a14434 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -37,11 +37,16 @@ namespace { class DelegatingDeserializationListener : public ASTDeserializationListener { ASTDeserializationListener *Previous; + bool DeletePrevious; public: explicit DelegatingDeserializationListener( - ASTDeserializationListener *Previous) - : Previous(Previous) { } + ASTDeserializationListener *Previous, bool DeletePrevious) + : Previous(Previous), DeletePrevious(DeletePrevious) {} + virtual ~DelegatingDeserializationListener() { + if (DeletePrevious) + delete Previous; + } void ReaderInitialized(ASTReader *Reader) override { if (Previous) @@ -74,8 +79,9 @@ public: /// \brief Dumps deserialized declarations. class DeserializedDeclsDumper : public DelegatingDeserializationListener { public: - explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous) - : DelegatingDeserializationListener(Previous) { } + explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous, + bool DeletePrevious) + : DelegatingDeserializationListener(Previous, DeletePrevious) {} void DeclRead(serialization::DeclID ID, const Decl *D) override { llvm::outs() << "PCH DECL: " << D->getDeclKindName(); @@ -96,9 +102,10 @@ class DeserializedDeclsChecker : public DelegatingDeserializationListener { public: DeserializedDeclsChecker(ASTContext &Ctx, const std::set<std::string> &NamesToCheck, - ASTDeserializationListener *Previous) - : DelegatingDeserializationListener(Previous), - Ctx(Ctx), NamesToCheck(NamesToCheck) { } + ASTDeserializationListener *Previous, + bool DeletePrevious) + : DelegatingDeserializationListener(Previous, DeletePrevious), Ctx(Ctx), + NamesToCheck(NamesToCheck) {} void DeclRead(serialization::DeclID ID, const Decl *D) override { if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) @@ -320,17 +327,24 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = Consumer->GetASTDeserializationListener(); - if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) - DeserialListener = new DeserializedDeclsDumper(DeserialListener); - if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) - DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), - CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, - DeserialListener); + bool DeleteDeserialListener = false; + if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) { + DeserialListener = new DeserializedDeclsDumper(DeserialListener, + DeleteDeserialListener); + DeleteDeserialListener = true; + } + if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) { + DeserialListener = new DeserializedDeclsChecker( + CI.getASTContext(), + CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, + DeserialListener, DeleteDeserialListener); + DeleteDeserialListener = true; + } CI.createPCHExternalASTSource( - CI.getPreprocessorOpts().ImplicitPCHInclude, - CI.getPreprocessorOpts().DisablePCHValidation, - CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, - DeserialListener); + CI.getPreprocessorOpts().ImplicitPCHInclude, + CI.getPreprocessorOpts().DisablePCHValidation, + CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener, + DeleteDeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } |