On Oct 27, 2011, at 10:55 AM, Ted Kremenek wrote: > Author: kremenek > Date: Thu Oct 27 12:55:18 2011 > New Revision: 143115 > > URL: http://llvm.org/viewvc/llvm-project?rev=143115&view=rev > Log: > Move ASTUnit's handling of temporary files and the preamble file into a > lazily-created static DenseMap. This DenseMap is cleared (and the files > erased) via an atexit routine in the case an ASTUnit is not destroyed. Fixes > <rdar://problem/10293367>.
How about storing the preamble PCH in memory in the corresponding ASTUnit instead ? There doesn't seem to be any benefits in creating a file for it, plus we save on the I/O and the worry of cleaning up behind us. -Argyrios > > Modified: > cfe/trunk/include/clang/Frontend/ASTUnit.h > cfe/trunk/lib/Frontend/ASTUnit.cpp > cfe/trunk/test/Index/crash-recovery-code-complete.c > cfe/trunk/test/Index/crash-recovery-reparse.c > > Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=143115&r1=143114&r2=143115&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Frontend/ASTUnit.h (original) > +++ cfe/trunk/include/clang/Frontend/ASTUnit.h Thu Oct 27 12:55:18 2011 > @@ -147,10 +147,6 @@ > /// the next. > unsigned NumStoredDiagnosticsFromDriver; > > - /// \brief Temporary files that should be removed when the ASTUnit is > - /// destroyed. > - SmallVector<llvm::sys::Path, 4> TemporaryFiles; > - > /// \brief Counter that determines when we want to try building a > /// precompiled preamble. > /// > @@ -161,10 +157,7 @@ > /// building the precompiled preamble fails, we won't try again for > /// some number of calls. > unsigned PreambleRebuildCounter; > - > - /// \brief The file in which the precompiled preamble is stored. > - std::string PreambleFile; > - > + > public: > class PreambleData { > const FileEntry *File; > @@ -468,9 +461,7 @@ > /// \brief Add a temporary file that the ASTUnit depends on. > /// > /// This file will be erased when the ASTUnit is destroyed. > - void addTemporaryFile(const llvm::sys::Path &TempFile) { > - TemporaryFiles.push_back(TempFile); > - } > + void addTemporaryFile(const llvm::sys::Path &TempFile); > > bool getOnlyLocalDecls() const { return OnlyLocalDecls; } > > > Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=143115&r1=143114&r2=143115&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/ASTUnit.cpp (original) > +++ cfe/trunk/lib/Frontend/ASTUnit.cpp Thu Oct 27 12:55:18 2011 > @@ -81,6 +81,102 @@ > } > } > }; > + > + struct OnDiskData { > + /// \brief The file in which the precompiled preamble is stored. > + std::string PreambleFile; > + > + /// \brief Temporary files that should be removed when the ASTUnit is > + /// destroyed. > + SmallVector<llvm::sys::Path, 4> TemporaryFiles; > + > + /// \brief Erase temporary files. > + void CleanTemporaryFiles(); > + > + /// \brief Erase the preamble file. > + void CleanPreambleFile(); > + > + /// \brief Erase temporary files and the preamble file. > + void Cleanup(); > + }; > +} > + > +static void cleanupOnDiskMapAtExit(void); > + > +typedef llvm::DenseMap<const ASTUnit *, OnDiskData *> OnDiskDataMap; > +static OnDiskDataMap &getOnDiskDataMap() { > + static OnDiskDataMap M; > + static bool hasRegisteredAtExit = false; > + if (!hasRegisteredAtExit) { > + hasRegisteredAtExit = true; > + atexit(cleanupOnDiskMapAtExit); > + } > + return M; > +} > + > +static void cleanupOnDiskMapAtExit(void) { > + OnDiskDataMap &M = getOnDiskDataMap(); > + for (OnDiskDataMap::iterator I = M.begin(), E = M.end(); I != E; ++I) { > + // We don't worry about freeing the memory associated with OnDiskDataMap. > + // All we care about is erasing stale files. > + I->second->Cleanup(); > + } > +} > + > +static OnDiskData &getOnDiskData(const ASTUnit *AU) { > + OnDiskDataMap &M = getOnDiskDataMap(); > + OnDiskData *&D = M[AU]; > + if (!D) > + D = new OnDiskData(); > + return *D; > +} > + > +static void erasePreambleFile(const ASTUnit *AU) { > + getOnDiskData(AU).CleanPreambleFile(); > +} > + > +static void removeOnDiskEntry(const ASTUnit *AU) { > + OnDiskDataMap &M = getOnDiskDataMap(); > + OnDiskDataMap::iterator I = M.find(AU); > + if (I != M.end()) { > + I->second->Cleanup(); > + delete I->second; > + M.erase(AU); > + } > +} > + > +static void setPreambleFile(const ASTUnit *AU, llvm::StringRef preambleFile) > { > + getOnDiskData(AU).PreambleFile = preambleFile; > +} > + > +static const std::string &getPreambleFile(const ASTUnit *AU) { > + return getOnDiskData(AU).PreambleFile; > +} > + > +void OnDiskData::CleanTemporaryFiles() { > + for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) > + TemporaryFiles[I].eraseFromDisk(); > + TemporaryFiles.clear(); > +} > + > +void OnDiskData::CleanPreambleFile() { > + if (!PreambleFile.empty()) { > + llvm::sys::Path(PreambleFile).eraseFromDisk(); > + PreambleFile.clear(); > + } > +} > + > +void OnDiskData::Cleanup() { > + CleanTemporaryFiles(); > + CleanPreambleFile(); > +} > + > +void ASTUnit::CleanTemporaryFiles() { > + getOnDiskData(this).CleanTemporaryFiles(); > +} > + > +void ASTUnit::addTemporaryFile(const llvm::sys::Path &TempFile) { > + getOnDiskData(this).TemporaryFiles.push_back(TempFile); > } > > /// \brief After failing to build a precompiled preamble (due to > @@ -114,10 +210,9 @@ > } > > ASTUnit::~ASTUnit() { > - CleanTemporaryFiles(); > - if (!PreambleFile.empty()) > - llvm::sys::Path(PreambleFile).eraseFromDisk(); > - > + // Clean up the temporary files and the preamble file. > + removeOnDiskEntry(this); > + > // Free the buffers associated with remapped files. We are required to > // perform this operation here because we explicitly request that the > // compiler instance *not* free these buffers for each invocation of the > @@ -143,12 +238,6 @@ > } > } > > -void ASTUnit::CleanTemporaryFiles() { > - for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) > - TemporaryFiles[I].eraseFromDisk(); > - TemporaryFiles.clear(); > -} > - > /// \brief Determine the set of code-completion contexts in which this > /// declaration should be shown. > static unsigned getDeclShowContexts(NamedDecl *ND, > @@ -939,7 +1028,7 @@ > PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size(); > PreprocessorOpts.PrecompiledPreambleBytes.second > = > PreambleEndsAtStartOfLine; > - PreprocessorOpts.ImplicitPCHInclude = PreambleFile; > + PreprocessorOpts.ImplicitPCHInclude = getPreambleFile(this); > PreprocessorOpts.DisablePCHValidation = true; > > // The stored diagnostic has the old source manager in it; update > @@ -971,7 +1060,7 @@ > goto error; > > if (OverrideMainBuffer) { > - std::string ModName = PreambleFile; > + std::string ModName = getPreambleFile(this); > TranslateStoredDiagnostics(Clang->getModuleManager(), ModName, > getSourceManager(), PreambleDiagnostics, > StoredDiagnostics); > @@ -1172,10 +1261,7 @@ > // We couldn't find a preamble in the main source. Clear out the current > // preamble, if we have one. It's obviously no good any more. > Preamble.clear(); > - if (!PreambleFile.empty()) { > - llvm::sys::Path(PreambleFile).eraseFromDisk(); > - PreambleFile.clear(); > - } > + erasePreambleFile(this); > > // The next time we actually see a preamble, precompile it. > PreambleRebuildCounter = 1; > @@ -1281,7 +1367,7 @@ > // We can't reuse the previously-computed preamble. Build a new one. > Preamble.clear(); > PreambleDiagnostics.clear(); > - llvm::sys::Path(PreambleFile).eraseFromDisk(); > + erasePreambleFile(this); > PreambleRebuildCounter = 1; > } else if (!AllowRebuild) { > // We aren't allowed to rebuild the precompiled preamble; just > @@ -1439,7 +1525,7 @@ > StoredDiagnostics.erase(stored_diag_afterDriver_begin(), stored_diag_end()); > > // Keep track of the preamble we precompiled. > - PreambleFile = FrontendOpts.OutputFile; > + setPreambleFile(this, FrontendOpts.OutputFile); > NumWarningsInPreamble = getDiagnostics().getNumWarnings(); > > // Keep track of all of the files that the source manager knows about, > @@ -1802,7 +1888,7 @@ > // If we have a preamble file lying around, or if we might try to > // build a precompiled preamble, do so now. > llvm::MemoryBuffer *OverrideMainBuffer = 0; > - if (!PreambleFile.empty() || PreambleRebuildCounter > 0) > + if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0) > OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation); > > // Clear out the diagnostics state. > @@ -2173,7 +2259,7 @@ > // point is within the main file, after the end of the precompiled > // preamble. > llvm::MemoryBuffer *OverrideMainBuffer = 0; > - if (!PreambleFile.empty()) { > + if (!getPreambleFile(this).empty()) { > using llvm::sys::FileStatus; > llvm::sys::PathWithStatus CompleteFilePath(File); > llvm::sys::PathWithStatus MainPath(OriginalSourceFile); > @@ -2197,7 +2283,7 @@ > PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size(); > PreprocessorOpts.PrecompiledPreambleBytes.second > = > PreambleEndsAtStartOfLine; > - PreprocessorOpts.ImplicitPCHInclude = PreambleFile; > + PreprocessorOpts.ImplicitPCHInclude = getPreambleFile(this); > PreprocessorOpts.DisablePCHValidation = true; > > OwnedBuffers.push_back(OverrideMainBuffer); > @@ -2214,7 +2300,7 @@ > if (Act->BeginSourceFile(*Clang.get(), > Clang->getFrontendOpts().Inputs[0].second, > Clang->getFrontendOpts().Inputs[0].first)) { > if (OverrideMainBuffer) { > - std::string ModName = PreambleFile; > + std::string ModName = getPreambleFile(this); > TranslateStoredDiagnostics(Clang->getModuleManager(), ModName, > getSourceManager(), PreambleDiagnostics, > StoredDiagnostics); > > Modified: cfe/trunk/test/Index/crash-recovery-code-complete.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/crash-recovery-code-complete.c?rev=143115&r1=143114&r2=143115&view=diff > ============================================================================== > --- cfe/trunk/test/Index/crash-recovery-code-complete.c (original) > +++ cfe/trunk/test/Index/crash-recovery-code-complete.c Thu Oct 27 12:55:18 > 2011 > @@ -3,7 +3,7 @@ > // RUN: "-remap-file=%s;%S/Inputs/crash-recovery-code-complete-remap.c" \ > // RUN: %s 2> %t.err > // RUN: FileCheck < %t.err -check-prefix=CHECK-CODE-COMPLETE-CRASH %s > -// RUN: rm %t-preamble.pch > +// RUN: test ! -e %t-preamble.pch > // CHECK-CODE-COMPLETE-CRASH: Unable to perform code completion! > // > // REQUIRES: crash-recovery > > Modified: cfe/trunk/test/Index/crash-recovery-reparse.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/crash-recovery-reparse.c?rev=143115&r1=143114&r2=143115&view=diff > ============================================================================== > --- cfe/trunk/test/Index/crash-recovery-reparse.c (original) > +++ cfe/trunk/test/Index/crash-recovery-reparse.c Thu Oct 27 12:55:18 2011 > @@ -3,7 +3,7 @@ > // RUN: -remap-file="%s;%S/Inputs/crash-recovery-reparse-remap.c" \ > // RUN: %s 2> %t.err > // RUN: FileCheck < %t.err -check-prefix=CHECK-REPARSE-SOURCE-CRASH %s > -// RUN: rm %t-preamble.pch > +// RUN: test ! -e $t-preamble.pch > // CHECK-REPARSE-SOURCE-CRASH: Unable to reparse translation unit > // > // REQUIRES: crash-recovery > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
