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/FileSystem.h"
33#include "llvm/Support/MathExtras.h"
34#include "llvm/Support/MemoryBuffer.h"
35#include "llvm/Support/Path.h"
36#include "llvm/Support/raw_ostream.h"
48using namespace SrcMgr;
49using llvm::MemoryBuffer;
51#define DEBUG_TYPE "source-manager"
55STATISTIC(MaxUsedSLocBytes,
"Maximum number of bytes used by source locations "
56 "(both loaded and local).");
65 return Buffer ? Buffer->getBufferSize() : 0;
71 if (Buffer ==
nullptr) {
72 assert(0 &&
"Buffer should never be null");
73 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
75 return Buffer->getBufferKind();
83 return Buffer ? (
unsigned)Buffer->getBufferSize()
91 const char *InvalidBOM =
92 llvm::StringSwitch<const char *>(BufStr)
93 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
95 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
97 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
98 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
99 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
100 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
101 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
102 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
103 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
104 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
110std::optional<llvm::MemoryBufferRef>
118 return Buffer->getMemBufferRef();
133 if (!BufferOrError) {
134 Diag.Report(
Loc, diag::err_cannot_open_file)
140 Buffer = std::move(*BufferOrError);
151 if (Buffer->getBufferSize() >= std::numeric_limits<unsigned>::max()) {
173 StringRef BufStr = Buffer->getBuffer();
177 Diag.Report(
Loc, diag::err_unsupported_bom)
184 return Buffer->getMemBufferRef();
188 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
190 FilenamesByID.push_back(&*IterBool.first);
191 return IterBool.first->second;
201 int FilenameID,
unsigned EntryExit,
203 std::vector<LineEntry> &Entries = LineEntries[FID];
205 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
206 "Adding line entries out of order!");
208 unsigned IncludeOffset = 0;
209 if (EntryExit == 1) {
211 IncludeOffset = Offset-1;
213 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();
214 if (EntryExit == 2) {
216 assert(PrevEntry && PrevEntry->IncludeOffset &&
217 "PPDirectives should have caught case when popping empty include "
219 PrevEntry = FindNearestLineEntry(FID, PrevEntry->IncludeOffset);
222 IncludeOffset = PrevEntry->IncludeOffset;
223 if (FilenameID == -1) {
226 FilenameID = PrevEntry->FilenameID;
231 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
239 const std::vector<LineEntry> &Entries = LineEntries[FID];
240 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
244 if (Entries.back().FileOffset <= Offset)
245 return &Entries.back();
248 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
249 if (I == Entries.begin())
257 const std::vector<LineEntry> &Entries) {
258 LineEntries[FID] = Entries;
263 return getLineTable().getLineTableFilenameID(Name);
270 int FilenameID,
bool IsFileEntry,
273 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
285 (void) getLineTable();
287 unsigned EntryExit = 0;
293 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
294 EntryExit, FileKind);
308 bool UserFilesAreVolatile)
309 :
Diag(
Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
318 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
319 if (MemBufferInfos[i]) {
320 MemBufferInfos[i]->~ContentCache();
321 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
324 for (
auto I = FileInfos.begin(),
E = FileInfos.end(); I !=
E; ++I) {
326 I->second->~ContentCache();
327 ContentCacheAlloc.Deallocate(I->second);
334 LocalSLocEntryTable.clear();
335 LoadedSLocEntryTable.clear();
336 SLocEntryLoaded.clear();
337 SLocEntryOffsetLoaded.clear();
338 LastLineNoFileIDQuery =
FileID();
339 LastLineNoContentCache =
nullptr;
340 LastFileIDLookup =
FileID();
342 IncludedLocMap.clear();
348 CurrentLoadedOffset = MaxLoadedOffset;
353 assert(MainFileID.
isValid() &&
"expected initialized SourceManager");
355 return FE->getUID() == SourceFile.
getUID();
360 assert(MainFileID.
isInvalid() &&
"expected uninitialized SourceManager");
365 Clone->ContentsEntry =
Cache->ContentsEntry;
366 Clone->BufferOverridden =
Cache->BufferOverridden;
367 Clone->IsFileVolatile =
Cache->IsFileVolatile;
368 Clone->IsTransient =
Cache->IsTransient;
369 Clone->setUnownedBuffer(
Cache->getBufferIfLoaded());
374 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
375 if (!Old.SLocEntryLoaded[I])
376 Old.loadSLocEntry(I,
nullptr);
379 for (
auto &
FileInfo : Old.FileInfos) {
383 Slot = CloneContentCache(
FileInfo.second);
397 if (OverriddenFilesInfo) {
400 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
401 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
404 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
420ContentCache &SourceManager::createMemBufferContentCache(
421 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
425 MemBufferInfos.push_back(Entry);
436 assert(!SLocEntryLoaded[Index]);
437 if (ExternalSLocEntries->
ReadSLocEntry(-(
static_cast<int>(Index) + 2))) {
441 if (!SLocEntryLoaded[Index]) {
443 if (!FakeSLocEntryForRecovery)
444 FakeSLocEntryForRecovery = std::make_unique<SLocEntry>(
SLocEntry::get(
447 return *FakeSLocEntryForRecovery;
451 return LoadedSLocEntryTable[Index];
454std::pair<int, SourceLocation::UIntTy>
457 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
459 if (CurrentLoadedOffset < TotalSize ||
460 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
461 return std::make_pair(0, 0);
463 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
464 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
465 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
466 CurrentLoadedOffset -= TotalSize;
467 updateSlocUsageStats();
468 int BaseID = -
int(LoadedSLocEntryTable.size()) - 1;
469 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
470 return std::make_pair(BaseID, CurrentLoadedOffset);
475llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery()
const {
476 if (!FakeBufferForRecovery)
477 FakeBufferForRecovery =
478 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
480 return *FakeBufferForRecovery;
486 if (!FakeContentCacheForRecovery) {
487 FakeContentCacheForRecovery = std::make_unique<SrcMgr::ContentCache>();
488 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
490 return *FakeContentCacheForRecovery;
495FileID SourceManager::getPreviousFileID(
FileID FID)
const {
506 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
510 return FileID::get(ID-1);
523 }
else if (ID+1 >= -1) {
527 return FileID::get(ID+1);
549 return createFileIDImpl(IR, SourceFile.
getName(), IncludePos, FileCharacter,
550 LoadedID, LoadedOffset);
562 StringRef Name = Buffer->getBufferIdentifier();
563 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
564 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
576 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
577 LoadedID, LoadedOffset, IncludeLoc);
593 llvm::ErrorOr<bool> NeedConversion =
594 llvm::needzOSConversion(
Filename.str().c_str());
595 return NeedConversion && *NeedConversion;
610 assert(LoadedID != -1 &&
"Loading sentinel FileID");
611 unsigned Index =
unsigned(-LoadedID) - 2;
612 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
613 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
616 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
617 return FileID::get(LoadedID);
619 unsigned FileSize =
File.getSize();
621 if (NeedConversion) {
624 if (std::optional<llvm::MemoryBufferRef> Buffer =
626 unsigned BufSize = Buffer->getBufferSize();
627 if (BufSize > FileSize) {
628 if (
File.ContentsEntry.has_value())
629 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
634 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
635 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
636 Diag.
Report(IncludePos, diag::err_sloc_space_too_large);
640 LocalSLocEntryTable.push_back(
645 NextLocalOffset += FileSize + 1;
646 updateSlocUsageStats();
650 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
651 return LastFileIDLookup = FID;
658 return createExpansionLocImpl(Info, Length);
664 bool ExpansionIsTokenRange,
int LoadedID,
667 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
668 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
675 "token spans multiple files");
676 return createExpansionLocImpl(
678 TokenEnd.getOffset() - TokenStart.getOffset());
682SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
683 unsigned Length,
int LoadedID,
686 assert(LoadedID != -1 &&
"Loading sentinel FileID");
687 unsigned Index =
unsigned(-LoadedID) - 2;
688 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
689 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
691 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] =
true;
692 return SourceLocation::getMacroLoc(LoadedOffset);
694 LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset, Info));
695 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
696 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
697 Diag.
Report(diag::err_sloc_space_too_large);
703 llvm::report_fatal_error(
"ran out of source locations");
706 NextLocalOffset += Length + 1;
707 updateSlocUsageStats();
708 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
711std::optional<llvm::MemoryBufferRef>
718 FileEntryRef SourceFile, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
724 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
730 "Different sizes, use the FileManager to create a virtual file with "
732 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
733 "This function should be called at the initialization stage, before "
734 "any parsing occurs.");
736 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
737 std::make_pair(SourceFile, NewFile));
739 Pair.first->second = NewFile;
751 (void)getOrCreateContentCache(*BypassFile);
759std::optional<StringRef>
762 if (Entry->getFile().getContentCache().
OrigEntry)
763 return Entry->getFile().getName();
771 return B ? *B :
"<<<<<INVALID SOURCE LOCATION>>>>>";
774std::optional<StringRef>
785 return B->getBuffer();
800 return FileID::get(0);
804 if (SLocOffset < NextLocalOffset)
805 return getFileIDLocal(SLocOffset);
806 return getFileIDLoaded(SLocOffset);
814 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
831 unsigned LessIndex = 0;
833 unsigned GreaterIndex = LocalSLocEntryTable.size();
834 if (LastFileIDLookup.ID >= 0) {
836 if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
837 LessIndex = LastFileIDLookup.ID;
839 GreaterIndex = LastFileIDLookup.ID;
843 unsigned NumProbes = 0;
846 assert(GreaterIndex < LocalSLocEntryTable.size());
847 if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
848 FileID Res = FileID::get(
int(GreaterIndex));
850 LastFileIDLookup = Res;
851 NumLinearScans += NumProbes+1;
854 if (++NumProbes == 8)
860 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
868 if (MidOffset > SLocOffset) {
869 GreaterIndex = MiddleIndex;
874 if (MiddleIndex + 1 == LocalSLocEntryTable.size() ||
876 FileID Res = FileID::get(MiddleIndex);
879 LastFileIDLookup = Res;
880 NumBinaryProbes += NumProbes;
885 LessIndex = MiddleIndex;
894 if (SLocOffset < CurrentLoadedOffset) {
895 assert(0 &&
"Invalid SLocOffset or bad function choice");
899 return FileID::get(ExternalSLocEntries->
getSLocEntryID(SLocOffset));
937std::pair<FileID, unsigned>
938SourceManager::getDecomposedExpansionLocSlowCase(
945 Loc =
E->getExpansion().getExpansionLocStart();
949 Offset =
Loc.getOffset()-
E->getOffset();
952 return std::make_pair(FID, Offset);
955std::pair<FileID, unsigned>
957 unsigned Offset)
const {
962 Loc =
E->getExpansion().getSpellingLoc();
967 Offset =
Loc.getOffset()-
E->getOffset();
970 return std::make_pair(FID, Offset);
995 assert(
Loc.
isMacroID() &&
"Not a macro expansion loc!");
1052 if (DecompLoc.second > 0)
1066 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1078 *MacroBegin = ExpLoc;
1101 FileID NextFID = getNextFileID(FID);
1131 bool CharDataInvalid =
false;
1133 if (CharDataInvalid || !Entry.
isFile()) {
1137 return "<<<<INVALID BUFFER>>>>";
1139 std::optional<llvm::MemoryBufferRef> Buffer =
1144 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1145 :
"<<<<INVALID BUFFER>>>>";
1160 if (FilePos > MemBuf->getBufferSize()) {
1166 const char *Buf = MemBuf->getBufferStart();
1169 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->
SourceLineCache &&
1170 LastLineNoResult < LastLineNoContentCache->SourceLineCache.
size()) {
1171 const unsigned *SourceLineCache =
1173 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1174 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1175 if (FilePos >= LineStart && FilePos < LineEnd) {
1180 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1181 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1184 return FilePos - LineStart + 1;
1188 unsigned LineStart = FilePos;
1189 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1191 return FilePos-LineStart+1;
1196template<
typename LocType>
1232 return ((x - ~
static_cast<T>(0) / 255 * (n + 1)) & ~x &
1233 ((x & ~
static_cast<T>(0) / 255 * 127) +
1234 (~
static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1235 ~static_cast<T>(0) / 255 * 128;
1239 llvm::BumpPtrAllocator &Alloc) {
1246 LineOffsets.push_back(0);
1248 const unsigned char *Start = (
const unsigned char *)Buffer.getBufferStart();
1249 const unsigned char *End = (
const unsigned char *)Buffer.getBufferEnd();
1250 const unsigned char *Buf = Start;
1256 if ((
unsigned long)(End - Start) >
sizeof(Word)) {
1258 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1262 Buf +=
sizeof(Word);
1270 unsigned N = llvm::countr_zero(Mask) - 7;
1273 unsigned char Byte = Word;
1282 LineOffsets.push_back(Buf - Start);
1284 }
while (Buf < End -
sizeof(Word) - 1);
1290 LineOffsets.push_back(Buf - Start + 1);
1291 }
else if (*Buf ==
'\r') {
1293 if (Buf + 1 < End && Buf[1] ==
'\n') {
1296 LineOffsets.push_back(Buf - Start + 1);
1305 llvm::BumpPtrAllocator &Alloc)
1306 : Storage(Alloc.Allocate<
unsigned>(LineOffsets.size() + 1)) {
1307 Storage[0] = LineOffsets.size();
1308 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1324 if (LastLineNoFileIDQuery == FID)
1325 Content = LastLineNoContentCache;
1327 bool MyInvalid =
false;
1328 const SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
1329 if (MyInvalid || !Entry.
isFile()) {
1341 std::optional<llvm::MemoryBufferRef> Buffer =
1356 const unsigned *SourceLineCacheStart = SourceLineCache;
1359 unsigned QueriedFilePos = FilePos+1;
1374 if (LastLineNoFileIDQuery == FID) {
1375 if (QueriedFilePos >= LastLineNoFilePos) {
1377 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1383 if (SourceLineCache+5 < SourceLineCacheEnd) {
1384 if (SourceLineCache[5] > QueriedFilePos)
1385 SourceLineCacheEnd = SourceLineCache+5;
1386 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1387 if (SourceLineCache[10] > QueriedFilePos)
1388 SourceLineCacheEnd = SourceLineCache+10;
1389 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1390 if (SourceLineCache[20] > QueriedFilePos)
1391 SourceLineCacheEnd = SourceLineCache+20;
1396 if (LastLineNoResult < Content->SourceLineCache.size())
1397 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1401 const unsigned *Pos =
1402 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1403 unsigned LineNo = Pos-SourceLineCacheStart;
1405 LastLineNoFileIDQuery = FID;
1406 LastLineNoContentCache = Content;
1407 LastLineNoFilePos = QueriedFilePos;
1408 LastLineNoResult = LineNo;
1415 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(
Loc);
1416 return getLineNumber(LocInfo.first, LocInfo.second);
1421 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1422 return getLineNumber(LocInfo.first, LocInfo.second);
1441 assert(
Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1442 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1443 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1454 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1457 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1473 auto B = getBufferOrNone(getFileID(
Loc));
1476 return B ? B->getBufferIdentifier() :
"<invalid buffer>";
1487 bool UseLineDirectives)
const {
1491 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1504 FileID FID = LocInfo.first;
1508 else if (
auto Buffer =
C->getBufferOrNone(
Diag, getFileManager()))
1509 Filename = Buffer->getBufferIdentifier();
1511 unsigned LineNo = getLineNumber(LocInfo.first, LocInfo.second, &
Invalid);
1514 unsigned ColNo = getColumnNumber(LocInfo.first, LocInfo.second, &
Invalid);
1523 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1526 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1528 if (Entry->FilenameID != -1) {
1529 Filename = LineTable->getFilename(Entry->FilenameID);
1532 FID = FileID::get(0);
1539 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1540 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1545 if (Entry->IncludeOffset) {
1546 IncludeLoc = getLocForStartOfFile(LocInfo.first);
1566 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(
Loc);
1568 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1577 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1578 if (Entry->IncludeOffset)
1593 if ((ID > 0 &&
unsigned(ID+1) == local_sloc_entry_size()))
1594 NextOffset = getNextLocalOffset();
1595 else if (ID+1 == -1)
1596 NextOffset = MaxLoadedOffset;
1598 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1600 return NextOffset - Entry.
getOffset() - 1;
1613 unsigned Col)
const {
1614 assert(SourceFile &&
"Null source file!");
1615 assert(
Line && Col &&
"Line and column should start from 1!");
1617 FileID FirstFID = translateFile(SourceFile);
1618 return translateLineCol(FirstFID,
Line, Col);
1626 assert(SourceFile &&
"Null source file!");
1630 if (MainFileID.isValid()) {
1644 for (
unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
1645 const SLocEntry &SLoc = getLocalSLocEntry(I);
1648 return FileID::get(I);
1652 for (
unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
1653 const SLocEntry &SLoc = getLoadedSLocEntry(I);
1656 return FileID::get(-
int(I) - 2);
1666 unsigned Col)
const {
1669 assert(
Line && Col &&
"Line and column should start from 1!");
1684 if (
Line == 1 && Col == 1)
1691 std::optional<llvm::MemoryBufferRef> Buffer =
1700 unsigned Size = Buffer->getBufferSize();
1707 const char *Buf = Buffer->getBufferStart() + FilePos;
1708 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1715 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1727void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1739 if (
unsigned(ID) >= local_sloc_entry_size())
1741 }
else if (ID == -1) {
1756 bool IncludedInFID =
1757 (IncludeLoc.
isValid() && isInFileID(IncludeLoc, FID)) ||
1761 (FID == MainFileID && Entry.
getFile().
getName() ==
"<built-in>");
1762 if (IncludedInFID) {
1765 if (Entry.
getFile().NumCreatedFIDs)
1766 ID += Entry.
getFile().NumCreatedFIDs - 1 ;
1786 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1788 SourceLocation::getMacroLoc(Entry.
getOffset()),
1789 getFileIDSize(FileID::get(ID)));
1793void SourceManager::associateFileChunkWithMacroArgExp(
1794 MacroArgsMap &MacroArgsCache,
1798 unsigned ExpansionLength)
const {
1809 unsigned SpellRelativeOffs;
1810 std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
1812 const SLocEntry &Entry = getSLocEntry(SpellFID);
1814 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1818 unsigned CurrSpellLength;
1819 if (SpellFIDEndOffs < SpellEndOffs)
1820 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1822 CurrSpellLength = ExpansionLength;
1823 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1825 ExpansionLoc, CurrSpellLength);
1828 if (SpellFIDEndOffs >= SpellEndOffs)
1832 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1836 SpellRelativeOffs = 0;
1843 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1846 unsigned EndOffs = BeginOffs + ExpansionLength;
1865 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1868 MacroArgsCache[BeginOffs] = ExpansionLoc;
1869 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1872void SourceManager::updateSlocUsageStats()
const {
1874 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1875 MaxUsedSLocBytes.updateMax(UsedBytes);
1894 std::tie(FID, Offset) = getDecomposedLoc(
Loc);
1898 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1899 if (!MacroArgsCache) {
1900 MacroArgsCache = std::make_unique<MacroArgsMap>();
1901 computeMacroArgsCache(*MacroArgsCache, FID);
1904 assert(!MacroArgsCache->empty());
1905 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1908 if (I == MacroArgsCache->begin())
1915 if (MacroArgExpandedLoc.
isValid())
1921std::pair<FileID, unsigned>
1924 return std::make_pair(
FileID(), 0);
1928 using DecompTy = std::pair<FileID, unsigned>;
1929 auto InsertOp = IncludedLocMap.try_emplace(FID);
1930 DecompTy &DecompLoc = InsertOp.first->second;
1931 if (!InsertOp.second)
1945 DecompLoc = getDecomposedLoc(UpperLoc);
1951 assert(isLoadedSourceLocation(
Loc) &&
1952 "Must be a source location in a loaded PCH/Module file");
1954 auto [FID, Ignore] = getDecomposedLoc(
Loc);
1960 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater<FileID>{});
1963 "The failure to find the first FileID of a "
1964 "loaded AST from a loaded source location was unexpected.");
1969 const std::pair<FileID, unsigned> &LOffs,
1970 const std::pair<FileID, unsigned> &ROffs)
const {
1972 if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1975 if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1976 auto FindSLocEntryAlloc = [
this](
FileID FID) {
1979 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1980 std::greater<FileID>{});
1984 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1998 std::pair<FileID, unsigned> UpperLoc =
SM.getDecomposedIncludedLoc(
Loc.first);
1999 if (UpperLoc.first.isInvalid() ||
2000 !
SM.isInTheSameTranslationUnitImpl(UpperLoc,
Loc))
2015 enum { MagicCacheSize = 300 };
2016 IsBeforeInTUCacheKey Key(LFID, RFID);
2022 if (IBTUCache.size() < MagicCacheSize)
2023 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
2026 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2027 if (I != IBTUCache.end())
2031 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
2032 return IBTUCacheOverflow;
2040 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2044 std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
2045 std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
2050 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2051 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2053 std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
2055 return InSameTU.second;
2057 return LOffs.first < ROffs.first;
2061 std::pair<FileID, unsigned> &LOffs,
2062 std::pair<FileID, unsigned> &ROffs)
const {
2064 if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2065 return std::make_pair(
false,
false);
2068 if (LOffs.first == ROffs.first)
2069 return std::make_pair(
true, LOffs.second < ROffs.second);
2074 getInBeforeInTUCache(LOffs.first, ROffs.first);
2079 return std::make_pair(
2089 std::pair<FileID, unsigned> DecomposedLoc;
2092 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2096 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2099 if (LOffs.first == ROffs.first)
2101 LChild = LOffs.first;
2106 auto LIt = LChain.find(ROffs.first);
2107 if (LIt != LChain.end()) {
2109 LOffs = LIt->second.DecomposedLoc;
2110 LChild = LIt->second.ChildFID;
2119 unsigned LChildID = LChild.ID;
2120 unsigned RChildID = RChild.ID;
2121 assert(((LOffs.second != ROffs.second) ||
2122 (LChildID == 0 || RChildID == 0) ||
2123 isInSameSLocAddrSpace(getComposedLoc(LChild, 0),
2124 getComposedLoc(RChild, 0),
nullptr)) &&
2125 "Mixed local/loaded FileIDs with same include location?");
2126 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2127 LChildID < RChildID);
2128 return std::make_pair(
2131 RChild = ROffs.first;
2137 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2138 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2140 bool LIsBuiltins = LB ==
"<built-in>";
2141 bool RIsBuiltins = RB ==
"<built-in>";
2143 if (LIsBuiltins || RIsBuiltins) {
2144 if (LIsBuiltins != RIsBuiltins)
2145 return std::make_pair(
true, LIsBuiltins);
2148 return std::make_pair(
true, LOffs.first < ROffs.first);
2151 bool LIsAsm = LB ==
"<inline asm>";
2152 bool RIsAsm = RB ==
"<inline asm>";
2154 if (LIsAsm || RIsAsm) {
2155 if (LIsAsm != RIsAsm)
2156 return std::make_pair(
true, RIsAsm);
2157 assert(LOffs.first == ROffs.first);
2158 return std::make_pair(
true,
false);
2161 bool LIsScratch = LB ==
"<scratch space>";
2162 bool RIsScratch = RB ==
"<scratch space>";
2164 if (LIsScratch || RIsScratch) {
2165 if (LIsScratch != RIsScratch)
2166 return std::make_pair(
true, LIsScratch);
2167 return std::make_pair(
true, LOffs.second < ROffs.second);
2170 llvm_unreachable(
"Unsortable locations found");
2174 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2175 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2176 <<
" mem buffers mapped.\n";
2177 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntries allocated ("
2178 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2179 <<
" bytes of capacity), " << NextLocalOffset
2180 <<
"B of SLoc address space used.\n";
2181 llvm::errs() << LoadedSLocEntryTable.size()
2182 <<
" loaded SLocEntries allocated ("
2183 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2184 <<
" bytes of capacity), "
2185 << MaxLoadedOffset - CurrentLoadedOffset
2186 <<
"B of SLoc address space used.\n";
2188 unsigned NumLineNumsComputed = 0;
2189 unsigned NumFileBytesMapped = 0;
2191 NumLineNumsComputed +=
bool(I->second->SourceLineCache);
2192 NumFileBytesMapped += I->second->getSizeBytesMapped();
2194 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2196 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2197 << NumLineNumsComputed <<
" files with line #'s computed, "
2198 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2199 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2200 << NumBinaryProbes <<
" binary.\n";
2204 llvm::raw_ostream &out = llvm::errs();
2207 std::optional<SourceLocation::UIntTy> NextStart) {
2208 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2209 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2211 out << *NextStart <<
">\n";
2214 if (Entry.isFile()) {
2215 auto &FI = Entry.getFile();
2216 if (FI.NumCreatedFIDs)
2217 out <<
" covers <FileID " << ID <<
":" <<
int(ID + FI.NumCreatedFIDs)
2219 if (FI.getIncludeLoc().isValid())
2220 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2221 auto &CC = FI.getContentCache();
2222 out <<
" for " << (CC.OrigEntry ? CC.OrigEntry->getName() :
"<none>")
2224 if (CC.BufferOverridden)
2225 out <<
" contents overridden\n";
2226 if (CC.ContentsEntry != CC.OrigEntry) {
2227 out <<
" contents from "
2228 << (CC.ContentsEntry ? CC.ContentsEntry->getName() :
"<none>")
2232 auto &EI = Entry.getExpansion();
2233 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2234 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2235 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":"
2236 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2241 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2242 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2243 ID == NumIDs - 1 ? NextLocalOffset
2244 : LocalSLocEntryTable[ID + 1].getOffset());
2247 std::optional<SourceLocation::UIntTy> NextStart;
2248 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2249 int ID = -(
int)Index - 2;
2250 if (SLocEntryLoaded[Index]) {
2251 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2252 NextStart = LoadedSLocEntryTable[Index].getOffset();
2254 NextStart = std::nullopt;
2265 unsigned Inclusions = 0;
2267 uint64_t DirectSize = 0;
2269 uint64_t TotalSize = 0;
2271 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2274 uint64_t CountedSize = 0;
2276 auto AddUsageForFileID = [&](
FileID ID) {
2279 unsigned Size = getFileIDSize(ID) + 1;
2284 FileID FileLocID = getFileID(FileStart);
2285 const FileEntry *Entry = getFileEntryForID(FileLocID);
2287 Info &EntryInfo = Usage[Entry];
2288 if (EntryInfo.Loc.isInvalid())
2289 EntryInfo.Loc = FileStart;
2290 if (ID == FileLocID) {
2291 ++EntryInfo.Inclusions;
2292 EntryInfo.DirectSize += Size;
2294 EntryInfo.TotalSize += Size;
2295 CountedSize += Size;
2299 for (
size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2300 AddUsageForFileID(FileID::get(-2 - Index));
2303 for (
size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2304 AddUsageForFileID(FileID::get(Index));
2309 auto SortedUsage = Usage.takeVector();
2310 auto Cmp = [](
const UsageMap::value_type &A,
const UsageMap::value_type &B) {
2311 return A.second.TotalSize > B.second.TotalSize ||
2312 (A.second.TotalSize == B.second.TotalSize &&
2313 A.second.Loc < B.second.Loc);
2315 auto SortedEnd = SortedUsage.end();
2316 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2317 SortedEnd = SortedUsage.begin() + *MaxNotes;
2318 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2320 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2323 uint64_t LocalUsage = NextLocalOffset;
2324 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2325 int UsagePercent =
static_cast<int>(100.0 *
double(LocalUsage + LoadedUsage) /
2327 Diag.Report(diag::note_total_sloc_usage)
2328 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2332 uint64_t ReportedSize = 0;
2334 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2338 ReportedSize +=
FileInfo.TotalSize;
2342 if (ReportedSize != CountedSize) {
2343 Diag.Report(diag::note_file_misc_sloc_usage)
2344 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2353 size_t malloc_bytes = 0;
2354 size_t mmap_bytes = 0;
2356 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2357 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2358 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2359 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2360 mmap_bytes += sized_mapped;
2362 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2363 malloc_bytes += sized_mapped;
2371 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2372 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2373 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2374 llvm::capacity_in_bytes(SLocEntryLoaded) +
2375 llvm::capacity_in_bytes(FileInfos);
2377 if (OverriddenFilesInfo)
2378 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2384 StringRef Content) {
2388 new llvm::vfs::InMemoryFileSystem);
2389 InMemoryFileSystem->addFile(
2391 llvm::MemoryBuffer::getMemBuffer(Content,
FileName,
2399 Diagnostics = std::make_unique<DiagnosticsEngine>(
2402 SourceMgr = std::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2406 assert(ID.isValid());
2407 SourceMgr->setMainFileID(ID);
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static ParseState advance(ParseState S, size_t N)
Defines the clang::SourceLocation class and associated facilities.
Defines implementation details of the clang::SourceManager class.
static constexpr T likelyhasbetween(T x, unsigned char m, unsigned char n)
static bool MoveUpTranslationUnitIncludeHierarchy(std::pair< FileID, unsigned > &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
static bool isInvalid(LocType Loc, bool *Invalid)
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
bool needConversion(StringRef Filename)
Helper function to determine if an input file requires conversion.
Defines the SourceManager interface.
Represents a character-granular source range.
void setEnd(SourceLocation e)
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setTokenRange(bool TR)
Used for handling and querying diagnostic IDs.
Options for controlling the compiler diagnostics engine.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void setSourceManager(SourceManager *SrcMgr)
virtual int getSLocEntryID(SourceLocation::UIntTy SLocOffset)=0
Get the index ID for the loaded SourceLocation offset.
virtual ~ExternalSLocEntrySource()
virtual bool ReadSLocEntry(int ID)=0
Read the source location entry with index ID, which will always be less than -1.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
OptionalFileEntryRef getBypassFile(FileEntryRef VFE)
Retrieve a FileEntry that bypasses VFE, which is expected to be a virtual file entry,...
Keeps track of options that affect how file operations are performed.
Holds the cache used by isBeforeInTranslationUnit.
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset, bool LParentBeforeRParent)
bool getCachedResult(unsigned LOffset, unsigned ROffset) const
If the cache is valid, compute the result given the specified offsets in the LHS/RHS FileID's.
bool isCacheValid() const
Return true if the currently cached values match up with the specified LHS/RHS query.
Used to hold and unique data used to represent #line information.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
unsigned getLineTableFilenameID(StringRef Str)
void AddEntry(FileID FID, const std::vector< LineEntry > &Entries)
Add a new line entry that has already been encoded into the internal representation of the line table...
void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table that indicates that there is a #line or GNU line marker at the spec...
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
unsigned getLine() const
Return the presumed line number of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
SourceManagerForFile(StringRef FileName, StringRef Content)
Creates SourceManager and necessary dependencies (e.g.
This class handles loading and caching of source files into memory.
std::optional< StringRef > getNonBuiltinFilenameForID(FileID FID) const
Returns the filename for the provided FileID, unless it's a built-in buffer that's not represented by...
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd=nullptr) const
Returns true if the given MacroID location points at the character end of the immediate macro expansi...
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, std::optional< unsigned > MaxNotes=32) const
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)
Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
void setFileIsTransient(FileEntryRef SourceFile)
Specify that a file is transient.
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
std::optional< StringRef > getBufferDataOrNone(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
void PrintStats() const
Print statistics to stderr.
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...
bool isInTheSameTranslationUnitImpl(const std::pair< FileID, unsigned > &LOffs, const std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same TU.
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const
Get a local SLocEntry. This is exposed for indexing.
OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)
Bypass the overridden contents of a file.
FileManager & getFileManager() const
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
std::optional< StringRef > getBufferDataIfLoaded(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if it's...
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
std::pair< int, SourceLocation::UIntTy > AllocateLoadedSLocEntries(unsigned NumSLocEntries, SourceLocation::UIntTy TotalSize)
Allocate a number of loaded SLocEntries, which will be actually loaded on demand from the external so...
void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
std::pair< bool, bool > isInTheSameTranslationUnit(std::pair< FileID, unsigned > &LOffs, std::pair< FileID, unsigned > &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
void initializeForReplay(const SourceManager &Old)
Initialize this source manager suitably to replay the compilation described by Old.
FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
std::pair< FileID, unsigned > getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
LineTableInfo & getLineTable()
Retrieve the stored line table.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLoc, unsigned Length)
Creates an expansion SLocEntry for the substitution of an argument into a function-like macro's body.
A trivial tuple used to represent a source range.
One instance of this struct is kept for every file loaded or used.
void setBuffer(std::unique_ptr< llvm::MemoryBuffer > B)
Set the buffer.
std::optional< StringRef > getBufferDataIfLoaded() const
Return a StringRef to the source buffer data, only if it has already been loaded.
OptionalFileEntryRef ContentsEntry
References the file which the contents were actually loaded from.
unsigned getSizeBytesMapped() const
Returns the number of bytes actually mapped for this ContentCache.
unsigned IsTransient
True if this file may be transient, that is, if it might not exist at some later point in time when t...
unsigned getSize() const
Returns the size of the content encapsulated by this ContentCache.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache.
unsigned IsFileVolatile
True if this content cache was initially created for a source file considered to be volatile (likely ...
LineOffsetMapping SourceLineCache
A bump pointer allocated array of offsets for each source line.
std::optional< llvm::MemoryBufferRef > getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM, SourceLocation Loc=SourceLocation()) const
Returns the memory buffer for the associated content.
static const char * getInvalidBOM(StringRef BufStr)
unsigned BufferOverridden
Indicates whether the buffer itself was provided to override the actual file contents.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)
Return a ExpansionInfo for an expansion.
bool isMacroBodyExpansion() const
SourceLocation getSpellingLoc() const
CharSourceRange getExpansionLocRange() const
bool isMacroArgExpansion() const
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)
Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)
Return a special ExpansionInfo representing a token that ends prematurely.
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)
Return a FileInfo object.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
void setHasLineDirectives()
Set the flag that indicates that this FileID has line table entries associated with it.
SourceLocation getIncludeLoc() const
StringRef getName() const
Returns the name of the file that was used when the file was loaded from the underlying file system.
Mapping of line offsets into a source file.
const unsigned * begin() const
LineOffsetMapping()=default
const unsigned * end() const
static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)
This is a discriminated union of FileInfo and ExpansionInfo.
SourceLocation::UIntTy getOffset() const
static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)
const FileInfo & getFile() const
const ExpansionInfo & getExpansion() const
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
The JSON file list parser is used to communicate input to InstallAPI.
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)