diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Basic/SourceManager.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Basic/SourceManager.cpp | 262 |
1 files changed, 172 insertions, 90 deletions
diff --git a/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp b/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp index 73f2ae96d4a3..12b0305e707c 100644 --- a/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp @@ -95,31 +95,8 @@ void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) { Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0); } -const char *ContentCache::getInvalidBOM(StringRef BufStr) { - // If the buffer is valid, check to see if it has a UTF Byte Order Mark - // (BOM). We only support UTF-8 with and without a BOM right now. See - // http://en.wikipedia.org/wiki/Byte_order_mark for more information. - const char *InvalidBOM = - llvm::StringSwitch<const char *>(BufStr) - .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"), - "UTF-32 (BE)") - .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"), - "UTF-32 (LE)") - .StartsWith("\xFE\xFF", "UTF-16 (BE)") - .StartsWith("\xFF\xFE", "UTF-16 (LE)") - .StartsWith("\x2B\x2F\x76", "UTF-7") - .StartsWith("\xF7\x64\x4C", "UTF-1") - .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC") - .StartsWith("\x0E\xFE\xFF", "SCSU") - .StartsWith("\xFB\xEE\x28", "BOCU-1") - .StartsWith("\x84\x31\x95\x33", "GB-18030") - .Default(nullptr); - - return InvalidBOM; -} - const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, - FileManager &FM, + const SourceManager &SM, SourceLocation Loc, bool *Invalid) const { // Lazily create the Buffer for ContentCaches that wrap files. If we already @@ -157,7 +134,9 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, return Buffer.getPointer(); } - auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile); + bool isVolatile = SM.userFilesAreVolatile() && !IsSystemFile; + auto BufferOrError = + SM.getFileManager().getBufferForFile(ContentsEntry, 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 @@ -213,7 +192,20 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag, // (BOM). We only support UTF-8 with and without a BOM right now. See // http://en.wikipedia.org/wiki/Byte_order_mark for more information. StringRef BufStr = Buffer.getPointer()->getBuffer(); - const char *InvalidBOM = getInvalidBOM(BufStr); + const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr) + .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"), + "UTF-32 (BE)") + .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"), + "UTF-32 (LE)") + .StartsWith("\xFE\xFF", "UTF-16 (BE)") + .StartsWith("\xFF\xFE", "UTF-16 (LE)") + .StartsWith("\x2B\x2F\x76", "UTF-7") + .StartsWith("\xF7\x64\x4C", "UTF-1") + .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC") + .StartsWith("\x0E\xFE\xFF", "SCSU") + .StartsWith("\xFB\xEE\x28", "BOCU-1") + .StartsWith("\x84\x31\x95\x33", "GB-18030") + .Default(nullptr); if (InvalidBOM) { Diag.Report(Loc, diag::err_unsupported_bom) @@ -397,7 +389,7 @@ void SourceManager::initializeForReplay(const SourceManager &Old) { Clone->OrigEntry = Cache->OrigEntry; Clone->ContentsEntry = Cache->ContentsEntry; Clone->BufferOverridden = Cache->BufferOverridden; - Clone->IsFileVolatile = Cache->IsFileVolatile; + Clone->IsSystemFile = Cache->IsSystemFile; Clone->IsTransient = Cache->IsTransient; Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true); return Clone; @@ -446,7 +438,7 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, new (Entry) ContentCache(FileEnt); } - Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile; + Entry->IsSystemFile = isSystemFile; Entry->IsTransient = FilesAreTransient; return Entry; @@ -474,9 +466,10 @@ const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, // 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, "")); + LoadedSLocEntryTable[Index] = SLocEntry::get(0, + FileInfo::get(SourceLocation(), + getFakeContentCacheForRecovery(), + SrcMgr::C_User)); } } @@ -512,7 +505,7 @@ llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { const SrcMgr::ContentCache * SourceManager::getFakeContentCacheForRecovery() const { if (!FakeContentCacheForRecovery) { - FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>(); + FakeContentCacheForRecovery = llvm::make_unique<SrcMgr::ContentCache>(); FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), /*DoNotFree=*/true); } @@ -563,7 +556,7 @@ FileID SourceManager::getNextFileID(FileID FID) const { /// createFileID - Create a new FileID for the specified ContentCache and /// include position. This works regardless of whether the ContentCache /// corresponds to a file or some other input source. -FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename, +FileID SourceManager::createFileID(const ContentCache *File, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID, unsigned LoadedOffset) { @@ -572,14 +565,14 @@ FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename, unsigned Index = unsigned(-LoadedID) - 2; assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); assert(!SLocEntryLoaded[Index] && "FileID already loaded"); - LoadedSLocEntryTable[Index] = SLocEntry::get( - LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename)); + LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, + FileInfo::get(IncludePos, File, FileCharacter)); SLocEntryLoaded[Index] = true; return FileID::get(LoadedID); } - LocalSLocEntryTable.push_back( - SLocEntry::get(NextLocalOffset, - FileInfo::get(IncludePos, File, FileCharacter, Filename))); + LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, + FileInfo::get(IncludePos, File, + FileCharacter))); unsigned FileSize = File->getSize(); assert(NextLocalOffset + FileSize + 1 > NextLocalOffset && NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset && @@ -653,7 +646,7 @@ const llvm::MemoryBuffer * SourceManager::getMemoryBufferForFile(const FileEntry *File, bool *Invalid) { const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); assert(IR && "getOrCreateContentCache() cannot return NULL"); - return IR->getBuffer(Diag, getFileManager(), SourceLocation(), Invalid); + return IR->getBuffer(Diag, *this, SourceLocation(), Invalid); } void SourceManager::overrideFileContents(const FileEntry *SourceFile, @@ -679,19 +672,17 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile; } -const FileEntry * -SourceManager::bypassFileContentsOverride(const FileEntry &File) { - assert(isFileOverridden(&File)); - llvm::Optional<FileEntryRef> BypassFile = - FileMgr.getBypassFile(FileEntryRef(File.getName(), File)); +void SourceManager::disableFileContentsOverride(const FileEntry *File) { + if (!isFileOverridden(File)) + return; - // If the file can't be found in the FS, give up. - if (!BypassFile) - return nullptr; + const SrcMgr::ContentCache *IR = getOrCreateContentCache(File); + const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(nullptr); + const_cast<SrcMgr::ContentCache *>(IR)->ContentsEntry = IR->OrigEntry; - const FileEntry *FE = &BypassFile->getFileEntry(); - (void)getOrCreateContentCache(FE); - return FE; + assert(OverriddenFilesInfo); + OverriddenFilesInfo->OverriddenFiles.erase(File); + OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File); } void SourceManager::setFileIsTransient(const FileEntry *File) { @@ -709,7 +700,7 @@ StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const { } const llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer( - Diag, getFileManager(), SourceLocation(), &MyInvalid); + Diag, *this, SourceLocation(), &MyInvalid); if (Invalid) *Invalid = MyInvalid; @@ -1140,7 +1131,7 @@ const char *SourceManager::getCharacterData(SourceLocation SL, } const llvm::MemoryBuffer *Buffer = Entry.getFile().getContentCache()->getBuffer( - Diag, getFileManager(), SourceLocation(), &CharDataInvalid); + Diag, *this, SourceLocation(), &CharDataInvalid); if (Invalid) *Invalid = CharDataInvalid; return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); @@ -1237,7 +1228,7 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, const SourceManager &SM, bool &Invalid) { // Note that calling 'getBuffer()' may lazily page in the file. const MemoryBuffer *Buffer = - FI->getBuffer(Diag, SM.getFileManager(), SourceLocation(), &Invalid); + FI->getBuffer(Diag, SM, SourceLocation(), &Invalid); if (Invalid) return; @@ -1250,18 +1241,23 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); - const std::size_t BufLen = End - Buf; unsigned I = 0; - while (I < BufLen) { - if (Buf[I] == '\n') { - LineOffsets.push_back(I + 1); - } else if (Buf[I] == '\r') { + while (true) { + // Skip over the contents of the line. + while (Buf[I] != '\n' && Buf[I] != '\r' && Buf[I] != '\0') + ++I; + + if (Buf[I] == '\n' || Buf[I] == '\r') { // If this is \r\n, skip both characters. - if (I + 1 < BufLen && Buf[I + 1] == '\n') + if (Buf[I] == '\r' && Buf[I+1] == '\n') ++I; - LineOffsets.push_back(I + 1); + ++I; + LineOffsets.push_back(I); + } else { + // Otherwise, this is a NUL. If end of file, exit. + if (Buf+I == End) break; + ++I; } - ++I; } // Copy the offsets into the FileInfo structure. @@ -1463,7 +1459,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc, if (C->OrigEntry) Filename = C->OrigEntry->getName(); else - Filename = C->getBuffer(Diag, getFileManager())->getBufferIdentifier(); + Filename = C->getBuffer(Diag, *this)->getBufferIdentifier(); unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid); if (Invalid) @@ -1562,6 +1558,22 @@ unsigned SourceManager::getFileIDSize(FileID FID) const { // Other miscellaneous methods. //===----------------------------------------------------------------------===// +/// Retrieve the inode for the given file entry, if possible. +/// +/// This routine involves a system call, and therefore should only be used +/// in non-performance-critical code. +static Optional<llvm::sys::fs::UniqueID> +getActualFileUID(const FileEntry *File) { + if (!File) + return None; + + llvm::sys::fs::UniqueID ID; + if (llvm::sys::fs::getUniqueID(File->getName(), ID)) + return None; + + return ID; +} + /// Get the source location for the given file:line:col triplet. /// /// If the source file is included multiple times, the source location will @@ -1583,8 +1595,13 @@ SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile, FileID SourceManager::translateFile(const FileEntry *SourceFile) const { assert(SourceFile && "Null source file!"); + // Find the first file ID that corresponds to the given file. + FileID FirstFID; + // First, check the main file ID, since it is common to look for a // location in the main file. + Optional<llvm::sys::fs::UniqueID> SourceFileUID; + Optional<StringRef> SourceFileName; if (MainFileID.isValid()) { bool Invalid = false; const SLocEntry &MainSLoc = getSLocEntry(MainFileID, &Invalid); @@ -1592,35 +1609,100 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const { return FileID(); if (MainSLoc.isFile()) { - const ContentCache *MainContentCache = - MainSLoc.getFile().getContentCache(); - if (MainContentCache && MainContentCache->OrigEntry == SourceFile) - return MainFileID; + const ContentCache *MainContentCache + = MainSLoc.getFile().getContentCache(); + if (!MainContentCache || !MainContentCache->OrigEntry) { + // Can't do anything + } else if (MainContentCache->OrigEntry == SourceFile) { + FirstFID = MainFileID; + } else { + // Fall back: check whether we have the same base name and inode + // as the main file. + const FileEntry *MainFile = MainContentCache->OrigEntry; + SourceFileName = llvm::sys::path::filename(SourceFile->getName()); + if (*SourceFileName == llvm::sys::path::filename(MainFile->getName())) { + SourceFileUID = getActualFileUID(SourceFile); + if (SourceFileUID) { + if (Optional<llvm::sys::fs::UniqueID> MainFileUID = + getActualFileUID(MainFile)) { + if (*SourceFileUID == *MainFileUID) { + FirstFID = MainFileID; + SourceFile = MainFile; + } + } + } + } + } } } - // The location we're looking for isn't in the main file; look - // through all of the local source locations. - for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { - bool Invalid = false; - const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); - if (Invalid) - return FileID(); + if (FirstFID.isInvalid()) { + // The location we're looking for isn't in the main file; look + // through all of the local source locations. + for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { + bool Invalid = false; + const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid); + if (Invalid) + return FileID(); - if (SLoc.isFile() && SLoc.getFile().getContentCache() && - SLoc.getFile().getContentCache()->OrigEntry == SourceFile) - return FileID::get(I); + if (SLoc.isFile() && + SLoc.getFile().getContentCache() && + SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { + FirstFID = FileID::get(I); + break; + } + } + // If that still didn't help, try the modules. + if (FirstFID.isInvalid()) { + for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { + const SLocEntry &SLoc = getLoadedSLocEntry(I); + if (SLoc.isFile() && + SLoc.getFile().getContentCache() && + SLoc.getFile().getContentCache()->OrigEntry == SourceFile) { + FirstFID = FileID::get(-int(I) - 2); + break; + } + } + } } - // If that still didn't help, try the modules. - for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) { - const SLocEntry &SLoc = getLoadedSLocEntry(I); - if (SLoc.isFile() && SLoc.getFile().getContentCache() && - SLoc.getFile().getContentCache()->OrigEntry == SourceFile) - return FileID::get(-int(I) - 2); + // If we haven't found what we want yet, try again, but this time stat() + // each of the files in case the files have changed since we originally + // parsed the file. + if (FirstFID.isInvalid() && + (SourceFileName || + (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) && + (SourceFileUID || (SourceFileUID = getActualFileUID(SourceFile)))) { + bool Invalid = false; + for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) { + FileID IFileID; + IFileID.ID = I; + const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid); + if (Invalid) + return FileID(); + + if (SLoc.isFile()) { + const ContentCache *FileContentCache + = SLoc.getFile().getContentCache(); + const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry + : nullptr; + if (Entry && + *SourceFileName == llvm::sys::path::filename(Entry->getName())) { + if (Optional<llvm::sys::fs::UniqueID> EntryUID = + getActualFileUID(Entry)) { + if (*SourceFileUID == *EntryUID) { + FirstFID = FileID::get(I); + SourceFile = Entry; + break; + } + } + } + } + } } - return FileID(); + (void) SourceFile; + return FirstFID; } /// Get the source location in \arg FID for the given line:col. @@ -1663,13 +1745,13 @@ SourceLocation SourceManager::translateLineCol(FileID FID, } if (Line > Content->NumLines) { - unsigned Size = Content->getBuffer(Diag, getFileManager())->getBufferSize(); + unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize(); if (Size > 0) --Size; return FileLoc.getLocWithOffset(Size); } - const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, getFileManager()); + const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this); unsigned FilePos = Content->SourceLineCache[Line - 1]; const char *Buf = Buffer->getBufferStart() + FilePos; unsigned BufLength = Buffer->getBufferSize() - FilePos; @@ -1845,7 +1927,7 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const { std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID]; if (!MacroArgsCache) { - MacroArgsCache = std::make_unique<MacroArgsMap>(); + MacroArgsCache = llvm::make_unique<MacroArgsMap>(); computeMacroArgsCache(*MacroArgsCache, FID); } @@ -2174,14 +2256,14 @@ SourceManagerForFile::SourceManagerForFile(StringRef FileName, // This is passed to `SM` as reference, so the pointer has to be referenced // in `Environment` so that `FileMgr` can out-live this function scope. FileMgr = - std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem); + llvm::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem); // This is passed to `SM` as reference, so the pointer has to be referenced // by `Environment` due to the same reason above. - Diagnostics = std::make_unique<DiagnosticsEngine>( + Diagnostics = llvm::make_unique<DiagnosticsEngine>( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), new DiagnosticOptions); - SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr); - FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName), + SourceMgr = llvm::make_unique<SourceManager>(*Diagnostics, *FileMgr); + FileID ID = SourceMgr->createFileID(FileMgr->getFile(FileName), SourceLocation(), clang::SrcMgr::C_User); assert(ID.isValid()); SourceMgr->setMainFileID(ID); |
