aboutsummaryrefslogtreecommitdiff
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.cpp506
1 files changed, 227 insertions, 279 deletions
diff --git a/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp b/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
index 0a76c78cd44f..c0b22837693b 100644
--- a/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
@@ -49,28 +49,22 @@ using llvm::MemoryBuffer;
// SourceManager Helper Classes
//===----------------------------------------------------------------------===//
-ContentCache::~ContentCache() {
- if (shouldFreeBuffer())
- delete Buffer.getPointer();
-}
-
/// getSizeBytesMapped - Returns the number of bytes actually mapped for this
/// ContentCache. This can be 0 if the MemBuffer was not actually expanded.
unsigned ContentCache::getSizeBytesMapped() const {
- return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
+ return Buffer ? Buffer->getBufferSize() : 0;
}
/// Returns the kind of memory used to back the memory buffer for
/// this content cache. This is used for performance analysis.
llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
- assert(Buffer.getPointer());
+ assert(Buffer);
// Should be unreachable, but keep for sanity.
- if (!Buffer.getPointer())
+ if (!Buffer)
return llvm::MemoryBuffer::MemoryBuffer_Malloc;
- const llvm::MemoryBuffer *buf = Buffer.getPointer();
- return buf->getBufferKind();
+ return Buffer->getBufferKind();
}
/// getSize - Returns the size of the content encapsulated by this ContentCache.
@@ -78,21 +72,8 @@ llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind() const {
/// scratch buffer. If the ContentCache encapsulates a source file, that
/// file is not lazily brought in from disk to satisfy this query.
unsigned ContentCache::getSize() const {
- return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
- : (unsigned) ContentsEntry->getSize();
-}
-
-void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) {
- if (B && B == Buffer.getPointer()) {
- assert(0 && "Replacing with the same buffer");
- Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
- return;
- }
-
- if (shouldFreeBuffer())
- delete Buffer.getPointer();
- Buffer.setPointer(B);
- Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0);
+ return Buffer ? (unsigned)Buffer->getBufferSize()
+ : (unsigned)ContentsEntry->getSize();
}
const char *ContentCache::getInvalidBOM(StringRef BufStr) {
@@ -118,44 +99,21 @@ const char *ContentCache::getInvalidBOM(StringRef BufStr) {
return InvalidBOM;
}
-const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
- FileManager &FM,
- SourceLocation Loc,
- bool *Invalid) const {
+llvm::Optional<llvm::MemoryBufferRef>
+ContentCache::getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
+ SourceLocation Loc) const {
// Lazily create the Buffer for ContentCaches that wrap files. If we already
// computed it, just return what we have.
- if (Buffer.getPointer() || !ContentsEntry) {
- if (Invalid)
- *Invalid = isBufferInvalid();
-
- return Buffer.getPointer();
- }
-
- // Check that the file's size fits in an 'unsigned' (with room for a
- // past-the-end value). This is deeply regrettable, but various parts of
- // Clang (including elsewhere in this file!) use 'unsigned' to represent file
- // offsets, line numbers, string literal lengths, and so on, and fail
- // miserably on large source files.
- if ((uint64_t)ContentsEntry->getSize() >=
- std::numeric_limits<unsigned>::max()) {
- // We can't make a memory buffer of the required size, so just make a small
- // one. We should never hit a situation where we've already parsed to a
- // later offset of the file, so it shouldn't matter that the buffer is
- // smaller than the file.
- Buffer.setPointer(
- llvm::MemoryBuffer::getMemBuffer("", ContentsEntry->getName())
- .release());
- if (Diag.isDiagnosticInFlight())
- Diag.SetDelayedDiagnostic(diag::err_file_too_large,
- ContentsEntry->getName());
- else
- Diag.Report(Loc, diag::err_file_too_large)
- << ContentsEntry->getName();
+ if (IsBufferInvalid)
+ return None;
+ if (Buffer)
+ return Buffer->getMemBufferRef();
+ if (!ContentsEntry)
+ return None;
- Buffer.setInt(Buffer.getInt() | InvalidFlag);
- if (Invalid) *Invalid = true;
- return Buffer.getPointer();
- }
+ // Start with the assumption that the buffer is invalid to simplify early
+ // return paths.
+ IsBufferInvalid = true;
auto BufferOrError = FM.getBufferForFile(ContentsEntry, IsFileVolatile);
@@ -164,20 +122,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
// exists. Most likely, we were using a stat cache with an invalid entry but
// the file could also have been removed during processing. Since we can't
// really deal with this situation, just create an empty buffer.
- //
- // FIXME: This is definitely not ideal, but our immediate clients can't
- // currently handle returning a null entry here. Ideally we should detect
- // that we are in an inconsistent situation and error out as quickly as
- // possible.
if (!BufferOrError) {
- StringRef FillStr("<<<MISSING SOURCE FILE>>>\n");
- auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
- ContentsEntry->getSize(), "<invalid>");
- char *Ptr = BackupBuffer->getBufferStart();
- for (unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
- Ptr[i] = FillStr[i % FillStr.size()];
- Buffer.setPointer(BackupBuffer.release());
-
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
ContentsEntry->getName(),
@@ -186,17 +131,36 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
Diag.Report(Loc, diag::err_cannot_open_file)
<< ContentsEntry->getName() << BufferOrError.getError().message();
- Buffer.setInt(Buffer.getInt() | InvalidFlag);
-
- if (Invalid) *Invalid = true;
- return Buffer.getPointer();
+ return None;
}
- Buffer.setPointer(BufferOrError->release());
+ Buffer = std::move(*BufferOrError);
- // Check that the file's size is the same as in the file entry (which may
+ // Check that the file's size fits in an 'unsigned' (with room for a
+ // past-the-end value). This is deeply regrettable, but various parts of
+ // Clang (including elsewhere in this file!) use 'unsigned' to represent file
+ // offsets, line numbers, string literal lengths, and so on, and fail
+ // miserably on large source files.
+ //
+ // Note: ContentsEntry could be a named pipe, in which case
+ // ContentsEntry::getSize() could have the wrong size. Use
+ // MemoryBuffer::getBufferSize() instead.
+ if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
+ if (Diag.isDiagnosticInFlight())
+ Diag.SetDelayedDiagnostic(diag::err_file_too_large,
+ ContentsEntry->getName());
+ else
+ Diag.Report(Loc, diag::err_file_too_large)
+ << ContentsEntry->getName();
+
+ return None;
+ }
+
+ // Unless this is a named pipe (in which case we can handle a mismatch),
+ // check that the file's size is the same as in the file entry (which may
// have come from a stat cache).
- if (getRawBuffer()->getBufferSize() != (size_t)ContentsEntry->getSize()) {
+ if (!ContentsEntry->isNamedPipe() &&
+ Buffer->getBufferSize() != (size_t)ContentsEntry->getSize()) {
if (Diag.isDiagnosticInFlight())
Diag.SetDelayedDiagnostic(diag::err_file_modified,
ContentsEntry->getName());
@@ -204,27 +168,24 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(DiagnosticsEngine &Diag,
Diag.Report(Loc, diag::err_file_modified)
<< ContentsEntry->getName();
- Buffer.setInt(Buffer.getInt() | InvalidFlag);
- if (Invalid) *Invalid = true;
- return Buffer.getPointer();
+ return None;
}
// 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.
- StringRef BufStr = Buffer.getPointer()->getBuffer();
+ StringRef BufStr = Buffer->getBuffer();
const char *InvalidBOM = getInvalidBOM(BufStr);
if (InvalidBOM) {
Diag.Report(Loc, diag::err_unsupported_bom)
<< InvalidBOM << ContentsEntry->getName();
- Buffer.setInt(Buffer.getInt() | InvalidFlag);
+ return None;
}
- if (Invalid)
- *Invalid = isBufferInvalid();
-
- return Buffer.getPointer();
+ // Buffer has been validated.
+ IsBufferInvalid = false;
+ return Buffer->getMemBufferRef();
}
unsigned LineTableInfo::getLineTableFilenameID(StringRef Name) {
@@ -389,12 +350,11 @@ void SourceManager::clearIDTables() {
createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
}
-bool SourceManager::isMainFile(FileEntryRef SourceFile) {
+bool SourceManager::isMainFile(const FileEntry &SourceFile) {
assert(MainFileID.isValid() && "expected initialized SourceManager");
- auto FE = getFileEntryRefForID(MainFileID);
- if (!FE)
- return false;
- return FE->getUID() == SourceFile.getUID();
+ if (auto *FE = getFileEntryForID(MainFileID))
+ return FE->getUID() == SourceFile.getUID();
+ return false;
}
void SourceManager::initializeForReplay(const SourceManager &Old) {
@@ -407,7 +367,7 @@ void SourceManager::initializeForReplay(const SourceManager &Old) {
Clone->BufferOverridden = Cache->BufferOverridden;
Clone->IsFileVolatile = Cache->IsFileVolatile;
Clone->IsTransient = Cache->IsTransient;
- Clone->replaceBuffer(Cache->getRawBuffer(), /*DoNotFree*/true);
+ Clone->setUnownedBuffer(Cache->getBufferIfLoaded());
return Clone;
};
@@ -425,16 +385,12 @@ void SourceManager::initializeForReplay(const SourceManager &Old) {
}
}
-/// getOrCreateContentCache - Create or return a cached ContentCache for the
-/// specified file.
-const ContentCache *
-SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
- bool isSystemFile) {
- assert(FileEnt && "Didn't specify a file entry to use?");
-
+ContentCache &SourceManager::getOrCreateContentCache(FileEntryRef FileEnt,
+ bool isSystemFile) {
// Do we already have information about this file?
ContentCache *&Entry = FileInfos[FileEnt];
- if (Entry) return Entry;
+ if (Entry)
+ return *Entry;
// Nope, create a new Cache entry.
Entry = ContentCacheAlloc.Allocate<ContentCache>();
@@ -456,21 +412,21 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt,
Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;
Entry->IsTransient = FilesAreTransient;
+ Entry->BufferOverridden |= FileEnt.isNamedPipe();
- return Entry;
+ return *Entry;
}
/// Create a new ContentCache for the specified memory buffer.
/// This does no caching.
-const ContentCache *
-SourceManager::createMemBufferContentCache(const llvm::MemoryBuffer *Buffer,
- bool DoNotFree) {
+ContentCache &SourceManager::createMemBufferContentCache(
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
// Add a new ContentCache to the MemBufferInfos list and return it.
ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
new (Entry) ContentCache();
MemBufferInfos.push_back(Entry);
- Entry->replaceBuffer(Buffer, DoNotFree);
- return Entry;
+ Entry->setBuffer(std::move(Buffer));
+ return *Entry;
}
const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,
@@ -482,9 +438,11 @@ 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, ""));
+ if (!FakeSLocEntryForRecovery)
+ FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(SLocEntry::get(
+ 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
+ SrcMgr::C_User, "")));
+ return *FakeSLocEntryForRecovery;
}
}
@@ -507,24 +465,22 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
/// As part of recovering from missing or changed content, produce a
/// fake, non-empty buffer.
-llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const {
+llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery() const {
if (!FakeBufferForRecovery)
FakeBufferForRecovery =
llvm::MemoryBuffer::getMemBuffer("<<<INVALID BUFFER>>");
- return FakeBufferForRecovery.get();
+ return *FakeBufferForRecovery;
}
/// As part of recovering from missing or changed content, produce a
/// fake content cache.
-const SrcMgr::ContentCache *
-SourceManager::getFakeContentCacheForRecovery() const {
+SrcMgr::ContentCache &SourceManager::getFakeContentCacheForRecovery() const {
if (!FakeContentCacheForRecovery) {
FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
- FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
- /*DoNotFree=*/true);
+ FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
}
- return FakeContentCacheForRecovery.get();
+ return *FakeContentCacheForRecovery;
}
/// Returns the previous in-order FileID or an invalid FileID if there
@@ -576,23 +532,24 @@ FileID SourceManager::createFileID(const FileEntry *SourceFile,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
int LoadedID, unsigned LoadedOffset) {
- assert(SourceFile && "Null source file!");
- const SrcMgr::ContentCache *IR =
- getOrCreateContentCache(SourceFile, isSystem(FileCharacter));
- assert(IR && "getOrCreateContentCache() cannot return NULL");
- return createFileID(IR, SourceFile->getName(), IncludePos, FileCharacter,
- LoadedID, LoadedOffset);
+ return createFileID(SourceFile->getLastRef(), IncludePos, FileCharacter,
+ LoadedID, LoadedOffset);
}
FileID SourceManager::createFileID(FileEntryRef SourceFile,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
int LoadedID, unsigned LoadedOffset) {
- const SrcMgr::ContentCache *IR = getOrCreateContentCache(
- &SourceFile.getFileEntry(), isSystem(FileCharacter));
- assert(IR && "getOrCreateContentCache() cannot return NULL");
- return createFileID(IR, SourceFile.getName(), IncludePos, FileCharacter,
- LoadedID, LoadedOffset);
+ SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile,
+ isSystem(FileCharacter));
+
+ // If this is a named pipe, immediately load the buffer to ensure subsequent
+ // calls to ContentCache::getSize() are accurate.
+ if (IR.ContentsEntry->isNamedPipe())
+ (void)IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
+
+ return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,
+ LoadedID, LoadedOffset);
}
/// Create a new FileID that represents the specified memory buffer.
@@ -604,22 +561,20 @@ FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
int LoadedID, unsigned LoadedOffset,
SourceLocation IncludeLoc) {
StringRef Name = Buffer->getBufferIdentifier();
- return createFileID(
- createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false),
- Name, IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
+ return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
+ IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
}
/// Create a new FileID that represents the specified memory buffer.
///
/// This does not take ownership of the MemoryBuffer. The memory buffer must
/// outlive the SourceManager.
-FileID SourceManager::createFileID(UnownedTag, const llvm::MemoryBuffer *Buffer,
+FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer,
SrcMgr::CharacteristicKind FileCharacter,
int LoadedID, unsigned LoadedOffset,
SourceLocation IncludeLoc) {
- return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true),
- Buffer->getBufferIdentifier(), IncludeLoc,
- FileCharacter, LoadedID, LoadedOffset);
+ return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
+ LoadedID, LoadedOffset, IncludeLoc);
}
/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
@@ -635,10 +590,10 @@ SourceManager::getOrCreateFileID(const FileEntry *SourceFile,
/// 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,
- SourceLocation IncludePos,
- SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID, unsigned LoadedOffset) {
+FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
+ SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ int LoadedID, unsigned LoadedOffset) {
if (LoadedID < 0) {
assert(LoadedID != -1 && "Loading sentinel FileID");
unsigned Index = unsigned(-LoadedID) - 2;
@@ -649,7 +604,7 @@ FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename,
SLocEntryLoaded[Index] = true;
return FileID::get(LoadedID);
}
- unsigned FileSize = File->getSize();
+ unsigned FileSize = File.getSize();
if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
Diag.Report(IncludePos, diag::err_include_too_large);
@@ -723,21 +678,18 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
}
-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);
+llvm::Optional<llvm::MemoryBufferRef>
+SourceManager::getMemoryBufferForFileOrNone(const FileEntry *File) {
+ SrcMgr::ContentCache &IR = getOrCreateContentCache(File->getLastRef());
+ return IR.getBufferOrNone(Diag, getFileManager(), SourceLocation());
}
-void SourceManager::overrideFileContents(const FileEntry *SourceFile,
- llvm::MemoryBuffer *Buffer,
- bool DoNotFree) {
- const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
- assert(IR && "getOrCreateContentCache() cannot return NULL");
+void SourceManager::overrideFileContents(
+ const FileEntry *SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile->getLastRef());
- const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
- const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true;
+ IR.setBuffer(std::move(Buffer));
+ IR.BufferOverridden = true;
getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
}
@@ -753,56 +705,51 @@ 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));
+Optional<FileEntryRef>
+SourceManager::bypassFileContentsOverride(FileEntryRef File) {
+ assert(isFileOverridden(&File.getFileEntry()));
+ llvm::Optional<FileEntryRef> BypassFile = FileMgr.getBypassFile(File);
// If the file can't be found in the FS, give up.
if (!BypassFile)
- return nullptr;
+ return None;
- const FileEntry *FE = &BypassFile->getFileEntry();
- (void)getOrCreateContentCache(FE);
- return FE;
+ (void)getOrCreateContentCache(*BypassFile);
+ return BypassFile;
}
void SourceManager::setFileIsTransient(const FileEntry *File) {
- const SrcMgr::ContentCache *CC = getOrCreateContentCache(File);
- const_cast<SrcMgr::ContentCache *>(CC)->IsTransient = true;
+ getOrCreateContentCache(File->getLastRef()).IsTransient = true;
}
-Optional<FileEntryRef> SourceManager::getFileEntryRefForID(FileID FID) const {
- bool Invalid = false;
- const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
- if (Invalid || !Entry.isFile())
- return None;
-
- const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache();
- if (!Content || !Content->OrigEntry)
- return None;
- return FileEntryRef(Entry.getFile().getName(), *Content->OrigEntry);
+Optional<StringRef>
+SourceManager::getNonBuiltinFilenameForID(FileID FID) const {
+ if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
+ if (Entry->getFile().getContentCache().OrigEntry)
+ return Entry->getFile().getName();
+ return None;
}
StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
- bool MyInvalid = false;
- const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
- if (!SLoc.isFile() || MyInvalid) {
- if (Invalid)
- *Invalid = true;
- return "<<<<<INVALID SOURCE LOCATION>>>>>";
- }
-
- const llvm::MemoryBuffer *Buf = SLoc.getFile().getContentCache()->getBuffer(
- Diag, getFileManager(), SourceLocation(), &MyInvalid);
+ auto B = getBufferDataOrNone(FID);
if (Invalid)
- *Invalid = MyInvalid;
+ *Invalid = !B;
+ return B ? *B : "<<<<<INVALID SOURCE LOCATION>>>>>";
+}
- if (MyInvalid)
- return "<<<<<INVALID SOURCE LOCATION>>>>>";
+llvm::Optional<StringRef>
+SourceManager::getBufferDataIfLoaded(FileID FID) const {
+ if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
+ return Entry->getFile().getContentCache().getBufferDataIfLoaded();
+ return None;
+}
- return Buf->getBuffer();
+llvm::Optional<StringRef> SourceManager::getBufferDataOrNone(FileID FID) const {
+ if (const SrcMgr::SLocEntry *Entry = getSLocEntryForFile(FID))
+ if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
+ Diag, getFileManager(), SourceLocation()))
+ return B->getBuffer();
+ return None;
}
//===----------------------------------------------------------------------===//
@@ -1219,24 +1166,24 @@ const char *SourceManager::getCharacterData(SourceLocation SL,
return "<<<<INVALID BUFFER>>>>";
}
- const llvm::MemoryBuffer *Buffer =
- Entry.getFile().getContentCache()->getBuffer(
- Diag, getFileManager(), SourceLocation(), &CharDataInvalid);
+ llvm::Optional<llvm::MemoryBufferRef> Buffer =
+ Entry.getFile().getContentCache().getBufferOrNone(Diag, getFileManager(),
+ SourceLocation());
if (Invalid)
- *Invalid = CharDataInvalid;
- return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
+ *Invalid = !Buffer;
+ return Buffer ? Buffer->getBufferStart() + LocInfo.second
+ : "<<<<INVALID BUFFER>>>>";
}
/// getColumnNumber - Return the column # for the specified file position.
/// this is significantly cheaper to compute than the line number.
unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
bool *Invalid) const {
- bool MyInvalid = false;
- const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid);
+ llvm::Optional<llvm::MemoryBufferRef> MemBuf = getBufferOrNone(FID);
if (Invalid)
- *Invalid = MyInvalid;
+ *Invalid = !MemBuf;
- if (MyInvalid)
+ if (!MemBuf)
return 1;
// It is okay to request a position just past the end of the buffer.
@@ -1249,10 +1196,10 @@ unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos,
const char *Buf = MemBuf->getBufferStart();
// See if we just calculated the line number for this FilePos and can use
// that to lookup the start of the line instead of searching for it.
- if (LastLineNoFileIDQuery == FID &&
- LastLineNoContentCache->SourceLineCache != nullptr &&
- LastLineNoResult < LastLineNoContentCache->NumLines) {
- unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache;
+ if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
+ LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
+ const unsigned *SourceLineCache =
+ LastLineNoContentCache->SourceLineCache.begin();
unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
unsigned LineEnd = SourceLineCache[LastLineNoResult];
if (FilePos >= LineStart && FilePos < LineEnd) {
@@ -1309,19 +1256,8 @@ unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc,
#include <emmintrin.h>
#endif
-static LLVM_ATTRIBUTE_NOINLINE void
-ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
- llvm::BumpPtrAllocator &Alloc,
- const SourceManager &SM, bool &Invalid);
-static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
- llvm::BumpPtrAllocator &Alloc,
- 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);
- if (Invalid)
- return;
-
+LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
+ llvm::BumpPtrAllocator &Alloc) {
// Find the file offsets of all of the *physical* source lines. This does
// not look at trigraphs, escaped newlines, or anything else tricky.
SmallVector<unsigned, 256> LineOffsets;
@@ -1329,8 +1265,8 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
// Line #1 starts at char 0.
LineOffsets.push_back(0);
- const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
- const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
+ 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) {
@@ -1345,10 +1281,14 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI,
++I;
}
- // Copy the offsets into the FileInfo structure.
- FI->NumLines = LineOffsets.size();
- FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
- std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
+ return LineOffsetMapping(LineOffsets, Alloc);
+}
+
+LineOffsetMapping::LineOffsetMapping(ArrayRef<unsigned> LineOffsets,
+ llvm::BumpPtrAllocator &Alloc)
+ : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
+ Storage[0] = LineOffsets.size();
+ std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
}
/// getLineNumber - Given a SourceLocation, return the spelling line number
@@ -1363,7 +1303,7 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
return 1;
}
- ContentCache *Content;
+ const ContentCache *Content;
if (LastLineNoFileIDQuery == FID)
Content = LastLineNoContentCache;
else {
@@ -1375,26 +1315,29 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
return 1;
}
- Content = const_cast<ContentCache*>(Entry.getFile().getContentCache());
+ Content = &Entry.getFile().getContentCache();
}
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
if (!Content->SourceLineCache) {
- bool MyInvalid = false;
- ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
+ llvm::Optional<llvm::MemoryBufferRef> Buffer =
+ Content->getBufferOrNone(Diag, getFileManager(), SourceLocation());
if (Invalid)
- *Invalid = MyInvalid;
- if (MyInvalid)
+ *Invalid = !Buffer;
+ if (!Buffer)
return 1;
+
+ Content->SourceLineCache =
+ LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
} else if (Invalid)
*Invalid = false;
// Okay, we know we have a line number table. Do a binary search to find the
// line number that this character position lands on.
- unsigned *SourceLineCache = Content->SourceLineCache;
- unsigned *SourceLineCacheStart = SourceLineCache;
- unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
+ const unsigned *SourceLineCache = Content->SourceLineCache.begin();
+ const unsigned *SourceLineCacheStart = SourceLineCache;
+ const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
unsigned QueriedFilePos = FilePos+1;
@@ -1433,13 +1376,13 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos,
}
}
} else {
- if (LastLineNoResult < Content->NumLines)
+ if (LastLineNoResult < Content->SourceLineCache.size())
SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
}
}
- unsigned *Pos
- = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
+ const unsigned *Pos =
+ std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
unsigned LineNo = Pos-SourceLineCacheStart;
LastLineNoFileIDQuery = FID;
@@ -1480,12 +1423,11 @@ SrcMgr::CharacteristicKind
SourceManager::getFileCharacteristic(SourceLocation Loc) const {
assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
- bool Invalid = false;
- const SLocEntry &SEntry = getSLocEntry(LocInfo.first, &Invalid);
- if (Invalid || !SEntry.isFile())
+ const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
+ if (!SEntry)
return C_User;
- const SrcMgr::FileInfo &FI = SEntry.getFile();
+ const SrcMgr::FileInfo &FI = SEntry->getFile();
// If there are no #line directives in this file, just return the whole-file
// state.
@@ -1511,7 +1453,10 @@ StringRef SourceManager::getBufferName(SourceLocation Loc,
bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return "<invalid loc>";
- return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
+ auto B = getBufferOrNone(getFileID(Loc));
+ if (Invalid)
+ *Invalid = !B;
+ return B ? B->getBufferIdentifier() : "<invalid buffer>";
}
/// getPresumedLoc - This method returns the "presumed" location of a
@@ -1534,7 +1479,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
return PresumedLoc();
const SrcMgr::FileInfo &FI = Entry.getFile();
- const SrcMgr::ContentCache *C = FI.getContentCache();
+ const SrcMgr::ContentCache *C = &FI.getContentCache();
// To get the source name, first consult the FileEntry (if one exists)
// before the MemBuffer as this will avoid unnecessarily paging in the
@@ -1543,8 +1488,8 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
StringRef Filename;
if (C->OrigEntry)
Filename = C->OrigEntry->getName();
- else
- Filename = C->getBuffer(Diag, getFileManager())->getBufferIdentifier();
+ else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
+ Filename = Buffer->getBufferIdentifier();
unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
if (Invalid)
@@ -1603,12 +1548,11 @@ bool SourceManager::isInMainFile(SourceLocation Loc) const {
// Presumed locations are always for expansion points.
std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
- bool Invalid = false;
- const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
- if (Invalid || !Entry.isFile())
+ const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
+ if (!Entry)
return false;
- const SrcMgr::FileInfo &FI = Entry.getFile();
+ const SrcMgr::FileInfo &FI = Entry->getFile();
// Check if there is a line directive for this location.
if (FI.hasLineDirectives())
@@ -1673,9 +1617,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
return FileID();
if (MainSLoc.isFile()) {
- const ContentCache *MainContentCache =
- MainSLoc.getFile().getContentCache();
- if (MainContentCache && MainContentCache->OrigEntry == SourceFile)
+ if (MainSLoc.getFile().getContentCache().OrigEntry == SourceFile)
return MainFileID;
}
}
@@ -1684,16 +1626,16 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
// through all of the local source locations.
for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
const SLocEntry &SLoc = getLocalSLocEntry(I);
- if (SLoc.isFile() && SLoc.getFile().getContentCache() &&
- SLoc.getFile().getContentCache()->OrigEntry == SourceFile)
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache().OrigEntry == SourceFile)
return FileID::get(I);
}
// 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)
+ if (SLoc.isFile() &&
+ SLoc.getFile().getContentCache().OrigEntry == SourceFile)
return FileID::get(-int(I) - 2);
}
@@ -1725,28 +1667,25 @@ SourceLocation SourceManager::translateLineCol(FileID FID,
if (Line == 1 && Col == 1)
return FileLoc;
- ContentCache *Content
- = const_cast<ContentCache *>(Entry.getFile().getContentCache());
- if (!Content)
- return SourceLocation();
+ const ContentCache *Content = &Entry.getFile().getContentCache();
// If this is the first use of line information for this buffer, compute the
// SourceLineCache for it on demand.
- if (!Content->SourceLineCache) {
- bool MyInvalid = false;
- ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
- if (MyInvalid)
- return SourceLocation();
- }
+ llvm::Optional<llvm::MemoryBufferRef> Buffer =
+ Content->getBufferOrNone(Diag, getFileManager());
+ if (!Buffer)
+ return SourceLocation();
+ if (!Content->SourceLineCache)
+ Content->SourceLineCache =
+ LineOffsetMapping::get(*Buffer, ContentCacheAlloc);
- if (Line > Content->NumLines) {
- unsigned Size = Content->getBuffer(Diag, getFileManager())->getBufferSize();
+ if (Line > Content->SourceLineCache.size()) {
+ unsigned Size = Buffer->getBufferSize();
if (Size > 0)
--Size;
return FileLoc.getLocWithOffset(Size);
}
- const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, getFileManager());
unsigned FilePos = Content->SourceLineCache[Line - 1];
const char *Buf = Buffer->getBufferStart() + FilePos;
unsigned BufLength = Buffer->getBufferSize() - FilePos;
@@ -1791,13 +1730,18 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
if (Invalid)
return;
if (Entry.isFile()) {
- SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc();
+ auto& File = Entry.getFile();
+ if (File.getFileCharacteristic() == C_User_ModuleMap ||
+ File.getFileCharacteristic() == C_System_ModuleMap)
+ continue;
+
+ SourceLocation IncludeLoc = File.getIncludeLoc();
bool IncludedInFID =
(IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
// Predefined header doesn't have a valid include location in main
// file, but any files created by it should still be skipped when
// computing macro args expanded in the main file.
- (FID == MainFileID && Entry.getFile().Filename == "<built-in>");
+ (FID == MainFileID && Entry.getFile().getName() == "<built-in>");
if (IncludedInFID) {
// Skip the files/macros of the #include'd file, we only care about
// macros that lexed macro arguments from our file.
@@ -1936,6 +1880,11 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
assert(!MacroArgsCache->empty());
MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
+ // In case every element in MacroArgsCache is greater than Offset we can't
+ // decrement the iterator.
+ if (I == MacroArgsCache->begin())
+ return Loc;
+
--I;
unsigned MacroArgBeginOffs = I->first;
@@ -2040,8 +1989,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// If we arrived here, the location is either in a built-ins buffer or
// associated with global inline asm. PR5662 and PR22576 are examples.
- StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
- StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
+ StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
+ StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
bool LIsBuiltins = LB == "<built-in>";
bool RIsBuiltins = RB == "<built-in>";
// Sort built-in before non-built-in.
@@ -2142,7 +2091,7 @@ void SourceManager::PrintStats() const {
unsigned NumLineNumsComputed = 0;
unsigned NumFileBytesMapped = 0;
for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
- NumLineNumsComputed += I->second->SourceLineCache != nullptr;
+ NumLineNumsComputed += bool(I->second->SourceLineCache);
NumFileBytesMapped += I->second->getSizeBytesMapped();
}
unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
@@ -2172,16 +2121,15 @@ LLVM_DUMP_METHOD void SourceManager::dump() const {
<< ">\n";
if (FI.getIncludeLoc().isValid())
out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
- if (auto *CC = FI.getContentCache()) {
- out << " for " << (CC->OrigEntry ? CC->OrigEntry->getName() : "<none>")
+ auto &CC = FI.getContentCache();
+ out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "<none>")
+ << "\n";
+ if (CC.BufferOverridden)
+ out << " contents overridden\n";
+ if (CC.ContentsEntry != CC.OrigEntry) {
+ out << " contents from "
+ << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "<none>")
<< "\n";
- if (CC->BufferOverridden)
- out << " contents overridden\n";
- if (CC->ContentsEntry != CC->OrigEntry) {
- out << " contents from "
- << (CC->ContentsEntry ? CC->ContentsEntry->getName() : "<none>")
- << "\n";
- }
}
} else {
auto &EI = Entry.getExpansion();