diff options
-rw-r--r-- | include/clang/Basic/SourceManager.h | 18 | ||||
-rw-r--r-- | lib/Basic/SourceManager.cpp | 35 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 9 |
3 files changed, 54 insertions, 8 deletions
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 685e318143..bcb2d561a4 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -519,7 +519,7 @@ class SourceManager : public RefCountedBase<SourceManager> { /// /// Negative FileIDs are indexes into this table. To get from ID to an index, /// use (-ID - 2). - std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable; + mutable std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable; /// \brief The starting offset of the next local SLocEntry. /// @@ -576,6 +576,8 @@ class SourceManager : public RefCountedBase<SourceManager> { // Cache for the "fake" buffer used for error-recovery purposes. mutable llvm::MemoryBuffer *FakeBufferForRecovery; + mutable SrcMgr::ContentCache *FakeContentCacheForRecovery; + /// \brief Lazily computed map of macro argument chunks to their expanded /// source location. typedef std::map<unsigned, SourceLocation> MacroArgsMap; @@ -1260,9 +1262,9 @@ public: const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid = 0) const { assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); - if (!SLocEntryLoaded[Index]) - ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2)); - return LoadedSLocEntryTable[Index]; + if (SLocEntryLoaded[Index]) + return LoadedSLocEntryTable[Index]; + return loadSLocEntry(Index, Invalid); } const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { @@ -1313,6 +1315,9 @@ public: private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; + + const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; /// \brief Get the entry with the given unwrapped FileID. const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const { @@ -1322,8 +1327,9 @@ private: return getLocalSLocEntry(static_cast<unsigned>(ID)); } - const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const { - return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2)); + const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID, + bool *Invalid = 0) const { + return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid); } /// createExpansionLoc - Implements the common elements of storing an diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 61f4e86652..a2540bc18a 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -370,7 +370,8 @@ LineTableInfo &SourceManager::getLineTable() { SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr) : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), - NumBinaryProbes(0), FakeBufferForRecovery(0) { + NumBinaryProbes(0), FakeBufferForRecovery(0), + FakeContentCacheForRecovery(0) { clearIDTables(); Diag.setSourceManager(this); } @@ -396,6 +397,7 @@ SourceManager::~SourceManager() { } delete FakeBufferForRecovery; + delete FakeContentCacheForRecovery; for (llvm::DenseMap<FileID, MacroArgsMap *>::iterator I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) { @@ -469,6 +471,25 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { return Entry; } +const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, + bool *Invalid) const { + assert(!SLocEntryLoaded[Index]); + if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) { + if (Invalid) + *Invalid = true; + // If the file of the SLocEntry changed we could still have loaded it. + if (!SLocEntryLoaded[Index]) { + // Try to recover; create a SLocEntry so the rest of clang can handle it. + LoadedSLocEntryTable[Index] = SLocEntry::get(0, + FileInfo::get(SourceLocation(), + getFakeContentCacheForRecovery(), + SrcMgr::C_User)); + } + } + + return LoadedSLocEntryTable[Index]; +} + std::pair<int, unsigned> SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize) { @@ -491,6 +512,18 @@ const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { return FakeBufferForRecovery; } +/// \brief As part of recovering from missing or changed content, produce a +/// fake content cache. +const SrcMgr::ContentCache * +SourceManager::getFakeContentCacheForRecovery() const { + if (!FakeContentCacheForRecovery) { + FakeContentCacheForRecovery = new ContentCache(); + FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), + /*DoNotFree=*/true); + } + return FakeContentCacheForRecovery; +} + //===----------------------------------------------------------------------===// // Methods to create new FileID's and macro expansions. //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 75b5d68ce6..dde54d6b79 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -1111,6 +1111,10 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { return Failure; } + // We will detect whether a file changed and return 'Failure' for it, but + // we will also try to fail gracefully by setting up the SLocEntry. + ASTReader::ASTReadResult Result = Success; + bool OverriddenBuffer = Record[6]; std::string OrigFilename(BlobStart, BlobStart + BlobLen); @@ -1149,7 +1153,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { #endif )) { Error(diag::err_fe_pch_file_modified, Filename); - return Failure; + Result = Failure; } SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]); @@ -1193,6 +1197,9 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) { Filename); SourceMgr.overrideFileContents(File, Buffer); } + + if (Result == Failure) + return Failure; break; } |