19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/AutoConvert.h"
28#include "llvm/Support/Capacity.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Endian.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/raw_ostream.h"
45using namespace SrcMgr;
46using llvm::MemoryBuffer;
48#define DEBUG_TYPE "source-manager"
52STATISTIC(MaxUsedSLocBytes,
"Maximum number of bytes used by source locations "
53 "(both loaded and local).");
62 return Buffer ? Buffer->getBufferSize() : 0;
68 if (Buffer ==
nullptr) {
69 assert(0 &&
"Buffer should never be null");
70 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
72 return Buffer->getBufferKind();
80 return Buffer ? (
unsigned)Buffer->getBufferSize()
88 const char *InvalidBOM =
89 llvm::StringSwitch<const char *>(BufStr)
90 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
92 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
94 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
95 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
96 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
97 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
98 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
99 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
100 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
101 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
107std::optional<llvm::MemoryBufferRef>
115 return Buffer->getMemBufferRef();
130 if (!BufferOrError) {
131 Diag.Report(
Loc, diag::err_cannot_open_file)
137 Buffer = std::move(*BufferOrError);
148 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
170 StringRef BufStr = Buffer->getBuffer();
174 Diag.Report(
Loc, diag::err_unsupported_bom)
181 return Buffer->getMemBufferRef();
185 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
187 FilenamesByID.push_back(&*IterBool.first);
188 return IterBool.first->second;
198 int FilenameID,
unsigned EntryExit,
200 std::vector<LineEntry> &Entries = LineEntries[FID];
202 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
203 "Adding line entries out of order!");
205 unsigned IncludeOffset = 0;
206 if (EntryExit == 1) {
208 IncludeOffset = Offset-1;
210 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();
211 if (EntryExit == 2) {
213 assert(PrevEntry && PrevEntry->IncludeOffset &&
214 "PPDirectives should have caught case when popping empty include "
216 PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset);
219 IncludeOffset = PrevEntry->IncludeOffset;
220 if (FilenameID == -1) {
223 FilenameID = PrevEntry->FilenameID;
228 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
236 const std::vector<LineEntry> &Entries = LineEntries[FID];
237 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
241 if (Entries.back().FileOffset <= Offset)
242 return &Entries.back();
245 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
246 if (I == Entries.begin())
254 const std::vector<LineEntry> &Entries) {
255 LineEntries[FID] = Entries;
260 return getLineTable().getLineTableFilenameID(Name);
267 int FilenameID,
bool IsFileEntry,
282 (void) getLineTable();
284 unsigned EntryExit = 0;
290 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
291 EntryExit, FileKind);
305 bool UserFilesAreVolatile)
306 :
Diag(
Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
315 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
316 if (MemBufferInfos[i]) {
317 MemBufferInfos[i]->~ContentCache();
318 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
321 for (
auto I = FileInfos.begin(),
E = FileInfos.end(); I !=
E; ++I) {
323 I->second->~ContentCache();
324 ContentCacheAlloc.Deallocate(I->second);
331 LocalSLocEntryTable.clear();
332 LocalLocOffsetTable.clear();
333 LoadedSLocEntryTable.clear();
334 SLocEntryLoaded.clear();
335 SLocEntryOffsetLoaded.clear();
336 LastLineNoFileIDQuery =
FileID();
337 LastLineNoContentCache =
nullptr;
338 LastFileIDLookup =
FileID();
339 LastLookupStartOffset = LastLookupEndOffset = 0;
341 IncludedLocMap.clear();
347 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 updateSlocUsageStats();
470 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
471 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
472 return std::make_pair(BaseID, CurrentLoadedOffset);
477llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
478 if (!FakeBufferForRecovery)
479 FakeBufferForRecovery =
480 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
482 return *FakeBufferForRecovery;
488 if (!FakeContentCacheForRecovery) {
489 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
490 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
492 return *FakeContentCacheForRecovery;
497FileID SourceManager::getPreviousFileID(
FileID FID)
const {
508 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
512 return FileID::get(ID-1);
525 }
else if (ID+1 >= -1) {
529 return FileID::get(ID+1);
551 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
552 LoadedID, LoadedOffset);
564 StringRef Name = Buffer->getBufferIdentifier();
565 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
566 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
578 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
579 LoadedID, LoadedOffset, IncludeLoc);
601 assert(LoadedID != -1 &&
"Loading sentinel FileID");
602 unsigned Index =
unsigned(-LoadedID) - 2;
603 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
604 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
607 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
608 return FileID::get(LoadedID);
610 unsigned FileSize =
File.getSize();
611 llvm::ErrorOr<bool> NeedConversion =
612 llvm::needConversion(
Filename.str().c_str());
613 if (NeedConversion && *NeedConversion) {
616 if (std::optional<llvm::MemoryBufferRef> Buffer =
618 unsigned BufSize = Buffer->getBufferSize();
619 if (BufSize > FileSize) {
620 if (
File.ContentsEntry.has_value())
621 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
626 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
627 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
628 Diag.
Report(IncludePos, diag::err_sloc_space_too_large);
632 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
633 LocalSLocEntryTable.push_back(
636 LocalLocOffsetTable.push_back(NextLocalOffset);
637 LastLookupStartOffset = NextLocalOffset;
640 NextLocalOffset += FileSize + 1;
641 LastLookupEndOffset = NextLocalOffset;
642 updateSlocUsageStats();
646 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
647 return LastFileIDLookup = FID;
654 return createExpansionLocImpl(Info, Length);
660 bool ExpansionIsTokenRange,
int LoadedID,
663 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
664 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
671 "token spans multiple files");
672 return createExpansionLocImpl(
674 TokenEnd.getOffset() - TokenStart.getOffset());
678SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
679 unsigned Length,
int LoadedID,
682 assert(LoadedID != -1 &&
"Loading sentinel FileID");
683 unsigned Index =
unsigned(-LoadedID) - 2;
684 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
685 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
687 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
688 return SourceLocation::getMacroLoc(LoadedOffset);
690 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
691 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
692 LocalLocOffsetTable.push_back(NextLocalOffset);
693 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
694 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
695 Diag.
Report(diag::err_sloc_space_too_large);
701 llvm::report_fatal_error(
"ran out of source locations");
704 NextLocalOffset += Length + 1;
705 updateSlocUsageStats();
706 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
709std::optional<llvm::MemoryBufferRef>
716 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
722 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
728 "Different sizes, use the FileManager to create a virtual file with "
730 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
731 "This function should be called at the initialization stage, before "
732 "any parsing occurs.");
734 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
735 std::make_pair(SourceFile, NewFile));
737 Pair.first->second = NewFile;
749 (void)getOrCreateContentCache(*BypassFile);
757std::optional<StringRef>
760 if (Entry->getFile().getContentCache().
OrigEntry)
761 return Entry->getFile().getName();
769 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
772std::optional<StringRef>
783 return B->getBuffer();
798 return FileID::get(0);
802 if (SLocOffset < NextLocalOffset)
803 return getFileIDLocal(SLocOffset);
804 return getFileIDLoaded(SLocOffset);
812 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
813 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
814 "Invalid SLocOffset");
815 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
816 assert(LastFileIDLookup.ID >= 0 &&
"Only cache local file sloc entry");
833 unsigned LessIndex = 0;
835 unsigned GreaterIndex = LocalLocOffsetTable.size();
837 if (LastLookupStartOffset < SLocOffset)
838 LessIndex = LastFileIDLookup.ID;
840 GreaterIndex = LastFileIDLookup.ID;
843 unsigned NumProbes = 0;
846 assert(GreaterIndex < LocalLocOffsetTable.size());
847 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
848 FileID Res = FileID::get(
int(GreaterIndex));
850 LastFileIDLookup = Res;
851 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
852 LastLookupEndOffset =
853 GreaterIndex + 1 >= LocalLocOffsetTable.size()
855 : LocalLocOffsetTable[GreaterIndex + 1];
856 NumLinearScans += NumProbes + 1;
859 if (++NumProbes == 8)
863 while (LessIndex < GreaterIndex) {
866 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
867 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
868 LessIndex = MiddleIndex + 1;
870 GreaterIndex = MiddleIndex;
876 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
877 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
878 return LastFileIDLookup = FileID::get(LessIndex - 1);
886 if (SLocOffset < CurrentLoadedOffset) {
887 assert(0 &&
"Invalid SLocOffset or bad function choice");
891 return FileID::get(ExternalSLocEntries->
getSLocEntryID(SLocOffset));
935 Loc =
E->getExpansion().getExpansionLocStart();
939 Offset =
Loc.getOffset()-
E->getOffset();
942 return std::make_pair(FID, Offset);
947 unsigned Offset)
const {
952 Loc =
E->getExpansion().getSpellingLoc();
957 Offset =
Loc.getOffset()-
E->getOffset();
960 return std::make_pair(FID, Offset);
985 assert(
Loc.
isMacroID() &&
"Not a macro expansion loc!");
1042 if (DecompLoc.second > 0)
1056 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1068 *MacroBegin = ExpLoc;
1091 FileID NextFID = getNextFileID(FID);
1121 bool CharDataInvalid =
false;
1123 if (CharDataInvalid || !Entry.
isFile()) {
1127 return "<<<<INVALID BUFFER>>>>";
1129 std::optional<llvm::MemoryBufferRef> Buffer =
1134 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1135 :
"<<<<INVALID BUFFER>>>>";
1150 if (FilePos > MemBuf->getBufferSize()) {
1156 const char *Buf = MemBuf->getBufferStart();
1159 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->
SourceLineCache &&
1160 LastLineNoResult < LastLineNoContentCache->SourceLineCache.
size()) {
1161 const unsigned *SourceLineCache =
1163 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1164 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1165 if (FilePos >= LineStart && FilePos < LineEnd) {
1170 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1171 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1174 return (FilePos - LineStart) + 1;
1178 unsigned LineStart = FilePos;
1179 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1181 return (FilePos - LineStart) + 1;
1186template<
typename LocType>
1222 return ((x - ~
static_cast<T>(0) / 255 * (n + 1)) & ~x &
1223 ((x & ~
static_cast<T>(0) / 255 * 127) +
1224 (~
static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1225 ~static_cast<T>(0) / 255 * 128;
1229 llvm::BumpPtrAllocator &Alloc) {
1236 LineOffsets.push_back(0);
1238 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1239 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1240 const unsigned char *Buf = Start;
1246 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1248 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1252 Buf +=
sizeof(Word);
1260 unsigned N = llvm::countr_zero(Mask) - 7;
1263 unsigned char Byte = Word;
1272 LineOffsets.push_back(Buf - Start);
1274 }
while (Buf < End -
sizeof(Word) - 1);
1280 LineOffsets.push_back(Buf - Start + 1);
1281 }
else if (*Buf ==
'\r') {
1283 if (Buf + 1 < End && Buf[1] ==
'\n') {
1286 LineOffsets.push_back(Buf - Start + 1);
1295 llvm::BumpPtrAllocator &Alloc)
1296 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.size() + 1)) {
1297 Storage[0] = LineOffsets.size();
1298 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1314 if (LastLineNoFileIDQuery == FID)
1315 Content = LastLineNoContentCache;
1317 bool MyInvalid =
false;
1318 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1319 if (MyInvalid || !Entry.
isFile()) {
1331 std::optional<llvm::MemoryBufferRef> Buffer =
1346 const unsigned *SourceLineCacheStart = SourceLineCache;
1349 unsigned QueriedFilePos = FilePos+1;
1364 if (LastLineNoFileIDQuery == FID) {
1365 if (QueriedFilePos >= LastLineNoFilePos) {
1367 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1373 if (SourceLineCache+5 < SourceLineCacheEnd) {
1374 if (SourceLineCache[5] > QueriedFilePos)
1375 SourceLineCacheEnd = SourceLineCache+5;
1376 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1377 if (SourceLineCache[10] > QueriedFilePos)
1378 SourceLineCacheEnd = SourceLineCache+10;
1379 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1380 if (SourceLineCache[20] > QueriedFilePos)
1381 SourceLineCacheEnd = SourceLineCache+20;
1386 if (LastLineNoResult < Content->SourceLineCache.size())
1387 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1391 const unsigned *Pos =
1392 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1393 unsigned LineNo = Pos-SourceLineCacheStart;
1395 LastLineNoFileIDQuery = FID;
1396 LastLineNoContentCache = Content;
1397 LastLineNoFilePos = QueriedFilePos;
1398 LastLineNoResult = LineNo;
1406 return getLineNumber(LocInfo.first, LocInfo.second);
1412 return getLineNumber(LocInfo.first, LocInfo.second);
1431 assert(
Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1433 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1444 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1447 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1463 auto B = getBufferOrNone(getFileID(
Loc));
1466 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1477 bool UseLineDirectives)
const {
1494 FileID FID = LocInfo.first;
1498 else if (
auto Buffer =
C->getBufferOrNone(
Diag, getFileManager()))
1499 Filename = Buffer->getBufferIdentifier();
1501 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &
Invalid);
1504 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &
Invalid);
1513 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1516 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1518 if (Entry->FilenameID != -1) {
1519 Filename = LineTable->getFilename(Entry->FilenameID);
1522 FID = FileID::get(0);
1529 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1530 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1535 if (Entry->IncludeOffset) {
1536 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1558 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1567 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1568 if (Entry->IncludeOffset)
1583 if ((ID > 0 &&
unsigned(ID+1) == local_sloc_entry_size()))
1584 NextOffset = getNextLocalOffset();
1585 else if (ID+1 == -1)
1586 NextOffset = MaxLoadedOffset;
1588 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1590 return NextOffset - Entry.
getOffset() - 1;
1603 unsigned Col)
const {
1604 assert(SourceFile &&
"Null source file!");
1605 assert(
Line && Col &&
"Line and column should start from 1!");
1607 FileID FirstFID = translateFile(SourceFile);
1608 return translateLineCol(FirstFID,
Line, Col);
1616 assert(SourceFile &&
"Null source file!");
1620 if (MainFileID.isValid()) {
1634 for (
unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1635 const SLocEntry &SLoc = getLocalSLocEntry(I);
1638 return FileID::get(I);
1642 for (
unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1643 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1646 return FileID::get(-
int(I) - 2);
1656 unsigned Col)
const {
1659 assert(
Line && Col &&
"Line and column should start from 1!");
1674 if (
Line == 1 && Col == 1)
1681 std::optional<llvm::MemoryBufferRef> Buffer =
1690 unsigned Size = Buffer->getBufferSize();
1697 const char *Buf = Buffer->getBufferStart() + FilePos;
1698 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1705 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1717void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1722 MacroArgsCache.try_emplace(0);
1729 if (
unsigned(ID) >= local_sloc_entry_size())
1731 }
else if (ID == -1) {
1746 bool IncludedInFID =
1747 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1751 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1752 if (IncludedInFID) {
1755 if (Entry.
getFile().NumCreatedFIDs)
1756 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1776 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1778 SourceLocation::getMacroLoc(Entry.
getOffset()),
1779 getFileIDSize(FileID::get(ID)));
1783void SourceManager::associateFileChunkWithMacroArgExp(
1784 MacroArgsMap &MacroArgsCache,
1788 unsigned ExpansionLength)
const {
1799 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1801 const SLocEntry &Entry = getSLocEntry(SpellFID);
1803 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1807 unsigned CurrSpellLength;
1808 if (SpellFIDEndOffs < SpellEndOffs)
1809 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1811 CurrSpellLength = ExpansionLength;
1812 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1814 ExpansionLoc, CurrSpellLength);
1817 if (SpellFIDEndOffs >= SpellEndOffs)
1821 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1825 SpellRelativeOffs = 0;
1832 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1835 unsigned EndOffs = BeginOffs + ExpansionLength;
1854 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1857 MacroArgsCache[BeginOffs] = ExpansionLoc;
1858 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1861void SourceManager::updateSlocUsageStats()
const {
1863 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1864 MaxUsedSLocBytes.updateMax(UsedBytes);
1881 auto [FID, Offset] = getDecomposedLoc(
Loc);
1885 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1886 if (!MacroArgsCache) {
1887 MacroArgsCache = std::make_unique<MacroArgsMap>();
1888 computeMacroArgsCache(*MacroArgsCache, FID);
1891 assert(!MacroArgsCache->empty());
1892 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1895 if (I == MacroArgsCache->begin())
1902 if (MacroArgExpandedLoc.
isValid())
1910 return std::make_pair(
FileID(), 0);
1915 auto InsertOp = IncludedLocMap.try_emplace(FID);
1916 DecompTy &DecompLoc = InsertOp.first->second;
1917 if (!InsertOp.second)
1931 DecompLoc = getDecomposedLoc(UpperLoc);
1937 assert(isLoadedSourceLocation(
Loc) &&
1938 "Must be a source location in a loaded PCH/Module file");
1940 auto [FID, Ignore] = getDecomposedLoc(
Loc);
1946 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1949 "The failure to find the first FileID of a "
1950 "loaded AST from a loaded source location was unexpected.");
1957 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1960 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1961 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1964 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1965 std::greater<FileID>{});
1969 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1983 if (UpperLoc.first.isInvalid() ||
1984 !
SM.isInTheSameTranslationUnitImpl(UpperLoc,
Loc))
1999 enum { MagicCacheSize = 300 };
2000 IsBeforeInTUCacheKey Key(LFID, RFID);
2006 if (IBTUCache.size() < MagicCacheSize)
2007 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
2010 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2011 if (I != IBTUCache.end())
2015 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2016 return IBTUCacheOverflow;
2024 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2034 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2035 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2037 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2039 return InSameTU.second;
2041 return LOffs.first < ROffs.first;
2044std::pair<bool, bool>
2048 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2049 return std::make_pair(
false,
false);
2052 if (LOffs.first == ROffs.first)
2053 return std::make_pair(
true, LOffs.second < ROffs.second);
2058 getInBeforeInTUCache(LOffs.first, ROffs.first);
2063 return std::make_pair(
2076 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2080 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2083 if (LOffs.first == ROffs.first)
2085 LChild = LOffs.first;
2090 auto LIt = LChain.find(ROffs.first);
2091 if (LIt != LChain.end()) {
2093 LOffs = LIt->second.DecomposedLoc;
2094 LChild = LIt->second.ChildFID;
2103 unsigned LChildID = LChild.ID;
2104 unsigned RChildID = RChild.ID;
2105 assert(((LOffs.second != ROffs.second) ||
2106 (LChildID == 0 || RChildID == 0) ||
2107 isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
2108 getComposedLoc(RChild, 0),
nullptr)) &&
2109 "Mixed local/loaded FileIDs with same include location?");
2110 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2111 LChildID < RChildID);
2112 return std::make_pair(
2115 RChild = ROffs.first;
2121 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2122 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2124 bool LIsBuiltins = LB ==
"<built-in>";
2125 bool RIsBuiltins = RB ==
"<built-in>";
2127 if (LIsBuiltins || RIsBuiltins) {
2128 if (LIsBuiltins != RIsBuiltins)
2129 return std::make_pair(
true, LIsBuiltins);
2132 return std::make_pair(
true, LOffs.first < ROffs.first);
2135 bool LIsAsm = LB ==
"<inline asm>";
2136 bool RIsAsm = RB ==
"<inline asm>";
2138 if (LIsAsm || RIsAsm) {
2139 if (LIsAsm != RIsAsm)
2140 return std::make_pair(
true, RIsAsm);
2141 assert(LOffs.first == ROffs.first);
2142 return std::make_pair(
true,
false);
2145 bool LIsScratch = LB ==
"<scratch space>";
2146 bool RIsScratch = RB ==
"<scratch space>";
2148 if (LIsScratch || RIsScratch) {
2149 if (LIsScratch != RIsScratch)
2150 return std::make_pair(
true, LIsScratch);
2151 return std::make_pair(
true, LOffs.second < ROffs.second);
2154 llvm_unreachable(
"Unsortable locations found");
2158 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2159 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2160 <<
" mem buffers mapped.\n";
2161 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2162 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2163 <<
" bytes of capacity), " << NextLocalOffset
2164 <<
"B of SLoc address space used.\n";
2165 llvm::errs() << LoadedSLocEntryTable.size()
2166 <<
" loaded SLocEntries allocated ("
2167 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2168 <<
" bytes of capacity), "
2169 << MaxLoadedOffset - CurrentLoadedOffset
2170 <<
"B of SLoc address space used.\n";
2172 unsigned NumLineNumsComputed = 0;
2173 unsigned NumFileBytesMapped = 0;
2175 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2176 NumFileBytesMapped += I->second->getSizeBytesMapped();
2178 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2180 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2181 << NumLineNumsComputed <<
" files with line #'s computed, "
2182 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2183 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2184 << NumBinaryProbes <<
" binary.\n";
2188 llvm::raw_ostream &
out = llvm::errs();
2191 std::optional<SourceLocation::UIntTy> NextStart) {
2192 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2193 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2195 out << *NextStart <<
">\n";
2198 if (Entry.isFile()) {
2199 auto &FI = Entry.getFile();
2200 if (FI.NumCreatedFIDs)
2201 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2203 if (FI.getIncludeLoc().isValid())
2204 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2205 auto &CC = FI.getContentCache();
2206 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2208 if (CC.BufferOverridden)
2209 out <<
" contents overridden\n";
2210 if (CC.ContentsEntry != CC.OrigEntry) {
2211 out <<
" contents from "
2212 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2216 auto &EI = Entry.getExpansion();
2217 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2218 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2219 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2220 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2225 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2226 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2227 ID == NumIDs - 1 ? NextLocalOffset
2228 : LocalSLocEntryTable[ID + 1].getOffset());
2231 std::optional<SourceLocation::UIntTy> NextStart;
2232 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2233 int ID = -(
int)Index - 2;
2234 if (SLocEntryLoaded[Index]) {
2235 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2236 NextStart = LoadedSLocEntryTable[Index].getOffset();
2238 NextStart = std::nullopt;
2249 unsigned Inclusions = 0;
2251 uint64_t DirectSize = 0;
2253 uint64_t TotalSize = 0;
2255 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2258 uint64_t CountedSize = 0;
2260 auto AddUsageForFileID = [&](
FileID ID) {
2263 unsigned Size = getFileIDSize(ID) + 1;
2268 FileID FileLocID = getFileID(FileStart);
2269 const FileEntry *Entry = getFileEntryForID(FileLocID);
2271 Info &EntryInfo = Usage[Entry];
2272 if (EntryInfo.Loc.isInvalid())
2273 EntryInfo.Loc = FileStart;
2274 if (ID == FileLocID) {
2275 ++EntryInfo.Inclusions;
2276 EntryInfo.DirectSize += Size;
2278 EntryInfo.TotalSize += Size;
2279 CountedSize += Size;
2283 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2284 AddUsageForFileID(FileID::get(-2 - Index));
2287 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2288 AddUsageForFileID(FileID::get(Index));
2293 auto SortedUsage = Usage.takeVector();
2294 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2295 return A.second.TotalSize > B.second.TotalSize ||
2296 (A.second.TotalSize == B.second.TotalSize &&
2297 A.second.Loc < B.second.Loc);
2299 auto SortedEnd = SortedUsage.end();
2300 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2301 SortedEnd = SortedUsage.begin() + *MaxNotes;
2302 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2304 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2307 uint64_t LocalUsage = NextLocalOffset;
2308 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2309 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2311 Diag.Report(diag::note_total_sloc_usage)
2312 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2316 uint64_t ReportedSize = 0;
2318 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2322 ReportedSize +=
FileInfo.TotalSize;
2326 if (ReportedSize != CountedSize) {
2327 Diag.Report(diag::note_file_misc_sloc_usage)
2328 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2337 size_t malloc_bytes = 0;
2338 size_t mmap_bytes = 0;
2340 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2341 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2342 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2343 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2344 mmap_bytes += sized_mapped;
2346 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2347 malloc_bytes += sized_mapped;
2355 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2356 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2357 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2358 llvm::capacity_in_bytes(SLocEntryLoaded) +
2359 llvm::capacity_in_bytes(FileInfos);
2361 if (OverriddenFilesInfo)
2362 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2368 StringRef Content) {
2369 auto InMemoryFileSystem =
2370 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
2371 InMemoryFileSystem->addFile(
2373 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2378 std::move(InMemoryFileSystem));
2379 DiagOpts = std::make_unique<DiagnosticOptions>();
2384 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2388 assert(ID.isValid());
2389 SourceMgr->setMainFileID(ID);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static ParseState advance(ParseState S, size_t N)
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool isInvalid(LocType Loc, bool *Invalid)
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
Defines the SourceManager interface.
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)
static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()
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)
void ResetPragmas()
We keep a cache of FileIDs for diagnostics mapped by pragmas.
virtual int getSLocEntryID(SourceLocation::UIntTy SLocOffset)=0
Get the index ID for the loaded SourceLocation offset.
virtual ~ExternalSLocEntrySource()
virtual bool ReadSLocEntry(int ID)=0
Read the source location entry with index ID, which will always be less than -1.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=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...
FileIDAndOffset getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
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.
bool isInTheSameTranslationUnitImpl(const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same TU.
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
void setFileIsTransient(FileEntryRef SourceFile)
Specify that a file is transient.
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
std::optional< StringRef > getBufferDataOrNone(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
void PrintStats() const
Print statistics to stderr.
FileID getUniqueLoadedASTFileID(SourceLocation Loc) const
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
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...
FileIDAndOffset getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
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.
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.
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.
FileIDAndOffset getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
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.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
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< bool, bool > isInTheSameTranslationUnit(FileIDAndOffset &LOffs, FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
LineTableInfo & getLineTable()
Retrieve the stored line table.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length)
Creates an expansion SLocEntry for the substitution of an argument into a function-like macro's body.
A trivial tuple used to represent a source range.
One instance of this struct is kept for every file loaded or used.
void setBuffer(std::unique_ptr< llvm::MemoryBuffer > B)
Set the buffer.
std::optional< StringRef > getBufferDataIfLoaded() const
Return a StringRef to the source buffer data, only if it has already been loaded.
OptionalFileEntryRef ContentsEntry
References the file which the contents were actually loaded from.
unsigned getSizeBytesMapped() const
Returns the number of bytes actually mapped for this ContentCache.
unsigned IsTransient
True if this file may be transient, that is, if it might not exist at some later point in time when t...
unsigned getSize() const
Returns the size of the content encapsulated by this ContentCache.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache.
unsigned IsFileVolatile
True if this content cache was initially created for a source file considered to be volatile (likely ...
LineOffsetMapping SourceLineCache
A bump pointer allocated array of offsets for each source line.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
static const char * getInvalidBOM(StringRef BufStr)
unsigned BufferOverridden
Indicates whether the buffer itself was provided to override the actual file contents.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)
Return a ExpansionInfo for an expansion.
bool isMacroBodyExpansion() const
SourceLocation getSpellingLoc() const
CharSourceRange getExpansionLocRange() const
bool isMacroArgExpansion() const
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)
Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)
Return a special ExpansionInfo representing a token that ends prematurely.
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)
Return a FileInfo object.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
void setHasLineDirectives()
Set the flag that indicates that this FileID has line table entries associated with it.
SourceLocation getIncludeLoc() const
StringRef getName() const
Returns the name of the file that was used when the file was loaded from the underlying file system.
Mapping of line offsets into a source file.
const unsigned * begin() const
LineOffsetMapping()=default
const unsigned * end() const
static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)
This is a discriminated union of FileInfo and ExpansionInfo.
SourceLocation::UIntTy getOffset() const
static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)
const FileInfo & getFile() const
const ExpansionInfo & getExpansion() const
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
The JSON file list parser is used to communicate input to InstallAPI.
std::pair< FileID, unsigned > FileIDAndOffset
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)