18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/Support/Capacity.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/raw_ostream.h"
30 using namespace clang;
31 using namespace SrcMgr;
32 using llvm::MemoryBuffer;
38 ContentCache::~ContentCache() {
39 if (shouldFreeBuffer())
40 delete Buffer.getPointer();
45 unsigned ContentCache::getSizeBytesMapped()
const {
46 return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
51 llvm::MemoryBuffer::BufferKind ContentCache::getMemoryBufferKind()
const {
52 assert(Buffer.getPointer());
55 if (!Buffer.getPointer())
56 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
58 llvm::MemoryBuffer *buf = Buffer.getPointer();
59 return buf->getBufferKind();
66 unsigned ContentCache::getSize()
const {
67 return Buffer.getPointer() ? (
unsigned) Buffer.getPointer()->getBufferSize()
68 : (
unsigned) ContentsEntry->getSize();
71 void ContentCache::replaceBuffer(llvm::MemoryBuffer *B,
bool DoNotFree) {
72 if (B && B == Buffer.getPointer()) {
73 assert(0 &&
"Replacing with the same buffer");
74 Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
78 if (shouldFreeBuffer())
79 delete Buffer.getPointer();
81 Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
87 bool *Invalid)
const {
90 if (Buffer.getPointer() || !ContentsEntry) {
92 *Invalid = isBufferInvalid();
94 return Buffer.getPointer();
111 if (!BufferOrError) {
112 StringRef FillStr(
"<<<MISSING SOURCE FILE>>>\n");
113 Buffer.setPointer(MemoryBuffer::getNewUninitMemBuffer(
114 ContentsEntry->getSize(),
"<invalid>").release());
115 char *Ptr =
const_cast<char*
>(Buffer.getPointer()->getBufferStart());
116 for (
unsigned i = 0, e = ContentsEntry->getSize(); i != e; ++i)
117 Ptr[i] = FillStr[i % FillStr.size()];
121 ContentsEntry->getName(),
122 BufferOrError.getError().message());
124 Diag.
Report(Loc, diag::err_cannot_open_file)
125 << ContentsEntry->getName() << BufferOrError.getError().message();
127 Buffer.setInt(Buffer.getInt() | InvalidFlag);
129 if (Invalid) *Invalid =
true;
130 return Buffer.getPointer();
133 Buffer.setPointer(BufferOrError->release());
137 if (getRawBuffer()->getBufferSize() != (
size_t)ContentsEntry->getSize()) {
140 ContentsEntry->getName());
142 Diag.
Report(Loc, diag::err_file_modified)
143 << ContentsEntry->getName();
145 Buffer.setInt(Buffer.getInt() | InvalidFlag);
146 if (Invalid) *Invalid =
true;
147 return Buffer.getPointer();
153 StringRef BufStr = Buffer.getPointer()->getBuffer();
154 const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr)
155 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
156 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
157 .StartsWith(
"\x00\x00\xFE\xFF",
"UTF-32 (BE)")
158 .StartsWith(
"\xFF\xFE\x00\x00",
"UTF-32 (LE)")
159 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
160 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
161 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
162 .StartsWith(
"\x0E\xFE\xFF",
"SDSU")
163 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
164 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
168 Diag.
Report(Loc, diag::err_unsupported_bom)
169 << InvalidBOM << ContentsEntry->getName();
170 Buffer.setInt(Buffer.getInt() | InvalidFlag);
174 *Invalid = isBufferInvalid();
176 return Buffer.getPointer();
181 FilenameIDs.insert(std::make_pair(Name, FilenamesByID.size()));
183 FilenamesByID.push_back(&*IterBool.first);
184 return IterBool.first->second;
191 unsigned LineNo,
int FilenameID) {
192 std::vector<LineEntry> &Entries = LineEntries[FID];
194 assert((Entries.empty() || Entries.back().FileOffset <
Offset) &&
195 "Adding line entries out of order!");
198 unsigned IncludeOffset = 0;
200 if (!Entries.empty()) {
203 if (FilenameID == -1)
204 FilenameID = Entries.back().FilenameID;
208 Kind = Entries.back().FileKind;
209 IncludeOffset = Entries.back().IncludeOffset;
212 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, Kind,
222 unsigned LineNo,
int FilenameID,
225 assert(FilenameID != -1 &&
"Unspecified filename should use other accessor");
227 std::vector<LineEntry> &Entries = LineEntries[FID];
229 assert((Entries.empty() || Entries.back().FileOffset <
Offset) &&
230 "Adding line entries out of order!");
232 unsigned IncludeOffset = 0;
233 if (EntryExit == 0) {
234 IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset;
235 }
else if (EntryExit == 1) {
236 IncludeOffset = Offset-1;
237 }
else if (EntryExit == 2) {
238 assert(!Entries.empty() && Entries.back().IncludeOffset &&
239 "PPDirectives should have caught case when popping empty include stack");
244 FindNearestLineEntry(FID, Entries.back().IncludeOffset))
245 IncludeOffset = PrevEntry->IncludeOffset;
248 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
257 const std::vector<LineEntry> &Entries = LineEntries[FID];
258 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
262 if (Entries.back().FileOffset <=
Offset)
263 return &Entries.back();
266 std::vector<LineEntry>::const_iterator I =
267 std::upper_bound(Entries.begin(), Entries.end(),
Offset);
268 if (I == Entries.begin())
return nullptr;
275 const std::vector<LineEntry> &Entries) {
276 LineEntries[FID] = Entries;
284 return LineTable->getLineTableFilenameID(Name);
293 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
295 bool Invalid =
false;
296 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
297 if (!Entry.
isFile() || Invalid)
307 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID);
312 int FilenameID,
bool IsFileEntry,
313 bool IsFileExit,
bool IsSystemHeader,
314 bool IsExternCHeader) {
317 if (FilenameID == -1) {
318 assert(!IsFileEntry && !IsFileExit && !IsSystemHeader && !IsExternCHeader &&
319 "Can't set flags without setting the filename!");
320 return AddLineNote(Loc, LineNo, FilenameID);
323 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
325 bool Invalid =
false;
326 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
327 if (!Entry.
isFile() || Invalid)
341 else if (IsSystemHeader)
346 unsigned EntryExit = 0;
352 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
353 EntryExit, FileKind);
367 bool UserFilesAreVolatile)
368 : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(
true),
369 UserFilesAreVolatile(UserFilesAreVolatile),
370 ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0),
382 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
383 if (MemBufferInfos[i]) {
384 MemBufferInfos[i]->~ContentCache();
385 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
388 for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
389 I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
391 I->second->~ContentCache();
392 ContentCacheAlloc.Deallocate(I->second);
396 llvm::DeleteContainerSeconds(MacroArgsCacheMap);
401 LocalSLocEntryTable.clear();
402 LoadedSLocEntryTable.clear();
403 SLocEntryLoaded.clear();
404 LastLineNoFileIDQuery =
FileID();
405 LastLineNoContentCache =
nullptr;
406 LastFileIDLookup =
FileID();
413 CurrentLoadedOffset = MaxLoadedOffset;
420 SourceManager::getOrCreateContentCache(
const FileEntry *FileEnt,
422 assert(FileEnt &&
"Didn't specify a file entry to use?");
425 ContentCache *&Entry = FileInfos[FileEnt];
426 if (Entry)
return Entry;
429 Entry = ContentCacheAlloc.Allocate<ContentCache>();
431 if (OverriddenFilesInfo) {
434 llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
435 overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
436 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
437 new (Entry) ContentCache(FileEnt);
439 new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
443 new (Entry) ContentCache(FileEnt);
446 Entry->IsSystemFile = isSystemFile;
454 const ContentCache *SourceManager::createMemBufferContentCache(
455 std::unique_ptr<llvm::MemoryBuffer> Buffer) {
457 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
458 new (Entry) ContentCache();
459 MemBufferInfos.push_back(Entry);
460 Entry->setBuffer(std::move(Buffer));
465 bool *Invalid)
const {
466 assert(!SLocEntryLoaded[Index]);
467 if (ExternalSLocEntries->
ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
471 if (!SLocEntryLoaded[Index]) {
473 LoadedSLocEntryTable[Index] = SLocEntry::get(0,
475 getFakeContentCacheForRecovery(),
480 return LoadedSLocEntryTable[Index];
483 std::pair<int, unsigned>
485 unsigned TotalSize) {
486 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
487 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
488 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
489 CurrentLoadedOffset -= TotalSize;
490 assert(CurrentLoadedOffset >= NextLocalOffset &&
"Out of source locations");
491 int ID = LoadedSLocEntryTable.size();
492 return std::make_pair(-ID - 1, CurrentLoadedOffset);
497 llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery()
const {
498 if (!FakeBufferForRecovery)
499 FakeBufferForRecovery =
500 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
502 return FakeBufferForRecovery.get();
507 const SrcMgr::ContentCache *
508 SourceManager::getFakeContentCacheForRecovery()
const {
509 if (!FakeContentCacheForRecovery) {
510 FakeContentCacheForRecovery = llvm::make_unique<SrcMgr::ContentCache>();
511 FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
514 return FakeContentCacheForRecovery.get();
519 FileID SourceManager::getPreviousFileID(
FileID FID)
const {
530 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
534 return FileID::get(ID-1);
547 }
else if (ID+1 >= -1) {
551 return FileID::get(ID+1);
564 int LoadedID,
unsigned LoadedOffset) {
566 assert(LoadedID != -1 &&
"Loading sentinel FileID");
567 unsigned Index =
unsigned(-LoadedID) - 2;
568 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
569 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
570 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset,
571 FileInfo::get(IncludePos, File, FileCharacter));
572 SLocEntryLoaded[Index] =
true;
573 return FileID::get(LoadedID);
575 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset,
576 FileInfo::get(IncludePos, File,
578 unsigned FileSize = File->getSize();
579 assert(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
580 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset &&
581 "Ran out of source locations!");
584 NextLocalOffset += FileSize + 1;
588 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
589 return LastFileIDLookup = FID;
595 unsigned TokLength) {
596 ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc,
598 return createExpansionLocImpl(Info, TokLength);
607 unsigned LoadedOffset) {
610 return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
614 SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
617 unsigned LoadedOffset) {
619 assert(LoadedID != -1 &&
"Loading sentinel FileID");
620 unsigned Index =
unsigned(-LoadedID) - 2;
621 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
622 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
623 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
624 SLocEntryLoaded[Index] =
true;
625 return SourceLocation::getMacroLoc(LoadedOffset);
627 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
628 assert(NextLocalOffset + TokLength + 1 > NextLocalOffset &&
629 NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset &&
630 "Ran out of source locations!");
632 NextLocalOffset += TokLength + 1;
633 return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
638 const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
639 assert(IR &&
"getOrCreateContentCache() cannot return NULL");
644 llvm::MemoryBuffer *Buffer,
646 const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
647 assert(IR &&
"getOrCreateContentCache() cannot return NULL");
649 const_cast<SrcMgr::ContentCache *
>(IR)->replaceBuffer(Buffer, DoNotFree);
650 const_cast<SrcMgr::ContentCache *
>(IR)->BufferOverridden =
true;
652 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
658 "Different sizes, use the FileManager to create a virtual file with "
660 assert(FileInfos.count(SourceFile) == 0 &&
661 "This function should be called at the initialization stage, before "
662 "any parsing occurs.");
663 getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
670 const SrcMgr::ContentCache *IR = getOrCreateContentCache(File);
671 const_cast<SrcMgr::ContentCache *
>(IR)->replaceBuffer(
nullptr);
672 const_cast<SrcMgr::ContentCache *
>(IR)->ContentsEntry = IR->OrigEntry;
674 assert(OverriddenFilesInfo);
675 OverriddenFilesInfo->OverriddenFiles.erase(File);
676 OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File);
680 bool MyInvalid =
false;
682 if (!SLoc.
isFile() || MyInvalid) {
685 return "<<<<<INVALID SOURCE LOCATION>>>>>";
691 *Invalid = MyInvalid;
694 return "<<<<<INVALID SOURCE LOCATION>>>>>";
696 return Buf->getBuffer();
708 FileID SourceManager::getFileIDSlow(
unsigned SLocOffset)
const {
710 return FileID::get(0);
714 if (SLocOffset < NextLocalOffset)
715 return getFileIDLocal(SLocOffset);
716 return getFileIDLoaded(SLocOffset);
723 FileID SourceManager::getFileIDLocal(
unsigned SLocOffset)
const {
724 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
739 if (LastFileIDLookup.ID < 0 ||
740 LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
742 I = LocalSLocEntryTable.end();
745 I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID;
750 unsigned NumProbes = 0;
754 FileID Res = FileID::get(
int(I - LocalSLocEntryTable.begin()));
759 LastFileIDLookup = Res;
760 NumLinearScans += NumProbes+1;
763 if (++NumProbes == 8)
769 unsigned GreaterIndex = I - LocalSLocEntryTable.begin();
773 unsigned LessIndex = 0;
776 bool Invalid =
false;
777 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
780 return FileID::get(0);
786 if (MidOffset > SLocOffset) {
787 GreaterIndex = MiddleIndex;
794 if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
795 FileID Res = FileID::get(MiddleIndex);
799 if (!LocalSLocEntryTable[MiddleIndex].isExpansion())
800 LastFileIDLookup = Res;
801 NumBinaryProbes += NumProbes;
806 LessIndex = MiddleIndex;
814 FileID SourceManager::getFileIDLoaded(
unsigned SLocOffset)
const {
816 if (SLocOffset < CurrentLoadedOffset) {
817 assert(0 &&
"Invalid SLocOffset or bad function choice");
826 int LastID = LastFileIDLookup.ID;
827 if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset)
830 I = (-LastID - 2) + 1;
833 for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) {
837 FileID Res = FileID::get(-
int(I) - 2);
840 LastFileIDLookup = Res;
841 NumLinearScans += NumProbes + 1;
849 unsigned GreaterIndex = I;
850 unsigned LessIndex = LoadedSLocEntryTable.size();
854 unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
863 if (GreaterIndex == MiddleIndex) {
864 assert(0 &&
"binary search missed the entry");
867 GreaterIndex = MiddleIndex;
871 if (isOffsetInFileID(FileID::get(-
int(MiddleIndex) - 2), SLocOffset)) {
872 FileID Res = FileID::get(-
int(MiddleIndex) - 2);
874 LastFileIDLookup = Res;
875 NumBinaryProbes += NumProbes;
880 if (LessIndex == MiddleIndex) {
881 assert(0 &&
"binary search missed the entry");
884 LessIndex = MiddleIndex;
923 std::pair<FileID, unsigned>
924 SourceManager::getDecomposedExpansionLocSlowCase(
938 return std::make_pair(FID, Offset);
941 std::pair<FileID, unsigned>
943 unsigned Offset)
const {
956 return std::make_pair(FID, Offset);
973 std::pair<SourceLocation,SourceLocation>
975 assert(Loc.
isMacroID() &&
"Not a macro expansion loc!");
982 std::pair<SourceLocation,SourceLocation>
984 if (Loc.
isFileID())
return std::make_pair(Loc, Loc);
986 std::pair<SourceLocation,SourceLocation> Res =
991 while (!Res.first.isFileID())
993 while (!Res.second.isFileID())
1019 if (DecompLoc.second > 0)
1022 bool Invalid =
false;
1033 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1045 *MacroBegin = ExpLoc;
1058 bool Invalid =
false;
1068 FileID NextFID = getNextFileID(FID);
1093 bool *Invalid)
const {
1099 bool CharDataInvalid =
false;
1101 if (CharDataInvalid || !Entry.
isFile()) {
1105 return "<<<<INVALID BUFFER>>>>";
1110 *Invalid = CharDataInvalid;
1111 return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
1118 bool *Invalid)
const {
1119 bool MyInvalid =
false;
1120 llvm::MemoryBuffer *MemBuf =
getBuffer(FID, &MyInvalid);
1122 *Invalid = MyInvalid;
1128 if (FilePos > MemBuf->getBufferSize()) {
1136 if (LastLineNoFileIDQuery == FID &&
1137 LastLineNoContentCache->SourceLineCache !=
nullptr &&
1138 LastLineNoResult < LastLineNoContentCache->NumLines) {
1139 unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache;
1140 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1141 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1142 if (FilePos >= LineStart && FilePos < LineEnd)
1143 return FilePos - LineStart + 1;
1146 const char *Buf = MemBuf->getBufferStart();
1147 unsigned LineStart = FilePos;
1148 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1150 return FilePos-LineStart+1;
1158 *Invalid = MyInvalid;
1163 bool *Invalid)
const {
1170 bool *Invalid)
const {
1177 bool *Invalid)
const {
1186 static LLVM_ATTRIBUTE_NOINLINE
void
1188 llvm::BumpPtrAllocator &Alloc,
1191 llvm::BumpPtrAllocator &Alloc,
1194 MemoryBuffer *Buffer = FI->getBuffer(Diag, SM,
SourceLocation(), &Invalid);
1203 LineOffsets.push_back(0);
1205 const unsigned char *Buf = (
const unsigned char *)Buffer->getBufferStart();
1206 const unsigned char *
End = (
const unsigned char *)Buffer->getBufferEnd();
1210 const unsigned char *NextBuf = (
const unsigned char *)Buf;
1216 __m128i CRs = _mm_set1_epi8(
'\r');
1217 __m128i LFs = _mm_set1_epi8(
'\n');
1220 while (((uintptr_t)NextBuf & 0xF) != 0) {
1221 if (*NextBuf ==
'\n' || *NextBuf ==
'\r' || *NextBuf ==
'\0')
1222 goto FoundSpecialChar;
1227 while (NextBuf+16 <= End) {
1228 const __m128i Chunk = *(
const __m128i*)NextBuf;
1229 __m128i Cmp = _mm_or_si128(_mm_cmpeq_epi8(Chunk, CRs),
1230 _mm_cmpeq_epi8(Chunk, LFs));
1231 unsigned Mask = _mm_movemask_epi8(Cmp);
1235 NextBuf += llvm::countTrailingZeros(Mask);
1236 goto FoundSpecialChar;
1242 while (*NextBuf !=
'\n' && *NextBuf !=
'\r' && *NextBuf !=
'\0')
1248 Offs += NextBuf-Buf;
1251 if (Buf[0] ==
'\n' || Buf[0] ==
'\r') {
1253 if ((Buf[1] ==
'\n' || Buf[1] ==
'\r') && Buf[0] != Buf[1])
1256 LineOffsets.push_back(Offs);
1259 if (Buf == End)
break;
1266 FI->NumLines = LineOffsets.size();
1267 FI->SourceLineCache = Alloc.Allocate<
unsigned>(LineOffsets.size());
1268 std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
1276 bool *Invalid)
const {
1283 ContentCache *Content;
1284 if (LastLineNoFileIDQuery == FID)
1285 Content = LastLineNoContentCache;
1287 bool MyInvalid =
false;
1289 if (MyInvalid || !Entry.
isFile()) {
1300 if (!Content->SourceLineCache) {
1301 bool MyInvalid =
false;
1304 *Invalid = MyInvalid;
1312 unsigned *SourceLineCache = Content->SourceLineCache;
1313 unsigned *SourceLineCacheStart = SourceLineCache;
1314 unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
1316 unsigned QueriedFilePos = FilePos+1;
1331 if (LastLineNoFileIDQuery == FID) {
1332 if (QueriedFilePos >= LastLineNoFilePos) {
1334 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1340 if (SourceLineCache+5 < SourceLineCacheEnd) {
1341 if (SourceLineCache[5] > QueriedFilePos)
1342 SourceLineCacheEnd = SourceLineCache+5;
1343 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1344 if (SourceLineCache[10] > QueriedFilePos)
1345 SourceLineCacheEnd = SourceLineCache+10;
1346 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1347 if (SourceLineCache[20] > QueriedFilePos)
1348 SourceLineCacheEnd = SourceLineCache+20;
1353 if (LastLineNoResult < Content->NumLines)
1354 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1359 = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1360 unsigned LineNo = Pos-SourceLineCacheStart;
1362 LastLineNoFileIDQuery = FID;
1363 LastLineNoContentCache = Content;
1364 LastLineNoFilePos = QueriedFilePos;
1365 LastLineNoResult = LineNo;
1370 bool *Invalid)
const {
1376 bool *Invalid)
const {
1382 bool *Invalid)
const {
1397 assert(!Loc.
isInvalid() &&
"Can't get file characteristic of invalid loc!");
1399 bool Invalid =
false;
1401 if (Invalid || !SEntry.
isFile())
1411 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1427 bool *Invalid)
const {
1428 if (
isInvalid(Loc, Invalid))
return "<invalid loc>";
1442 bool UseLineDirectives)
const {
1448 bool Invalid =
false;
1450 if (Invalid || !Entry.
isFile())
1459 const char *Filename;
1461 Filename = C->OrigEntry->getName();
1463 Filename = C->getBuffer(Diag, *
this)->getBufferIdentifier();
1465 unsigned LineNo =
getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
1468 unsigned ColNo =
getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
1477 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1482 if (Entry->FilenameID != -1)
1483 Filename = LineTable->
getFilename(Entry->FilenameID);
1489 unsigned MarkerLineNo =
getLineNumber(LocInfo.first, Entry->FileOffset);
1490 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1495 if (Entry->IncludeOffset) {
1502 return PresumedLoc(Filename, LineNo, ColNo, IncludeLoc);
1518 bool Invalid =
false;
1520 if (Invalid || !Entry.
isFile())
1529 if (Entry->IncludeOffset)
1537 bool Invalid =
false;
1543 unsigned NextOffset;
1546 else if (ID+1 == -1)
1547 NextOffset = MaxLoadedOffset;
1551 return NextOffset - Entry.
getOffset() - 1;
1567 llvm::sys::fs::UniqueID
ID;
1568 if (llvm::sys::fs::getUniqueID(File->
getName(),
ID))
1580 unsigned Col)
const {
1581 assert(SourceFile &&
"Null source file!");
1582 assert(Line && Col &&
"Line and column should start from 1!");
1593 assert(SourceFile &&
"Null source file!");
1603 bool Invalid =
false;
1609 const ContentCache *MainContentCache
1611 if (!MainContentCache) {
1613 }
else if (MainContentCache->OrigEntry == SourceFile) {
1614 FirstFID = MainFileID;
1618 const FileEntry *MainFile = MainContentCache->OrigEntry;
1619 SourceFileName = llvm::sys::path::filename(SourceFile->
getName());
1620 if (*SourceFileName == llvm::sys::path::filename(MainFile->
getName())) {
1622 if (SourceFileUID) {
1625 if (*SourceFileUID == *MainFileUID) {
1626 FirstFID = MainFileID;
1627 SourceFile = MainFile;
1640 bool Invalid =
false;
1648 FirstFID = FileID::get(I);
1659 FirstFID = FileID::get(-
int(I) - 2);
1671 (SourceFileName = llvm::sys::path::filename(SourceFile->
getName()))) &&
1673 bool Invalid =
false;
1682 const ContentCache *FileContentCache
1684 const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry
1687 *SourceFileName == llvm::sys::path::filename(Entry->
getName())) {
1690 if (*SourceFileUID == *EntryUID) {
1691 FirstFID = FileID::get(I);
1709 unsigned Col)
const {
1712 assert(Line != 0 &&
"Passed a zero-based line");
1717 bool Invalid =
false;
1727 if (Line == 1 && Col == 1)
1730 ContentCache *Content
1737 if (!Content->SourceLineCache) {
1738 bool MyInvalid =
false;
1744 if (Line > Content->NumLines) {
1745 unsigned Size = Content->getBuffer(Diag, *
this)->getBufferSize();
1751 llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *
this);
1752 unsigned FilePos = Content->SourceLineCache[Line - 1];
1753 const char *Buf = Buffer->getBufferStart() + FilePos;
1754 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1761 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1773 void SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr,
1778 CachePtr =
new MacroArgsMap();
1779 MacroArgsMap &MacroArgsCache = *CachePtr;
1790 }
else if (ID == -1) {
1794 bool Invalid =
false;
1807 if (Entry.
getFile().NumCreatedFIDs)
1808 ID += Entry.
getFile().NumCreatedFIDs - 1;
1822 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1824 SourceLocation::getMacroLoc(Entry.
getOffset()),
1829 void SourceManager::associateFileChunkWithMacroArgExp(
1830 MacroArgsMap &MacroArgsCache,
1834 unsigned ExpansionLength)
const {
1836 unsigned SpellBeginOffs = SpellLoc.getOffset();
1837 unsigned SpellEndOffs = SpellBeginOffs + ExpansionLength;
1845 unsigned SpellRelativeOffs;
1849 unsigned SpellFIDBeginOffs = Entry.
getOffset();
1851 unsigned SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
1854 unsigned CurrSpellLength;
1855 if (SpellFIDEndOffs < SpellEndOffs)
1856 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1858 CurrSpellLength = ExpansionLength;
1859 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1861 ExpansionLoc, CurrSpellLength);
1864 if (SpellFIDEndOffs >= SpellEndOffs)
1868 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1870 ExpansionLength -= advance;
1872 SpellRelativeOffs = 0;
1883 unsigned EndOffs = BeginOffs + ExpansionLength;
1902 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1905 MacroArgsCache[BeginOffs] = ExpansionLoc;
1906 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1929 MacroArgsMap *&MacroArgsCache = MacroArgsCacheMap[FID];
1930 if (!MacroArgsCache)
1931 computeMacroArgsCache(MacroArgsCache, FID);
1933 assert(!MacroArgsCache->empty());
1934 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1937 unsigned MacroArgBeginOffs = I->first;
1939 if (MacroArgExpandedLoc.
isValid())
1945 std::pair<FileID, unsigned>
1948 return std::make_pair(
FileID(), 0);
1952 typedef std::pair<FileID, unsigned> DecompTy;
1953 typedef llvm::DenseMap<FileID, DecompTy>
MapTy;
1954 std::pair<MapTy::iterator, bool>
1955 InsertOp = IncludedLocMap.insert(std::make_pair(FID, DecompTy()));
1956 DecompTy &DecompLoc = InsertOp.first->second;
1957 if (!InsertOp.second)
1961 bool Invalid =
false;
1983 if (UpperLoc.first.isInvalid())
1997 enum { MagicCacheSize = 300 };
1998 IsBeforeInTUCacheKey Key(LFID, RFID);
2004 if (IBTUCache.size() < MagicCacheSize)
2005 return IBTUCache[Key];
2008 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2009 if (I != IBTUCache.end())
2013 return IBTUCacheOverflow;
2021 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2031 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2032 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2035 if (LOffs.first == ROffs.first)
2036 return LOffs.second < ROffs.second;
2041 getInBeforeInTUCache(LOffs.first, ROffs.first);
2045 if (IsBeforeInTUCache.
isCacheValid(LOffs.first, ROffs.first))
2049 IsBeforeInTUCache.
setQueryFIDs(LOffs.first, ROffs.first,
2050 LOffs.first.ID < ROffs.first.ID);
2057 typedef llvm::SmallDenseMap<FileID, unsigned, 16> LocSet;
2060 LChain.insert(LOffs);
2065 while((I = LChain.find(ROffs.first)) == LChain.end()) {
2069 if (I != LChain.end())
2074 if (LOffs.first == ROffs.first) {
2075 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
2083 IsBeforeInTUCache.
clear();
2084 llvm::MemoryBuffer *LBuf =
getBuffer(LOffs.first);
2085 llvm::MemoryBuffer *RBuf =
getBuffer(ROffs.first);
2086 bool LIsBuiltins = strcmp(
"<built-in>", LBuf->getBufferIdentifier()) == 0;
2087 bool RIsBuiltins = strcmp(
"<built-in>", RBuf->getBufferIdentifier()) == 0;
2089 if (LIsBuiltins || RIsBuiltins) {
2090 if (LIsBuiltins != RIsBuiltins)
2094 return LOffs.first < ROffs.first;
2096 bool LIsAsm = strcmp(
"<inline asm>", LBuf->getBufferIdentifier()) == 0;
2097 bool RIsAsm = strcmp(
"<inline asm>", RBuf->getBufferIdentifier()) == 0;
2099 if (LIsAsm || RIsAsm) {
2100 if (LIsAsm != RIsAsm)
2102 assert(LOffs.first == ROffs.first);
2105 llvm_unreachable(
"Unsortable locations found");
2109 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2110 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2111 <<
" mem buffers mapped.\n";
2112 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntry's allocated ("
2113 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2114 <<
" bytes of capacity), "
2115 << NextLocalOffset <<
"B of Sloc address space used.\n";
2116 llvm::errs() << LoadedSLocEntryTable.size()
2117 <<
" loaded SLocEntries allocated, "
2118 << MaxLoadedOffset - CurrentLoadedOffset
2119 <<
"B of Sloc address space used.\n";
2121 unsigned NumLineNumsComputed = 0;
2122 unsigned NumFileBytesMapped = 0;
2124 NumLineNumsComputed += I->second->SourceLineCache !=
nullptr;
2125 NumFileBytesMapped += I->second->getSizeBytesMapped();
2127 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2129 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, "
2130 << NumLineNumsComputed <<
" files with line #'s computed, "
2131 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2132 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, "
2133 << NumBinaryProbes <<
" binary.\n";
2141 size_t malloc_bytes = 0;
2142 size_t mmap_bytes = 0;
2144 for (
unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2145 if (
size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2146 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2147 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2148 mmap_bytes += sized_mapped;
2150 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2151 malloc_bytes += sized_mapped;
2159 size_t size = llvm::capacity_in_bytes(MemBufferInfos)
2160 + llvm::capacity_in_bytes(LocalSLocEntryTable)
2161 + llvm::capacity_in_bytes(LoadedSLocEntryTable)
2162 + llvm::capacity_in_bytes(SLocEntryLoaded)
2163 + llvm::capacity_in_bytes(FileInfos);
2165 if (OverriddenFilesInfo)
2166 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
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.
This is a discriminated union of FileInfo and ExpansionInfo.
static bool MoveUpIncludeHierarchy(std::pair< FileID, unsigned > &Loc, const SourceManager &SM)
unsigned getColumn() const
Return the presumed column number of this location.
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Implements support for file system lookup, file system caching, and directory search management...
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
Defines the clang::FileManager interface and associated types.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
Defines the SourceManager interface.
unsigned getNextLocalOffset() const
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded...
const ExpansionInfo & getExpansion() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID)
Set up a new query.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID)
Add a line note to the line table for the FileID and offset specified by Loc.
llvm::DenseMap< Stmt *, Stmt * > MapTy
fileinfo_iterator fileinfo_begin() const
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset)
SourceLocation getIncludeLoc() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
virtual bool ReadSLocEntry(int ID)=0
Read the source location entry with index ID, which will always be less than -1.
unsigned getLineTableFilenameID(StringRef Str)
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1="", StringRef Arg2="")
Set the "delayed" diagnostic that will be emitted once the current diagnostic completes.
static LLVM_ATTRIBUTE_NOINLINE void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, llvm::BumpPtrAllocator &Alloc, const SourceManager &SM, bool &Invalid)
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Used to hold and unique data used to represent #line information.
void disableFileContentsOverride(const FileEntry *File)
Disable overridding the contents of a file, previously enabled with overrideFileContents.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
std::pair< SourceLocation, SourceLocation > getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
bool isDiagnosticInFlight() const
Determine whethere there is already a diagnostic in flight.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
bool isFileOverridden(const FileEntry *File)
Returns true if the file contents have been overridden.
void setSourceManager(SourceManager *SrcMgr)
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
std::pair< FileID, unsigned > getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body. ...
Concrete class used by the front-end to report problems and issues.
unsigned getLine() const
Return the presumed line number of this location.
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isMacroBodyExpansion() const
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
virtual ~ExternalSLocEntrySource()
ID
Defines the set of possible language-specific address spaces.
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col. Returns null location if FID is not a file SLo...
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager...
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...
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
static Optional< llvm::sys::fs::UniqueID > getActualFileUID(const FileEntry *File)
Retrieve the inode for the given file entry, if possible.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
Defines implementation details of the clang::SourceManager class.
FileManager & getFileManager() const
SourceLocation createMacroArgExpansionLoc(SourceLocation Loc, SourceLocation ExpansionLoc, unsigned TokLength)
Return a new SourceLocation that encodes the fact that a token from SpellingLoc should actually be re...
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a local SLocEntry. This is exposed for indexing.
const char * getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Represents an unpacked "presumed" location which can be presented to the user.
SourceLocation createExpansionLoc(SourceLocation Loc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned TokLength, int LoadedID=0, unsigned LoadedOffset=0)
Return a new SourceLocation that encodes the fact that a token from SpellingLoc should actually be re...
SourceLocation getExpansionLocEnd() const
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
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 overrideFileContents(const FileEntry *SourceFile, llvm::MemoryBuffer *Buffer, bool DoNotFree)
Override the contents of the given source file by providing an already-allocated buffer.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
Information about a FileID, basically just the logical file that it represents and include stack info...
const char * getName() const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
bool isValid() const
Return true if this is a valid SourceLocation object.
unsigned getOffset() const
Cached information about one file (either on disk or in the virtual file system). ...
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 getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
llvm::MemoryBuffer * getMemoryBufferForFile(const FileEntry *File, bool *Invalid=nullptr)
Retrieve the memory buffer associated with the given file.
bool isCacheValid(FileID LHS, FileID RHS) const
Return true if the currently cached values match up with the specified LHS/RHS query.
const FileInfo & getFile() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
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...
const char * getFilename(unsigned ID) const
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion...
std::pair< SourceLocation, SourceLocation > getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const FileEntry *Entry, bool isVolatile=false, bool ShouldCloseOpenFile=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID)
const ContentCache * getContentCache() const
fileinfo_iterator fileinfo_end() const
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
SourceLocation getExpansionLocStart() const
llvm::DenseMap< const FileEntry *, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
Defines the Diagnostic-related interfaces.
bool userFilesAreVolatile() const
True if non-system source files should be treated as volatile (likely to change while trying to use t...
bool isMacroArgExpansion() const
Holds the cache used by isBeforeInTranslationUnit.
std::pair< int, unsigned > AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize)
Allocate a number of loaded SLocEntries, which will be actually loaded on demand from the external so...
static bool isInvalid(SourceLocation Loc, bool *Invalid)
void PrintStats() const
Print statistics to stderr.
LineTableInfo & getLineTable()
Retrieve the stored line table.
unsigned loaded_sloc_entry_size() const
Get the number of loaded SLocEntries we have.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
std::pair< SourceLocation, SourceLocation > getExpansionLocRange() const
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
This class handles loading and caching of source files into memory.
SourceLocation getSpellingLoc() const
bool isMacroArgExpansion(SourceLocation Loc) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.