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/StringRef.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/Support/Allocator.h"
26#include "llvm/Support/Capacity.h"
27#include "llvm/Support/Compiler.h"
28#include "llvm/Support/Endian.h"
29#include "llvm/Support/ErrorHandling.h"
30#include "llvm/Support/FileSystem.h"
31#include "llvm/Support/MathExtras.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/Path.h"
34#include "llvm/Support/raw_ostream.h"
46using namespace SrcMgr;
47using llvm::MemoryBuffer;
56 return Buffer ? Buffer->getBufferSize() : 0;
62 if (Buffer ==
nullptr) {
63 assert(0 &&
"Buffer should never be null");
64 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
66 return Buffer->getBufferKind();
74 return Buffer ? (
unsigned)Buffer->getBufferSize()
82 const char *InvalidBOM =
83 llvm::StringSwitch<const char *>(BufStr)
84 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
86 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
88 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
89 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
90 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
91 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
92 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
93 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
94 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
95 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
101std::optional<llvm::MemoryBufferRef>
109 return Buffer->getMemBufferRef();
124 if (!BufferOrError) {
125 if (
Diag.isDiagnosticInFlight())
126 Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
128 BufferOrError.getError().message());
130 Diag.Report(Loc, diag::err_cannot_open_file)
136 Buffer = std::move(*BufferOrError);
147 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
148 if (
Diag.isDiagnosticInFlight())
149 Diag.SetDelayedDiagnostic(diag::err_file_too_large,
152 Diag.Report(Loc, diag::err_file_too_large)
163 if (
Diag.isDiagnosticInFlight())
164 Diag.SetDelayedDiagnostic(diag::err_file_modified,
167 Diag.Report(Loc, diag::err_file_modified)
176 StringRef BufStr = Buffer->getBuffer();
180 Diag.Report(Loc, diag::err_unsupported_bom)
187 return Buffer->getMemBufferRef();
191 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
193 FilenamesByID.push_back(&*IterBool.first);
194 return IterBool.first->second;
204 int FilenameID,
unsigned EntryExit,
206 std::vector<LineEntry> &Entries = LineEntries[FID];
208 assert((Entries.empty() || Entries.back().FileOffset <
Offset) &&
209 "Adding line entries out of order!");
211 unsigned IncludeOffset = 0;
212 if (EntryExit == 1) {
216 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();
217 if (EntryExit == 2) {
219 assert(PrevEntry && PrevEntry->IncludeOffset &&
220 "PPDirectives should have caught case when popping empty include "
222 PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset);
225 IncludeOffset = PrevEntry->IncludeOffset;
226 if (FilenameID == -1) {
229 FilenameID = PrevEntry->FilenameID;
242 const std::vector<LineEntry> &Entries = LineEntries[FID];
243 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
247 if (Entries.back().FileOffset <=
Offset)
248 return &Entries.back();
251 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries,
Offset);
252 if (I == Entries.begin())
260 const std::vector<LineEntry> &Entries) {
261 LineEntries[FID] = Entries;
266 return getLineTable().getLineTableFilenameID(Name);
273 int FilenameID,
bool IsFileEntry,
276 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
288 (void) getLineTable();
290 unsigned EntryExit = 0;
296 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
297 EntryExit, FileKind);
311 bool UserFilesAreVolatile)
312 :
Diag(
Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
321 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
322 if (MemBufferInfos[i]) {
323 MemBufferInfos[i]->~ContentCache();
324 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
327 for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
328 I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
330 I->second->~ContentCache();
331 ContentCacheAlloc.Deallocate(I->second);
338 LocalSLocEntryTable.clear();
339 LoadedSLocEntryTable.clear();
340 SLocEntryLoaded.clear();
341 LastLineNoFileIDQuery =
FileID();
342 LastLineNoContentCache =
nullptr;
343 LastFileIDLookup =
FileID();
350 CurrentLoadedOffset = MaxLoadedOffset;
355 assert(MainFileID.
isValid() &&
"expected initialized SourceManager");
357 return FE->getUID() == SourceFile.
getUID();
362 assert(MainFileID.
isInvalid() &&
"expected uninitialized SourceManager");
367 Clone->ContentsEntry =
Cache->ContentsEntry;
368 Clone->BufferOverridden =
Cache->BufferOverridden;
369 Clone->IsFileVolatile =
Cache->IsFileVolatile;
370 Clone->IsTransient =
Cache->IsTransient;
371 Clone->setUnownedBuffer(
Cache->getBufferIfLoaded());
376 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
377 if (!Old.SLocEntryLoaded[I])
378 Old.loadSLocEntry(I,
nullptr);
381 for (
auto &
FileInfo : Old.FileInfos) {
385 Slot = CloneContentCache(
FileInfo.second);
399 if (OverriddenFilesInfo) {
402 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
403 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
406 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
422ContentCache &SourceManager::createMemBufferContentCache(
423 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
427 MemBufferInfos.push_back(Entry);
434 assert(!SLocEntryLoaded[Index]);
435 if (ExternalSLocEntries->
ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
439 if (!SLocEntryLoaded[Index]) {
441 if (!FakeSLocEntryForRecovery)
442 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
445 return *FakeSLocEntryForRecovery;
449 return LoadedSLocEntryTable[Index];
452std::pair<int, SourceLocation::UIntTy>
455 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
457 if (CurrentLoadedOffset < TotalSize ||
458 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
459 return std::make_pair(0, 0);
461 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
462 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
463 CurrentLoadedOffset -= TotalSize;
464 int ID = LoadedSLocEntryTable.size();
465 return std::make_pair(-ID - 1, CurrentLoadedOffset);
470llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
471 if (!FakeBufferForRecovery)
472 FakeBufferForRecovery =
473 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
475 return *FakeBufferForRecovery;
481 if (!FakeContentCacheForRecovery) {
482 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
483 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
485 return *FakeContentCacheForRecovery;
490FileID SourceManager::getPreviousFileID(
FileID FID)
const {
501 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
505 return FileID::get(ID-1);
518 }
else if (ID+1 >= -1) {
522 return FileID::get(ID+1);
539 LoadedID, LoadedOffset);
555 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
556 LoadedID, LoadedOffset);
568 StringRef Name = Buffer->getBufferIdentifier();
569 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
570 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
582 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
583 LoadedID, LoadedOffset, IncludeLoc);
605 assert(LoadedID != -1 &&
"Loading sentinel FileID");
606 unsigned Index =
unsigned(-LoadedID) - 2;
607 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
608 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
611 SLocEntryLoaded[Index] =
true;
612 return FileID::get(LoadedID);
614 unsigned FileSize =
File.getSize();
615 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
616 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
617 Diag.
Report(IncludePos, diag::err_include_too_large);
621 LocalSLocEntryTable.push_back(
626 NextLocalOffset += FileSize + 1;
630 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
631 return LastFileIDLookup = FID;
638 return createExpansionLocImpl(Info, Length);
644 bool ExpansionIsTokenRange,
int LoadedID,
647 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
648 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
655 "token spans multiple files");
656 return createExpansionLocImpl(
658 TokenEnd.getOffset() - TokenStart.getOffset());
662SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
663 unsigned Length,
int LoadedID,
666 assert(LoadedID != -1 &&
"Loading sentinel FileID");
667 unsigned Index =
unsigned(-LoadedID) - 2;
668 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
669 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
671 SLocEntryLoaded[Index] =
true;
672 return SourceLocation::getMacroLoc(LoadedOffset);
674 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
676 assert(NextLocalOffset + Length + 1 > NextLocalOffset &&
677 NextLocalOffset + Length + 1 <= CurrentLoadedOffset &&
678 "Ran out of source locations!");
680 NextLocalOffset += Length + 1;
681 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
684std::optional<llvm::MemoryBufferRef>
691 const FileEntry *SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
697 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
703 "Different sizes, use the FileManager to create a virtual file with "
705 assert(FileInfos.count(SourceFile) == 0 &&
706 "This function should be called at the initialization stage, before "
707 "any parsing occurs.");
709 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
710 std::make_pair(SourceFile, NewFile));
712 Pair.first->second = NewFile;
724 (void)getOrCreateContentCache(*BypassFile);
732std::optional<StringRef>
735 if (Entry->getFile().getContentCache().
OrigEntry)
736 return Entry->getFile().getName();
744 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
747std::optional<StringRef>
758 return B->getBuffer();
773 return FileID::get(0);
777 if (SLocOffset < NextLocalOffset)
778 return getFileIDLocal(SLocOffset);
779 return getFileIDLoaded(SLocOffset);
787 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
804 unsigned LessIndex = 0;
806 unsigned GreaterIndex = LocalSLocEntryTable.size();
807 if (LastFileIDLookup.ID >= 0) {
809 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
810 LessIndex = LastFileIDLookup.ID;
812 GreaterIndex = LastFileIDLookup.ID;
816 unsigned NumProbes = 0;
819 assert(GreaterIndex < LocalSLocEntryTable.size());
820 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
821 FileID Res = FileID::get(
int(GreaterIndex));
823 LastFileIDLookup = Res;
824 NumLinearScans += NumProbes+1;
827 if (++NumProbes == 8)
833 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
841 if (MidOffset > SLocOffset) {
842 GreaterIndex = MiddleIndex;
847 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
849 FileID Res = FileID::get(MiddleIndex);
852 LastFileIDLookup = Res;
853 NumBinaryProbes += NumProbes;
858 LessIndex = MiddleIndex;
867 if (SLocOffset < CurrentLoadedOffset) {
868 assert(0 &&
"Invalid SLocOffset or bad function choice");
876 unsigned GreaterIndex = 0;
877 unsigned LessIndex = LoadedSLocEntryTable.size();
878 if (LastFileIDLookup.ID < 0) {
880 int LastID = LastFileIDLookup.ID;
881 if (getLoadedSLocEntryByID(LastID).getOffset() > SLocOffset)
885 LessIndex = -LastID - 2;
891 for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++GreaterIndex) {
897 FileID Res = FileID::get(-
int(GreaterIndex) - 2);
898 LastFileIDLookup = Res;
899 NumLinearScans += NumProbes + 1;
908 unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
914 if (GreaterIndex == MiddleIndex) {
915 assert(0 &&
"binary search missed the entry");
918 GreaterIndex = MiddleIndex;
922 if (isOffsetInFileID(FileID::get(-
int(MiddleIndex) - 2), SLocOffset)) {
923 FileID Res = FileID::get(-
int(MiddleIndex) - 2);
924 LastFileIDLookup = Res;
925 NumBinaryProbes += NumProbes;
929 if (LessIndex == MiddleIndex) {
930 assert(0 &&
"binary search missed the entry");
933 LessIndex = MiddleIndex;
972std::pair<FileID, unsigned>
973SourceManager::getDecomposedExpansionLocSlowCase(
987 return std::make_pair(FID,
Offset);
990std::pair<FileID, unsigned>
1005 return std::make_pair(FID,
Offset);
1022 return F->getName();
1030 assert(Loc.
isMacroID() &&
"Not a macro expansion loc!");
1087 if (DecompLoc.second > 0)
1101 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1113 *MacroBegin = ExpLoc;
1136 FileID NextFID = getNextFileID(FID);
1166 bool CharDataInvalid =
false;
1168 if (CharDataInvalid || !Entry.
isFile()) {
1172 return "<<<<INVALID BUFFER>>>>";
1174 std::optional<llvm::MemoryBufferRef> Buffer =
1179 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1180 :
"<<<<INVALID BUFFER>>>>";
1195 if (FilePos > MemBuf->getBufferSize()) {
1201 const char *Buf = MemBuf->getBufferStart();
1204 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->
SourceLineCache &&
1205 LastLineNoResult < LastLineNoContentCache->SourceLineCache.
size()) {
1206 const unsigned *SourceLineCache =
1208 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1209 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1210 if (FilePos >= LineStart && FilePos < LineEnd) {
1215 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1216 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1219 return FilePos - LineStart + 1;
1223 unsigned LineStart = FilePos;
1224 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1226 return FilePos-LineStart+1;
1231template<
typename LocType>
1233 bool MyInvalid = Loc.isInvalid();
1267 return ((x - ~
static_cast<T
>(0) / 255 * (n + 1)) & ~x &
1268 ((x & ~
static_cast<T
>(0) / 255 * 127) +
1269 (~
static_cast<T
>(0) / 255 * (127 - (m - 1))))) &
1270 ~static_cast<T>(0) / 255 * 128;
1274 llvm::BumpPtrAllocator &Alloc) {
1281 LineOffsets.push_back(0);
1283 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1284 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1285 const unsigned char *Buf = Start;
1291 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1293 Word = llvm::support::endian::read64(Buf, llvm::support::little);
1297 Buf +=
sizeof(Word);
1305 unsigned N = llvm::countr_zero(Mask) - 7;
1308 unsigned char Byte = Word;
1317 LineOffsets.push_back(Buf - Start);
1319 }
while (Buf < End -
sizeof(Word) - 1);
1325 LineOffsets.push_back(Buf - Start + 1);
1326 }
else if (*Buf ==
'\r') {
1328 if (Buf + 1 < End && Buf[1] ==
'\n') {
1331 LineOffsets.push_back(Buf - Start + 1);
1340 llvm::BumpPtrAllocator &Alloc)
1341 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.size() + 1)) {
1342 Storage[0] = LineOffsets.size();
1343 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1359 if (LastLineNoFileIDQuery == FID)
1360 Content = LastLineNoContentCache;
1362 bool MyInvalid =
false;
1363 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1364 if (MyInvalid || !Entry.
isFile()) {
1376 std::optional<llvm::MemoryBufferRef> Buffer =
1391 const unsigned *SourceLineCacheStart = SourceLineCache;
1394 unsigned QueriedFilePos = FilePos+1;
1409 if (LastLineNoFileIDQuery == FID) {
1410 if (QueriedFilePos >= LastLineNoFilePos) {
1412 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1418 if (SourceLineCache+5 < SourceLineCacheEnd) {
1419 if (SourceLineCache[5] > QueriedFilePos)
1420 SourceLineCacheEnd = SourceLineCache+5;
1421 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1422 if (SourceLineCache[10] > QueriedFilePos)
1423 SourceLineCacheEnd = SourceLineCache+10;
1424 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1425 if (SourceLineCache[20] > QueriedFilePos)
1426 SourceLineCacheEnd = SourceLineCache+20;
1431 if (LastLineNoResult < Content->SourceLineCache.size())
1432 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1436 const unsigned *Pos =
1437 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1438 unsigned LineNo = Pos-SourceLineCacheStart;
1440 LastLineNoFileIDQuery = FID;
1441 LastLineNoContentCache = Content;
1442 LastLineNoFilePos = QueriedFilePos;
1443 LastLineNoResult = LineNo;
1450 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
1451 return getLineNumber(LocInfo.first, LocInfo.second);
1456 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1457 return getLineNumber(LocInfo.first, LocInfo.second);
1476 assert(Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1477 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1478 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1489 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1492 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1508 auto B = getBufferOrNone(getFileID(Loc));
1511 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1522 bool UseLineDirectives)
const {
1526 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1539 FileID FID = LocInfo.first;
1543 else if (
auto Buffer =
C->getBufferOrNone(
Diag, getFileManager()))
1544 Filename = Buffer->getBufferIdentifier();
1546 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &
Invalid);
1549 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &
Invalid);
1558 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1561 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1563 if (Entry->FilenameID != -1) {
1564 Filename = LineTable->getFilename(Entry->FilenameID);
1567 FID = FileID::get(0);
1574 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1575 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1580 if (Entry->IncludeOffset) {
1581 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1601 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1603 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1612 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1613 if (Entry->IncludeOffset)
1628 if ((ID > 0 &&
unsigned(ID+1) == local_sloc_entry_size()))
1629 NextOffset = getNextLocalOffset();
1630 else if (ID+1 == -1)
1631 NextOffset = MaxLoadedOffset;
1633 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1635 return NextOffset - Entry.
getOffset() - 1;
1648 unsigned Col)
const {
1649 assert(SourceFile &&
"Null source file!");
1650 assert(Line && Col &&
"Line and column should start from 1!");
1652 FileID FirstFID = translateFile(SourceFile);
1653 return translateLineCol(FirstFID, Line, Col);
1661 assert(SourceFile &&
"Null source file!");
1665 if (MainFileID.isValid()) {
1679 for (
unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1680 const SLocEntry &SLoc = getLocalSLocEntry(I);
1683 return FileID::get(I);
1687 for (
unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1688 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1691 return FileID::get(-
int(I) - 2);
1701 unsigned Col)
const {
1704 assert(Line && Col &&
"Line and column should start from 1!");
1719 if (Line == 1 && Col == 1)
1726 std::optional<llvm::MemoryBufferRef> Buffer =
1735 unsigned Size = Buffer->getBufferSize();
1742 const char *Buf = Buffer->getBufferStart() + FilePos;
1743 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1750 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1762void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1774 if (
unsigned(ID) >= local_sloc_entry_size())
1776 }
else if (ID == -1) {
1791 bool IncludedInFID =
1792 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1796 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1797 if (IncludedInFID) {
1800 if (Entry.
getFile().NumCreatedFIDs)
1801 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1821 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1823 SourceLocation::getMacroLoc(Entry.
getOffset()),
1824 getFileIDSize(FileID::get(ID)));
1828void SourceManager::associateFileChunkWithMacroArgExp(
1829 MacroArgsMap &MacroArgsCache,
1833 unsigned ExpansionLength)
const {
1844 unsigned SpellRelativeOffs;
1845 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1847 const SLocEntry &Entry = getSLocEntry(SpellFID);
1849 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1853 unsigned CurrSpellLength;
1854 if (SpellFIDEndOffs < SpellEndOffs)
1855 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1857 CurrSpellLength = ExpansionLength;
1858 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1860 ExpansionLoc, CurrSpellLength);
1863 if (SpellFIDEndOffs >= SpellEndOffs)
1867 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1871 SpellRelativeOffs = 0;
1878 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1881 unsigned EndOffs = BeginOffs + ExpansionLength;
1900 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1903 MacroArgsCache[BeginOffs] = ExpansionLoc;
1904 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1923 std::tie(FID,
Offset) = getDecomposedLoc(Loc);
1927 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1928 if (!MacroArgsCache) {
1929 MacroArgsCache = std::make_unique<MacroArgsMap>();
1930 computeMacroArgsCache(*MacroArgsCache, FID);
1933 assert(!MacroArgsCache->empty());
1934 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(
Offset);
1937 if (I == MacroArgsCache->begin())
1944 if (MacroArgExpandedLoc.
isValid())
1950std::pair<FileID, unsigned>
1953 return std::make_pair(
FileID(), 0);
1957 using DecompTy = std::pair<FileID, unsigned>;
1958 auto InsertOp = IncludedLocMap.try_emplace(FID);
1959 DecompTy &DecompLoc = InsertOp.first->second;
1960 if (!InsertOp.second)
1974 DecompLoc = getDecomposedLoc(UpperLoc);
1985 std::pair<FileID, unsigned> UpperLoc =
SM.getDecomposedIncludedLoc(Loc.first);
1986 if (UpperLoc.first.isInvalid())
2001 enum { MagicCacheSize = 300 };
2002 IsBeforeInTUCacheKey Key(LFID, RFID);
2008 if (IBTUCache.size() < MagicCacheSize)
2009 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
2012 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2013 if (I != IBTUCache.end())
2017 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2018 return IBTUCacheOverflow;
2026 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2030 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
2031 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
2036 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2037 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2039 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2041 return InSameTU.second;
2046 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2047 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2048 bool LIsBuiltins = LB ==
"<built-in>";
2049 bool RIsBuiltins = RB ==
"<built-in>";
2051 if (LIsBuiltins || RIsBuiltins) {
2052 if (LIsBuiltins != RIsBuiltins)
2056 return LOffs.first < ROffs.first;
2058 bool LIsAsm = LB ==
"<inline asm>";
2059 bool RIsAsm = RB ==
"<inline asm>";
2061 if (LIsAsm || RIsAsm) {
2062 if (LIsAsm != RIsAsm)
2064 assert(LOffs.first == ROffs.first);
2067 bool LIsScratch = LB ==
"<scratch space>";
2068 bool RIsScratch = RB ==
"<scratch space>";
2070 if (LIsScratch || RIsScratch) {
2071 if (LIsScratch != RIsScratch)
2073 return LOffs.second < ROffs.second;
2075 llvm_unreachable(
"Unsortable locations found");
2079 std::pair<FileID, unsigned> &LOffs,
2080 std::pair<FileID, unsigned> &ROffs)
const {
2082 if (LOffs.first == ROffs.first)
2083 return std::make_pair(
true, LOffs.second < ROffs.second);
2088 getInBeforeInTUCache(LOffs.first, ROffs.first);
2093 return std::make_pair(
2106 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2110 LChain.try_emplace(LOffs.first, Entry{LOffs.second, Parent});
2113 if (LOffs.first == ROffs.first)
2120 auto I = LChain.find(ROffs.first);
2121 if (I != LChain.end()) {
2123 LOffs.first = I->first;
2124 LOffs.second = I->second.Offset;
2132 unsigned LParent = I->second.ParentFID.ID;
2133 unsigned RParent =
Parent.ID;
2134 assert(((LOffs.second != ROffs.second) ||
2135 (LParent == 0 || RParent == 0) ||
2136 isInSameSLocAddrSpace(getComposedLoc(I->second.ParentFID, 0),
2137 getComposedLoc(
Parent, 0),
nullptr)) &&
2138 "Mixed local/loaded FileIDs with same include location?");
2139 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2141 return std::make_pair(
2149 return std::make_pair(
false,
false);
2153 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2154 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2155 <<
" mem buffers mapped.\n";
2156 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntry's allocated ("
2157 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2158 <<
" bytes of capacity), "
2159 << NextLocalOffset <<
"B of Sloc address space used.\n";
2160 llvm::errs() << LoadedSLocEntryTable.size()
2161 <<
" loaded SLocEntries allocated, "
2162 << MaxLoadedOffset - CurrentLoadedOffset
2163 <<
"B of Sloc address space used.\n";
2165 unsigned NumLineNumsComputed = 0;
2166 unsigned NumFileBytesMapped = 0;
2168 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2169 NumFileBytesMapped += I->second->getSizeBytesMapped();
2171 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2173 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2174 << NumLineNumsComputed <<
" files with line #'s computed, "
2175 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2176 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2177 << NumBinaryProbes <<
" binary.\n";
2181 llvm::raw_ostream &out = llvm::errs();
2184 std::optional<SourceLocation::UIntTy> NextStart) {
2185 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2186 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2188 out << *NextStart <<
">\n";
2191 if (Entry.isFile()) {
2192 auto &FI = Entry.getFile();
2193 if (FI.NumCreatedFIDs)
2194 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2196 if (FI.getIncludeLoc().isValid())
2197 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2198 auto &CC = FI.getContentCache();
2199 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2201 if (CC.BufferOverridden)
2202 out <<
" contents overridden\n";
2203 if (CC.ContentsEntry != CC.OrigEntry) {
2204 out <<
" contents from "
2205 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2209 auto &EI = Entry.getExpansion();
2210 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2211 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2212 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2213 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2218 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2219 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2220 ID == NumIDs - 1 ? NextLocalOffset
2221 : LocalSLocEntryTable[ID + 1].getOffset());
2224 std::optional<SourceLocation::UIntTy> NextStart;
2225 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2226 int ID = -(
int)Index - 2;
2227 if (SLocEntryLoaded[Index]) {
2228 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2229 NextStart = LoadedSLocEntryTable[Index].getOffset();
2231 NextStart = std::nullopt;
2242 unsigned Inclusions = 0;
2244 uint64_t DirectSize = 0;
2246 uint64_t TotalSize = 0;
2248 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2251 uint64_t CountedSize = 0;
2253 auto AddUsageForFileID = [&](
FileID ID) {
2256 unsigned Size = getFileIDSize(ID) + 1;
2261 FileID FileLocID = getFileID(FileStart);
2262 const FileEntry *Entry = getFileEntryForID(FileLocID);
2264 Info &EntryInfo = Usage[Entry];
2265 if (EntryInfo.Loc.isInvalid())
2266 EntryInfo.Loc = FileStart;
2267 if (ID == FileLocID) {
2268 ++EntryInfo.Inclusions;
2269 EntryInfo.DirectSize += Size;
2271 EntryInfo.TotalSize += Size;
2272 CountedSize += Size;
2276 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2277 AddUsageForFileID(FileID::get(-2 - Index));
2280 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2281 AddUsageForFileID(FileID::get(Index));
2286 auto SortedUsage = Usage.takeVector();
2287 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2288 return A.second.TotalSize > B.second.TotalSize ||
2289 (A.second.TotalSize == B.second.TotalSize &&
2290 A.second.Loc < B.second.Loc);
2292 auto SortedEnd = SortedUsage.end();
2293 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2294 SortedEnd = SortedUsage.begin() + *MaxNotes;
2295 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2297 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2300 uint64_t LocalUsage = NextLocalOffset;
2301 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2302 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2305 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent;
2308 uint64_t ReportedSize = 0;
2310 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2314 ReportedSize +=
FileInfo.TotalSize;
2318 if (ReportedSize != CountedSize) {
2320 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2329 size_t malloc_bytes = 0;
2330 size_t mmap_bytes = 0;
2332 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2333 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2334 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2335 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2336 mmap_bytes += sized_mapped;
2338 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2339 malloc_bytes += sized_mapped;
2347 size_t size = llvm::capacity_in_bytes(MemBufferInfos)
2348 + llvm::capacity_in_bytes(LocalSLocEntryTable)
2349 + llvm::capacity_in_bytes(LoadedSLocEntryTable)
2350 + llvm::capacity_in_bytes(SLocEntryLoaded)
2351 + llvm::capacity_in_bytes(FileInfos);
2353 if (OverriddenFilesInfo)
2354 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2360 StringRef Content) {
2364 new llvm::vfs::InMemoryFileSystem);
2365 InMemoryFileSystem->addFile(
2367 llvm::MemoryBuffer::getMemBuffer(Content, FileName,
2375 Diagnostics = std::make_unique<DiagnosticsEngine>(
2378 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2379 FileID ID = SourceMgr->createFileID(*FileMgr->getFile(FileName),
2381 assert(ID.isValid());
2382 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 isInvalid(LocType Loc, bool *Invalid)
static bool MoveUpIncludeHierarchy(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...
Defines the SourceManager interface.
TypePropertyCache< Private > Cache
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 ~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).
FileEntryRef getLastRef() const
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)
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...
void setFileIsTransient(const FileEntry *SourceFile)
Specify that a file is transient.
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...
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.
void overrideFileContents(const FileEntry *SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
void PrintStats() const
Print statistics to stderr.
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...
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.
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
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...
FileID getOrCreateFileID(const FileEntry *SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID createFileID(const FileEntry *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...
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.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(const FileEntry *File)
Retrieve the memory buffer associated with the given file.
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.
llvm::DenseMap< const FileEntry *, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
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.
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.
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...
OptionalFileEntryRefDegradesToFileEntryPtr OrigEntry
Reference to the file entry representing this ContentCache.
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.
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.
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.
@ C
Languages that the frontend can parse and compile.
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)