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/Path.h"
34#include "llvm/Support/VirtualFileSystem.h"
35#include "llvm/Support/raw_ostream.h"
49using llvm::MemoryBuffer;
51#define DEBUG_TYPE "source-manager"
57 Clone->ContentsEntry =
Other.ContentsEntry;
58 Clone->Filename =
Other.Filename;
59 Clone->BufferOverridden =
Other.BufferOverridden;
60 Clone->IsFileVolatile =
Other.IsFileVolatile;
61 Clone->IsTransient =
Other.IsTransient;
62 Clone->IsBufferInvalid =
Other.IsBufferInvalid;
63 Clone->setUnownedBuffer(
Other.getBufferIfLoaded());
69STATISTIC(MaxUsedSLocBytes,
"Maximum number of bytes used by source locations "
70 "(both loaded and local).");
79 return Buffer ? Buffer->getBufferSize() : 0;
85 if (Buffer ==
nullptr) {
86 assert(0 &&
"Buffer should never be null");
87 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
89 return Buffer->getBufferKind();
97 return Buffer ? (
unsigned)Buffer->getBufferSize()
105 const char *InvalidBOM =
106 llvm::StringSwitch<const char *>(BufStr)
107 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
109 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
111 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
112 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
113 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
114 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
115 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
116 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
117 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
118 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
124std::optional<llvm::MemoryBufferRef>
132 return Buffer->getMemBufferRef();
147 if (!BufferOrError) {
148 Diag.Report(Loc, diag::err_cannot_open_file)
149 <<
ContentsEntry->getName() << BufferOrError.getError().message();
154 Buffer = std::move(*BufferOrError);
165 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
176 assert(Buffer->getBufferSize() >= (
size_t)
ContentsEntry->getSize());
178 Buffer->getBufferSize() < (
size_t)
ContentsEntry->getSize()) {
187 StringRef BufStr = Buffer->getBuffer();
191 Diag.Report(Loc, diag::err_unsupported_bom)
198 return Buffer->getMemBufferRef();
202 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
204 FilenamesByID.push_back(&*IterBool.first);
205 return IterBool.first->second;
215 int FilenameID,
unsigned EntryExit,
217 std::vector<LineEntry> &Entries = LineEntries[FID];
219 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
220 "Adding line entries out of order!");
222 unsigned IncludeOffset = 0;
223 if (EntryExit == 1) {
225 IncludeOffset = Offset-1;
227 const auto *PrevEntry = Entries.empty() ?
nullptr : &Entries.back();
228 if (EntryExit == 2) {
230 assert(PrevEntry && PrevEntry->IncludeOffset &&
231 "PPDirectives should have caught case when popping empty include "
236 IncludeOffset = PrevEntry->IncludeOffset;
237 if (FilenameID == -1) {
240 FilenameID = PrevEntry->FilenameID;
245 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
253 const std::vector<LineEntry> &Entries = LineEntries[FID];
254 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
258 if (Entries.back().FileOffset <= Offset)
259 return &Entries.back();
262 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
263 if (I == Entries.begin())
271 const std::vector<LineEntry> &Entries) {
272 LineEntries[FID] = Entries;
284 int FilenameID,
bool IsFileEntry,
301 unsigned EntryExit = 0;
307 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
308 EntryExit, FileKind);
322 bool UserFilesAreVolatile)
323 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
325 Diag.setSourceManager(
this);
332 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
333 if (MemBufferInfos[i]) {
334 MemBufferInfos[i]->~ContentCache();
335 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
338 for (
auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
340 I->second->~ContentCache();
341 ContentCacheAlloc.Deallocate(I->second);
344 for (
unsigned i = 0, e = FileIDContentCaches.size(); i != e; ++i) {
345 if (FileIDContentCaches[i]) {
346 FileIDContentCaches[i]->~ContentCache();
347 ContentCacheAlloc.Deallocate(FileIDContentCaches[i]);
353 for (
unsigned i = 0, e = FileIDContentCaches.size(); i != e; ++i) {
354 if (FileIDContentCaches[i]) {
355 FileIDContentCaches[i]->~ContentCache();
356 ContentCacheAlloc.Deallocate(FileIDContentCaches[i]);
359 FileIDContentCaches.clear();
362 LocalSLocEntryTable.clear();
363 LocalLocOffsetTable.clear();
364 LoadedSLocEntryTable.clear();
365 SLocEntryLoaded.clear();
366 SLocEntryOffsetLoaded.clear();
367 LastLineNoFileIDQuery =
FileID();
368 LastLineNoContentCache =
nullptr;
369 LastFileIDLookup =
FileID();
370 LastLookupStartOffset = LastLookupEndOffset = 0;
372 IncludedLocMap.clear();
378 CurrentLoadedOffset = MaxLoadedOffset;
386 assert(MainFileID.isValid() &&
"expected initialized SourceManager");
388 return FE->getUID() == SourceFile.
getUID();
393 assert(MainFileID.isInvalid() &&
"expected uninitialized SourceManager");
396 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
397 if (!Old.SLocEntryLoaded[I])
398 Old.loadSLocEntry(I,
nullptr);
401 for (
auto &
FileInfo : Old.FileInfos) {
419 if (OverriddenFilesInfo) {
422 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
423 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
426 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
442ContentCache &SourceManager::createMemBufferContentCache(
443 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
445 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
446 new (Entry) ContentCache();
447 MemBufferInfos.push_back(Entry);
458 assert(!SLocEntryLoaded[Index]);
459 if (ExternalSLocEntries->ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
463 if (!SLocEntryLoaded[Index]) {
465 if (!FakeSLocEntryForRecovery)
466 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
467 0,
FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
469 return *FakeSLocEntryForRecovery;
473 return LoadedSLocEntryTable[Index];
476std::pair<int, SourceLocation::UIntTy>
479 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
481 if (CurrentLoadedOffset < TotalSize ||
482 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
483 return std::make_pair(0, 0);
485 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
486 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
487 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
488 CurrentLoadedOffset -= TotalSize;
489 updateSlocUsageStats();
490 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
491 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
492 return std::make_pair(BaseID, CurrentLoadedOffset);
497llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
498 if (!FakeBufferForRecovery)
499 FakeBufferForRecovery =
500 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
502 return *FakeBufferForRecovery;
508 if (!FakeContentCacheForRecovery) {
509 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
510 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
512 return *FakeContentCacheForRecovery;
517FileID SourceManager::getPreviousFileID(
FileID FID)
const {
528 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
532 return FileID::get(ID-1);
545 }
else if (ID+1 >= -1) {
549 return FileID::get(ID+1);
566 StringRef Filename = SourceFile.
getName();
570 Cache->OrigEntry = SourceFile;
571 FileIDContentCaches.push_back(
Cache);
576 if (
Cache->ContentsEntry->isNamedPipe())
579 return createFileIDImpl(*
Cache, Filename, IncludePos, FileCharacter, LoadedID,
592 StringRef Name = Buffer->getBufferIdentifier();
593 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
594 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
606 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
607 LoadedID, LoadedOffset, IncludeLoc);
629 assert(LoadedID != -1 &&
"Loading sentinel FileID");
630 unsigned Index =
unsigned(-LoadedID) - 2;
631 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
632 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
635 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
636 return FileID::get(LoadedID);
638 unsigned FileSize =
File.getSize();
639 llvm::ErrorOr<bool> NeedConversion = llvm::needConversion(Filename);
640 if (NeedConversion && *NeedConversion) {
643 if (std::optional<llvm::MemoryBufferRef> Buffer =
645 unsigned BufSize = Buffer->getBufferSize();
646 if (BufSize > FileSize) {
647 if (
File.ContentsEntry.has_value())
648 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
653 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
654 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
655 Diag.Report(IncludePos, diag::err_sloc_space_too_large);
659 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
660 LocalSLocEntryTable.push_back(
663 LocalLocOffsetTable.push_back(NextLocalOffset);
664 LastLookupStartOffset = NextLocalOffset;
667 NextLocalOffset += FileSize + 1;
668 LastLookupEndOffset = NextLocalOffset;
669 updateSlocUsageStats();
673 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
674 return LastFileIDLookup = FID;
681 return createExpansionLocImpl(Info, Length);
687 bool ExpansionIsTokenRange,
int LoadedID,
690 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
691 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
698 "token spans multiple files");
699 return createExpansionLocImpl(
701 TokenEnd.getOffset() - TokenStart.getOffset());
705SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
706 unsigned Length,
int LoadedID,
709 assert(LoadedID != -1 &&
"Loading sentinel FileID");
710 unsigned Index =
unsigned(-LoadedID) - 2;
711 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
712 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
714 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
715 return SourceLocation::getMacroLoc(LoadedOffset);
717 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
718 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
719 LocalLocOffsetTable.push_back(NextLocalOffset);
720 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
721 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
722 Diag.Report(diag::err_sloc_space_too_large);
728 llvm::report_fatal_error(
"ran out of source locations");
731 NextLocalOffset += Length + 1;
732 updateSlocUsageStats();
733 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
736std::optional<llvm::MemoryBufferRef>
743 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
749 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
755 "Different sizes, use the FileManager to create a virtual file with "
757 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
758 "This function should be called at the initialization stage, before "
759 "any parsing occurs.");
761 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
762 std::make_pair(SourceFile, NewFile));
764 Pair.first->second = NewFile;
776 (void)getOrCreateContentCache(*BypassFile);
781 getOrCreateContentCache(
File).IsTransient =
true;
784std::optional<StringRef>
787 if (Entry->getFile().getContentCache().
OrigEntry)
788 return Entry->getFile().getName();
796 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
799std::optional<StringRef>
810 return B->getBuffer();
825 return FileID::get(0);
829 if (SLocOffset < NextLocalOffset)
830 return getFileIDLocal(SLocOffset);
831 return getFileIDLoaded(SLocOffset);
839 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
840 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
841 "Invalid SLocOffset");
842 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
843 assert(LastFileIDLookup.ID >= 0 &&
"Only cache local file sloc entry");
860 unsigned LessIndex = 0;
862 unsigned GreaterIndex = LocalLocOffsetTable.size();
864 if (LastLookupStartOffset < SLocOffset)
865 LessIndex = LastFileIDLookup.ID;
867 GreaterIndex = LastFileIDLookup.ID;
870 unsigned NumProbes = 0;
873 assert(GreaterIndex < LocalLocOffsetTable.size());
874 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
875 FileID Res = FileID::get(
int(GreaterIndex));
877 LastFileIDLookup = Res;
878 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
879 LastLookupEndOffset =
880 GreaterIndex + 1 >= LocalLocOffsetTable.size()
882 : LocalLocOffsetTable[GreaterIndex + 1];
883 NumLinearScans += NumProbes + 1;
886 if (++NumProbes == 8)
890 while (LessIndex < GreaterIndex) {
893 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
894 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
895 LessIndex = MiddleIndex + 1;
897 GreaterIndex = MiddleIndex;
903 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
904 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
905 return LastFileIDLookup = FileID::get(LessIndex - 1);
913 if (SLocOffset < CurrentLoadedOffset) {
914 assert(0 &&
"Invalid SLocOffset or bad function choice");
918 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
946 unsigned MaxDepth)
const {
949 if (Depth++ == MaxDepth)
950 return SourceLocation();
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 =
1162 LastLineNoContentCache->SourceLineCache.begin();
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>
1188 bool MyInvalid = Loc.isInvalid();
1216 return ((x - ~
static_cast<T>(0) / 255 * (n + 1)) & ~x &
1217 ((x & ~
static_cast<T>(0) / 255 * 127) +
1218 (~
static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1219 ~static_cast<T>(0) / 255 * 128;
1223 llvm::BumpPtrAllocator &Alloc) {
1230 LineOffsets.push_back(0);
1232 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1233 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1234 const unsigned char *Buf = Start;
1240 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1242 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1246 Buf +=
sizeof(Word);
1254 unsigned N = llvm::countr_zero(Mask) - 7;
1257 unsigned char Byte = Word;
1266 LineOffsets.push_back(Buf - Start);
1268 }
while (Buf < End -
sizeof(Word) - 1);
1274 LineOffsets.push_back(Buf - Start + 1);
1275 }
else if (*Buf ==
'\r') {
1277 if (Buf + 1 < End && Buf[1] ==
'\n') {
1280 LineOffsets.push_back(Buf - Start + 1);
1289 llvm::BumpPtrAllocator &Alloc)
1290 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.
size() + 1)) {
1291 Storage[0] = LineOffsets.size();
1292 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1308 if (LastLineNoFileIDQuery == FID)
1309 Content = LastLineNoContentCache;
1311 bool MyInvalid =
false;
1313 if (MyInvalid || !Entry.
isFile()) {
1325 std::optional<llvm::MemoryBufferRef> Buffer =
1340 const unsigned *SourceLineCacheStart = SourceLineCache;
1343 unsigned QueriedFilePos = FilePos+1;
1358 if (LastLineNoFileIDQuery == FID) {
1359 if (QueriedFilePos >= LastLineNoFilePos) {
1361 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1367 if (SourceLineCache+5 < SourceLineCacheEnd) {
1368 if (SourceLineCache[5] > QueriedFilePos)
1369 SourceLineCacheEnd = SourceLineCache+5;
1370 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1371 if (SourceLineCache[10] > QueriedFilePos)
1372 SourceLineCacheEnd = SourceLineCache+10;
1373 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1374 if (SourceLineCache[20] > QueriedFilePos)
1375 SourceLineCacheEnd = SourceLineCache+20;
1380 if (LastLineNoResult < Content->SourceLineCache.size())
1381 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1385 const unsigned *Pos =
1386 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1387 unsigned LineNo = Pos-SourceLineCacheStart;
1389 LastLineNoFileIDQuery = FID;
1390 LastLineNoContentCache = Content;
1391 LastLineNoFilePos = QueriedFilePos;
1392 LastLineNoResult = LineNo;
1420 assert(Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1422 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1433 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1436 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1455 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1466 bool UseLineDirectives)
const {
1483 FileID FID = LocInfo.first;
1486 Filename =
C->OrigEntry->getName();
1488 Filename = Buffer->getBufferIdentifier();
1502 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1505 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1507 if (Entry->FilenameID != -1) {
1508 Filename = LineTable->getFilename(Entry->FilenameID);
1511 FID = FileID::get(0);
1518 unsigned MarkerLineNo =
getLineNumber(LocInfo.first, Entry->FileOffset);
1519 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1524 if (Entry->IncludeOffset) {
1531 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1547 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1556 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1557 if (Entry->IncludeOffset)
1574 else if (ID+1 == -1)
1575 NextOffset = MaxLoadedOffset;
1577 NextOffset =
getSLocEntry(FileID::get(ID+1)).getOffset();
1579 return NextOffset - Entry.
getOffset() - 1;
1592 unsigned Col)
const {
1593 assert(SourceFile &&
"Null source file!");
1594 assert(
Line && Col &&
"Line and column should start from 1!");
1605 assert(SourceFile &&
"Null source file!");
1609 if (MainFileID.isValid()) {
1627 return FileID::get(I);
1635 return FileID::get(-
int(I) - 2);
1645 unsigned Col)
const {
1648 assert(
Line && Col &&
"Line and column should start from 1!");
1663 if (
Line == 1 && Col == 1)
1670 std::optional<llvm::MemoryBufferRef> Buffer =
1679 unsigned Size = Buffer->getBufferSize();
1686 const char *Buf = Buffer->getBufferStart() + FilePos;
1687 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1694 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1706void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1711 MacroArgsCache.try_emplace(0);
1718 if (
unsigned(ID) >= local_sloc_entry_size())
1720 }
else if (ID == -1) {
1725 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &
Invalid);
1735 bool IncludedInFID =
1736 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1740 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1741 if (IncludedInFID) {
1744 if (Entry.
getFile().NumCreatedFIDs)
1745 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1765 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1767 SourceLocation::getMacroLoc(Entry.
getOffset()),
1768 getFileIDSize(FileID::get(ID)));
1772void SourceManager::associateFileChunkWithMacroArgExp(
1773 MacroArgsMap &MacroArgsCache,
1775 SourceLocation SpellLoc,
1776 SourceLocation ExpansionLoc,
1777 unsigned ExpansionLength)
const {
1788 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1790 const SLocEntry &Entry = getSLocEntry(SpellFID);
1792 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1796 unsigned CurrSpellLength;
1797 if (SpellFIDEndOffs < SpellEndOffs)
1798 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1800 CurrSpellLength = ExpansionLength;
1801 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1803 ExpansionLoc, CurrSpellLength);
1806 if (SpellFIDEndOffs >= SpellEndOffs)
1810 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1814 SpellRelativeOffs = 0;
1821 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1824 unsigned EndOffs = BeginOffs + ExpansionLength;
1843 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1845 SourceLocation EndOffsMappedLoc = I->second;
1846 MacroArgsCache[BeginOffs] = ExpansionLoc;
1847 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1850void SourceManager::updateSlocUsageStats()
const {
1852 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1853 MaxUsedSLocBytes.updateMax(UsedBytes);
1874 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1875 if (!MacroArgsCache) {
1876 MacroArgsCache = std::make_unique<MacroArgsMap>();
1877 computeMacroArgsCache(*MacroArgsCache, FID);
1880 assert(!MacroArgsCache->empty());
1881 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1884 if (I == MacroArgsCache->begin())
1891 if (MacroArgExpandedLoc.
isValid())
1899 return std::make_pair(
FileID(), 0);
1904 auto InsertOp = IncludedLocMap.try_emplace(FID);
1905 DecompTy &DecompLoc = InsertOp.first->second;
1906 if (!InsertOp.second)
1927 "Must be a source location in a loaded PCH/Module file");
1935 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1938 "The failure to find the first FileID of a "
1939 "loaded AST from a loaded source location was unexpected.");
1950 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1953 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1954 std::greater<FileID>{});
1958 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1972 if (UpperLoc.first.isInvalid() ||
1982InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1983 FileID RFID)
const {
1988 enum { MagicCacheSize = 300 };
1989 IsBeforeInTUCacheKey Key(LFID, RFID);
1995 if (IBTUCache.size() < MagicCacheSize)
1996 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1999 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2000 if (I != IBTUCache.end())
2004 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2005 return IBTUCacheOverflow;
2013 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2023 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2024 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2028 return InSameTU.second;
2030 return LOffs.first < ROffs.first;
2033std::pair<bool, bool>
2038 return std::make_pair(
false,
false);
2041 if (LOffs.first == ROffs.first)
2042 return std::make_pair(
true, LOffs.second < ROffs.second);
2047 getInBeforeInTUCache(LOffs.first, ROffs.first);
2052 return std::make_pair(
2065 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2069 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2072 if (LOffs.first == ROffs.first)
2074 LChild = LOffs.first;
2079 auto LIt = LChain.find(ROffs.first);
2080 if (LIt != LChain.end()) {
2082 LOffs = LIt->second.DecomposedLoc;
2083 LChild = LIt->second.ChildFID;
2092 unsigned LChildID = LChild.ID;
2093 unsigned RChildID = RChild.ID;
2094 assert(((LOffs.second != ROffs.second) ||
2095 (LChildID == 0 || RChildID == 0) ||
2098 "Mixed local/loaded FileIDs with same include location?");
2099 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2100 LChildID < RChildID);
2101 return std::make_pair(
2104 RChild = ROffs.first;
2113 bool LIsBuiltins = LB ==
"<built-in>";
2114 bool RIsBuiltins = RB ==
"<built-in>";
2116 if (LIsBuiltins || RIsBuiltins) {
2117 if (LIsBuiltins != RIsBuiltins)
2118 return std::make_pair(
true, LIsBuiltins);
2121 return std::make_pair(
true, LOffs.first < ROffs.first);
2124 bool LIsAsm = LB ==
"<inline asm>";
2125 bool RIsAsm = RB ==
"<inline asm>";
2127 if (LIsAsm || RIsAsm) {
2128 if (LIsAsm != RIsAsm)
2129 return std::make_pair(
true, RIsAsm);
2130 assert(LOffs.first == ROffs.first);
2131 return std::make_pair(
true,
false);
2134 bool LIsScratch = LB ==
"<scratch space>";
2135 bool RIsScratch = RB ==
"<scratch space>";
2137 if (LIsScratch || RIsScratch) {
2138 if (LIsScratch != RIsScratch)
2139 return std::make_pair(
true, LIsScratch);
2140 return std::make_pair(
true, LOffs.second < ROffs.second);
2143 llvm_unreachable(
"Unsortable locations found");
2147 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2148 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2149 <<
" mem buffers mapped.\n";
2150 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2151 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2152 <<
" bytes of capacity), " << NextLocalOffset
2153 <<
"B of SLoc address space used.\n";
2154 llvm::errs() << LoadedSLocEntryTable.size()
2155 <<
" loaded SLocEntries allocated ("
2156 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2157 <<
" bytes of capacity), "
2158 << MaxLoadedOffset - CurrentLoadedOffset
2159 <<
"B of SLoc address space used.\n";
2161 unsigned NumLineNumsComputed = 0;
2162 unsigned NumFileBytesMapped = 0;
2164 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2165 NumFileBytesMapped += I->second->getSizeBytesMapped();
2167 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2169 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2170 << NumLineNumsComputed <<
" files with line #'s computed, "
2171 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2172 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2173 << NumBinaryProbes <<
" binary.\n";
2177 llvm::raw_ostream &
out = llvm::errs();
2180 std::optional<SourceLocation::UIntTy> NextStart) {
2181 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2182 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2184 out << *NextStart <<
">\n";
2187 if (Entry.isFile()) {
2188 auto &FI = Entry.getFile();
2189 if (FI.NumCreatedFIDs)
2190 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2192 if (FI.getIncludeLoc().isValid())
2193 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2194 auto &CC = FI.getContentCache();
2195 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2197 if (CC.BufferOverridden)
2198 out <<
" contents overridden\n";
2199 if (CC.ContentsEntry != CC.OrigEntry) {
2200 out <<
" contents from "
2201 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2205 auto &EI = Entry.getExpansion();
2206 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2207 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2208 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2209 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2214 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2215 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2216 ID == NumIDs - 1 ? NextLocalOffset
2217 : LocalSLocEntryTable[ID + 1].getOffset());
2220 std::optional<SourceLocation::UIntTy> NextStart;
2221 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2222 int ID = -(int)Index - 2;
2223 if (SLocEntryLoaded[Index]) {
2224 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2225 NextStart = LoadedSLocEntryTable[Index].getOffset();
2227 NextStart = std::nullopt;
2238 unsigned Inclusions = 0;
2240 uint64_t DirectSize = 0;
2242 uint64_t TotalSize = 0;
2244 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2247 uint64_t CountedSize = 0;
2249 auto AddUsageForFileID = [&](
FileID ID) {
2260 Info &EntryInfo = Usage[Entry];
2261 if (EntryInfo.Loc.isInvalid())
2262 EntryInfo.Loc = FileStart;
2263 if (ID == FileLocID) {
2264 ++EntryInfo.Inclusions;
2265 EntryInfo.DirectSize += Size;
2267 EntryInfo.TotalSize += Size;
2268 CountedSize += Size;
2272 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2273 AddUsageForFileID(FileID::get(-2 - Index));
2276 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2277 AddUsageForFileID(FileID::get(Index));
2282 auto SortedUsage = Usage.takeVector();
2283 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2284 return A.second.TotalSize > B.second.TotalSize ||
2285 (A.second.TotalSize == B.second.TotalSize &&
2286 A.second.Loc < B.second.Loc);
2288 auto SortedEnd = SortedUsage.end();
2289 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2290 SortedEnd = SortedUsage.begin() + *MaxNotes;
2291 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(),
Cmp);
2293 std::sort(SortedUsage.begin(), SortedEnd,
Cmp);
2296 uint64_t LocalUsage = NextLocalOffset;
2297 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2298 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2300 Diag.Report(diag::note_total_sloc_usage)
2301 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2305 uint64_t ReportedSize = 0;
2307 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2308 Diag.Report(
FileInfo.Loc, diag::note_file_sloc_usage)
2311 ReportedSize +=
FileInfo.TotalSize;
2315 if (ReportedSize != CountedSize) {
2316 Diag.Report(diag::note_file_misc_sloc_usage)
2317 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2326 size_t malloc_bytes = 0;
2327 size_t mmap_bytes = 0;
2329 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2330 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2331 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2332 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2333 mmap_bytes += sized_mapped;
2335 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2336 malloc_bytes += sized_mapped;
2344 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2345 llvm::capacity_in_bytes(FileIDContentCaches) +
2346 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2347 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2348 llvm::capacity_in_bytes(SLocEntryLoaded) +
2349 llvm::capacity_in_bytes(FileInfos);
2351 if (OverriddenFilesInfo)
2352 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2358 StringRef Content) {
2359 auto InMemoryFileSystem =
2360 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
2361 InMemoryFileSystem->addFile(
2363 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2368 std::move(InMemoryFileSystem));
2369 DiagOpts = std::make_unique<DiagnosticOptions>();
2374 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2378 assert(ID.isValid());
2379 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...
static SrcMgr::ContentCache * cloneContentCache(llvm::BumpPtrAllocator &Alloc, const ContentCache &Other)
Defines the SourceManager interface.
Represents a byte-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.
virtual ~ExternalSLocEntrySource()
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
bool isSameRef(const FileEntryRef &RHS) const
Check if RHS referenced the file in exactly the same way.
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,...
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...
SourceLocation::UIntTy getNextLocalOffset() const
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...
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...
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const
Get a local SLocEntry. This is exposed for indexing.
SourceLocation getComposedLoc(FileID FID, unsigned Offset) const
Form a SourceLocation from a FileID and Offset pair.
OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)
Bypass the overridden contents of a file.
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
FileManager & getFileManager() const
fileinfo_iterator fileinfo_end() 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.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
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.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
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.
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.
bool isLoadedSourceLocation(SourceLocation Loc) const
Returns true if Loc came from a PCH/Module.
unsigned loaded_sloc_entry_size() const
Get the number of loaded SLocEntries we have.
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.
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, SourceLocation::IntTy *RelativeOffset) const
Return true if both LHS and RHS are in the local source location address space or the loaded one.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
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.
SourceLocation getFileLoc(SourceLocation Loc, unsigned MaxDepth=std::numeric_limits< unsigned >::max()) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
fileinfo_iterator fileinfo_begin() const
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
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
Public enums and private classes that are part of the SourceManager implementation.
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.
StringRef getName(const HeaderType T)
Top level wrappers for InstallAPI frontend operations.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::pair< FileID, unsigned > FileIDAndOffset
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
const FunctionProtoType * T
@ Other
Other implicit parameter.
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)