diff options
-rw-r--r-- | include/clang/Basic/FileManager.h | 3 | ||||
-rw-r--r-- | include/clang/Basic/SourceManager.h | 31 | ||||
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 15 | ||||
-rw-r--r-- | lib/Basic/FileManager.cpp | 16 | ||||
-rw-r--r-- | lib/Basic/SourceManager.cpp | 14 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 28 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 8 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 4 | ||||
-rw-r--r-- | tools/libclang/Indexing.cpp | 7 |
9 files changed, 94 insertions, 32 deletions
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index ea58e2d76a..930523f4a7 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -221,7 +221,8 @@ public: /// \brief Open the specified file as a MemoryBuffer, returning a new /// MemoryBuffer if successful, otherwise returning null. llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry, - std::string *ErrorStr = 0); + std::string *ErrorStr = 0, + bool isVolatile = false); llvm::MemoryBuffer *getBufferForFile(StringRef Filename, std::string *ErrorStr = 0); diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 415b017b73..082cbb1fb1 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -128,14 +128,20 @@ namespace SrcMgr { /// When true, the original entry may be a virtual file that does not /// exist. unsigned BufferOverridden : 1; + + /// \brief True if this content cache was initially created for a source + /// file considered as a system one. + unsigned IsSystemFile : 1; ContentCache(const FileEntry *Ent = 0) : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent), - SourceLineCache(0), NumLines(0), BufferOverridden(false) {} + SourceLineCache(0), NumLines(0), BufferOverridden(false), + IsSystemFile(false) {} ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), - SourceLineCache(0), NumLines(0), BufferOverridden(false) {} + SourceLineCache(0), NumLines(0), BufferOverridden(false), + IsSystemFile(false) {} ~ContentCache(); @@ -143,7 +149,8 @@ namespace SrcMgr { /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory /// is not transferred, so this is a logical error. ContentCache(const ContentCache &RHS) - : Buffer(0, false), SourceLineCache(0), BufferOverridden(false) + : Buffer(0, false), SourceLineCache(0), BufferOverridden(false), + IsSystemFile(false) { OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; @@ -534,6 +541,10 @@ class SourceManager : public RefCountedBase<SourceManager> { /// files, should report the original file name. Defaults to true. bool OverridenFilesKeepOriginalName; + /// \brief True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). Defaults to false. + bool UserFilesAreVolatile; + struct OverriddenFilesInfoTy { /// \brief Files that have been overriden with the contents from another /// file. @@ -639,7 +650,8 @@ class SourceManager : public RefCountedBase<SourceManager> { explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); public: - SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr); + SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, + bool UserFilesAreVolatile = false); ~SourceManager(); void clearIDTables(); @@ -654,6 +666,10 @@ public: OverridenFilesKeepOriginalName = value; } + /// \brief True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). + bool userFilesAreVolatile() const { return UserFilesAreVolatile; } + /// \brief Create the FileID for a memory buffer that will represent the /// FileID for the main source. /// @@ -706,7 +722,9 @@ public: FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID = 0, unsigned LoadedOffset = 0) { - const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); + const SrcMgr::ContentCache * + IR = getOrCreateContentCache(SourceFile, + /*isSystemFile=*/FileCharacter != SrcMgr::C_User); assert(IR && "getOrCreateContentCache() cannot return NULL"); return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset); } @@ -1519,7 +1537,8 @@ private: int LoadedID, unsigned LoadedOffset); const SrcMgr::ContentCache * - getOrCreateContentCache(const FileEntry *SourceFile); + getOrCreateContentCache(const FileEntry *SourceFile, + bool isSystemFile = false); /// \brief Create a new ContentCache for the specified memory buffer. const SrcMgr::ContentCache* diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index afaf60e89a..8dd863e304 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -254,6 +254,10 @@ private: /// \brief Whether to include brief documentation within the set of code /// completions cached. bool IncludeBriefCommentsInCodeCompletion : 1; + + /// \brief True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). + bool UserFilesAreVolatile : 1; /// \brief The language options used when we load an AST file. LangOptions ASTFileLangOpts; @@ -619,7 +623,8 @@ public: /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. static ASTUnit *create(CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics, + bool UserFilesAreVolatile); /// \brief Create a ASTUnit from an AST file. /// @@ -636,7 +641,8 @@ public: RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, bool CaptureDiagnostics = false, - bool AllowPCHWithCompilerErrors = false); + bool AllowPCHWithCompilerErrors = false, + bool UserFilesAreVolatile = false); private: /// \brief Helper function for \c LoadFromCompilerInvocation() and @@ -687,6 +693,7 @@ public: bool PrecompilePreamble = false, bool CacheCodeCompletionResults = false, bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false, OwningPtr<ASTUnit> *ErrAST = 0); /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a @@ -707,7 +714,8 @@ public: bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, bool CacheCodeCompletionResults = false, - bool IncludeBriefCommentsInCodeCompletion = false); + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -742,6 +750,7 @@ public: bool IncludeBriefCommentsInCodeCompletion = false, bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, + bool UserFilesAreVolatile = false, OwningPtr<ASTUnit> *ErrAST = 0); /// \brief Reparse the source files using the same command-line options that diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index ddf8934b62..b921f3e0d9 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -488,15 +488,21 @@ void FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const { } llvm::MemoryBuffer *FileManager:: -getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { +getBufferForFile(const FileEntry *Entry, std::string *ErrorStr, + bool isVolatile) { OwningPtr<llvm::MemoryBuffer> Result; llvm::error_code ec; + uint64_t FileSize = Entry->getSize(); + // If there's a high enough chance that the file have changed since we + // got its size, force a stat before opening it. + if (isVolatile) + FileSize = -1; + const char *Filename = Entry->getName(); // If the file is already open, use the open file descriptor. if (Entry->FD != -1) { - ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, - Entry->getSize()); + ec = llvm::MemoryBuffer::getOpenFile(Entry->FD, Filename, Result, FileSize); if (ErrorStr) *ErrorStr = ec.message(); @@ -508,7 +514,7 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { // Otherwise, open the file. if (FileSystemOpts.WorkingDir.empty()) { - ec = llvm::MemoryBuffer::getFile(Filename, Result, Entry->getSize()); + ec = llvm::MemoryBuffer::getFile(Filename, Result, FileSize); if (ec && ErrorStr) *ErrorStr = ec.message(); return Result.take(); @@ -516,7 +522,7 @@ getBufferForFile(const FileEntry *Entry, std::string *ErrorStr) { SmallString<128> FilePath(Entry->getName()); FixupRelativePath(FilePath); - ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, Entry->getSize()); + ec = llvm::MemoryBuffer::getFile(FilePath.str(), Result, FileSize); if (ec && ErrorStr) *ErrorStr = ec.message(); return Result.take(); diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 5dc100a07a..9ec2474299 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -97,7 +97,10 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, } std::string ErrorStr; - Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, &ErrorStr)); + bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile; + Buffer.setPointer(SM.getFileManager().getBufferForFile(ContentsEntry, + &ErrorStr, + isVolatile)); // If we were unable to open the file, then we are in an inconsistent // situation where the content cache referenced a file which no longer @@ -367,8 +370,10 @@ LineTableInfo &SourceManager::getLineTable() { // Private 'Create' methods. //===----------------------------------------------------------------------===// -SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr) +SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, + bool UserFilesAreVolatile) : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), + UserFilesAreVolatile(UserFilesAreVolatile), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), NumBinaryProbes(0), FakeBufferForRecovery(0), FakeContentCacheForRecovery(0) { @@ -426,7 +431,8 @@ void SourceManager::clearIDTables() { /// getOrCreateContentCache - Create or return a cached ContentCache for the /// specified file. const ContentCache * -SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { +SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, + bool isSystemFile) { assert(FileEnt && "Didn't specify a file entry to use?"); // Do we already have information about this file? @@ -455,6 +461,8 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) { new (Entry) ContentCache(FileEnt); } + Entry->IsSystemFile = isSystemFile; + return Entry; } diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 7be25e96b4..ea2f773c56 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -215,7 +215,7 @@ ASTUnit::ASTUnit(bool _MainFileIsAST) PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0), NumWarningsInPreamble(0), ShouldCacheCodeCompletionResults(false), - IncludeBriefCommentsInCodeCompletion(false), + IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false), CompletionCacheTopLevelHashValue(0), PreambleTopLevelHashValue(0), CurrentTopLevelHashValue(0), @@ -658,7 +658,8 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool CaptureDiagnostics, - bool AllowPCHWithCompilerErrors) { + bool AllowPCHWithCompilerErrors, + bool UserFilesAreVolatile) { OwningPtr<ASTUnit> AST(new ASTUnit(true)); // Recover resources if we crash before exiting this method. @@ -674,8 +675,10 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, AST->CaptureDiagnostics = CaptureDiagnostics; AST->Diagnostics = Diags; AST->FileMgr = new FileManager(FileSystemOpts); + AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->SourceMgr = new SourceManager(AST->getDiagnostics(), - AST->getFileManager()); + AST->getFileManager(), + UserFilesAreVolatile); AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(), AST->getDiagnostics(), AST->ASTFileLangOpts, @@ -1077,7 +1080,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { LangOpts = &Clang->getLangOpts(); FileSystemOpts = Clang->getFileSystemOpts(); FileMgr = new FileManager(FileSystemOpts); - SourceMgr = new SourceManager(getDiagnostics(), *FileMgr); + SourceMgr = new SourceManager(getDiagnostics(), *FileMgr, + UserFilesAreVolatile); TheSema.reset(); Ctx = 0; PP = 0; @@ -1665,7 +1669,8 @@ StringRef ASTUnit::getMainFileName() const { ASTUnit *ASTUnit::create(CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool CaptureDiagnostics) { + bool CaptureDiagnostics, + bool UserFilesAreVolatile) { OwningPtr<ASTUnit> AST; AST.reset(new ASTUnit(false)); ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics); @@ -1673,7 +1678,9 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI, AST->Invocation = CI; AST->FileSystemOpts = CI->getFileSystemOpts(); AST->FileMgr = new FileManager(AST->FileSystemOpts); - AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr); + AST->UserFilesAreVolatile = UserFilesAreVolatile; + AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, + UserFilesAreVolatile); return AST.take(); } @@ -1689,6 +1696,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, bool PrecompilePreamble, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, + bool UserFilesAreVolatile, OwningPtr<ASTUnit> *ErrAST) { assert(CI && "A CompilerInvocation is required"); @@ -1696,7 +1704,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, ASTUnit *AST = Unit; if (!AST) { // Create the AST unit. - OwnAST.reset(create(CI, Diags, CaptureDiagnostics)); + OwnAST.reset(create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile)); AST = OwnAST.get(); } @@ -1859,7 +1867,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, bool PrecompilePreamble, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, - bool IncludeBriefCommentsInCodeCompletion) { + bool IncludeBriefCommentsInCodeCompletion, + bool UserFilesAreVolatile) { // Create the AST unit. OwningPtr<ASTUnit> AST; AST.reset(new ASTUnit(false)); @@ -1872,6 +1881,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, AST->IncludeBriefCommentsInCodeCompletion = IncludeBriefCommentsInCodeCompletion; AST->Invocation = CI; + AST->UserFilesAreVolatile = UserFilesAreVolatile; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> @@ -1898,6 +1908,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, bool IncludeBriefCommentsInCodeCompletion, bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, + bool UserFilesAreVolatile, OwningPtr<ASTUnit> *ErrAST) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object @@ -1957,6 +1968,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; AST->IncludeBriefCommentsInCodeCompletion = IncludeBriefCommentsInCodeCompletion; + AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); AST->Invocation = CI; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 46bd55e83e..4073e32c2c 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1127,8 +1127,9 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { // This is the module's main file. IncludeLoc = getImportLocation(F); } - FileID FID = SourceMgr.createFileID(File, IncludeLoc, - (SrcMgr::CharacteristicKind)Record[2], + SrcMgr::CharacteristicKind + FileCharacter = (SrcMgr::CharacteristicKind)Record[2]; + FileID FID = SourceMgr.createFileID(File, IncludeLoc, FileCharacter, ID, BaseOffset + Record[0]); SrcMgr::FileInfo &FileInfo = const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()); @@ -1145,7 +1146,8 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { } const SrcMgr::ContentCache *ContentCache - = SourceMgr.getOrCreateContentCache(File); + = SourceMgr.getOrCreateContentCache(File, + /*isSystemFile=*/FileCharacter != SrcMgr::C_User); if (OverriddenBuffer && !ContentCache->BufferOverridden && ContentCache->ContentsEntry == ContentCache->OrigEntry) { unsigned Code = SLocEntryCursor.ReadCode(); diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 2233a1125e..de56b19931 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -2464,7 +2464,8 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, CXXIdx->getOnlyLocalDecls(), 0, 0, /*CaptureDiagnostics=*/true, - /*AllowPCHWithCompilerErrors=*/true); + /*AllowPCHWithCompilerErrors=*/true, + /*UserFilesAreVolatile=*/true); return MakeCXTranslationUnit(CXXIdx, TU); } @@ -2612,6 +2613,7 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { IncludeBriefCommentsInCodeCompletion, /*AllowPCHWithCompilerErrors=*/true, SkipFunctionBodies, + /*UserFilesAreVolatile=*/true, &ErrUnit)); if (NumErrors != Diags->getClient()->getNumErrors()) { diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 6b681340f1..8fe9c36556 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -353,7 +353,8 @@ static void clang_indexSourceFile_Impl(void *UserData) { CInvok->getDiagnosticOpts().IgnoreWarnings = true; ASTUnit *Unit = ASTUnit::create(CInvok.getPtr(), Diags, - /*CaptureDiagnostics=*/true); + /*CaptureDiagnostics=*/true, + /*UserFilesAreVolatile=*/true); OwningPtr<CXTUOwner> CXTU(new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit))); // Recover resources if we crash before exiting this method. @@ -396,7 +397,9 @@ static void clang_indexSourceFile_Impl(void *UserData) { OnlyLocalDecls, /*CaptureDiagnostics=*/true, PrecompilePreamble, - CacheCodeCompletionResults); + CacheCodeCompletionResults, + /*IncludeBriefCommentsInCodeCompletion=*/false, + /*UserFilesAreVolatile=*/true); if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics()) printDiagsToStderr(Unit); |