19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/AutoConvert.h"
28#include "llvm/Support/Capacity.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Endian.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/raw_ostream.h"
46using llvm::MemoryBuffer;
48#define DEBUG_TYPE "source-manager"
52STATISTIC(MaxUsedSLocBytes,
"Maximum number of bytes used by source locations "
53 "(both loaded and local).");
62 return Buffer ? Buffer->getBufferSize() : 0;
68 if (Buffer ==
nullptr) {
69 assert(0 &&
"Buffer should never be null");
70 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
72 return Buffer->getBufferKind();
80 return Buffer ? (
unsigned)Buffer->getBufferSize()
88 const char *InvalidBOM =
89 llvm::StringSwitch<const char *>(BufStr)
90 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
92 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
94 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
95 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
96 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
97 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
98 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
99 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
100 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
101 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
107std::optional<llvm::MemoryBufferRef>
115 return Buffer->getMemBufferRef();
130 if (!BufferOrError) {
131 Diag.Report(Loc, diag::err_cannot_open_file)
132 <<
ContentsEntry->getName() << BufferOrError.getError().message();
137 Buffer = std::move(*BufferOrError);
148 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
159 assert(Buffer->getBufferSize() >= (
size_t)
ContentsEntry->getSize());
161 Buffer->getBufferSize() < (
size_t)
ContentsEntry->getSize()) {
170 StringRef BufStr = Buffer->getBuffer();
174 Diag.Report(Loc, diag::err_unsupported_bom)
181 return Buffer->getMemBufferRef();
185 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
187 FilenamesByID.push_back(&*IterBool.first);
188 return IterBool.first->second;
198 int FilenameID,
unsigned EntryExit,
200 std::vector<LineEntry> &Entries = LineEntries[FID];
202 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
203 "Adding line entries out of order!");
205 unsigned IncludeOffset = 0;
206 if (EntryExit == 1) {
208 IncludeOffset = Offset-1;
210 const auto *PrevEntry = Entries.empty() ?
nullptr : &Entries.back();
211 if (EntryExit == 2) {
213 assert(PrevEntry && PrevEntry->IncludeOffset &&
214 "PPDirectives should have caught case when popping empty include "
219 IncludeOffset = PrevEntry->IncludeOffset;
220 if (FilenameID == -1) {
223 FilenameID = PrevEntry->FilenameID;
228 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
236 const std::vector<LineEntry> &Entries = LineEntries[FID];
237 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
241 if (Entries.back().FileOffset <= Offset)
242 return &Entries.back();
245 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
246 if (I == Entries.begin())
254 const std::vector<LineEntry> &Entries) {
255 LineEntries[FID] = Entries;
267 int FilenameID,
bool IsFileEntry,
284 unsigned EntryExit = 0;
290 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
291 EntryExit, FileKind);
305 bool UserFilesAreVolatile)
306 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
308 Diag.setSourceManager(
this);
315 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
316 if (MemBufferInfos[i]) {
317 MemBufferInfos[i]->~ContentCache();
318 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
321 for (
auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
323 I->second->~ContentCache();
324 ContentCacheAlloc.Deallocate(I->second);
331 LocalSLocEntryTable.clear();
332 LocalLocOffsetTable.clear();
333 LoadedSLocEntryTable.clear();
334 SLocEntryLoaded.clear();
335 SLocEntryOffsetLoaded.clear();
336 LastLineNoFileIDQuery =
FileID();
337 LastLineNoContentCache =
nullptr;
338 LastFileIDLookup =
FileID();
339 LastLookupStartOffset = LastLookupEndOffset = 0;
341 IncludedLocMap.clear();
347 CurrentLoadedOffset = MaxLoadedOffset;
355 assert(MainFileID.isValid() &&
"expected initialized SourceManager");
357 return FE->getUID() == SourceFile.
getUID();
362 assert(MainFileID.isInvalid() &&
"expected uninitialized SourceManager");
367 Clone->ContentsEntry =
Cache->ContentsEntry;
368 Clone->BufferOverridden =
Cache->BufferOverridden;
369 Clone->IsFileVolatile =
Cache->IsFileVolatile;
370 Clone->IsTransient =
Cache->IsTransient;
371 Clone->setUnownedBuffer(
Cache->getBufferIfLoaded());
376 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
377 if (!Old.SLocEntryLoaded[I])
378 Old.loadSLocEntry(I,
nullptr);
381 for (
auto &
FileInfo : Old.FileInfos) {
385 Slot = CloneContentCache(
FileInfo.second);
399 if (OverriddenFilesInfo) {
402 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
403 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
406 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
422ContentCache &SourceManager::createMemBufferContentCache(
423 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
425 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
426 new (Entry) ContentCache();
427 MemBufferInfos.push_back(Entry);
438 assert(!SLocEntryLoaded[Index]);
439 if (ExternalSLocEntries->ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
443 if (!SLocEntryLoaded[Index]) {
445 if (!FakeSLocEntryForRecovery)
446 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
447 0,
FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
449 return *FakeSLocEntryForRecovery;
453 return LoadedSLocEntryTable[Index];
456std::pair<int, SourceLocation::UIntTy>
459 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
461 if (CurrentLoadedOffset < TotalSize ||
462 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
463 return std::make_pair(0, 0);
465 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
466 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
467 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
468 CurrentLoadedOffset -= TotalSize;
469 updateSlocUsageStats();
470 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
471 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
472 return std::make_pair(BaseID, CurrentLoadedOffset);
477llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
478 if (!FakeBufferForRecovery)
479 FakeBufferForRecovery =
480 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
482 return *FakeBufferForRecovery;
488 if (!FakeContentCacheForRecovery) {
489 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
490 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
492 return *FakeContentCacheForRecovery;
497FileID SourceManager::getPreviousFileID(
FileID FID)
const {
508 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
512 return FileID::get(ID-1);
525 }
else if (ID+1 >= -1) {
529 return FileID::get(ID+1);
551 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
552 LoadedID, LoadedOffset);
564 StringRef Name = Buffer->getBufferIdentifier();
565 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
566 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
578 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
579 LoadedID, LoadedOffset, IncludeLoc);
601 assert(LoadedID != -1 &&
"Loading sentinel FileID");
602 unsigned Index =
unsigned(-LoadedID) - 2;
603 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
604 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
607 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
608 return FileID::get(LoadedID);
610 unsigned FileSize =
File.getSize();
611 llvm::ErrorOr<bool> NeedConversion = llvm::needConversion(Filename);
612 if (NeedConversion && *NeedConversion) {
615 if (std::optional<llvm::MemoryBufferRef> Buffer =
617 unsigned BufSize = Buffer->getBufferSize();
618 if (BufSize > FileSize) {
619 if (
File.ContentsEntry.has_value())
620 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
625 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
626 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
627 Diag.Report(IncludePos, diag::err_sloc_space_too_large);
631 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
632 LocalSLocEntryTable.push_back(
635 LocalLocOffsetTable.push_back(NextLocalOffset);
636 LastLookupStartOffset = NextLocalOffset;
639 NextLocalOffset += FileSize + 1;
640 LastLookupEndOffset = NextLocalOffset;
641 updateSlocUsageStats();
645 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
646 return LastFileIDLookup = FID;
653 return createExpansionLocImpl(Info, Length);
659 bool ExpansionIsTokenRange,
int LoadedID,
662 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
663 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
670 "token spans multiple files");
671 return createExpansionLocImpl(
673 TokenEnd.getOffset() - TokenStart.getOffset());
677SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
678 unsigned Length,
int LoadedID,
681 assert(LoadedID != -1 &&
"Loading sentinel FileID");
682 unsigned Index =
unsigned(-LoadedID) - 2;
683 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
684 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
686 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
687 return SourceLocation::getMacroLoc(LoadedOffset);
689 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
690 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
691 LocalLocOffsetTable.push_back(NextLocalOffset);
692 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
693 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
694 Diag.Report(diag::err_sloc_space_too_large);
700 llvm::report_fatal_error(
"ran out of source locations");
703 NextLocalOffset += Length + 1;
704 updateSlocUsageStats();
705 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
708std::optional<llvm::MemoryBufferRef>
715 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
721 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
727 "Different sizes, use the FileManager to create a virtual file with "
729 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
730 "This function should be called at the initialization stage, before "
731 "any parsing occurs.");
733 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
734 std::make_pair(SourceFile, NewFile));
736 Pair.first->second = NewFile;
748 (void)getOrCreateContentCache(*BypassFile);
753 getOrCreateContentCache(
File).IsTransient =
true;
756std::optional<StringRef>
759 if (Entry->getFile().getContentCache().
OrigEntry)
760 return Entry->getFile().getName();
768 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
771std::optional<StringRef>
782 return B->getBuffer();
797 return FileID::get(0);
801 if (SLocOffset < NextLocalOffset)
802 return getFileIDLocal(SLocOffset);
803 return getFileIDLoaded(SLocOffset);
811 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
812 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
813 "Invalid SLocOffset");
814 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
815 assert(LastFileIDLookup.ID >= 0 &&
"Only cache local file sloc entry");
832 unsigned LessIndex = 0;
834 unsigned GreaterIndex = LocalLocOffsetTable.size();
836 if (LastLookupStartOffset < SLocOffset)
837 LessIndex = LastFileIDLookup.ID;
839 GreaterIndex = LastFileIDLookup.ID;
842 unsigned NumProbes = 0;
845 assert(GreaterIndex < LocalLocOffsetTable.size());
846 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
847 FileID Res = FileID::get(
int(GreaterIndex));
849 LastFileIDLookup = Res;
850 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
851 LastLookupEndOffset =
852 GreaterIndex + 1 >= LocalLocOffsetTable.size()
854 : LocalLocOffsetTable[GreaterIndex + 1];
855 NumLinearScans += NumProbes + 1;
858 if (++NumProbes == 8)
862 while (LessIndex < GreaterIndex) {
865 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
866 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
867 LessIndex = MiddleIndex + 1;
869 GreaterIndex = MiddleIndex;
875 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
876 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
877 return LastFileIDLookup = FileID::get(LessIndex - 1);
885 if (SLocOffset < CurrentLoadedOffset) {
886 assert(0 &&
"Invalid SLocOffset or bad function choice");
890 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
953 assert(Loc.
isMacroID() &&
"Not a macro expansion loc!");
1010 if (DecompLoc.second > 0)
1024 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1036 *MacroBegin = ExpLoc;
1059 FileID NextFID = getNextFileID(FID);
1089 bool CharDataInvalid =
false;
1091 if (CharDataInvalid || !Entry.
isFile()) {
1095 return "<<<<INVALID BUFFER>>>>";
1097 std::optional<llvm::MemoryBufferRef> Buffer =
1102 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1103 :
"<<<<INVALID BUFFER>>>>";
1118 if (FilePos > MemBuf->getBufferSize()) {
1124 const char *Buf = MemBuf->getBufferStart();
1127 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1128 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1129 const unsigned *SourceLineCache =
1130 LastLineNoContentCache->SourceLineCache.begin();
1131 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1132 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1133 if (FilePos >= LineStart && FilePos < LineEnd) {
1138 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1139 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1142 return (FilePos - LineStart) + 1;
1146 unsigned LineStart = FilePos;
1147 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1149 return (FilePos - LineStart) + 1;
1154template<
typename LocType>
1156 bool MyInvalid = Loc.isInvalid();
1184 return ((x - ~
static_cast<T>(0) / 255 * (n + 1)) & ~x &
1185 ((x & ~
static_cast<T>(0) / 255 * 127) +
1186 (~
static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1187 ~static_cast<T>(0) / 255 * 128;
1191 llvm::BumpPtrAllocator &Alloc) {
1198 LineOffsets.push_back(0);
1200 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1201 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1202 const unsigned char *Buf = Start;
1208 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1210 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1214 Buf +=
sizeof(Word);
1222 unsigned N = llvm::countr_zero(Mask) - 7;
1225 unsigned char Byte = Word;
1234 LineOffsets.push_back(Buf - Start);
1236 }
while (Buf < End -
sizeof(Word) - 1);
1242 LineOffsets.push_back(Buf - Start + 1);
1243 }
else if (*Buf ==
'\r') {
1245 if (Buf + 1 < End && Buf[1] ==
'\n') {
1248 LineOffsets.push_back(Buf - Start + 1);
1257 llvm::BumpPtrAllocator &Alloc)
1258 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.
size() + 1)) {
1259 Storage[0] = LineOffsets.size();
1260 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1276 if (LastLineNoFileIDQuery == FID)
1277 Content = LastLineNoContentCache;
1279 bool MyInvalid =
false;
1281 if (MyInvalid || !Entry.
isFile()) {
1293 std::optional<llvm::MemoryBufferRef> Buffer =
1308 const unsigned *SourceLineCacheStart = SourceLineCache;
1311 unsigned QueriedFilePos = FilePos+1;
1326 if (LastLineNoFileIDQuery == FID) {
1327 if (QueriedFilePos >= LastLineNoFilePos) {
1329 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1335 if (SourceLineCache+5 < SourceLineCacheEnd) {
1336 if (SourceLineCache[5] > QueriedFilePos)
1337 SourceLineCacheEnd = SourceLineCache+5;
1338 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1339 if (SourceLineCache[10] > QueriedFilePos)
1340 SourceLineCacheEnd = SourceLineCache+10;
1341 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1342 if (SourceLineCache[20] > QueriedFilePos)
1343 SourceLineCacheEnd = SourceLineCache+20;
1348 if (LastLineNoResult < Content->SourceLineCache.size())
1349 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1353 const unsigned *Pos =
1354 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1355 unsigned LineNo = Pos-SourceLineCacheStart;
1357 LastLineNoFileIDQuery = FID;
1358 LastLineNoContentCache = Content;
1359 LastLineNoFilePos = QueriedFilePos;
1360 LastLineNoResult = LineNo;
1388 assert(Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1390 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1401 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1404 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1423 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1434 bool UseLineDirectives)
const {
1451 FileID FID = LocInfo.first;
1454 Filename =
C->OrigEntry->getName();
1456 Filename = Buffer->getBufferIdentifier();
1470 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1473 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1475 if (Entry->FilenameID != -1) {
1476 Filename = LineTable->getFilename(Entry->FilenameID);
1479 FID = FileID::get(0);
1486 unsigned MarkerLineNo =
getLineNumber(LocInfo.first, Entry->FileOffset);
1487 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1492 if (Entry->IncludeOffset) {
1499 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1515 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1524 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1525 if (Entry->IncludeOffset)
1542 else if (ID+1 == -1)
1543 NextOffset = MaxLoadedOffset;
1545 NextOffset =
getSLocEntry(FileID::get(ID+1)).getOffset();
1547 return NextOffset - Entry.
getOffset() - 1;
1560 unsigned Col)
const {
1561 assert(SourceFile &&
"Null source file!");
1562 assert(
Line && Col &&
"Line and column should start from 1!");
1573 assert(SourceFile &&
"Null source file!");
1577 if (MainFileID.isValid()) {
1595 return FileID::get(I);
1603 return FileID::get(-
int(I) - 2);
1613 unsigned Col)
const {
1616 assert(
Line && Col &&
"Line and column should start from 1!");
1631 if (
Line == 1 && Col == 1)
1638 std::optional<llvm::MemoryBufferRef> Buffer =
1647 unsigned Size = Buffer->getBufferSize();
1654 const char *Buf = Buffer->getBufferStart() + FilePos;
1655 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1662 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1674void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1679 MacroArgsCache.try_emplace(0);
1686 if (
unsigned(ID) >= local_sloc_entry_size())
1688 }
else if (ID == -1) {
1693 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &
Invalid);
1703 bool IncludedInFID =
1704 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1708 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1709 if (IncludedInFID) {
1712 if (Entry.
getFile().NumCreatedFIDs)
1713 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1733 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1735 SourceLocation::getMacroLoc(Entry.
getOffset()),
1736 getFileIDSize(FileID::get(ID)));
1740void SourceManager::associateFileChunkWithMacroArgExp(
1741 MacroArgsMap &MacroArgsCache,
1743 SourceLocation SpellLoc,
1744 SourceLocation ExpansionLoc,
1745 unsigned ExpansionLength)
const {
1756 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1758 const SLocEntry &Entry = getSLocEntry(SpellFID);
1760 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1764 unsigned CurrSpellLength;
1765 if (SpellFIDEndOffs < SpellEndOffs)
1766 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1768 CurrSpellLength = ExpansionLength;
1769 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1771 ExpansionLoc, CurrSpellLength);
1774 if (SpellFIDEndOffs >= SpellEndOffs)
1778 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1782 SpellRelativeOffs = 0;
1789 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1792 unsigned EndOffs = BeginOffs + ExpansionLength;
1811 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1813 SourceLocation EndOffsMappedLoc = I->second;
1814 MacroArgsCache[BeginOffs] = ExpansionLoc;
1815 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1818void SourceManager::updateSlocUsageStats()
const {
1820 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1821 MaxUsedSLocBytes.updateMax(UsedBytes);
1842 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1843 if (!MacroArgsCache) {
1844 MacroArgsCache = std::make_unique<MacroArgsMap>();
1845 computeMacroArgsCache(*MacroArgsCache, FID);
1848 assert(!MacroArgsCache->empty());
1849 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1852 if (I == MacroArgsCache->begin())
1859 if (MacroArgExpandedLoc.
isValid())
1867 return std::make_pair(
FileID(), 0);
1872 auto InsertOp = IncludedLocMap.try_emplace(FID);
1873 DecompTy &DecompLoc = InsertOp.first->second;
1874 if (!InsertOp.second)
1895 "Must be a source location in a loaded PCH/Module file");
1903 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1906 "The failure to find the first FileID of a "
1907 "loaded AST from a loaded source location was unexpected.");
1918 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1921 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1922 std::greater<FileID>{});
1926 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1940 if (UpperLoc.first.isInvalid() ||
1941 !
SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
1950InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1951 FileID RFID)
const {
1956 enum { MagicCacheSize = 300 };
1957 IsBeforeInTUCacheKey Key(LFID, RFID);
1963 if (IBTUCache.size() < MagicCacheSize)
1964 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1967 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1968 if (I != IBTUCache.end())
1972 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
1973 return IBTUCacheOverflow;
1981 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
1991 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
1992 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
1996 return InSameTU.second;
1998 return LOffs.first < ROffs.first;
2001std::pair<bool, bool>
2006 return std::make_pair(
false,
false);
2009 if (LOffs.first == ROffs.first)
2010 return std::make_pair(
true, LOffs.second < ROffs.second);
2015 getInBeforeInTUCache(LOffs.first, ROffs.first);
2020 return std::make_pair(
2033 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2037 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2040 if (LOffs.first == ROffs.first)
2042 LChild = LOffs.first;
2047 auto LIt = LChain.find(ROffs.first);
2048 if (LIt != LChain.end()) {
2050 LOffs = LIt->second.DecomposedLoc;
2051 LChild = LIt->second.ChildFID;
2060 unsigned LChildID = LChild.ID;
2061 unsigned RChildID = RChild.ID;
2062 assert(((LOffs.second != ROffs.second) ||
2063 (LChildID == 0 || RChildID == 0) ||
2066 "Mixed local/loaded FileIDs with same include location?");
2067 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2068 LChildID < RChildID);
2069 return std::make_pair(
2072 RChild = ROffs.first;
2081 bool LIsBuiltins = LB ==
"<built-in>";
2082 bool RIsBuiltins = RB ==
"<built-in>";
2084 if (LIsBuiltins || RIsBuiltins) {
2085 if (LIsBuiltins != RIsBuiltins)
2086 return std::make_pair(
true, LIsBuiltins);
2089 return std::make_pair(
true, LOffs.first < ROffs.first);
2092 bool LIsAsm = LB ==
"<inline asm>";
2093 bool RIsAsm = RB ==
"<inline asm>";
2095 if (LIsAsm || RIsAsm) {
2096 if (LIsAsm != RIsAsm)
2097 return std::make_pair(
true, RIsAsm);
2098 assert(LOffs.first == ROffs.first);
2099 return std::make_pair(
true,
false);
2102 bool LIsScratch = LB ==
"<scratch space>";
2103 bool RIsScratch = RB ==
"<scratch space>";
2105 if (LIsScratch || RIsScratch) {
2106 if (LIsScratch != RIsScratch)
2107 return std::make_pair(
true, LIsScratch);
2108 return std::make_pair(
true, LOffs.second < ROffs.second);
2111 llvm_unreachable(
"Unsortable locations found");
2115 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2116 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2117 <<
" mem buffers mapped.\n";
2118 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2119 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2120 <<
" bytes of capacity), " << NextLocalOffset
2121 <<
"B of SLoc address space used.\n";
2122 llvm::errs() << LoadedSLocEntryTable.size()
2123 <<
" loaded SLocEntries allocated ("
2124 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2125 <<
" bytes of capacity), "
2126 << MaxLoadedOffset - CurrentLoadedOffset
2127 <<
"B of SLoc address space used.\n";
2129 unsigned NumLineNumsComputed = 0;
2130 unsigned NumFileBytesMapped = 0;
2132 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2133 NumFileBytesMapped += I->second->getSizeBytesMapped();
2135 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2137 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2138 << NumLineNumsComputed <<
" files with line #'s computed, "
2139 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2140 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2141 << NumBinaryProbes <<
" binary.\n";
2145 llvm::raw_ostream &
out = llvm::errs();
2148 std::optional<SourceLocation::UIntTy> NextStart) {
2149 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2150 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2152 out << *NextStart <<
">\n";
2155 if (Entry.isFile()) {
2156 auto &FI = Entry.getFile();
2157 if (FI.NumCreatedFIDs)
2158 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2160 if (FI.getIncludeLoc().isValid())
2161 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2162 auto &CC = FI.getContentCache();
2163 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2165 if (CC.BufferOverridden)
2166 out <<
" contents overridden\n";
2167 if (CC.ContentsEntry != CC.OrigEntry) {
2168 out <<
" contents from "
2169 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2173 auto &EI = Entry.getExpansion();
2174 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2175 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2176 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2177 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2182 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2183 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2184 ID == NumIDs - 1 ? NextLocalOffset
2185 : LocalSLocEntryTable[ID + 1].getOffset());
2188 std::optional<SourceLocation::UIntTy> NextStart;
2189 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2190 int ID = -(int)Index - 2;
2191 if (SLocEntryLoaded[Index]) {
2192 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2193 NextStart = LoadedSLocEntryTable[Index].getOffset();
2195 NextStart = std::nullopt;
2206 unsigned Inclusions = 0;
2208 uint64_t DirectSize = 0;
2210 uint64_t TotalSize = 0;
2212 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2215 uint64_t CountedSize = 0;
2217 auto AddUsageForFileID = [&](
FileID ID) {
2228 Info &EntryInfo = Usage[Entry];
2229 if (EntryInfo.Loc.isInvalid())
2230 EntryInfo.Loc = FileStart;
2231 if (ID == FileLocID) {
2232 ++EntryInfo.Inclusions;
2233 EntryInfo.DirectSize += Size;
2235 EntryInfo.TotalSize += Size;
2236 CountedSize += Size;
2240 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2241 AddUsageForFileID(FileID::get(-2 - Index));
2244 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2245 AddUsageForFileID(FileID::get(Index));
2250 auto SortedUsage = Usage.takeVector();
2251 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2252 return A.second.TotalSize > B.second.TotalSize ||
2253 (A.second.TotalSize == B.second.TotalSize &&
2254 A.second.Loc < B.second.Loc);
2256 auto SortedEnd = SortedUsage.end();
2257 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2258 SortedEnd = SortedUsage.begin() + *MaxNotes;
2259 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2261 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2264 uint64_t LocalUsage = NextLocalOffset;
2265 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2266 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2268 Diag.Report(diag::note_total_sloc_usage)
2269 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2273 uint64_t ReportedSize = 0;
2275 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2276 Diag.Report(
FileInfo.Loc, diag::note_file_sloc_usage)
2279 ReportedSize +=
FileInfo.TotalSize;
2283 if (ReportedSize != CountedSize) {
2284 Diag.Report(diag::note_file_misc_sloc_usage)
2285 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2294 size_t malloc_bytes = 0;
2295 size_t mmap_bytes = 0;
2297 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2298 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2299 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2300 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2301 mmap_bytes += sized_mapped;
2303 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2304 malloc_bytes += sized_mapped;
2312 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2313 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2314 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2315 llvm::capacity_in_bytes(SLocEntryLoaded) +
2316 llvm::capacity_in_bytes(FileInfos);
2318 if (OverriddenFilesInfo)
2319 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2325 StringRef Content) {
2326 auto InMemoryFileSystem =
2327 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
2328 InMemoryFileSystem->addFile(
2330 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2335 std::move(InMemoryFileSystem));
2336 DiagOpts = std::make_unique<DiagnosticOptions>();
2341 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2345 assert(ID.isValid());
2346 SourceMgr->setMainFileID(ID);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static ParseState advance(ParseState S, size_t N)
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool isInvalid(LocType Loc, bool *Invalid)
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
Defines the SourceManager interface.
Represents a character-granular source range.
void setEnd(SourceLocation e)
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setTokenRange(bool TR)
static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()
Concrete class used by the front-end to report problems and issues.
virtual ~ExternalSLocEntrySource()
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
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',...
const FunctionProtoType * T
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)