summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Basic/SourceManager.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Basic/SourceManager.cpp262
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);