19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/Capacity.h"
28#include "llvm/Support/Compiler.h"
29#include "llvm/Support/Endian.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/FileSystem.h"
32#include "llvm/Support/MathExtras.h"
33#include "llvm/Support/MemoryBuffer.h"
34#include "llvm/Support/Path.h"
35#include "llvm/Support/raw_ostream.h"
47using namespace SrcMgr;
48using llvm::MemoryBuffer;
50#define DEBUG_TYPE "source-manager"
54STATISTIC(MaxUsedSLocBytes,
"Maximum number of bytes used by source locations "
55 "(both loaded and local).");
64 return Buffer ? Buffer->getBufferSize() : 0;
70 if (Buffer ==
nullptr) {
71 assert(0 &&
"Buffer should never be null");
72 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
74 return Buffer->getBufferKind();
82 return Buffer ? (
unsigned)Buffer->getBufferSize()
90 const char *InvalidBOM =
91 llvm::StringSwitch<const char *>(BufStr)
92 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
94 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
96 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
97 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
98 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
99 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
100 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
101 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
102 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
103 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
109std::optional<llvm::MemoryBufferRef>
117 return Buffer->getMemBufferRef();
132 if (!BufferOrError) {
133 if (
Diag.isDiagnosticInFlight())
134 Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
136 BufferOrError.getError().message());
138 Diag.Report(
Loc, diag::err_cannot_open_file)
144 Buffer = std::move(*BufferOrError);
155 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
156 if (
Diag.isDiagnosticInFlight())
157 Diag.SetDelayedDiagnostic(diag::err_file_too_large,
160 Diag.Report(
Loc, diag::err_file_too_large)
171 if (
Diag.isDiagnosticInFlight())
172 Diag.SetDelayedDiagnostic(diag::err_file_modified,
175 Diag.Report(
Loc, diag::err_file_modified)
184 StringRef BufStr = Buffer->getBuffer();
188 Diag.Report(
Loc, diag::err_unsupported_bom)
195 return Buffer->getMemBufferRef();
199 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
201 FilenamesByID.push_back(&*IterBool.first);
202 return IterBool.first->second;
212 int FilenameID,
unsigned EntryExit,
214 std::vector<LineEntry> &Entries = LineEntries[FID];
216 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
217 "Adding line entries out of order!");
219 unsigned IncludeOffset = 0;
220 if (EntryExit == 1) {
222 IncludeOffset = Offset-1;
224 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();
225 if (EntryExit == 2) {
227 assert(PrevEntry && PrevEntry->IncludeOffset &&
228 "PPDirectives should have caught case when popping empty include "
230 PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset);
233 IncludeOffset = PrevEntry->IncludeOffset;
234 if (FilenameID == -1) {
237 FilenameID = PrevEntry->FilenameID;
242 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
250 const std::vector<LineEntry> &Entries = LineEntries[FID];
251 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
255 if (Entries.back().FileOffset <= Offset)
256 return &Entries.back();
259 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
260 if (I == Entries.begin())
268 const std::vector<LineEntry> &Entries) {
269 LineEntries[FID] = Entries;
274 return getLineTable().getLineTableFilenameID(Name);
281 int FilenameID,
bool IsFileEntry,
284 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
296 (void) getLineTable();
298 unsigned EntryExit = 0;
304 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
305 EntryExit, FileKind);
319 bool UserFilesAreVolatile)
320 :
Diag(
Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
329 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
330 if (MemBufferInfos[i]) {
331 MemBufferInfos[i]->~ContentCache();
332 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
335 for (
auto I = FileInfos.begin(),
E = FileInfos.end(); I !=
E; ++I) {
337 I->second->~ContentCache();
338 ContentCacheAlloc.Deallocate(I->second);
345 LocalSLocEntryTable.clear();
346 LoadedSLocEntryTable.clear();
347 SLocEntryLoaded.clear();
348 SLocEntryOffsetLoaded.clear();
349 LastLineNoFileIDQuery =
FileID();
350 LastLineNoContentCache =
nullptr;
351 LastFileIDLookup =
FileID();
358 CurrentLoadedOffset = MaxLoadedOffset;
363 assert(MainFileID.
isValid() &&
"expected initialized SourceManager");
365 return FE->getUID() == SourceFile.
getUID();
370 assert(MainFileID.
isInvalid() &&
"expected uninitialized SourceManager");
375 Clone->ContentsEntry =
Cache->ContentsEntry;
376 Clone->BufferOverridden =
Cache->BufferOverridden;
377 Clone->IsFileVolatile =
Cache->IsFileVolatile;
378 Clone->IsTransient =
Cache->IsTransient;
379 Clone->setUnownedBuffer(
Cache->getBufferIfLoaded());
384 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
385 if (!Old.SLocEntryLoaded[I])
386 Old.loadSLocEntry(I,
nullptr);
389 for (
auto &
FileInfo : Old.FileInfos) {
393 Slot = CloneContentCache(
FileInfo.second);
407 if (OverriddenFilesInfo) {
410 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
411 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
414 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
430ContentCache &SourceManager::createMemBufferContentCache(
431 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
435 MemBufferInfos.push_back(Entry);
446 assert(!SLocEntryLoaded[Index]);
447 if (ExternalSLocEntries->
ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
451 if (!SLocEntryLoaded[Index]) {
453 if (!FakeSLocEntryForRecovery)
454 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
457 return *FakeSLocEntryForRecovery;
461 return LoadedSLocEntryTable[Index];
464std::pair<int, SourceLocation::UIntTy>
467 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
469 if (CurrentLoadedOffset < TotalSize ||
470 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
471 return std::make_pair(0, 0);
473 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
474 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
475 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
476 CurrentLoadedOffset -= TotalSize;
477 updateSlocUsageStats();
478 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
479 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
480 return std::make_pair(BaseID, CurrentLoadedOffset);
485llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
486 if (!FakeBufferForRecovery)
487 FakeBufferForRecovery =
488 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
490 return *FakeBufferForRecovery;
496 if (!FakeContentCacheForRecovery) {
497 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
498 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
500 return *FakeContentCacheForRecovery;
505FileID SourceManager::getPreviousFileID(
FileID FID)
const {
516 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
520 return FileID::get(ID-1);
533 }
else if (ID+1 >= -1) {
537 return FileID::get(ID+1);
559 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
560 LoadedID, LoadedOffset);
572 StringRef Name = Buffer->getBufferIdentifier();
573 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
574 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
586 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
587 LoadedID, LoadedOffset, IncludeLoc);
609 assert(LoadedID != -1 &&
"Loading sentinel FileID");
610 unsigned Index =
unsigned(-LoadedID) - 2;
611 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
612 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
615 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
616 return FileID::get(LoadedID);
618 unsigned FileSize =
File.getSize();
619 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
620 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
621 Diag.
Report(IncludePos, diag::err_sloc_space_too_large);
625 LocalSLocEntryTable.push_back(
630 NextLocalOffset += FileSize + 1;
631 updateSlocUsageStats();
635 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
636 return LastFileIDLookup = FID;
643 return createExpansionLocImpl(Info, Length);
649 bool ExpansionIsTokenRange,
int LoadedID,
652 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
653 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
660 "token spans multiple files");
661 return createExpansionLocImpl(
663 TokenEnd.getOffset() - TokenStart.getOffset());
667SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
668 unsigned Length,
int LoadedID,
671 assert(LoadedID != -1 &&
"Loading sentinel FileID");
672 unsigned Index =
unsigned(-LoadedID) - 2;
673 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
674 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
676 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
677 return SourceLocation::getMacroLoc(LoadedOffset);
679 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
680 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
681 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
688 llvm::report_fatal_error(
"ran out of source locations");
691 NextLocalOffset += Length + 1;
692 updateSlocUsageStats();
693 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
696std::optional<llvm::MemoryBufferRef>
703 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
709 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
715 "Different sizes, use the FileManager to create a virtual file with "
717 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
718 "This function should be called at the initialization stage, before "
719 "any parsing occurs.");
721 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
722 std::make_pair(SourceFile, NewFile));
724 Pair.first->second = NewFile;
736 (void)getOrCreateContentCache(*BypassFile);
744std::optional<StringRef>
747 if (Entry->getFile().getContentCache().
OrigEntry)
748 return Entry->getFile().getName();
756 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
759std::optional<StringRef>
770 return B->getBuffer();
785 return FileID::get(0);
789 if (SLocOffset < NextLocalOffset)
790 return getFileIDLocal(SLocOffset);
791 return getFileIDLoaded(SLocOffset);
799 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
816 unsigned LessIndex = 0;
818 unsigned GreaterIndex = LocalSLocEntryTable.size();
819 if (LastFileIDLookup.ID >= 0) {
821 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
822 LessIndex = LastFileIDLookup.ID;
824 GreaterIndex = LastFileIDLookup.ID;
828 unsigned NumProbes = 0;
831 assert(GreaterIndex < LocalSLocEntryTable.size());
832 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
833 FileID Res = FileID::get(
int(GreaterIndex));
835 LastFileIDLookup = Res;
836 NumLinearScans += NumProbes+1;
839 if (++NumProbes == 8)
845 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
853 if (MidOffset > SLocOffset) {
854 GreaterIndex = MiddleIndex;
859 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
861 FileID Res = FileID::get(MiddleIndex);
864 LastFileIDLookup = Res;
865 NumBinaryProbes += NumProbes;
870 LessIndex = MiddleIndex;
879 if (SLocOffset < CurrentLoadedOffset) {
880 assert(0 &&
"Invalid SLocOffset or bad function choice");
884 return FileID::get(ExternalSLocEntries->
getSLocEntryID(SLocOffset));
922std::pair<FileID, unsigned>
923SourceManager::getDecomposedExpansionLocSlowCase(
930 Loc =
E->getExpansion().getExpansionLocStart();
934 Offset =
Loc.getOffset()-
E->getOffset();
937 return std::make_pair(FID, Offset);
940std::pair<FileID, unsigned>
942 unsigned Offset)
const {
947 Loc =
E->getExpansion().getSpellingLoc();
952 Offset =
Loc.getOffset()-
E->getOffset();
955 return std::make_pair(FID, Offset);
980 assert(
Loc.
isMacroID() &&
"Not a macro expansion loc!");
1037 if (DecompLoc.second > 0)
1051 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1063 *MacroBegin = ExpLoc;
1086 FileID NextFID = getNextFileID(FID);
1116 bool CharDataInvalid =
false;
1118 if (CharDataInvalid || !Entry.
isFile()) {
1122 return "<<<<INVALID BUFFER>>>>";
1124 std::optional<llvm::MemoryBufferRef> Buffer =
1129 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1130 :
"<<<<INVALID BUFFER>>>>";
1145 if (FilePos > MemBuf->getBufferSize()) {
1151 const char *Buf = MemBuf->getBufferStart();
1154 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->
SourceLineCache &&
1155 LastLineNoResult < LastLineNoContentCache->SourceLineCache.
size()) {
1156 const unsigned *SourceLineCache =
1158 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1159 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1160 if (FilePos >= LineStart && FilePos < LineEnd) {
1165 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1166 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1169 return FilePos - LineStart + 1;
1173 unsigned LineStart = FilePos;
1174 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1176 return FilePos-LineStart+1;
1181template<
typename LocType>
1217 return ((x - ~
static_cast<T>(0) / 255 * (n + 1)) & ~x &
1218 ((x & ~
static_cast<T>(0) / 255 * 127) +
1219 (~
static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1220 ~static_cast<T>(0) / 255 * 128;
1224 llvm::BumpPtrAllocator &Alloc) {
1231 LineOffsets.push_back(0);
1233 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1234 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1235 const unsigned char *Buf = Start;
1241 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1243 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1247 Buf +=
sizeof(Word);
1255 unsigned N = llvm::countr_zero(Mask) - 7;
1258 unsigned char Byte = Word;
1267 LineOffsets.push_back(Buf - Start);
1269 }
while (Buf < End -
sizeof(Word) - 1);
1275 LineOffsets.push_back(Buf - Start + 1);
1276 }
else if (*Buf ==
'\r') {
1278 if (Buf + 1 < End && Buf[1] ==
'\n') {
1281 LineOffsets.push_back(Buf - Start + 1);
1290 llvm::BumpPtrAllocator &Alloc)
1291 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.size() + 1)) {
1292 Storage[0] = LineOffsets.size();
1293 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1309 if (LastLineNoFileIDQuery == FID)
1310 Content = LastLineNoContentCache;
1312 bool MyInvalid =
false;
1313 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1314 if (MyInvalid || !Entry.
isFile()) {
1326 std::optional<llvm::MemoryBufferRef> Buffer =
1341 const unsigned *SourceLineCacheStart = SourceLineCache;
1344 unsigned QueriedFilePos = FilePos+1;
1359 if (LastLineNoFileIDQuery == FID) {
1360 if (QueriedFilePos >= LastLineNoFilePos) {
1362 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1368 if (SourceLineCache+5 < SourceLineCacheEnd) {
1369 if (SourceLineCache[5] > QueriedFilePos)
1370 SourceLineCacheEnd = SourceLineCache+5;
1371 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1372 if (SourceLineCache[10] > QueriedFilePos)
1373 SourceLineCacheEnd = SourceLineCache+10;
1374 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1375 if (SourceLineCache[20] > QueriedFilePos)
1376 SourceLineCacheEnd = SourceLineCache+20;
1381 if (LastLineNoResult < Content->SourceLineCache.size())
1382 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1386 const unsigned *Pos =
1387 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1388 unsigned LineNo = Pos-SourceLineCacheStart;
1390 LastLineNoFileIDQuery = FID;
1391 LastLineNoContentCache = Content;
1392 LastLineNoFilePos = QueriedFilePos;
1393 LastLineNoResult = LineNo;
1400 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(
Loc);
1401 return getLineNumber(LocInfo.first, LocInfo.second);
1406 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1407 return getLineNumber(LocInfo.first, LocInfo.second);
1426 assert(
Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1427 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1428 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1439 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1442 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1458 auto B = getBufferOrNone(getFileID(
Loc));
1461 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1472 bool UseLineDirectives)
const {
1476 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1489 FileID FID = LocInfo.first;
1493 else if (
auto Buffer =
C->getBufferOrNone(
Diag, getFileManager()))
1494 Filename = Buffer->getBufferIdentifier();
1496 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &
Invalid);
1499 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &
Invalid);
1508 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1511 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1513 if (Entry->FilenameID != -1) {
1514 Filename = LineTable->getFilename(Entry->FilenameID);
1517 FID = FileID::get(0);
1524 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1525 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1530 if (Entry->IncludeOffset) {
1531 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1551 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1553 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1562 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1563 if (Entry->IncludeOffset)
1578 if ((ID > 0 &&
unsigned(ID+1) == local_sloc_entry_size()))
1579 NextOffset = getNextLocalOffset();
1580 else if (ID+1 == -1)
1581 NextOffset = MaxLoadedOffset;
1583 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1585 return NextOffset - Entry.
getOffset() - 1;
1598 unsigned Col)
const {
1599 assert(SourceFile &&
"Null source file!");
1600 assert(
Line && Col &&
"Line and column should start from 1!");
1602 FileID FirstFID = translateFile(SourceFile);
1603 return translateLineCol(FirstFID,
Line, Col);
1611 assert(SourceFile &&
"Null source file!");
1615 if (MainFileID.isValid()) {
1629 for (
unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1630 const SLocEntry &SLoc = getLocalSLocEntry(I);
1633 return FileID::get(I);
1637 for (
unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1638 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1641 return FileID::get(-
int(I) - 2);
1651 unsigned Col)
const {
1654 assert(
Line && Col &&
"Line and column should start from 1!");
1669 if (
Line == 1 && Col == 1)
1676 std::optional<llvm::MemoryBufferRef> Buffer =
1685 unsigned Size = Buffer->getBufferSize();
1692 const char *Buf = Buffer->getBufferStart() + FilePos;
1693 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1700 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1712void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1724 if (
unsigned(ID) >= local_sloc_entry_size())
1726 }
else if (ID == -1) {
1741 bool IncludedInFID =
1742 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1746 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1747 if (IncludedInFID) {
1750 if (Entry.
getFile().NumCreatedFIDs)
1751 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1771 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1773 SourceLocation::getMacroLoc(Entry.
getOffset()),
1774 getFileIDSize(FileID::get(ID)));
1778void SourceManager::associateFileChunkWithMacroArgExp(
1779 MacroArgsMap &MacroArgsCache,
1783 unsigned ExpansionLength)
const {
1794 unsigned SpellRelativeOffs;
1795 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1797 const SLocEntry &Entry = getSLocEntry(SpellFID);
1799 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1803 unsigned CurrSpellLength;
1804 if (SpellFIDEndOffs < SpellEndOffs)
1805 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1807 CurrSpellLength = ExpansionLength;
1808 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1810 ExpansionLoc, CurrSpellLength);
1813 if (SpellFIDEndOffs >= SpellEndOffs)
1817 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1821 SpellRelativeOffs = 0;
1828 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1831 unsigned EndOffs = BeginOffs + ExpansionLength;
1850 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1853 MacroArgsCache[BeginOffs] = ExpansionLoc;
1854 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1857void SourceManager::updateSlocUsageStats()
const {
1859 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1860 MaxUsedSLocBytes.updateMax(UsedBytes);
1879 std::tie(FID, Offset) = getDecomposedLoc(
Loc);
1883 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1884 if (!MacroArgsCache) {
1885 MacroArgsCache = std::make_unique<MacroArgsMap>();
1886 computeMacroArgsCache(*MacroArgsCache, FID);
1889 assert(!MacroArgsCache->empty());
1890 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1893 if (I == MacroArgsCache->begin())
1900 if (MacroArgExpandedLoc.
isValid())
1906std::pair<FileID, unsigned>
1909 return std::make_pair(
FileID(), 0);
1913 using DecompTy = std::pair<FileID, unsigned>;
1914 auto InsertOp = IncludedLocMap.try_emplace(FID);
1915 DecompTy &DecompLoc = InsertOp.first->second;
1916 if (!InsertOp.second)
1930 DecompLoc = getDecomposedLoc(UpperLoc);
1936 assert(isLoadedSourceLocation(
Loc) &&
1937 "Must be a source location in a loaded PCH/Module file");
1939 auto [FID, Ignore] = getDecomposedLoc(
Loc);
1945 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1948 "The failure to find the first FileID of a "
1949 "loaded AST from a loaded source location was unexpected.");
1954 const std::pair<FileID, unsigned> &LOffs,
1955 const std::pair<FileID, unsigned> &ROffs)
const {
1957 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1960 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1961 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1964 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1965 std::greater<FileID>{});
1969 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1983 std::pair<FileID, unsigned> UpperLoc =
SM.getDecomposedIncludedLoc(
Loc.first);
1984 if (UpperLoc.first.isInvalid() ||
1985 !
SM.isInTheSameTranslationUnitImpl(UpperLoc,
Loc))
2000 enum { MagicCacheSize = 300 };
2001 IsBeforeInTUCacheKey Key(LFID, RFID);
2007 if (IBTUCache.size() < MagicCacheSize)
2008 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
2011 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2012 if (I != IBTUCache.end())
2016 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2017 return IBTUCacheOverflow;
2025 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2029 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
2030 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
2035 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2036 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2038 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2040 return InSameTU.second;
2042 return LOffs.first < ROffs.first;
2046 std::pair<FileID, unsigned> &LOffs,
2047 std::pair<FileID, unsigned> &ROffs)
const {
2049 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2050 return std::make_pair(
false,
false);
2053 if (LOffs.first == ROffs.first)
2054 return std::make_pair(
true, LOffs.second < ROffs.second);
2059 getInBeforeInTUCache(LOffs.first, ROffs.first);
2064 return std::make_pair(
2074 std::pair<FileID, unsigned> DecomposedLoc;
2077 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2081 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2084 if (LOffs.first == ROffs.first)
2086 LChild = LOffs.first;
2091 auto LIt = LChain.find(ROffs.first);
2092 if (LIt != LChain.end()) {
2094 LOffs = LIt->second.DecomposedLoc;
2095 LChild = LIt->second.ChildFID;
2104 unsigned LChildID = LChild.ID;
2105 unsigned RChildID = RChild.ID;
2106 assert(((LOffs.second != ROffs.second) ||
2107 (LChildID == 0 || RChildID == 0) ||
2108 isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
2109 getComposedLoc(RChild, 0),
nullptr)) &&
2110 "Mixed local/loaded FileIDs with same include location?");
2111 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2112 LChildID < RChildID);
2113 return std::make_pair(
2116 RChild = ROffs.first;
2122 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2123 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2125 bool LIsBuiltins = LB ==
"<built-in>";
2126 bool RIsBuiltins = RB ==
"<built-in>";
2128 if (LIsBuiltins || RIsBuiltins) {
2129 if (LIsBuiltins != RIsBuiltins)
2130 return std::make_pair(
true, LIsBuiltins);
2133 return std::make_pair(
true, LOffs.first < ROffs.first);
2136 bool LIsAsm = LB ==
"<inline asm>";
2137 bool RIsAsm = RB ==
"<inline asm>";
2139 if (LIsAsm || RIsAsm) {
2140 if (LIsAsm != RIsAsm)
2141 return std::make_pair(
true, RIsAsm);
2142 assert(LOffs.first == ROffs.first);
2143 return std::make_pair(
true,
false);
2146 bool LIsScratch = LB ==
"<scratch space>";
2147 bool RIsScratch = RB ==
"<scratch space>";
2149 if (LIsScratch || RIsScratch) {
2150 if (LIsScratch != RIsScratch)
2151 return std::make_pair(
true, LIsScratch);
2152 return std::make_pair(
true, LOffs.second < ROffs.second);
2155 llvm_unreachable(
"Unsortable locations found");
2159 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2160 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2161 <<
" mem buffers mapped.\n";
2162 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2163 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2164 <<
" bytes of capacity), " << NextLocalOffset
2165 <<
"B of SLoc address space used.\n";
2166 llvm::errs() << LoadedSLocEntryTable.size()
2167 <<
" loaded SLocEntries allocated ("
2168 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2169 <<
" bytes of capacity), "
2170 << MaxLoadedOffset - CurrentLoadedOffset
2171 <<
"B of SLoc address space used.\n";
2173 unsigned NumLineNumsComputed = 0;
2174 unsigned NumFileBytesMapped = 0;
2176 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2177 NumFileBytesMapped += I->second->getSizeBytesMapped();
2179 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2181 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2182 << NumLineNumsComputed <<
" files with line #'s computed, "
2183 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2184 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2185 << NumBinaryProbes <<
" binary.\n";
2189 llvm::raw_ostream &out = llvm::errs();
2192 std::optional<SourceLocation::UIntTy> NextStart) {
2193 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2194 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2196 out << *NextStart <<
">\n";
2199 if (Entry.isFile()) {
2200 auto &FI = Entry.getFile();
2201 if (FI.NumCreatedFIDs)
2202 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2204 if (FI.getIncludeLoc().isValid())
2205 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2206 auto &CC = FI.getContentCache();
2207 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2209 if (CC.BufferOverridden)
2210 out <<
" contents overridden\n";
2211 if (CC.ContentsEntry != CC.OrigEntry) {
2212 out <<
" contents from "
2213 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2217 auto &EI = Entry.getExpansion();
2218 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2219 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2220 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2221 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2226 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2227 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2228 ID == NumIDs - 1 ? NextLocalOffset
2229 : LocalSLocEntryTable[ID + 1].getOffset());
2232 std::optional<SourceLocation::UIntTy> NextStart;
2233 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2234 int ID = -(
int)Index - 2;
2235 if (SLocEntryLoaded[Index]) {
2236 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2237 NextStart = LoadedSLocEntryTable[Index].getOffset();
2239 NextStart = std::nullopt;
2250 unsigned Inclusions = 0;
2252 uint64_t DirectSize = 0;
2254 uint64_t TotalSize = 0;
2256 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2259 uint64_t CountedSize = 0;
2261 auto AddUsageForFileID = [&](
FileID ID) {
2264 unsigned Size = getFileIDSize(ID) + 1;
2269 FileID FileLocID = getFileID(FileStart);
2270 const FileEntry *Entry = getFileEntryForID(FileLocID);
2272 Info &EntryInfo = Usage[Entry];
2273 if (EntryInfo.Loc.isInvalid())
2274 EntryInfo.Loc = FileStart;
2275 if (ID == FileLocID) {
2276 ++EntryInfo.Inclusions;
2277 EntryInfo.DirectSize += Size;
2279 EntryInfo.TotalSize += Size;
2280 CountedSize += Size;
2284 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2285 AddUsageForFileID(FileID::get(-2 - Index));
2288 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2289 AddUsageForFileID(FileID::get(Index));
2294 auto SortedUsage = Usage.takeVector();
2295 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2296 return A.second.TotalSize > B.second.TotalSize ||
2297 (A.second.TotalSize == B.second.TotalSize &&
2298 A.second.Loc < B.second.Loc);
2300 auto SortedEnd = SortedUsage.end();
2301 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2302 SortedEnd = SortedUsage.begin() + *MaxNotes;
2303 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2305 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2308 uint64_t LocalUsage = NextLocalOffset;
2309 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2310 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2313 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent;
2316 uint64_t ReportedSize = 0;
2318 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2322 ReportedSize +=
FileInfo.TotalSize;
2326 if (ReportedSize != CountedSize) {
2328 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2337 size_t malloc_bytes = 0;
2338 size_t mmap_bytes = 0;
2340 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2341 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2342 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2343 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2344 mmap_bytes += sized_mapped;
2346 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2347 malloc_bytes += sized_mapped;
2355 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2356 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2357 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2358 llvm::capacity_in_bytes(SLocEntryLoaded) +
2359 llvm::capacity_in_bytes(FileInfos);
2361 if (OverriddenFilesInfo)
2362 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2368 StringRef Content) {
2372 new llvm::vfs::InMemoryFileSystem);
2373 InMemoryFileSystem->addFile(
2375 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2383 Diagnostics = std::make_unique<DiagnosticsEngine>(
2386 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2390 assert(ID.isValid());
2391 SourceMgr->setMainFileID(ID);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static ParseState advance(ParseState S, size_t N)
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool MoveUpTranslationUnitIncludeHierarchy(std::pair< FileID, unsigned > &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
static bool isInvalid(LocType Loc, bool *Invalid)
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
Defines the SourceManager interface.
Represents a character-granular source range.
void setEnd(SourceLocation e)
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setTokenRange(bool TR)
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void setSourceManager(SourceManager *SrcMgr)
virtual int getSLocEntryID(SourceLocation::UIntTy SLocOffset)=0
Get the index ID for the loaded SourceLocation offset.
virtual ~ExternalSLocEntrySource()
virtual bool ReadSLocEntry(int ID)=0
Read the source location entry with index ID, which will always be less than -1.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
OptionalFileEntryRef getBypassFile(FileEntryRef VFE)
Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual file entry,...
Keeps track of options that affect how file operations are performed.
Holds the cache used by isBeforeInTranslationUnit.
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset, bool LParentBeforeRParent)
bool getCachedResult(unsigned LOffset, unsigned ROffset) const
If the cache is valid, compute the result given the specified offsets in the LHS/RHS FileID's.
bool isCacheValid() const
Return true if the currently cached values match up with the specified LHS/RHS query.
Used to hold and unique data used to represent #line information.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
unsigned getLineTableFilenameID(StringRef Str)
void AddEntry(FileID FID, const std::vector< LineEntry > &Entries)
Add a new line entry that has already been encoded into the internal representation of the line table...
void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table that indicates that there is a #line or GNU line marker at the spec...
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
SourceManagerForFile(StringRef FileName, StringRef Content)
Creates SourceManager and necessary dependencies (e.g.
This class handles loading and caching of source files into memory.
std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const
Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd=nullptr) const
Returns true if the given MacroID location points at the character end of the immediate macro expansi...
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, std::optional< unsigned > MaxNotes=32) const
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)
Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
void setFileIsTransient(FileEntryRef SourceFile)
Specify that a file is transient.
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
std::optional< StringRef > getBufferDataOrNone(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
void PrintStats() const
Print statistics to stderr.
FileID getUniqueLoadedASTFileID(SourceLocation Loc) const
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
bool isInTheSameTranslationUnitImpl(const std::pair< FileID, unsigned > &LOffs, const std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same TU.
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const
Get a local SLocEntry. This is exposed for indexing.
OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)
Bypass the overridden contents of a file.
FileManager & getFileManager() const
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
std::optional< StringRef > getBufferDataIfLoaded(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if it's...
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
std::pair< int, SourceLocation::UIntTy > AllocateLoadedSLocEntries(unsigned NumSLocEntries, SourceLocation::UIntTy TotalSize)
Allocate a number of loaded SLocEntries, which will be actually loaded on demand from the external so...
void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
std::pair< bool, bool > isInTheSameTranslationUnit(std::pair< FileID, unsigned > &LOffs, std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
void initializeForReplay(const SourceManager &Old)
Initialize this source manager suitably to replay the compilation described by Old.
FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
std::pair< FileID, unsigned > getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
LineTableInfo & getLineTable()
Retrieve the stored line table.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length)
Creates an expansion SLocEntry for the substitution of an argument into a function-like macro's body.
A trivial tuple used to represent a source range.
One instance of this struct is kept for every file loaded or used.
void setBuffer(std::unique_ptr< llvm::MemoryBuffer > B)
Set the buffer.
std::optional< StringRef > getBufferDataIfLoaded() const
Return a StringRef to the source buffer data, only if it has already been loaded.
OptionalFileEntryRef ContentsEntry
References the file which the contents were actually loaded from.
unsigned getSizeBytesMapped() const
Returns the number of bytes actually mapped for this ContentCache.
unsigned IsTransient
True if this file may be transient, that is, if it might not exist at some later point in time when t...
unsigned getSize() const
Returns the size of the content encapsulated by this ContentCache.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache.
unsigned IsFileVolatile
True if this content cache was initially created for a source file considered to be volatile (likely ...
LineOffsetMapping SourceLineCache
A bump pointer allocated array of offsets for each source line.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
static const char * getInvalidBOM(StringRef BufStr)
unsigned BufferOverridden
Indicates whether the buffer itself was provided to override the actual file contents.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)
Return a ExpansionInfo for an expansion.
bool isMacroBodyExpansion() const
SourceLocation getSpellingLoc() const
CharSourceRange getExpansionLocRange() const
bool isMacroArgExpansion() const
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)
Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)
Return a special ExpansionInfo representing a token that ends prematurely.
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)
Return a FileInfo object.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
void setHasLineDirectives()
Set the flag that indicates that this FileID has line table entries associated with it.
SourceLocation getIncludeLoc() const
StringRef getName() const
Returns the name of the file that was used when the file was loaded from the underlying file system.
Mapping of line offsets into a source file.
const unsigned * begin() const
LineOffsetMapping()=default
const unsigned * end() const
static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)
This is a discriminated union of FileInfo and ExpansionInfo.
SourceLocation::UIntTy getOffset() const
static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)
const FileInfo & getFile() const
const ExpansionInfo & getExpansion() const
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)