From 4f32786ac45210143654390177105eb749b614e9 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 21 Mar 2011 18:40:17 +0000 Subject: [PATCH] Improve crash recovery cleanup to recovery CompilerInstances during crash recovery. This was a huge resource "root" during crashes. This change requires making a bunch of fundamental Clang structures (optionally) reference counted to allow correct ownership semantics of these objects (e.g., ASTContext) to play out between an active ASTUnit and CompilerInstance object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128011 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 3 +- include/clang/Basic/FileManager.h | 3 +- include/clang/Basic/SourceManager.h | 3 +- include/clang/Basic/TargetInfo.h | 4 +- include/clang/Frontend/ASTUnit.h | 20 +-- include/clang/Frontend/CompilerInstance.h | 73 +++++------ include/clang/Frontend/CompilerInvocation.h | 3 +- include/clang/Lex/Preprocessor.h | 3 +- lib/Frontend/ASTUnit.cpp | 117 ++++++++---------- lib/Frontend/CompilerInstance.cpp | 40 +++--- lib/Frontend/FrontendAction.cpp | 18 +-- .../ExecuteCompilerInvocation.cpp | 5 +- tools/libclang/CIndexCodeCompletion.cpp | 12 +- 13 files changed, 141 insertions(+), 163 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 68a12bba24..9e3d10f63b 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -28,6 +28,7 @@ #include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" @@ -78,7 +79,7 @@ namespace clang { /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. -class ASTContext { +class ASTContext : public llvm::RefCountedBase { ASTContext &this_() { return *this; } mutable std::vector Types; diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 465f856f94..2ca344d553 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_FILEMANAGER_H #include "clang/Basic/FileSystemOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -105,7 +106,7 @@ public: /// properties, such as uniquing files based on "inode", so that a file with two /// names (e.g. symlinked) will be treated as a single file. /// -class FileManager { +class FileManager : public llvm::RefCountedBase { FileSystemOptions FileSystemOpts; class UniqueDirContainer; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 799ee3438f..4c8a805538 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -19,6 +19,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/DenseMap.h" #include #include @@ -378,7 +379,7 @@ public: /// user's view. In the case of a macro expansion, for example, the spelling /// location indicates where the expanded token came from and the instantiation /// location specifies where it was expanded. -class SourceManager { +class SourceManager : public llvm::RefCountedBase { /// \brief Diagnostic object. Diagnostic &Diag; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index fd9e373b73..af5fd5598a 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_BASIC_TARGETINFO_H #define LLVM_CLANG_BASIC_TARGETINFO_H -// FIXME: Daniel isn't smart enough to use a prototype for this. +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" @@ -57,7 +57,7 @@ enum TargetCXXABI { /// TargetInfo - This class exposes information about the current target. /// -class TargetInfo { +class TargetInfo : public llvm::RefCountedBase { llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index a0c99f12e9..57c59d951e 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -71,12 +71,12 @@ public: private: llvm::IntrusiveRefCntPtr Diagnostics; - llvm::OwningPtr FileMgr; - llvm::OwningPtr SourceMgr; + llvm::IntrusiveRefCntPtr FileMgr; + llvm::IntrusiveRefCntPtr SourceMgr; llvm::OwningPtr HeaderInfo; - llvm::OwningPtr Target; - llvm::OwningPtr PP; - llvm::OwningPtr Ctx; + llvm::IntrusiveRefCntPtr Target; + llvm::IntrusiveRefCntPtr PP; + llvm::IntrusiveRefCntPtr Ctx; FileSystemOptions FileSystemOpts; @@ -90,7 +90,7 @@ private: /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. - llvm::OwningPtr Invocation; + llvm::IntrusiveRefCntPtr Invocation; /// \brief The set of target features. /// @@ -396,11 +396,11 @@ public: const SourceManager &getSourceManager() const { return *SourceMgr; } SourceManager &getSourceManager() { return *SourceMgr; } - const Preprocessor &getPreprocessor() const { return *PP.get(); } - Preprocessor &getPreprocessor() { return *PP.get(); } + const Preprocessor &getPreprocessor() const { return *PP; } + Preprocessor &getPreprocessor() { return *PP; } - const ASTContext &getASTContext() const { return *Ctx.get(); } - ASTContext &getASTContext() { return *Ctx.get(); } + const ASTContext &getASTContext() const { return *Ctx; } + ASTContext &getASTContext() { return *Ctx; } bool hasSema() const { return TheSema; } Sema &getSema() const { diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 7ea79e5599..2c37c9568e 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -59,25 +59,25 @@ class TargetInfo; /// and a long form that takes explicit instances of any required objects. class CompilerInstance { /// The options used in this compiler instance. - llvm::OwningPtr Invocation; + llvm::IntrusiveRefCntPtr Invocation; /// The diagnostics engine instance. llvm::IntrusiveRefCntPtr Diagnostics; /// The target being compiled for. - llvm::OwningPtr Target; + llvm::IntrusiveRefCntPtr Target; /// The file manager. - llvm::OwningPtr FileMgr; + llvm::IntrusiveRefCntPtr FileMgr; /// The source manager. - llvm::OwningPtr SourceMgr; + llvm::IntrusiveRefCntPtr SourceMgr; /// The preprocessor. - llvm::OwningPtr PP; + llvm::IntrusiveRefCntPtr PP; /// The AST context. - llvm::OwningPtr Context; + llvm::IntrusiveRefCntPtr Context; /// The AST consumer. llvm::OwningPtr Consumer; @@ -161,10 +161,7 @@ public: return *Invocation; } - CompilerInvocation *takeInvocation() { return Invocation.take(); } - - /// setInvocation - Replace the current invocation; the compiler instance - /// takes ownership of \arg Value. + /// setInvocation - Replace the current invocation. void setInvocation(CompilerInvocation *Value); /// } @@ -251,13 +248,13 @@ public: bool hasDiagnostics() const { return Diagnostics != 0; } + /// Get the current diagnostics engine. Diagnostic &getDiagnostics() const { assert(Diagnostics && "Compiler instance has no diagnostics!"); return *Diagnostics; } - /// setDiagnostics - Replace the current diagnostics engine; the compiler - /// instance takes ownership of \arg Value. + /// setDiagnostics - Replace the current diagnostics engine. void setDiagnostics(Diagnostic *Value); DiagnosticClient &getDiagnosticClient() const { @@ -277,12 +274,7 @@ public: return *Target; } - /// takeTarget - Remove the current diagnostics engine and give ownership - /// to the caller. - TargetInfo *takeTarget() { return Target.take(); } - - /// setTarget - Replace the current diagnostics engine; the compiler - /// instance takes ownership of \arg Value. + /// Replace the current diagnostics engine. void setTarget(TargetInfo *Value); /// } @@ -291,17 +283,17 @@ public: bool hasFileManager() const { return FileMgr != 0; } + /// Return the current file manager to the caller. FileManager &getFileManager() const { assert(FileMgr && "Compiler instance has no file manager!"); return *FileMgr; } + + void resetAndLeakFileManager() { + FileMgr.resetWithoutRelease(); + } - /// takeFileManager - Remove the current file manager and give ownership to - /// the caller. - FileManager *takeFileManager() { return FileMgr.take(); } - - /// setFileManager - Replace the current file manager; the compiler instance - /// takes ownership of \arg Value. + /// setFileManager - Replace the current file manager. void setFileManager(FileManager *Value); /// } @@ -310,17 +302,17 @@ public: bool hasSourceManager() const { return SourceMgr != 0; } + /// Return the current source manager. SourceManager &getSourceManager() const { assert(SourceMgr && "Compiler instance has no source manager!"); return *SourceMgr; } + + void resetAndLeakSourceManager() { + SourceMgr.resetWithoutRelease(); + } - /// takeSourceManager - Remove the current source manager and give ownership - /// to the caller. - SourceManager *takeSourceManager() { return SourceMgr.take(); } - - /// setSourceManager - Replace the current source manager; the compiler - /// instance takes ownership of \arg Value. + /// setSourceManager - Replace the current source manager. void setSourceManager(SourceManager *Value); /// } @@ -329,17 +321,17 @@ public: bool hasPreprocessor() const { return PP != 0; } + /// Return the current preprocessor. Preprocessor &getPreprocessor() const { assert(PP && "Compiler instance has no preprocessor!"); return *PP; } - /// takePreprocessor - Remove the current preprocessor and give ownership to - /// the caller. - Preprocessor *takePreprocessor() { return PP.take(); } + void resetAndLeakPreprocessor() { + PP.resetWithoutRelease(); + } - /// setPreprocessor - Replace the current preprocessor; the compiler instance - /// takes ownership of \arg Value. + /// Replace the current preprocessor. void setPreprocessor(Preprocessor *Value); /// } @@ -352,13 +344,12 @@ public: assert(Context && "Compiler instance has no AST context!"); return *Context; } + + void resetAndLeakASTContext() { + Context.resetWithoutRelease(); + } - /// takeASTContext - Remove the current AST context and give ownership to the - /// caller. - ASTContext *takeASTContext() { return Context.take(); } - - /// setASTContext - Replace the current AST context; the compiler instance - /// takes ownership of \arg Value. + /// setASTContext - Replace the current AST context. void setASTContext(ASTContext *Value); /// \brief Replace the current Sema; the compiler instance takes ownership diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index e0329dbc96..e18f3fe632 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -22,6 +22,7 @@ #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/PreprocessorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" #include @@ -41,7 +42,7 @@ class Diagnostic; /// This class is designed to represent an abstract "invocation" of the /// compiler, including data such as the include paths, the code generation /// options, the warning flags, and so on. -class CompilerInvocation { +class CompilerInvocation : public llvm::RefCountedBase { /// Options controlling the static analyzer. AnalyzerOptions AnalyzerOpts; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 5dc13eb4ea..04b3e3224f 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -25,6 +25,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -53,7 +54,7 @@ class PreprocessingRecord; /// single source file, and don't know anything about preprocessor-level issues /// like the #include stack, token expansion, etc. /// -class Preprocessor { +class Preprocessor : public llvm::RefCountedBase { Diagnostic *Diags; LangOptions Features; const TargetInfo &Target; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index afae18f7d9..4a3b5f9f62 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -121,7 +121,7 @@ ASTUnit::~ASTUnit() { // perform this operation here because we explicitly request that the // compiler instance *not* free these buffers for each invocation of the // parser. - if (Invocation.get() && OwnsRemappedFileBuffers) { + if (Invocation.getPtr() && OwnsRemappedFileBuffers) { PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); for (PreprocessorOptions::remapped_file_buffer_iterator FB = PPOpts.remapped_file_buffer_begin(), @@ -512,9 +512,9 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->Diagnostics = Diags; - AST->FileMgr.reset(new FileManager(FileSystemOpts)); - AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics(), - AST->getFileManager())); + AST->FileMgr = new FileManager(FileSystemOpts); + AST->SourceMgr = new SourceManager(AST->getDiagnostics(), + AST->getFileManager()); AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager())); for (unsigned I = 0; I != NumRemappedFiles; ++I) { @@ -602,12 +602,11 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, TargetOpts.CPU = ""; TargetOpts.Features.clear(); TargetOpts.Triple = TargetTriple; - AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(), - TargetOpts)); - AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo, - *AST->Target.get(), - AST->getSourceManager(), HeaderInfo)); - Preprocessor &PP = *AST->PP.get(); + AST->Target = TargetInfo::CreateTargetInfo(AST->getDiagnostics(), + TargetOpts); + AST->PP = new Preprocessor(AST->getDiagnostics(), LangInfo, *AST->Target, + AST->getSourceManager(), HeaderInfo); + Preprocessor &PP = *AST->PP; PP.setPredefines(Reader->getSuggestedPredefines()); PP.setCounterValue(Counter); @@ -615,14 +614,14 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, // Create and initialize the ASTContext. - AST->Ctx.reset(new ASTContext(LangInfo, - AST->getSourceManager(), - *AST->Target.get(), - PP.getIdentifierTable(), - PP.getSelectorTable(), - PP.getBuiltinInfo(), - /* size_reserve = */0)); - ASTContext &Context = *AST->Ctx.get(); + AST->Ctx = new ASTContext(LangInfo, + AST->getSourceManager(), + *AST->Target, + PP.getIdentifierTable(), + PP.getSelectorTable(), + PP.getBuiltinInfo(), + /* size_reserve = */0); + ASTContext &Context = *AST->Ctx; Reader->InitializeContext(Context); @@ -842,7 +841,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { delete SavedMainFileBuffer; SavedMainFileBuffer = 0; - if (!Invocation.get()) { + if (!Invocation) { delete OverrideMainBuffer; return true; } @@ -855,7 +854,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { CICleanup(llvm::CrashRecoveryContextCleanup:: create(Clang.get())); - Clang->setInvocation(Invocation.take()); + Clang->setInvocation(&*Invocation); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing any diagnostics that would @@ -865,7 +864,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // Create the target instance. Clang->getTargetOpts().Features = TargetFeatures; Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), - Clang->getTargetOpts())); + Clang->getTargetOpts())); if (!Clang->hasTarget()) { delete OverrideMainBuffer; return true; @@ -887,11 +886,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // Configure the various subsystems. // FIXME: Should we retain the previous file manager? FileSystemOpts = Clang->getFileSystemOpts(); - FileMgr.reset(new FileManager(FileSystemOpts)); - SourceMgr.reset(new SourceManager(getDiagnostics(), *FileMgr)); + FileMgr = new FileManager(FileSystemOpts); + SourceMgr = new SourceManager(getDiagnostics(), *FileMgr); TheSema.reset(); - Ctx.reset(); - PP.reset(); + Ctx = 0; + PP = 0; // Clear out old caches and data. TopLevelDecls.clear(); @@ -954,15 +953,14 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { Act->Execute(); - // Steal the created target, context, and preprocessor, and take back the - // source and file managers. + // Steal the created target, context, and preprocessor. TheSema.reset(Clang->takeSema()); Consumer.reset(Clang->takeASTConsumer()); - Ctx.reset(Clang->takeASTContext()); - PP.reset(Clang->takePreprocessor()); - Clang->takeSourceManager(); - Clang->takeFileManager(); - Target.reset(Clang->takeTarget()); + Ctx = &Clang->getASTContext(); + PP = &Clang->getPreprocessor(); + Clang->setSourceManager(0); + Clang->setFileManager(0); + Target = &Clang->getTarget(); Act->EndSourceFile(); @@ -973,9 +971,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude; } - Invocation.reset(Clang->takeInvocation()); return false; - + error: // Remove the overridden buffer we used for the preamble. if (OverrideMainBuffer) { @@ -987,9 +984,6 @@ error: } StoredDiagnostics.clear(); - Clang->takeSourceManager(); - Clang->takeFileManager(); - Invocation.reset(Clang->takeInvocation()); return true; } @@ -1392,13 +1386,12 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // Create the source manager. Clang->setSourceManager(new SourceManager(getDiagnostics(), - Clang->getFileManager())); + Clang->getFileManager())); llvm::OwningPtr Act; Act.reset(new PrecompilePreambleAction(*this)); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, Clang->getFrontendOpts().Inputs[0].first)) { - Clang->takeInvocation(); llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); Preamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; @@ -1409,8 +1402,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( Act->Execute(); Act->EndSourceFile(); - Clang->takeInvocation(); - + if (Diagnostics->hasErrorOccurred()) { // There were errors parsing the preamble, so no precompiled header was // generated. Forget that we even tried. @@ -1548,10 +1540,10 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI, AST.reset(new ASTUnit(false)); ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics=*/false); AST->Diagnostics = Diags; - AST->Invocation.reset(CI); + AST->Invocation = CI; AST->FileSystemOpts = CI->getFileSystemOpts(); - AST->FileMgr.reset(new FileManager(AST->FileSystemOpts)); - AST->SourceMgr.reset(new SourceManager(*Diags, *AST->FileMgr)); + AST->FileMgr = new FileManager(AST->FileSystemOpts); + AST->SourceMgr = new SourceManager(*Diags, *AST->FileMgr); return AST.take(); } @@ -1597,7 +1589,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, AST->CaptureDiagnostics = CaptureDiagnostics; AST->CompleteTranslationUnit = CompleteTranslationUnit; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; - AST->Invocation.reset(CI); + AST->Invocation = CI; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1639,7 +1631,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, llvm::SmallVector StoredDiagnostics; - llvm::OwningPtr CI; + llvm::IntrusiveRefCntPtr CI; { CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags, @@ -1679,7 +1671,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, } const driver::ArgStringList &CCArgs = Cmd->getArguments(); - CI.reset(new CompilerInvocation); + CI = new CompilerInvocation(); CompilerInvocation::CreateFromArgs(*CI, const_cast(CCArgs.data()), const_cast(CCArgs.data()) + @@ -1721,7 +1713,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); - AST->FileMgr.reset(new FileManager(AST->FileSystemOpts)); + AST->FileMgr = new FileManager(AST->FileSystemOpts); AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->CompleteTranslationUnit = CompleteTranslationUnit; @@ -1729,7 +1721,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); - AST->Invocation.reset(CI.take()); + AST->Invocation = CI; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1740,7 +1732,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, } bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { - if (!Invocation.get()) + if (!Invocation) return true; SimpleTimer ParsingTimer(WantTiming); @@ -2036,16 +2028,18 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, SourceManager &SourceMgr, FileManager &FileMgr, llvm::SmallVectorImpl &StoredDiagnostics, llvm::SmallVectorImpl &OwnedBuffers) { - if (!Invocation.get()) + if (!Invocation) return; SimpleTimer CompletionTimer(WantTiming); CompletionTimer.setOutput("Code completion @ " + File + ":" + llvm::Twine(Line) + ":" + llvm::Twine(Column)); - CompilerInvocation CCInvocation(*Invocation); - FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts(); - PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts(); + llvm::IntrusiveRefCntPtr + CCInvocation(new CompilerInvocation(*Invocation)); + + FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts(); + PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts(); FrontendOpts.ShowMacrosInCodeCompletion = IncludeMacros && CachedCompletionResults.empty(); @@ -2057,7 +2051,7 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, FrontendOpts.CodeCompletionAt.Column = Column; // Set the language options appropriately. - LangOpts = CCInvocation.getLangOpts(); + LangOpts = CCInvocation->getLangOpts(); llvm::OwningPtr Clang(new CompilerInstance()); @@ -2066,12 +2060,12 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, CICleanup(llvm::CrashRecoveryContextCleanup:: create(Clang.get())); - Clang->setInvocation(&CCInvocation); + Clang->setInvocation(&*CCInvocation); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing any diagnostics produced. Clang->setDiagnostics(&Diag); - ProcessWarningOptions(Diag, CCInvocation.getDiagnosticOpts()); + ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts()); CaptureDroppedDiagnostics Capture(true, Clang->getDiagnostics(), StoredDiagnostics); @@ -2081,7 +2075,7 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), Clang->getTargetOpts())); if (!Clang->hasTarget()) { - Clang->takeInvocation(); + Clang->setInvocation(0); return; } @@ -2140,7 +2134,7 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, if (const FileStatus *MainStatus = MainPath.getFileStatus()) if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID()) OverrideMainBuffer - = getMainBufferWithPrecompiledPreamble(CCInvocation, false, + = getMainBufferWithPrecompiledPreamble(*CCInvocation, false, Line - 1); } @@ -2182,11 +2176,6 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, Act->Execute(); Act->EndSourceFile(); } - - // Steal back our resources. - Clang->takeFileManager(); - Clang->takeSourceManager(); - Clang->takeInvocation(); } bool ASTUnit::Save(llvm::StringRef File) { diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index b47da312a1..26d40e4f80 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -47,7 +47,7 @@ CompilerInstance::~CompilerInstance() { } void CompilerInstance::setInvocation(CompilerInvocation *Value) { - Invocation.reset(Value); + Invocation = Value; } void CompilerInstance::setDiagnostics(Diagnostic *Value) { @@ -55,24 +55,20 @@ void CompilerInstance::setDiagnostics(Diagnostic *Value) { } void CompilerInstance::setTarget(TargetInfo *Value) { - Target.reset(Value); + Target = Value; } void CompilerInstance::setFileManager(FileManager *Value) { - FileMgr.reset(Value); + FileMgr = Value; } -void CompilerInstance::setSourceManager(SourceManager *Value) { - SourceMgr.reset(Value); +void CompilerInstance::setSourceManager(SourceManager *Value) { + SourceMgr = Value; } -void CompilerInstance::setPreprocessor(Preprocessor *Value) { - PP.reset(Value); -} +void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; } -void CompilerInstance::setASTContext(ASTContext *Value) { - Context.reset(Value); -} +void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; } void CompilerInstance::setSema(Sema *S) { TheSema.reset(S); @@ -145,23 +141,23 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts, // File Manager void CompilerInstance::createFileManager() { - FileMgr.reset(new FileManager(getFileSystemOpts())); + FileMgr = new FileManager(getFileSystemOpts()); } // Source Manager void CompilerInstance::createSourceManager(FileManager &FileMgr) { - SourceMgr.reset(new SourceManager(getDiagnostics(), FileMgr)); + SourceMgr = new SourceManager(getDiagnostics(), FileMgr); } // Preprocessor void CompilerInstance::createPreprocessor() { - PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(), - getPreprocessorOpts(), getHeaderSearchOpts(), - getDependencyOutputOpts(), getTarget(), - getFrontendOpts(), getSourceManager(), - getFileManager())); + PP = createPreprocessor(getDiagnostics(), getLangOpts(), + getPreprocessorOpts(), getHeaderSearchOpts(), + getDependencyOutputOpts(), getTarget(), + getFrontendOpts(), getSourceManager(), + getFileManager()); } Preprocessor * @@ -219,10 +215,10 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags, void CompilerInstance::createASTContext() { Preprocessor &PP = getPreprocessor(); - Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(), - getTarget(), PP.getIdentifierTable(), - PP.getSelectorTable(), PP.getBuiltinInfo(), - /*size_reserve=*/ 0)); + Context = new ASTContext(getLangOpts(), PP.getSourceManager(), + getTarget(), PP.getIdentifierTable(), + PP.getSelectorTable(), PP.getBuiltinInfo(), + /*size_reserve=*/ 0); } // ExternalASTSource diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 5c34e9491b..42da44c2c7 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -258,10 +258,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, // matching EndSourceFile(). failure: if (isCurrentFileAST()) { - CI.takeASTContext(); - CI.takePreprocessor(); - CI.takeSourceManager(); - CI.takeFileManager(); + CI.setASTContext(0); + CI.setPreprocessor(0); + CI.setSourceManager(0); + CI.setFileManager(0); } CI.getDiagnosticClient().EndSourceFile(); @@ -313,7 +313,7 @@ void FrontendAction::EndSourceFile() { CI.takeASTConsumer(); if (!isCurrentFileAST()) { CI.takeSema(); - CI.takeASTContext(); + CI.resetAndLeakASTContext(); } } else { if (!isCurrentFileAST()) { @@ -342,10 +342,10 @@ void FrontendAction::EndSourceFile() { if (isCurrentFileAST()) { CI.takeSema(); - CI.takeASTContext(); - CI.takePreprocessor(); - CI.takeSourceManager(); - CI.takeFileManager(); + CI.resetAndLeakASTContext(); + CI.resetAndLeakPreprocessor(); + CI.resetAndLeakSourceManager(); + CI.resetAndLeakFileManager(); } setCompilerInstance(0); diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 664b53351d..0f02f7ac61 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -149,11 +149,8 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { if (!Clang->getDiagnostics().hasErrorOccurred()) { // Create and execute the frontend action. llvm::OwningPtr Act(CreateFrontendAction(*Clang)); - if (Act) { + if (Act) Success = Clang->ExecuteAction(*Act); - if (Clang->getFrontendOpts().DisableFree) - Act.take(); - } } return Success; diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index 2b4a791b50..e85e80246f 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -216,10 +216,10 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { FileSystemOptions FileSystemOpts; /// \brief File manager, used for diagnostics. - FileManager FileMgr; + llvm::IntrusiveRefCntPtr FileMgr; /// \brief Source manager, used for diagnostics. - SourceManager SourceMgr; + llvm::IntrusiveRefCntPtr SourceMgr; /// \brief Temporary files that should be removed once we have finished /// with the code-completion results. @@ -249,8 +249,8 @@ AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults( Diag(new Diagnostic( llvm::IntrusiveRefCntPtr(new DiagnosticIDs))), FileSystemOpts(FileSystemOpts), - FileMgr(FileSystemOpts), - SourceMgr(*Diag, FileMgr) { + FileMgr(new FileManager(FileSystemOpts)), + SourceMgr(new SourceManager(*Diag, *FileMgr)) { if (getenv("LIBCLANG_OBJTRACKING")) { llvm::sys::AtomicIncrement(&CodeCompletionResultObjects); fprintf(stderr, "+++ %d completion results\n", CodeCompletionResultObjects); @@ -396,8 +396,8 @@ void clang_codeCompleteAt_Impl(void *UserData) { (options & CXCodeComplete_IncludeMacros), (options & CXCodeComplete_IncludeCodePatterns), Capture, - *Results->Diag, Results->LangOpts, Results->SourceMgr, - Results->FileMgr, Results->Diagnostics, + *Results->Diag, Results->LangOpts, *Results->SourceMgr, + *Results->FileMgr, Results->Diagnostics, Results->TemporaryBuffers); // Keep a reference to the allocator used for cached global completions, so -- 2.40.0