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);
438 assert(!SLocEntryLoaded[Index]);
439 if (ExternalSLocEntries->
ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
443 if (!SLocEntryLoaded[Index]) {
445 if (!FakeSLocEntryForRecovery)
446 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
449 return *FakeSLocEntryForRecovery;
453 return LoadedSLocEntryTable[Index];
456std::pair<int, SourceLocation::UIntTy>
459 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
461 if (CurrentLoadedOffset < TotalSize ||
462 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
463 return std::make_pair(0, 0);
465 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
466 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
467 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
468 CurrentLoadedOffset -= TotalSize;
469 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
470 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
471 return std::make_pair(BaseID, CurrentLoadedOffset);
476llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
477 if (!FakeBufferForRecovery)
478 FakeBufferForRecovery =
479 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
481 return *FakeBufferForRecovery;
487 if (!FakeContentCacheForRecovery) {
488 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
489 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
491 return *FakeContentCacheForRecovery;
496FileID SourceManager::getPreviousFileID(
FileID FID)
const {
507 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
511 return FileID::get(ID-1);
524 }
else if (ID+1 >= -1) {
528 return FileID::get(ID+1);
550 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
551 LoadedID, LoadedOffset);
563 StringRef Name = Buffer->getBufferIdentifier();
564 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
565 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
577 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
578 LoadedID, LoadedOffset, IncludeLoc);
600 assert(LoadedID != -1 &&
"Loading sentinel FileID");
601 unsigned Index =
unsigned(-LoadedID) - 2;
602 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
603 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
606 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
607 return FileID::get(LoadedID);
609 unsigned FileSize =
File.getSize();
610 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
611 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
612 Diag.
Report(IncludePos, diag::err_sloc_space_too_large);
616 LocalSLocEntryTable.push_back(
621 NextLocalOffset += FileSize + 1;
625 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
626 return LastFileIDLookup = FID;
633 return createExpansionLocImpl(Info, Length);
639 bool ExpansionIsTokenRange,
int LoadedID,
642 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
643 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
650 "token spans multiple files");
651 return createExpansionLocImpl(
653 TokenEnd.getOffset() - TokenStart.getOffset());
657SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
658 unsigned Length,
int LoadedID,
661 assert(LoadedID != -1 &&
"Loading sentinel FileID");
662 unsigned Index =
unsigned(-LoadedID) - 2;
663 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
664 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
666 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
667 return SourceLocation::getMacroLoc(LoadedOffset);
669 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
670 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
671 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
678 llvm::report_fatal_error(
"ran out of source locations");
681 NextLocalOffset += Length + 1;
682 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
685std::optional<llvm::MemoryBufferRef>
692 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
698 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
704 "Different sizes, use the FileManager to create a virtual file with "
706 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
707 "This function should be called at the initialization stage, before "
708 "any parsing occurs.");
710 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
711 std::make_pair(SourceFile, NewFile));
713 Pair.first->second = NewFile;
725 (void)getOrCreateContentCache(*BypassFile);
733std::optional<StringRef>
736 if (Entry->getFile().getContentCache().
OrigEntry)
737 return Entry->getFile().getName();
745 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
748std::optional<StringRef>
759 return B->getBuffer();
774 return FileID::get(0);
778 if (SLocOffset < NextLocalOffset)
779 return getFileIDLocal(SLocOffset);
780 return getFileIDLoaded(SLocOffset);
788 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
805 unsigned LessIndex = 0;
807 unsigned GreaterIndex = LocalSLocEntryTable.size();
808 if (LastFileIDLookup.ID >= 0) {
810 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
811 LessIndex = LastFileIDLookup.ID;
813 GreaterIndex = LastFileIDLookup.ID;
817 unsigned NumProbes = 0;
820 assert(GreaterIndex < LocalSLocEntryTable.size());
821 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
822 FileID Res = FileID::get(
int(GreaterIndex));
824 LastFileIDLookup = Res;
825 NumLinearScans += NumProbes+1;
828 if (++NumProbes == 8)
834 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
842 if (MidOffset > SLocOffset) {
843 GreaterIndex = MiddleIndex;
848 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
850 FileID Res = FileID::get(MiddleIndex);
853 LastFileIDLookup = Res;
854 NumBinaryProbes += NumProbes;
859 LessIndex = MiddleIndex;
868 if (SLocOffset < CurrentLoadedOffset) {
869 assert(0 &&
"Invalid SLocOffset or bad function choice");
873 return FileID::get(ExternalSLocEntries->
getSLocEntryID(SLocOffset));
911std::pair<FileID, unsigned>
912SourceManager::getDecomposedExpansionLocSlowCase(
926 return std::make_pair(FID, Offset);
929std::pair<FileID, unsigned>
931 unsigned Offset)
const {
944 return std::make_pair(FID, Offset);
969 assert(
Loc.
isMacroID() &&
"Not a macro expansion loc!");
1026 if (DecompLoc.second > 0)
1040 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1052 *MacroBegin = ExpLoc;
1075 FileID NextFID = getNextFileID(FID);
1105 bool CharDataInvalid =
false;
1107 if (CharDataInvalid || !Entry.
isFile()) {
1111 return "<<<<INVALID BUFFER>>>>";
1113 std::optional<llvm::MemoryBufferRef> Buffer =
1118 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1119 :
"<<<<INVALID BUFFER>>>>";
1134 if (FilePos > MemBuf->getBufferSize()) {
1140 const char *Buf = MemBuf->getBufferStart();
1143 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->
SourceLineCache &&
1144 LastLineNoResult < LastLineNoContentCache->SourceLineCache.
size()) {
1145 const unsigned *SourceLineCache =
1147 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1148 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1149 if (FilePos >= LineStart && FilePos < LineEnd) {
1154 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1155 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1158 return FilePos - LineStart + 1;
1162 unsigned LineStart = FilePos;
1163 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1165 return FilePos-LineStart+1;
1170template<
typename LocType>
1206 return ((x - ~
static_cast<T>(0) / 255 * (n + 1)) & ~x &
1207 ((x & ~
static_cast<T>(0) / 255 * 127) +
1208 (~
static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1209 ~static_cast<T>(0) / 255 * 128;
1213 llvm::BumpPtrAllocator &Alloc) {
1220 LineOffsets.push_back(0);
1222 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1223 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1224 const unsigned char *Buf = Start;
1230 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1232 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1236 Buf +=
sizeof(Word);
1244 unsigned N = llvm::countr_zero(Mask) - 7;
1247 unsigned char Byte = Word;
1256 LineOffsets.push_back(Buf - Start);
1258 }
while (Buf < End -
sizeof(Word) - 1);
1264 LineOffsets.push_back(Buf - Start + 1);
1265 }
else if (*Buf ==
'\r') {
1267 if (Buf + 1 < End && Buf[1] ==
'\n') {
1270 LineOffsets.push_back(Buf - Start + 1);
1279 llvm::BumpPtrAllocator &Alloc)
1280 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.size() + 1)) {
1281 Storage[0] = LineOffsets.size();
1282 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1298 if (LastLineNoFileIDQuery == FID)
1299 Content = LastLineNoContentCache;
1301 bool MyInvalid =
false;
1302 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1303 if (MyInvalid || !Entry.
isFile()) {
1315 std::optional<llvm::MemoryBufferRef> Buffer =
1330 const unsigned *SourceLineCacheStart = SourceLineCache;
1333 unsigned QueriedFilePos = FilePos+1;
1348 if (LastLineNoFileIDQuery == FID) {
1349 if (QueriedFilePos >= LastLineNoFilePos) {
1351 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1357 if (SourceLineCache+5 < SourceLineCacheEnd) {
1358 if (SourceLineCache[5] > QueriedFilePos)
1359 SourceLineCacheEnd = SourceLineCache+5;
1360 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1361 if (SourceLineCache[10] > QueriedFilePos)
1362 SourceLineCacheEnd = SourceLineCache+10;
1363 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1364 if (SourceLineCache[20] > QueriedFilePos)
1365 SourceLineCacheEnd = SourceLineCache+20;
1370 if (LastLineNoResult < Content->SourceLineCache.size())
1371 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1375 const unsigned *Pos =
1376 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1377 unsigned LineNo = Pos-SourceLineCacheStart;
1379 LastLineNoFileIDQuery = FID;
1380 LastLineNoContentCache = Content;
1381 LastLineNoFilePos = QueriedFilePos;
1382 LastLineNoResult = LineNo;
1389 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(
Loc);
1390 return getLineNumber(LocInfo.first, LocInfo.second);
1395 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1396 return getLineNumber(LocInfo.first, LocInfo.second);
1415 assert(
Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1416 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1417 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1428 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1431 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1447 auto B = getBufferOrNone(getFileID(
Loc));
1450 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1461 bool UseLineDirectives)
const {
1465 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1478 FileID FID = LocInfo.first;
1482 else if (
auto Buffer =
C->getBufferOrNone(
Diag, getFileManager()))
1483 Filename = Buffer->getBufferIdentifier();
1485 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &
Invalid);
1488 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &
Invalid);
1497 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1500 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1502 if (Entry->FilenameID != -1) {
1503 Filename = LineTable->getFilename(Entry->FilenameID);
1506 FID = FileID::get(0);
1513 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1514 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1519 if (Entry->IncludeOffset) {
1520 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1540 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1542 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1551 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1552 if (Entry->IncludeOffset)
1567 if ((ID > 0 &&
unsigned(ID+1) == local_sloc_entry_size()))
1568 NextOffset = getNextLocalOffset();
1569 else if (ID+1 == -1)
1570 NextOffset = MaxLoadedOffset;
1572 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1574 return NextOffset - Entry.
getOffset() - 1;
1587 unsigned Col)
const {
1588 assert(SourceFile &&
"Null source file!");
1589 assert(
Line && Col &&
"Line and column should start from 1!");
1591 FileID FirstFID = translateFile(SourceFile);
1592 return translateLineCol(FirstFID,
Line, Col);
1600 assert(SourceFile &&
"Null source file!");
1604 if (MainFileID.isValid()) {
1618 for (
unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1619 const SLocEntry &SLoc = getLocalSLocEntry(I);
1622 return FileID::get(I);
1626 for (
unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1627 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1630 return FileID::get(-
int(I) - 2);
1640 unsigned Col)
const {
1643 assert(
Line && Col &&
"Line and column should start from 1!");
1658 if (
Line == 1 && Col == 1)
1665 std::optional<llvm::MemoryBufferRef> Buffer =
1674 unsigned Size = Buffer->getBufferSize();
1681 const char *Buf = Buffer->getBufferStart() + FilePos;
1682 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1689 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1701void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1713 if (
unsigned(ID) >= local_sloc_entry_size())
1715 }
else if (ID == -1) {
1730 bool IncludedInFID =
1731 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1735 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1736 if (IncludedInFID) {
1739 if (Entry.
getFile().NumCreatedFIDs)
1740 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1760 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1762 SourceLocation::getMacroLoc(Entry.
getOffset()),
1763 getFileIDSize(FileID::get(ID)));
1767void SourceManager::associateFileChunkWithMacroArgExp(
1768 MacroArgsMap &MacroArgsCache,
1772 unsigned ExpansionLength)
const {
1783 unsigned SpellRelativeOffs;
1784 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1786 const SLocEntry &Entry = getSLocEntry(SpellFID);
1788 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1792 unsigned CurrSpellLength;
1793 if (SpellFIDEndOffs < SpellEndOffs)
1794 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1796 CurrSpellLength = ExpansionLength;
1797 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1799 ExpansionLoc, CurrSpellLength);
1802 if (SpellFIDEndOffs >= SpellEndOffs)
1806 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1810 SpellRelativeOffs = 0;
1817 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1820 unsigned EndOffs = BeginOffs + ExpansionLength;
1839 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1842 MacroArgsCache[BeginOffs] = ExpansionLoc;
1843 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1862 std::tie(FID, Offset) = getDecomposedLoc(
Loc);
1866 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1867 if (!MacroArgsCache) {
1868 MacroArgsCache = std::make_unique<MacroArgsMap>();
1869 computeMacroArgsCache(*MacroArgsCache, FID);
1872 assert(!MacroArgsCache->empty());
1873 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1876 if (I == MacroArgsCache->begin())
1883 if (MacroArgExpandedLoc.
isValid())
1889std::pair<FileID, unsigned>
1892 return std::make_pair(
FileID(), 0);
1896 using DecompTy = std::pair<FileID, unsigned>;
1897 auto InsertOp = IncludedLocMap.try_emplace(FID);
1898 DecompTy &DecompLoc = InsertOp.first->second;
1899 if (!InsertOp.second)
1913 DecompLoc = getDecomposedLoc(UpperLoc);
1919 const std::pair<FileID, unsigned> &LOffs,
1920 const std::pair<FileID, unsigned> &ROffs)
const {
1922 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1925 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1926 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1929 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1930 std::greater<FileID>{});
1934 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1948 std::pair<FileID, unsigned> UpperLoc =
SM.getDecomposedIncludedLoc(
Loc.first);
1949 if (UpperLoc.first.isInvalid() ||
1950 !
SM.isInTheSameTranslationUnitImpl(UpperLoc,
Loc))
1965 enum { MagicCacheSize = 300 };
1966 IsBeforeInTUCacheKey Key(LFID, RFID);
1972 if (IBTUCache.size() < MagicCacheSize)
1973 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1976 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1977 if (I != IBTUCache.end())
1981 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
1982 return IBTUCacheOverflow;
1990 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
1994 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
1995 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
2000 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2001 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2003 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2005 return InSameTU.second;
2008 return LOffs.first < ROffs.first;
2012 std::pair<FileID, unsigned> &LOffs,
2013 std::pair<FileID, unsigned> &ROffs)
const {
2015 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2016 return std::make_pair(
false,
false);
2019 if (LOffs.first == ROffs.first)
2020 return std::make_pair(
true, LOffs.second < ROffs.second);
2025 getInBeforeInTUCache(LOffs.first, ROffs.first);
2030 return std::make_pair(
2040 std::pair<FileID, unsigned> DecomposedLoc;
2043 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2047 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2050 if (LOffs.first == ROffs.first)
2052 LChild = LOffs.first;
2057 auto LIt = LChain.find(ROffs.first);
2058 if (LIt != LChain.end()) {
2060 LOffs = LIt->second.DecomposedLoc;
2061 LChild = LIt->second.ChildFID;
2070 unsigned LChildID = LChild.ID;
2071 unsigned RChildID = RChild.ID;
2072 assert(((LOffs.second != ROffs.second) ||
2073 (LChildID == 0 || RChildID == 0) ||
2074 isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
2075 getComposedLoc(RChild, 0),
nullptr)) &&
2076 "Mixed local/loaded FileIDs with same include location?");
2077 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2078 LChildID < RChildID);
2079 return std::make_pair(
2082 RChild = ROffs.first;
2088 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2089 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2091 bool LIsBuiltins = LB ==
"<built-in>";
2092 bool RIsBuiltins = RB ==
"<built-in>";
2094 if (LIsBuiltins || RIsBuiltins) {
2095 if (LIsBuiltins != RIsBuiltins)
2096 return std::make_pair(
true, LIsBuiltins);
2099 return std::make_pair(
true, LOffs.first < ROffs.first);
2102 bool LIsAsm = LB ==
"<inline asm>";
2103 bool RIsAsm = RB ==
"<inline asm>";
2105 if (LIsAsm || RIsAsm) {
2106 if (LIsAsm != RIsAsm)
2107 return std::make_pair(
true, RIsAsm);
2108 assert(LOffs.first == ROffs.first);
2109 return std::make_pair(
true,
false);
2112 bool LIsScratch = LB ==
"<scratch space>";
2113 bool RIsScratch = RB ==
"<scratch space>";
2115 if (LIsScratch || RIsScratch) {
2116 if (LIsScratch != RIsScratch)
2117 return std::make_pair(
true, LIsScratch);
2118 return std::make_pair(
true, LOffs.second < ROffs.second);
2121 llvm_unreachable(
"Unsortable locations found");
2125 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2126 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2127 <<
" mem buffers mapped.\n";
2128 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2129 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2130 <<
" bytes of capacity), " << NextLocalOffset
2131 <<
"B of SLoc address space used.\n";
2132 llvm::errs() << LoadedSLocEntryTable.size()
2133 <<
" loaded SLocEntries allocated ("
2134 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2135 <<
" bytes of capacity), "
2136 << MaxLoadedOffset - CurrentLoadedOffset
2137 <<
"B of SLoc address space used.\n";
2139 unsigned NumLineNumsComputed = 0;
2140 unsigned NumFileBytesMapped = 0;
2142 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2143 NumFileBytesMapped += I->second->getSizeBytesMapped();
2145 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2147 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2148 << NumLineNumsComputed <<
" files with line #'s computed, "
2149 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2150 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2151 << NumBinaryProbes <<
" binary.\n";
2155 llvm::raw_ostream &out = llvm::errs();
2158 std::optional<SourceLocation::UIntTy> NextStart) {
2159 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2160 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2162 out << *NextStart <<
">\n";
2165 if (Entry.isFile()) {
2166 auto &FI = Entry.getFile();
2167 if (FI.NumCreatedFIDs)
2168 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2170 if (FI.getIncludeLoc().isValid())
2171 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2172 auto &CC = FI.getContentCache();
2173 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2175 if (CC.BufferOverridden)
2176 out <<
" contents overridden\n";
2177 if (CC.ContentsEntry != CC.OrigEntry) {
2178 out <<
" contents from "
2179 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2183 auto &EI = Entry.getExpansion();
2184 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2185 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2186 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2187 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2192 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2193 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2194 ID == NumIDs - 1 ? NextLocalOffset
2195 : LocalSLocEntryTable[ID + 1].getOffset());
2198 std::optional<SourceLocation::UIntTy> NextStart;
2199 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2200 int ID = -(
int)Index - 2;
2201 if (SLocEntryLoaded[Index]) {
2202 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2203 NextStart = LoadedSLocEntryTable[Index].getOffset();
2205 NextStart = std::nullopt;
2216 unsigned Inclusions = 0;
2218 uint64_t DirectSize = 0;
2220 uint64_t TotalSize = 0;
2222 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2225 uint64_t CountedSize = 0;
2227 auto AddUsageForFileID = [&](
FileID ID) {
2230 unsigned Size = getFileIDSize(ID) + 1;
2235 FileID FileLocID = getFileID(FileStart);
2236 const FileEntry *Entry = getFileEntryForID(FileLocID);
2238 Info &EntryInfo = Usage[Entry];
2239 if (EntryInfo.Loc.isInvalid())
2240 EntryInfo.Loc = FileStart;
2241 if (ID == FileLocID) {
2242 ++EntryInfo.Inclusions;
2243 EntryInfo.DirectSize += Size;
2245 EntryInfo.TotalSize += Size;
2246 CountedSize += Size;
2250 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2251 AddUsageForFileID(FileID::get(-2 - Index));
2254 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2255 AddUsageForFileID(FileID::get(Index));
2260 auto SortedUsage = Usage.takeVector();
2261 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2262 return A.second.TotalSize > B.second.TotalSize ||
2263 (A.second.TotalSize == B.second.TotalSize &&
2264 A.second.Loc < B.second.Loc);
2266 auto SortedEnd = SortedUsage.end();
2267 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2268 SortedEnd = SortedUsage.begin() + *MaxNotes;
2269 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2271 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2274 uint64_t LocalUsage = NextLocalOffset;
2275 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2276 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2279 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent;
2282 uint64_t ReportedSize = 0;
2284 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2288 ReportedSize +=
FileInfo.TotalSize;
2292 if (ReportedSize != CountedSize) {
2294 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2303 size_t malloc_bytes = 0;
2304 size_t mmap_bytes = 0;
2306 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2307 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2308 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2309 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2310 mmap_bytes += sized_mapped;
2312 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2313 malloc_bytes += sized_mapped;
2321 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2322 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2323 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2324 llvm::capacity_in_bytes(SLocEntryLoaded) +
2325 llvm::capacity_in_bytes(FileInfos);
2327 if (OverriddenFilesInfo)
2328 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2334 StringRef Content) {
2338 new llvm::vfs::InMemoryFileSystem);
2339 InMemoryFileSystem->addFile(
2341 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2349 Diagnostics = std::make_unique<DiagnosticsEngine>(
2352 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2356 assert(ID.isValid());
2357 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.
const FunctionProtoType * T
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)