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/raw_ostream.h"
48using llvm::MemoryBuffer;
50#define DEBUG_TYPE "source-manager"
56 Clone->ContentsEntry =
Other.ContentsEntry;
57 Clone->Filename =
Other.Filename;
58 Clone->BufferOverridden =
Other.BufferOverridden;
59 Clone->IsFileVolatile =
Other.IsFileVolatile;
60 Clone->IsTransient =
Other.IsTransient;
61 Clone->IsBufferInvalid =
Other.IsBufferInvalid;
62 Clone->setUnownedBuffer(
Other.getBufferIfLoaded());
68STATISTIC(MaxUsedSLocBytes,
"Maximum number of bytes used by source locations "
69 "(both loaded and local).");
78 return Buffer ? Buffer->getBufferSize() : 0;
84 if (Buffer ==
nullptr) {
85 assert(0 &&
"Buffer should never be null");
86 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
88 return Buffer->getBufferKind();
96 return Buffer ? (
unsigned)Buffer->getBufferSize()
104 const char *InvalidBOM =
105 llvm::StringSwitch<const char *>(BufStr)
106 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
108 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
110 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
111 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
112 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
113 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
114 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
115 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
116 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
117 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
123std::optional<llvm::MemoryBufferRef>
131 return Buffer->getMemBufferRef();
146 if (!BufferOrError) {
147 Diag.Report(Loc, diag::err_cannot_open_file)
148 <<
ContentsEntry->getName() << BufferOrError.getError().message();
153 Buffer = std::move(*BufferOrError);
164 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
175 assert(Buffer->getBufferSize() >= (
size_t)
ContentsEntry->getSize());
177 Buffer->getBufferSize() < (
size_t)
ContentsEntry->getSize()) {
186 StringRef BufStr = Buffer->getBuffer();
190 Diag.Report(Loc, diag::err_unsupported_bom)
197 return Buffer->getMemBufferRef();
201 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
203 FilenamesByID.push_back(&*IterBool.first);
204 return IterBool.first->second;
214 int FilenameID,
unsigned EntryExit,
216 std::vector<LineEntry> &Entries = LineEntries[FID];
218 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
219 "Adding line entries out of order!");
221 unsigned IncludeOffset = 0;
222 if (EntryExit == 1) {
224 IncludeOffset = Offset-1;
226 const auto *PrevEntry = Entries.empty() ?
nullptr : &Entries.back();
227 if (EntryExit == 2) {
229 assert(PrevEntry && PrevEntry->IncludeOffset &&
230 "PPDirectives should have caught case when popping empty include "
235 IncludeOffset = PrevEntry->IncludeOffset;
236 if (FilenameID == -1) {
239 FilenameID = PrevEntry->FilenameID;
244 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
252 const std::vector<LineEntry> &Entries = LineEntries[FID];
253 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
257 if (Entries.back().FileOffset <= Offset)
258 return &Entries.back();
261 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
262 if (I == Entries.begin())
270 const std::vector<LineEntry> &Entries) {
271 LineEntries[FID] = Entries;
283 int FilenameID,
bool IsFileEntry,
300 unsigned EntryExit = 0;
306 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
307 EntryExit, FileKind);
321 bool UserFilesAreVolatile)
322 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
324 Diag.setSourceManager(
this);
331 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
332 if (MemBufferInfos[i]) {
333 MemBufferInfos[i]->~ContentCache();
334 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
337 for (
auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
339 I->second->~ContentCache();
340 ContentCacheAlloc.Deallocate(I->second);
343 for (
unsigned i = 0, e = FileIDContentCaches.size(); i != e; ++i) {
344 if (FileIDContentCaches[i]) {
345 FileIDContentCaches[i]->~ContentCache();
346 ContentCacheAlloc.Deallocate(FileIDContentCaches[i]);
352 for (
unsigned i = 0, e = FileIDContentCaches.size(); i != e; ++i) {
353 if (FileIDContentCaches[i]) {
354 FileIDContentCaches[i]->~ContentCache();
355 ContentCacheAlloc.Deallocate(FileIDContentCaches[i]);
358 FileIDContentCaches.clear();
361 LocalSLocEntryTable.clear();
362 LocalLocOffsetTable.clear();
363 LoadedSLocEntryTable.clear();
364 SLocEntryLoaded.clear();
365 SLocEntryOffsetLoaded.clear();
366 LastLineNoFileIDQuery =
FileID();
367 LastLineNoContentCache =
nullptr;
368 LastFileIDLookup =
FileID();
369 LastLookupStartOffset = LastLookupEndOffset = 0;
371 IncludedLocMap.clear();
377 CurrentLoadedOffset = MaxLoadedOffset;
385 assert(MainFileID.isValid() &&
"expected initialized SourceManager");
387 return FE->getUID() == SourceFile.
getUID();
392 assert(MainFileID.isInvalid() &&
"expected uninitialized SourceManager");
395 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
396 if (!Old.SLocEntryLoaded[I])
397 Old.loadSLocEntry(I,
nullptr);
400 for (
auto &
FileInfo : Old.FileInfos) {
418 if (OverriddenFilesInfo) {
421 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
422 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
425 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
441ContentCache &SourceManager::createMemBufferContentCache(
442 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
444 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
445 new (Entry) ContentCache();
446 MemBufferInfos.push_back(Entry);
457 assert(!SLocEntryLoaded[Index]);
458 if (ExternalSLocEntries->ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
462 if (!SLocEntryLoaded[Index]) {
464 if (!FakeSLocEntryForRecovery)
465 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
466 0,
FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
468 return *FakeSLocEntryForRecovery;
472 return LoadedSLocEntryTable[Index];
475std::pair<int, SourceLocation::UIntTy>
478 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
480 if (CurrentLoadedOffset < TotalSize ||
481 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
482 return std::make_pair(0, 0);
484 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
485 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
486 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
487 CurrentLoadedOffset -= TotalSize;
488 updateSlocUsageStats();
489 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
490 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
491 return std::make_pair(BaseID, CurrentLoadedOffset);
496llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
497 if (!FakeBufferForRecovery)
498 FakeBufferForRecovery =
499 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
501 return *FakeBufferForRecovery;
507 if (!FakeContentCacheForRecovery) {
508 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
509 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
511 return *FakeContentCacheForRecovery;
516FileID SourceManager::getPreviousFileID(
FileID FID)
const {
527 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
531 return FileID::get(ID-1);
544 }
else if (ID+1 >= -1) {
548 return FileID::get(ID+1);
565 StringRef Filename = SourceFile.
getName();
569 Cache->OrigEntry = SourceFile;
570 FileIDContentCaches.push_back(
Cache);
575 if (
Cache->ContentsEntry->isNamedPipe())
578 return createFileIDImpl(*
Cache, Filename, IncludePos, FileCharacter, LoadedID,
591 StringRef Name = Buffer->getBufferIdentifier();
592 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
593 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
605 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
606 LoadedID, LoadedOffset, IncludeLoc);
628 assert(LoadedID != -1 &&
"Loading sentinel FileID");
629 unsigned Index =
unsigned(-LoadedID) - 2;
630 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
631 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
634 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
635 return FileID::get(LoadedID);
637 unsigned FileSize =
File.getSize();
638 llvm::ErrorOr<bool> NeedConversion = llvm::needConversion(Filename);
639 if (NeedConversion && *NeedConversion) {
642 if (std::optional<llvm::MemoryBufferRef> Buffer =
644 unsigned BufSize = Buffer->getBufferSize();
645 if (BufSize > FileSize) {
646 if (
File.ContentsEntry.has_value())
647 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
652 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
653 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
654 Diag.Report(IncludePos, diag::err_sloc_space_too_large);
658 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
659 LocalSLocEntryTable.push_back(
662 LocalLocOffsetTable.push_back(NextLocalOffset);
663 LastLookupStartOffset = NextLocalOffset;
666 NextLocalOffset += FileSize + 1;
667 LastLookupEndOffset = NextLocalOffset;
668 updateSlocUsageStats();
672 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
673 return LastFileIDLookup = FID;
680 return createExpansionLocImpl(Info, Length);
686 bool ExpansionIsTokenRange,
int LoadedID,
689 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
690 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
697 "token spans multiple files");
698 return createExpansionLocImpl(
700 TokenEnd.getOffset() - TokenStart.getOffset());
704SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
705 unsigned Length,
int LoadedID,
708 assert(LoadedID != -1 &&
"Loading sentinel FileID");
709 unsigned Index =
unsigned(-LoadedID) - 2;
710 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
711 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
713 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
714 return SourceLocation::getMacroLoc(LoadedOffset);
716 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
717 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
718 LocalLocOffsetTable.push_back(NextLocalOffset);
719 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
720 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
721 Diag.Report(diag::err_sloc_space_too_large);
727 llvm::report_fatal_error(
"ran out of source locations");
730 NextLocalOffset += Length + 1;
731 updateSlocUsageStats();
732 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
735std::optional<llvm::MemoryBufferRef>
742 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
748 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
754 "Different sizes, use the FileManager to create a virtual file with "
756 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
757 "This function should be called at the initialization stage, before "
758 "any parsing occurs.");
760 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
761 std::make_pair(SourceFile, NewFile));
763 Pair.first->second = NewFile;
775 (void)getOrCreateContentCache(*BypassFile);
780 getOrCreateContentCache(
File).IsTransient =
true;
783std::optional<StringRef>
786 if (Entry->getFile().getContentCache().
OrigEntry)
787 return Entry->getFile().getName();
795 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
798std::optional<StringRef>
809 return B->getBuffer();
824 return FileID::get(0);
828 if (SLocOffset < NextLocalOffset)
829 return getFileIDLocal(SLocOffset);
830 return getFileIDLoaded(SLocOffset);
838 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
839 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
840 "Invalid SLocOffset");
841 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
842 assert(LastFileIDLookup.ID >= 0 &&
"Only cache local file sloc entry");
859 unsigned LessIndex = 0;
861 unsigned GreaterIndex = LocalLocOffsetTable.size();
863 if (LastLookupStartOffset < SLocOffset)
864 LessIndex = LastFileIDLookup.ID;
866 GreaterIndex = LastFileIDLookup.ID;
869 unsigned NumProbes = 0;
872 assert(GreaterIndex < LocalLocOffsetTable.size());
873 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
874 FileID Res = FileID::get(
int(GreaterIndex));
876 LastFileIDLookup = Res;
877 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
878 LastLookupEndOffset =
879 GreaterIndex + 1 >= LocalLocOffsetTable.size()
881 : LocalLocOffsetTable[GreaterIndex + 1];
882 NumLinearScans += NumProbes + 1;
885 if (++NumProbes == 8)
889 while (LessIndex < GreaterIndex) {
892 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
893 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
894 LessIndex = MiddleIndex + 1;
896 GreaterIndex = MiddleIndex;
902 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
903 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
904 return LastFileIDLookup = FileID::get(LessIndex - 1);
912 if (SLocOffset < CurrentLoadedOffset) {
913 assert(0 &&
"Invalid SLocOffset or bad function choice");
917 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
980 assert(Loc.
isMacroID() &&
"Not a macro expansion loc!");
1037 if (DecompLoc.second > 0)
1051 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1063 *MacroBegin = ExpLoc;
1086 FileID NextFID = getNextFileID(FID);
1116 bool CharDataInvalid =
false;
1118 if (CharDataInvalid || !Entry.
isFile()) {
1122 return "<<<<INVALID BUFFER>>>>";
1124 std::optional<llvm::MemoryBufferRef> Buffer =
1129 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1130 :
"<<<<INVALID BUFFER>>>>";
1145 if (FilePos > MemBuf->getBufferSize()) {
1151 const char *Buf = MemBuf->getBufferStart();
1154 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1155 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1156 const unsigned *SourceLineCache =
1157 LastLineNoContentCache->SourceLineCache.begin();
1158 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1159 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1160 if (FilePos >= LineStart && FilePos < LineEnd) {
1165 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1166 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1169 return (FilePos - LineStart) + 1;
1173 unsigned LineStart = FilePos;
1174 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1176 return (FilePos - LineStart) + 1;
1181template<
typename LocType>
1183 bool MyInvalid = Loc.isInvalid();
1211 return ((x - ~
static_cast<T
>(0) / 255 * (n + 1)) & ~x &
1212 ((x & ~
static_cast<T
>(0) / 255 * 127) +
1213 (~
static_cast<T
>(0) / 255 * (127 - (m - 1))))) &
1214 ~static_cast<T>(0) / 255 * 128;
1218 llvm::BumpPtrAllocator &Alloc) {
1225 LineOffsets.push_back(0);
1227 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1228 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1229 const unsigned char *Buf = Start;
1235 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1237 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1241 Buf +=
sizeof(Word);
1249 unsigned N = llvm::countr_zero(Mask) - 7;
1252 unsigned char Byte = Word;
1261 LineOffsets.push_back(Buf - Start);
1263 }
while (Buf < End -
sizeof(Word) - 1);
1269 LineOffsets.push_back(Buf - Start + 1);
1270 }
else if (*Buf ==
'\r') {
1272 if (Buf + 1 < End && Buf[1] ==
'\n') {
1275 LineOffsets.push_back(Buf - Start + 1);
1284 llvm::BumpPtrAllocator &Alloc)
1285 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.
size() + 1)) {
1286 Storage[0] = LineOffsets.size();
1287 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1303 if (LastLineNoFileIDQuery == FID)
1304 Content = LastLineNoContentCache;
1306 bool MyInvalid =
false;
1308 if (MyInvalid || !Entry.
isFile()) {
1320 std::optional<llvm::MemoryBufferRef> Buffer =
1335 const unsigned *SourceLineCacheStart = SourceLineCache;
1338 unsigned QueriedFilePos = FilePos+1;
1353 if (LastLineNoFileIDQuery == FID) {
1354 if (QueriedFilePos >= LastLineNoFilePos) {
1356 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1362 if (SourceLineCache+5 < SourceLineCacheEnd) {
1363 if (SourceLineCache[5] > QueriedFilePos)
1364 SourceLineCacheEnd = SourceLineCache+5;
1365 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1366 if (SourceLineCache[10] > QueriedFilePos)
1367 SourceLineCacheEnd = SourceLineCache+10;
1368 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1369 if (SourceLineCache[20] > QueriedFilePos)
1370 SourceLineCacheEnd = SourceLineCache+20;
1375 if (LastLineNoResult < Content->SourceLineCache.size())
1376 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1380 const unsigned *Pos =
1381 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1382 unsigned LineNo = Pos-SourceLineCacheStart;
1384 LastLineNoFileIDQuery = FID;
1385 LastLineNoContentCache = Content;
1386 LastLineNoFilePos = QueriedFilePos;
1387 LastLineNoResult = LineNo;
1415 assert(Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1417 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1428 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1431 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1450 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1461 bool UseLineDirectives)
const {
1478 FileID FID = LocInfo.first;
1481 Filename =
C->OrigEntry->getName();
1483 Filename = Buffer->getBufferIdentifier();
1497 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1500 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1502 if (Entry->FilenameID != -1) {
1503 Filename = LineTable->getFilename(Entry->FilenameID);
1506 FID = FileID::get(0);
1513 unsigned MarkerLineNo =
getLineNumber(LocInfo.first, Entry->FileOffset);
1514 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1519 if (Entry->IncludeOffset) {
1526 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1542 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1551 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1552 if (Entry->IncludeOffset)
1569 else if (ID+1 == -1)
1570 NextOffset = MaxLoadedOffset;
1572 NextOffset =
getSLocEntry(FileID::get(ID+1)).getOffset();
1574 return NextOffset - Entry.
getOffset() - 1;
1587 unsigned Col)
const {
1588 assert(SourceFile &&
"Null source file!");
1589 assert(
Line && Col &&
"Line and column should start from 1!");
1600 assert(SourceFile &&
"Null source file!");
1604 if (MainFileID.isValid()) {
1622 return FileID::get(I);
1630 return FileID::get(-
int(I) - 2);
1640 unsigned Col)
const {
1643 assert(
Line && Col &&
"Line and column should start from 1!");
1658 if (
Line == 1 && Col == 1)
1665 std::optional<llvm::MemoryBufferRef> Buffer =
1674 unsigned Size = Buffer->getBufferSize();
1681 const char *Buf = Buffer->getBufferStart() + FilePos;
1682 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1689 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1701void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1706 MacroArgsCache.try_emplace(0);
1713 if (
unsigned(ID) >= local_sloc_entry_size())
1715 }
else if (ID == -1) {
1720 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &
Invalid);
1730 bool IncludedInFID =
1731 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1735 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1736 if (IncludedInFID) {
1739 if (Entry.
getFile().NumCreatedFIDs)
1740 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1760 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1762 SourceLocation::getMacroLoc(Entry.
getOffset()),
1763 getFileIDSize(FileID::get(ID)));
1767void SourceManager::associateFileChunkWithMacroArgExp(
1768 MacroArgsMap &MacroArgsCache,
1770 SourceLocation SpellLoc,
1771 SourceLocation ExpansionLoc,
1772 unsigned ExpansionLength)
const {
1783 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1785 const SLocEntry &Entry = getSLocEntry(SpellFID);
1787 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1791 unsigned CurrSpellLength;
1792 if (SpellFIDEndOffs < SpellEndOffs)
1793 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1795 CurrSpellLength = ExpansionLength;
1796 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1798 ExpansionLoc, CurrSpellLength);
1801 if (SpellFIDEndOffs >= SpellEndOffs)
1805 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1809 SpellRelativeOffs = 0;
1816 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1819 unsigned EndOffs = BeginOffs + ExpansionLength;
1838 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1840 SourceLocation EndOffsMappedLoc = I->second;
1841 MacroArgsCache[BeginOffs] = ExpansionLoc;
1842 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1845void SourceManager::updateSlocUsageStats()
const {
1847 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1848 MaxUsedSLocBytes.updateMax(UsedBytes);
1869 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1870 if (!MacroArgsCache) {
1871 MacroArgsCache = std::make_unique<MacroArgsMap>();
1872 computeMacroArgsCache(*MacroArgsCache, FID);
1875 assert(!MacroArgsCache->empty());
1876 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1879 if (I == MacroArgsCache->begin())
1886 if (MacroArgExpandedLoc.
isValid())
1894 return std::make_pair(
FileID(), 0);
1899 auto InsertOp = IncludedLocMap.try_emplace(FID);
1900 DecompTy &DecompLoc = InsertOp.first->second;
1901 if (!InsertOp.second)
1922 "Must be a source location in a loaded PCH/Module file");
1930 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1933 "The failure to find the first FileID of a "
1934 "loaded AST from a loaded source location was unexpected.");
1945 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1948 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1949 std::greater<FileID>{});
1953 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1967 if (UpperLoc.first.isInvalid() ||
1968 !
SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
1977InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1978 FileID RFID)
const {
1983 enum { MagicCacheSize = 300 };
1984 IsBeforeInTUCacheKey Key(LFID, RFID);
1990 if (IBTUCache.size() < MagicCacheSize)
1991 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1994 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1995 if (I != IBTUCache.end())
1999 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2000 return IBTUCacheOverflow;
2008 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2018 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2019 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2023 return InSameTU.second;
2025 return LOffs.first < ROffs.first;
2028std::pair<bool, bool>
2033 return std::make_pair(
false,
false);
2036 if (LOffs.first == ROffs.first)
2037 return std::make_pair(
true, LOffs.second < ROffs.second);
2042 getInBeforeInTUCache(LOffs.first, ROffs.first);
2047 return std::make_pair(
2060 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2064 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2067 if (LOffs.first == ROffs.first)
2069 LChild = LOffs.first;
2074 auto LIt = LChain.find(ROffs.first);
2075 if (LIt != LChain.end()) {
2077 LOffs = LIt->second.DecomposedLoc;
2078 LChild = LIt->second.ChildFID;
2087 unsigned LChildID = LChild.ID;
2088 unsigned RChildID = RChild.ID;
2089 assert(((LOffs.second != ROffs.second) ||
2090 (LChildID == 0 || RChildID == 0) ||
2093 "Mixed local/loaded FileIDs with same include location?");
2094 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2095 LChildID < RChildID);
2096 return std::make_pair(
2099 RChild = ROffs.first;
2108 bool LIsBuiltins = LB ==
"<built-in>";
2109 bool RIsBuiltins = RB ==
"<built-in>";
2111 if (LIsBuiltins || RIsBuiltins) {
2112 if (LIsBuiltins != RIsBuiltins)
2113 return std::make_pair(
true, LIsBuiltins);
2116 return std::make_pair(
true, LOffs.first < ROffs.first);
2119 bool LIsAsm = LB ==
"<inline asm>";
2120 bool RIsAsm = RB ==
"<inline asm>";
2122 if (LIsAsm || RIsAsm) {
2123 if (LIsAsm != RIsAsm)
2124 return std::make_pair(
true, RIsAsm);
2125 assert(LOffs.first == ROffs.first);
2126 return std::make_pair(
true,
false);
2129 bool LIsScratch = LB ==
"<scratch space>";
2130 bool RIsScratch = RB ==
"<scratch space>";
2132 if (LIsScratch || RIsScratch) {
2133 if (LIsScratch != RIsScratch)
2134 return std::make_pair(
true, LIsScratch);
2135 return std::make_pair(
true, LOffs.second < ROffs.second);
2138 llvm_unreachable(
"Unsortable locations found");
2142 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2143 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2144 <<
" mem buffers mapped.\n";
2145 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2146 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2147 <<
" bytes of capacity), " << NextLocalOffset
2148 <<
"B of SLoc address space used.\n";
2149 llvm::errs() << LoadedSLocEntryTable.size()
2150 <<
" loaded SLocEntries allocated ("
2151 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2152 <<
" bytes of capacity), "
2153 << MaxLoadedOffset - CurrentLoadedOffset
2154 <<
"B of SLoc address space used.\n";
2156 unsigned NumLineNumsComputed = 0;
2157 unsigned NumFileBytesMapped = 0;
2159 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2160 NumFileBytesMapped += I->second->getSizeBytesMapped();
2162 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2164 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2165 << NumLineNumsComputed <<
" files with line #'s computed, "
2166 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2167 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2168 << NumBinaryProbes <<
" binary.\n";
2172 llvm::raw_ostream &
out = llvm::errs();
2175 std::optional<SourceLocation::UIntTy> NextStart) {
2176 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2177 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2179 out << *NextStart <<
">\n";
2182 if (Entry.isFile()) {
2183 auto &FI = Entry.getFile();
2184 if (FI.NumCreatedFIDs)
2185 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2187 if (FI.getIncludeLoc().isValid())
2188 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2189 auto &CC = FI.getContentCache();
2190 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2192 if (CC.BufferOverridden)
2193 out <<
" contents overridden\n";
2194 if (CC.ContentsEntry != CC.OrigEntry) {
2195 out <<
" contents from "
2196 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2200 auto &EI = Entry.getExpansion();
2201 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2202 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2203 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2204 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2209 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2210 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2211 ID == NumIDs - 1 ? NextLocalOffset
2212 : LocalSLocEntryTable[ID + 1].getOffset());
2215 std::optional<SourceLocation::UIntTy> NextStart;
2216 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2217 int ID = -(int)Index - 2;
2218 if (SLocEntryLoaded[Index]) {
2219 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2220 NextStart = LoadedSLocEntryTable[Index].getOffset();
2222 NextStart = std::nullopt;
2233 unsigned Inclusions = 0;
2235 uint64_t DirectSize = 0;
2237 uint64_t TotalSize = 0;
2239 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2242 uint64_t CountedSize = 0;
2244 auto AddUsageForFileID = [&](
FileID ID) {
2255 Info &EntryInfo = Usage[Entry];
2256 if (EntryInfo.Loc.isInvalid())
2257 EntryInfo.Loc = FileStart;
2258 if (ID == FileLocID) {
2259 ++EntryInfo.Inclusions;
2260 EntryInfo.DirectSize += Size;
2262 EntryInfo.TotalSize += Size;
2263 CountedSize += Size;
2267 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2268 AddUsageForFileID(FileID::get(-2 - Index));
2271 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2272 AddUsageForFileID(FileID::get(Index));
2277 auto SortedUsage = Usage.takeVector();
2278 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2279 return A.second.TotalSize > B.second.TotalSize ||
2280 (A.second.TotalSize == B.second.TotalSize &&
2281 A.second.Loc < B.second.Loc);
2283 auto SortedEnd = SortedUsage.end();
2284 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2285 SortedEnd = SortedUsage.begin() + *MaxNotes;
2286 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(),
Cmp);
2288 std::sort(SortedUsage.begin(), SortedEnd,
Cmp);
2291 uint64_t LocalUsage = NextLocalOffset;
2292 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2293 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2295 Diag.Report(diag::note_total_sloc_usage)
2296 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2300 uint64_t ReportedSize = 0;
2302 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2303 Diag.Report(
FileInfo.Loc, diag::note_file_sloc_usage)
2306 ReportedSize +=
FileInfo.TotalSize;
2310 if (ReportedSize != CountedSize) {
2311 Diag.Report(diag::note_file_misc_sloc_usage)
2312 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2321 size_t malloc_bytes = 0;
2322 size_t mmap_bytes = 0;
2324 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2325 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2326 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2327 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2328 mmap_bytes += sized_mapped;
2330 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2331 malloc_bytes += sized_mapped;
2339 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2340 llvm::capacity_in_bytes(FileIDContentCaches) +
2341 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2342 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2343 llvm::capacity_in_bytes(SLocEntryLoaded) +
2344 llvm::capacity_in_bytes(FileInfos);
2346 if (OverriddenFilesInfo)
2347 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2353 StringRef Content) {
2354 auto InMemoryFileSystem =
2355 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
2356 InMemoryFileSystem->addFile(
2358 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2363 std::move(InMemoryFileSystem));
2364 DiagOpts = std::make_unique<DiagnosticOptions>();
2369 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2373 assert(ID.isValid());
2374 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 getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
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.
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)
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::pair< FileID, unsigned > FileIDAndOffset
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ 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)