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) {
214 IncludeOffset = Offset-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;
234 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
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 (
auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
329 I->second->~ContentCache();
330 ContentCacheAlloc.Deallocate(I->second);
337 LocalSLocEntryTable.clear();
338 LoadedSLocEntryTable.clear();
339 SLocEntryLoaded.clear();
340 SLocEntryOffsetLoaded.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 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
464 CurrentLoadedOffset -= TotalSize;
465 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
466 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
467 return std::make_pair(BaseID, CurrentLoadedOffset);
472llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
473 if (!FakeBufferForRecovery)
474 FakeBufferForRecovery =
475 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
477 return *FakeBufferForRecovery;
483 if (!FakeContentCacheForRecovery) {
484 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
485 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
487 return *FakeContentCacheForRecovery;
492FileID SourceManager::getPreviousFileID(
FileID FID)
const {
503 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
507 return FileID::get(ID-1);
520 }
else if (ID+1 >= -1) {
524 return FileID::get(ID+1);
546 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
547 LoadedID, LoadedOffset);
559 StringRef Name = Buffer->getBufferIdentifier();
560 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
561 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
573 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
574 LoadedID, LoadedOffset, IncludeLoc);
596 assert(LoadedID != -1 &&
"Loading sentinel FileID");
597 unsigned Index =
unsigned(-LoadedID) - 2;
598 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
599 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
602 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
603 return FileID::get(LoadedID);
605 unsigned FileSize =
File.getSize();
606 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
607 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
608 Diag.
Report(IncludePos, diag::err_sloc_space_too_large);
612 LocalSLocEntryTable.push_back(
617 NextLocalOffset += FileSize + 1;
621 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
622 return LastFileIDLookup = FID;
629 return createExpansionLocImpl(Info, Length);
635 bool ExpansionIsTokenRange,
int LoadedID,
638 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
639 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
646 "token spans multiple files");
647 return createExpansionLocImpl(
649 TokenEnd.getOffset() - TokenStart.getOffset());
653SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
654 unsigned Length,
int LoadedID,
657 assert(LoadedID != -1 &&
"Loading sentinel FileID");
658 unsigned Index =
unsigned(-LoadedID) - 2;
659 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
660 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
662 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
663 return SourceLocation::getMacroLoc(LoadedOffset);
665 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
666 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
667 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
674 llvm::report_fatal_error(
"ran out of source locations");
677 NextLocalOffset += Length + 1;
678 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
681std::optional<llvm::MemoryBufferRef>
688 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
694 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
700 "Different sizes, use the FileManager to create a virtual file with "
702 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
703 "This function should be called at the initialization stage, before "
704 "any parsing occurs.");
706 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
707 std::make_pair(SourceFile, NewFile));
709 Pair.first->second = NewFile;
721 (void)getOrCreateContentCache(*BypassFile);
729std::optional<StringRef>
732 if (Entry->getFile().getContentCache().
OrigEntry)
733 return Entry->getFile().getName();
741 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
744std::optional<StringRef>
755 return B->getBuffer();
770 return FileID::get(0);
774 if (SLocOffset < NextLocalOffset)
775 return getFileIDLocal(SLocOffset);
776 return getFileIDLoaded(SLocOffset);
784 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
801 unsigned LessIndex = 0;
803 unsigned GreaterIndex = LocalSLocEntryTable.size();
804 if (LastFileIDLookup.ID >= 0) {
806 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
807 LessIndex = LastFileIDLookup.ID;
809 GreaterIndex = LastFileIDLookup.ID;
813 unsigned NumProbes = 0;
816 assert(GreaterIndex < LocalSLocEntryTable.size());
817 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
818 FileID Res = FileID::get(
int(GreaterIndex));
820 LastFileIDLookup = Res;
821 NumLinearScans += NumProbes+1;
824 if (++NumProbes == 8)
830 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
838 if (MidOffset > SLocOffset) {
839 GreaterIndex = MiddleIndex;
844 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
846 FileID Res = FileID::get(MiddleIndex);
849 LastFileIDLookup = Res;
850 NumBinaryProbes += NumProbes;
855 LessIndex = MiddleIndex;
864 if (SLocOffset < CurrentLoadedOffset) {
865 assert(0 &&
"Invalid SLocOffset or bad function choice");
869 return FileID::get(ExternalSLocEntries->
getSLocEntryID(SLocOffset));
907std::pair<FileID, unsigned>
908SourceManager::getDecomposedExpansionLocSlowCase(
922 return std::make_pair(FID, Offset);
925std::pair<FileID, unsigned>
927 unsigned Offset)
const {
940 return std::make_pair(FID, Offset);
965 assert(Loc.
isMacroID() &&
"Not a macro expansion loc!");
1022 if (DecompLoc.second > 0)
1036 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1048 *MacroBegin = ExpLoc;
1071 FileID NextFID = getNextFileID(FID);
1101 bool CharDataInvalid =
false;
1103 if (CharDataInvalid || !Entry.
isFile()) {
1107 return "<<<<INVALID BUFFER>>>>";
1109 std::optional<llvm::MemoryBufferRef> Buffer =
1114 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1115 :
"<<<<INVALID BUFFER>>>>";
1130 if (FilePos > MemBuf->getBufferSize()) {
1136 const char *Buf = MemBuf->getBufferStart();
1139 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->
SourceLineCache &&
1140 LastLineNoResult < LastLineNoContentCache->SourceLineCache.
size()) {
1141 const unsigned *SourceLineCache =
1143 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1144 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1145 if (FilePos >= LineStart && FilePos < LineEnd) {
1150 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1151 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1154 return FilePos - LineStart + 1;
1158 unsigned LineStart = FilePos;
1159 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1161 return FilePos-LineStart+1;
1166template<
typename LocType>
1168 bool MyInvalid = Loc.isInvalid();
1202 return ((x - ~
static_cast<T
>(0) / 255 * (n + 1)) & ~x &
1203 ((x & ~
static_cast<T
>(0) / 255 * 127) +
1204 (~
static_cast<T
>(0) / 255 * (127 - (m - 1))))) &
1205 ~static_cast<T>(0) / 255 * 128;
1209 llvm::BumpPtrAllocator &Alloc) {
1216 LineOffsets.push_back(0);
1218 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1219 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1220 const unsigned char *Buf = Start;
1226 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1228 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1232 Buf +=
sizeof(Word);
1240 unsigned N = llvm::countr_zero(Mask) - 7;
1243 unsigned char Byte = Word;
1252 LineOffsets.push_back(Buf - Start);
1254 }
while (Buf < End -
sizeof(Word) - 1);
1260 LineOffsets.push_back(Buf - Start + 1);
1261 }
else if (*Buf ==
'\r') {
1263 if (Buf + 1 < End && Buf[1] ==
'\n') {
1266 LineOffsets.push_back(Buf - Start + 1);
1275 llvm::BumpPtrAllocator &Alloc)
1276 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.size() + 1)) {
1277 Storage[0] = LineOffsets.size();
1278 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1294 if (LastLineNoFileIDQuery == FID)
1295 Content = LastLineNoContentCache;
1297 bool MyInvalid =
false;
1298 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1299 if (MyInvalid || !Entry.
isFile()) {
1311 std::optional<llvm::MemoryBufferRef> Buffer =
1326 const unsigned *SourceLineCacheStart = SourceLineCache;
1329 unsigned QueriedFilePos = FilePos+1;
1344 if (LastLineNoFileIDQuery == FID) {
1345 if (QueriedFilePos >= LastLineNoFilePos) {
1347 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1353 if (SourceLineCache+5 < SourceLineCacheEnd) {
1354 if (SourceLineCache[5] > QueriedFilePos)
1355 SourceLineCacheEnd = SourceLineCache+5;
1356 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1357 if (SourceLineCache[10] > QueriedFilePos)
1358 SourceLineCacheEnd = SourceLineCache+10;
1359 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1360 if (SourceLineCache[20] > QueriedFilePos)
1361 SourceLineCacheEnd = SourceLineCache+20;
1366 if (LastLineNoResult < Content->SourceLineCache.size())
1367 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1371 const unsigned *Pos =
1372 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1373 unsigned LineNo = Pos-SourceLineCacheStart;
1375 LastLineNoFileIDQuery = FID;
1376 LastLineNoContentCache = Content;
1377 LastLineNoFilePos = QueriedFilePos;
1378 LastLineNoResult = LineNo;
1385 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
1386 return getLineNumber(LocInfo.first, LocInfo.second);
1391 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1392 return getLineNumber(LocInfo.first, LocInfo.second);
1411 assert(Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1412 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1413 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1424 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1427 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1443 auto B = getBufferOrNone(getFileID(Loc));
1446 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1457 bool UseLineDirectives)
const {
1461 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1474 FileID FID = LocInfo.first;
1478 else if (
auto Buffer =
C->getBufferOrNone(
Diag, getFileManager()))
1479 Filename = Buffer->getBufferIdentifier();
1481 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &
Invalid);
1484 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &
Invalid);
1493 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1496 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1498 if (Entry->FilenameID != -1) {
1499 Filename = LineTable->getFilename(Entry->FilenameID);
1502 FID = FileID::get(0);
1509 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1510 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1515 if (Entry->IncludeOffset) {
1516 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1536 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
1538 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1547 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1548 if (Entry->IncludeOffset)
1563 if ((ID > 0 &&
unsigned(ID+1) == local_sloc_entry_size()))
1564 NextOffset = getNextLocalOffset();
1565 else if (ID+1 == -1)
1566 NextOffset = MaxLoadedOffset;
1568 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1570 return NextOffset - Entry.
getOffset() - 1;
1583 unsigned Col)
const {
1584 assert(SourceFile &&
"Null source file!");
1585 assert(
Line && Col &&
"Line and column should start from 1!");
1587 FileID FirstFID = translateFile(SourceFile);
1588 return translateLineCol(FirstFID,
Line, Col);
1596 assert(SourceFile &&
"Null source file!");
1600 if (MainFileID.isValid()) {
1614 for (
unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1615 const SLocEntry &SLoc = getLocalSLocEntry(I);
1618 return FileID::get(I);
1622 for (
unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1623 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1626 return FileID::get(-
int(I) - 2);
1636 unsigned Col)
const {
1639 assert(
Line && Col &&
"Line and column should start from 1!");
1654 if (
Line == 1 && Col == 1)
1661 std::optional<llvm::MemoryBufferRef> Buffer =
1670 unsigned Size = Buffer->getBufferSize();
1677 const char *Buf = Buffer->getBufferStart() + FilePos;
1678 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1685 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1697void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1709 if (
unsigned(ID) >= local_sloc_entry_size())
1711 }
else if (ID == -1) {
1726 bool IncludedInFID =
1727 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1731 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1732 if (IncludedInFID) {
1735 if (Entry.
getFile().NumCreatedFIDs)
1736 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1756 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1758 SourceLocation::getMacroLoc(Entry.
getOffset()),
1759 getFileIDSize(FileID::get(ID)));
1763void SourceManager::associateFileChunkWithMacroArgExp(
1764 MacroArgsMap &MacroArgsCache,
1768 unsigned ExpansionLength)
const {
1779 unsigned SpellRelativeOffs;
1780 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1782 const SLocEntry &Entry = getSLocEntry(SpellFID);
1784 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1788 unsigned CurrSpellLength;
1789 if (SpellFIDEndOffs < SpellEndOffs)
1790 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1792 CurrSpellLength = ExpansionLength;
1793 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1795 ExpansionLoc, CurrSpellLength);
1798 if (SpellFIDEndOffs >= SpellEndOffs)
1802 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1806 SpellRelativeOffs = 0;
1813 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1816 unsigned EndOffs = BeginOffs + ExpansionLength;
1835 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1838 MacroArgsCache[BeginOffs] = ExpansionLoc;
1839 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1858 std::tie(FID, Offset) = getDecomposedLoc(Loc);
1862 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1863 if (!MacroArgsCache) {
1864 MacroArgsCache = std::make_unique<MacroArgsMap>();
1865 computeMacroArgsCache(*MacroArgsCache, FID);
1868 assert(!MacroArgsCache->empty());
1869 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1872 if (I == MacroArgsCache->begin())
1879 if (MacroArgExpandedLoc.
isValid())
1885std::pair<FileID, unsigned>
1888 return std::make_pair(
FileID(), 0);
1892 using DecompTy = std::pair<FileID, unsigned>;
1893 auto InsertOp = IncludedLocMap.try_emplace(FID);
1894 DecompTy &DecompLoc = InsertOp.first->second;
1895 if (!InsertOp.second)
1909 DecompLoc = getDecomposedLoc(UpperLoc);
1915 const std::pair<FileID, unsigned> &LOffs,
1916 const std::pair<FileID, unsigned> &ROffs)
const {
1918 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1921 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1922 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1925 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1926 std::greater<FileID>{});
1930 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1944 std::pair<FileID, unsigned> UpperLoc =
SM.getDecomposedIncludedLoc(Loc.first);
1945 if (UpperLoc.first.isInvalid() ||
1946 !
SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
1961 enum { MagicCacheSize = 300 };
1962 IsBeforeInTUCacheKey Key(LFID, RFID);
1968 if (IBTUCache.size() < MagicCacheSize)
1969 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1972 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1973 if (I != IBTUCache.end())
1977 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
1978 return IBTUCacheOverflow;
1986 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
1990 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
1991 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
1996 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
1997 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
1999 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2001 return InSameTU.second;
2004 return LOffs.first < ROffs.first;
2008 std::pair<FileID, unsigned> &LOffs,
2009 std::pair<FileID, unsigned> &ROffs)
const {
2011 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2012 return std::make_pair(
false,
false);
2015 if (LOffs.first == ROffs.first)
2016 return std::make_pair(
true, LOffs.second < ROffs.second);
2021 getInBeforeInTUCache(LOffs.first, ROffs.first);
2026 return std::make_pair(
2036 std::pair<FileID, unsigned> DecomposedLoc;
2039 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2043 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2046 if (LOffs.first == ROffs.first)
2048 LChild = LOffs.first;
2053 auto LIt = LChain.find(ROffs.first);
2054 if (LIt != LChain.end()) {
2056 LOffs = LIt->second.DecomposedLoc;
2057 LChild = LIt->second.ChildFID;
2066 unsigned LChildID = LChild.ID;
2067 unsigned RChildID = RChild.ID;
2068 assert(((LOffs.second != ROffs.second) ||
2069 (LChildID == 0 || RChildID == 0) ||
2070 isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
2071 getComposedLoc(RChild, 0),
nullptr)) &&
2072 "Mixed local/loaded FileIDs with same include location?");
2073 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2074 LChildID < RChildID);
2075 return std::make_pair(
2078 RChild = ROffs.first;
2084 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2085 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2087 bool LIsBuiltins = LB ==
"<built-in>";
2088 bool RIsBuiltins = RB ==
"<built-in>";
2090 if (LIsBuiltins || RIsBuiltins) {
2091 if (LIsBuiltins != RIsBuiltins)
2092 return std::make_pair(
true, LIsBuiltins);
2095 return std::make_pair(
true, LOffs.first < ROffs.first);
2098 bool LIsAsm = LB ==
"<inline asm>";
2099 bool RIsAsm = RB ==
"<inline asm>";
2101 if (LIsAsm || RIsAsm) {
2102 if (LIsAsm != RIsAsm)
2103 return std::make_pair(
true, RIsAsm);
2104 assert(LOffs.first == ROffs.first);
2105 return std::make_pair(
true,
false);
2108 bool LIsScratch = LB ==
"<scratch space>";
2109 bool RIsScratch = RB ==
"<scratch space>";
2111 if (LIsScratch || RIsScratch) {
2112 if (LIsScratch != RIsScratch)
2113 return std::make_pair(
true, LIsScratch);
2114 return std::make_pair(
true, LOffs.second < ROffs.second);
2117 llvm_unreachable(
"Unsortable locations found");
2121 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2122 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2123 <<
" mem buffers mapped.\n";
2124 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2125 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2126 <<
" bytes of capacity), " << NextLocalOffset
2127 <<
"B of SLoc address space used.\n";
2128 llvm::errs() << LoadedSLocEntryTable.size()
2129 <<
" loaded SLocEntries allocated ("
2130 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2131 <<
" bytes of capacity), "
2132 << MaxLoadedOffset - CurrentLoadedOffset
2133 <<
"B of SLoc address space used.\n";
2135 unsigned NumLineNumsComputed = 0;
2136 unsigned NumFileBytesMapped = 0;
2138 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2139 NumFileBytesMapped += I->second->getSizeBytesMapped();
2141 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2143 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2144 << NumLineNumsComputed <<
" files with line #'s computed, "
2145 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2146 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2147 << NumBinaryProbes <<
" binary.\n";
2151 llvm::raw_ostream &out = llvm::errs();
2154 std::optional<SourceLocation::UIntTy> NextStart) {
2155 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2156 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2158 out << *NextStart <<
">\n";
2161 if (Entry.isFile()) {
2162 auto &FI = Entry.getFile();
2163 if (FI.NumCreatedFIDs)
2164 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2166 if (FI.getIncludeLoc().isValid())
2167 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2168 auto &CC = FI.getContentCache();
2169 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2171 if (CC.BufferOverridden)
2172 out <<
" contents overridden\n";
2173 if (CC.ContentsEntry != CC.OrigEntry) {
2174 out <<
" contents from "
2175 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2179 auto &EI = Entry.getExpansion();
2180 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2181 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2182 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2183 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2188 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2189 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2190 ID == NumIDs - 1 ? NextLocalOffset
2191 : LocalSLocEntryTable[ID + 1].getOffset());
2194 std::optional<SourceLocation::UIntTy> NextStart;
2195 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2196 int ID = -(
int)Index - 2;
2197 if (SLocEntryLoaded[Index]) {
2198 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2199 NextStart = LoadedSLocEntryTable[Index].getOffset();
2201 NextStart = std::nullopt;
2212 unsigned Inclusions = 0;
2214 uint64_t DirectSize = 0;
2216 uint64_t TotalSize = 0;
2218 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2221 uint64_t CountedSize = 0;
2223 auto AddUsageForFileID = [&](
FileID ID) {
2226 unsigned Size = getFileIDSize(ID) + 1;
2231 FileID FileLocID = getFileID(FileStart);
2232 const FileEntry *Entry = getFileEntryForID(FileLocID);
2234 Info &EntryInfo = Usage[Entry];
2235 if (EntryInfo.Loc.isInvalid())
2236 EntryInfo.Loc = FileStart;
2237 if (ID == FileLocID) {
2238 ++EntryInfo.Inclusions;
2239 EntryInfo.DirectSize += Size;
2241 EntryInfo.TotalSize += Size;
2242 CountedSize += Size;
2246 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2247 AddUsageForFileID(FileID::get(-2 - Index));
2250 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2251 AddUsageForFileID(FileID::get(Index));
2256 auto SortedUsage = Usage.takeVector();
2257 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2258 return A.second.TotalSize > B.second.TotalSize ||
2259 (A.second.TotalSize == B.second.TotalSize &&
2260 A.second.Loc < B.second.Loc);
2262 auto SortedEnd = SortedUsage.end();
2263 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2264 SortedEnd = SortedUsage.begin() + *MaxNotes;
2265 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2267 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2270 uint64_t LocalUsage = NextLocalOffset;
2271 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2272 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2275 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent;
2278 uint64_t ReportedSize = 0;
2280 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2284 ReportedSize +=
FileInfo.TotalSize;
2288 if (ReportedSize != CountedSize) {
2290 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2299 size_t malloc_bytes = 0;
2300 size_t mmap_bytes = 0;
2302 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2303 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2304 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2305 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2306 mmap_bytes += sized_mapped;
2308 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2309 malloc_bytes += sized_mapped;
2317 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2318 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2319 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2320 llvm::capacity_in_bytes(SLocEntryLoaded) +
2321 llvm::capacity_in_bytes(FileInfos);
2323 if (OverriddenFilesInfo)
2324 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2330 StringRef Content) {
2334 new llvm::vfs::InMemoryFileSystem);
2335 InMemoryFileSystem->addFile(
2337 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2345 Diagnostics = std::make_unique<DiagnosticsEngine>(
2348 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2352 assert(ID.isValid());
2353 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)
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)
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.
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.
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.
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)