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.cpp165
1 files changed, 125 insertions, 40 deletions
diff --git a/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp b/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
index 73f2ae96d4a3..0a76c78cd44f 100644
--- a/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
+++ b/contrib/llvm-project/clang/lib/Basic/SourceManager.cpp
@@ -17,12 +17,12 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/Compiler.h"
@@ -389,6 +389,14 @@ void SourceManager::clearIDTables() {
createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
}
+bool SourceManager::isMainFile(FileEntryRef SourceFile) {
+ assert(MainFileID.isValid() && "expected initialized SourceManager");
+ auto FE = getFileEntryRefForID(MainFileID);
+ if (!FE)
+ return false;
+ return FE->getUID() == SourceFile.getUID();
+}
+
void SourceManager::initializeForReplay(const SourceManager &Old) {
assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
@@ -560,6 +568,70 @@ FileID SourceManager::getNextFileID(FileID FID) const {
// Methods to create new FileID's and macro expansions.
//===----------------------------------------------------------------------===//
+/// Create a new FileID that represents the specified file
+/// being \#included from the specified IncludePosition.
+///
+/// This translates NULL into standard input.
+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);
+}
+
+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);
+}
+
+/// Create a new FileID that represents the specified memory buffer.
+///
+/// This does no caching of the buffer and takes ownership of the
+/// MemoryBuffer, so only pass a MemoryBuffer to this once.
+FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ SrcMgr::CharacteristicKind FileCharacter,
+ int LoadedID, unsigned LoadedOffset,
+ SourceLocation IncludeLoc) {
+ StringRef Name = Buffer->getBufferIdentifier();
+ return createFileID(
+ createMemBufferContentCache(Buffer.release(), /*DoNotFree*/ false),
+ 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,
+ SrcMgr::CharacteristicKind FileCharacter,
+ int LoadedID, unsigned LoadedOffset,
+ SourceLocation IncludeLoc) {
+ return createFileID(createMemBufferContentCache(Buffer, /*DoNotFree*/ true),
+ Buffer->getBufferIdentifier(), IncludeLoc,
+ FileCharacter, LoadedID, LoadedOffset);
+}
+
+/// Get the FileID for \p SourceFile if it exists. Otherwise, create a
+/// new FileID for the \p SourceFile.
+FileID
+SourceManager::getOrCreateFileID(const FileEntry *SourceFile,
+ SrcMgr::CharacteristicKind FileCharacter) {
+ FileID ID = translateFile(SourceFile);
+ return ID.isValid() ? ID : createFileID(SourceFile, SourceLocation(),
+ FileCharacter);
+}
+
/// 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.
@@ -577,13 +649,15 @@ FileID SourceManager::createFileID(const ContentCache *File, StringRef Filename,
SLocEntryLoaded[Index] = true;
return FileID::get(LoadedID);
}
+ unsigned FileSize = File->getSize();
+ if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
+ NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
+ Diag.Report(IncludePos, diag::err_include_too_large);
+ return FileID();
+ }
LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset,
FileInfo::get(IncludePos, File, FileCharacter, Filename)));
- unsigned FileSize = File->getSize();
- assert(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
- NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset &&
- "Ran out of source locations!");
// We do a +1 here because we want a SourceLocation that means "the end of the
// file", e.g. for the "no newline at the end of the file" diagnostic.
NextLocalOffset += FileSize + 1;
@@ -699,6 +773,18 @@ void SourceManager::setFileIsTransient(const FileEntry *File) {
const_cast<SrcMgr::ContentCache *>(CC)->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);
+}
+
StringRef SourceManager::getBufferData(FileID FID, bool *Invalid) const {
bool MyInvalid = false;
const SLocEntry &SLoc = getSLocEntry(FID, &MyInvalid);
@@ -775,11 +861,8 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
--I;
if (I->getOffset() <= SLocOffset) {
FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin()));
-
- // If this isn't an expansion, remember it. We have good locality across
- // FileID lookups.
- if (!I->isExpansion())
- LastFileIDLookup = Res;
+ // Remember it. We have good locality across FileID lookups.
+ LastFileIDLookup = Res;
NumLinearScans += NumProbes+1;
return Res;
}
@@ -796,11 +879,8 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
unsigned LessIndex = 0;
NumProbes = 0;
while (true) {
- bool Invalid = false;
unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
- unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset();
- if (Invalid)
- return FileID::get(0);
+ unsigned MidOffset = getLocalSLocEntry(MiddleIndex).getOffset();
++NumProbes;
@@ -812,15 +892,12 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
}
// If the middle index contains the value, succeed and return.
- // FIXME: This could be made faster by using a function that's aware of
- // being in the local area.
- if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
+ if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
+ SLocOffset < getLocalSLocEntry(MiddleIndex + 1).getOffset()) {
FileID Res = FileID::get(MiddleIndex);
- // If this isn't a macro expansion, remember it. We have good locality
- // across FileID lookups.
- if (!LocalSLocEntryTable[MiddleIndex].isExpansion())
- LastFileIDLookup = Res;
+ // Remember it. We have good locality across FileID lookups.
+ LastFileIDLookup = Res;
NumBinaryProbes += NumProbes;
return Res;
}
@@ -858,9 +935,7 @@ FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
const SrcMgr::SLocEntry &E = getLoadedSLocEntry(I);
if (E.getOffset() <= SLocOffset) {
FileID Res = FileID::get(-int(I) - 2);
-
- if (!E.isExpansion())
- LastFileIDLookup = Res;
+ LastFileIDLookup = Res;
NumLinearScans += NumProbes + 1;
return Res;
}
@@ -893,8 +968,7 @@ FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) {
FileID Res = FileID::get(-int(MiddleIndex) - 2);
- if (!E.isExpansion())
- LastFileIDLookup = Res;
+ LastFileIDLookup = Res;
NumBinaryProbes += NumProbes;
return Res;
}
@@ -990,6 +1064,13 @@ SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{
return Loc.getLocWithOffset(LocInfo.second);
}
+/// Return the filename of the file containing a SourceLocation.
+StringRef SourceManager::getFilename(SourceLocation SpellingLoc) const {
+ if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
+ return F->getName();
+ return StringRef();
+}
+
/// getImmediateExpansionRange - Loc is required to be an expansion location.
/// Return the start/end of the expansion information.
CharSourceRange
@@ -1602,11 +1683,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
// 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();
-
+ const SLocEntry &SLoc = getLocalSLocEntry(I);
if (SLoc.isFile() && SLoc.getFile().getContentCache() &&
SLoc.getFile().getContentCache()->OrigEntry == SourceFile)
return FileID::get(I);
@@ -1715,15 +1792,23 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
return;
if (Entry.isFile()) {
SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc();
- if (IncludeLoc.isInvalid())
+ 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>");
+ if (IncludedInFID) {
+ // Skip the files/macros of the #include'd file, we only care about
+ // macros that lexed macro arguments from our file.
+ if (Entry.getFile().NumCreatedFIDs)
+ ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/;
continue;
- if (!isInFileID(IncludeLoc, FID))
- return; // No more files/macros that may be "contained" in this file.
-
- // Skip the files/macros of the #include'd file, we only care about macros
- // that lexed macro arguments from our file.
- if (Entry.getFile().NumCreatedFIDs)
- ID += Entry.getFile().NumCreatedFIDs - 1/*because of next ++ID*/;
+ } else if (IncludeLoc.isValid()) {
+ // If file was included but not from FID, there is no more files/macros
+ // that may be "contained" in this file.
+ return;
+ }
continue;
}