19 #include "llvm/ADT/DenseMap.h" 20 #include "llvm/ADT/Optional.h" 21 #include "llvm/ADT/None.h" 22 #include "llvm/ADT/STLExtras.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/ADT/StringSwitch.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/Support/Allocator.h" 27 #include "llvm/Support/Capacity.h" 28 #include "llvm/Support/Compiler.h" 29 #include "llvm/Support/ErrorHandling.h" 30 #include "llvm/Support/FileSystem.h" 31 #include "llvm/Support/MathExtras.h" 32 #include "llvm/Support/MemoryBuffer.h" 33 #include "llvm/Support/Path.h" 34 #include "llvm/Support/raw_ostream.h" 44 using namespace clang;
45 using namespace SrcMgr;
46 using llvm::MemoryBuffer;
54 delete Buffer.getPointer();
60 return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
66 assert(Buffer.getPointer());
69 if (!Buffer.getPointer())
70 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
72 const llvm::MemoryBuffer *buf = Buffer.getPointer();
73 return buf->getBufferKind();
81 return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
86 if (B && B == Buffer.getPointer()) {
87 assert(0 &&
"Replacing with the same buffer");
88 Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
93 delete Buffer.getPointer();
95 Buffer.setInt((B && DoNotFree) ? DoNotFreeFlag : 0);
101 bool *Invalid)
const {
108 return Buffer.getPointer();
129 Diag.
Report(Loc, diag::err_file_too_large)
132 Buffer.setInt(Buffer.getInt() | InvalidFlag);
133 if (Invalid) *Invalid =
true;
134 return Buffer.getPointer();
151 if (!BufferOrError) {
152 StringRef FillStr(
"<<<MISSING SOURCE FILE>>>\n");
153 auto BackupBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
155 char *Ptr = BackupBuffer->getBufferStart();
157 Ptr[
i] = FillStr[
i % FillStr.size()];
158 Buffer.setPointer(BackupBuffer.release());
163 BufferOrError.getError().message());
165 Diag.
Report(Loc, diag::err_cannot_open_file)
168 Buffer.setInt(Buffer.getInt() | InvalidFlag);
170 if (Invalid) *Invalid =
true;
171 return Buffer.getPointer();
174 Buffer.setPointer(BufferOrError->release());
183 Diag.
Report(Loc, diag::err_file_modified)
186 Buffer.setInt(Buffer.getInt() | InvalidFlag);
187 if (Invalid) *Invalid =
true;
188 return Buffer.getPointer();
194 StringRef BufStr = Buffer.getPointer()->getBuffer();
195 const char *InvalidBOM = llvm::StringSwitch<const char *>(BufStr)
196 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\x00\x00\xFE\xFF"),
198 .StartsWith(llvm::StringLiteral::withInnerNUL(
"\xFF\xFE\x00\x00"),
200 .StartsWith(
"\xFE\xFF",
"UTF-16 (BE)")
201 .StartsWith(
"\xFF\xFE",
"UTF-16 (LE)")
202 .StartsWith(
"\x2B\x2F\x76",
"UTF-7")
203 .StartsWith(
"\xF7\x64\x4C",
"UTF-1")
204 .StartsWith(
"\xDD\x73\x66\x73",
"UTF-EBCDIC")
205 .StartsWith(
"\x0E\xFE\xFF",
"SCSU")
206 .StartsWith(
"\xFB\xEE\x28",
"BOCU-1")
207 .StartsWith(
"\x84\x31\x95\x33",
"GB-18030")
211 Diag.
Report(Loc, diag::err_unsupported_bom)
213 Buffer.setInt(Buffer.getInt() | InvalidFlag);
219 return Buffer.getPointer();
223 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
225 FilenamesByID.push_back(&*IterBool.first);
226 return IterBool.first->second;
236 int FilenameID,
unsigned EntryExit,
238 std::vector<LineEntry> &Entries = LineEntries[FID];
242 if (FilenameID == -1 && !Entries.empty())
243 FilenameID = Entries.back().FilenameID;
245 assert((Entries.empty() || Entries.back().FileOffset <
Offset) &&
246 "Adding line entries out of order!");
248 unsigned IncludeOffset = 0;
249 if (EntryExit == 0) {
250 IncludeOffset = Entries.empty() ? 0 : Entries.back().IncludeOffset;
251 }
else if (EntryExit == 1) {
252 IncludeOffset = Offset-1;
253 }
else if (EntryExit == 2) {
254 assert(!Entries.empty() && Entries.back().IncludeOffset &&
255 "PPDirectives should have caught case when popping empty include stack");
260 FindNearestLineEntry(FID, Entries.back().IncludeOffset))
261 IncludeOffset = PrevEntry->IncludeOffset;
264 Entries.push_back(
LineEntry::get(Offset, LineNo, FilenameID, FileKind,
272 const std::vector<LineEntry> &Entries = LineEntries[FID];
273 assert(!Entries.empty() &&
"No #line entries for this FID after all!");
277 if (Entries.back().FileOffset <=
Offset)
278 return &Entries.back();
281 std::vector<LineEntry>::const_iterator I = llvm::upper_bound(Entries, Offset);
282 if (I == Entries.begin())
290 const std::vector<LineEntry> &Entries) {
291 LineEntries[FID] = Entries;
296 return getLineTable().getLineTableFilenameID(Name);
303 int FilenameID,
bool IsFileEntry,
306 std::pair<FileID, unsigned> LocInfo = getDecomposedExpansionLoc(Loc);
308 bool Invalid =
false;
309 const SLocEntry &Entry = getSLocEntry(LocInfo.first, &Invalid);
310 if (!Entry.
isFile() || Invalid)
318 (void) getLineTable();
320 unsigned EntryExit = 0;
326 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
327 EntryExit, FileKind);
341 bool UserFilesAreVolatile)
342 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
351 for (
unsigned i = 0, e = MemBufferInfos.size();
i != e; ++
i) {
352 if (MemBufferInfos[
i]) {
353 MemBufferInfos[
i]->~ContentCache();
354 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
357 for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
358 I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
360 I->second->~ContentCache();
361 ContentCacheAlloc.Deallocate(I->second);
368 LocalSLocEntryTable.clear();
369 LoadedSLocEntryTable.clear();
370 SLocEntryLoaded.clear();
371 LastLineNoFileIDQuery =
FileID();
372 LastLineNoContentCache =
nullptr;
373 LastFileIDLookup =
FileID();
380 CurrentLoadedOffset = MaxLoadedOffset;
385 assert(MainFileID.
isInvalid() &&
"expected uninitialized SourceManager");
390 Clone->ContentsEntry =
Cache->ContentsEntry;
391 Clone->BufferOverridden =
Cache->BufferOverridden;
392 Clone->IsSystemFile =
Cache->IsSystemFile;
393 Clone->IsTransient =
Cache->IsTransient;
394 Clone->replaceBuffer(
Cache->getRawBuffer(),
true);
399 for (
unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
400 if (!Old.SLocEntryLoaded[I])
401 Old.loadSLocEntry(I,
nullptr);
404 for (
auto &
FileInfo : Old.FileInfos) {
408 Slot = CloneContentCache(
FileInfo.second);
415 SourceManager::getOrCreateContentCache(
const FileEntry *FileEnt,
417 assert(FileEnt &&
"Didn't specify a file entry to use?");
421 if (Entry)
return Entry;
426 if (OverriddenFilesInfo) {
429 llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
430 overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
431 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
434 new (Entry)
ContentCache(OverridenFilesKeepOriginalName ? FileEnt
450 SourceManager::createMemBufferContentCache(
const llvm::MemoryBuffer *Buffer,
455 MemBufferInfos.push_back(Entry);
461 bool *Invalid)
const {
462 assert(!SLocEntryLoaded[Index]);
463 if (ExternalSLocEntries->
ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
467 if (!SLocEntryLoaded[Index]) {
469 LoadedSLocEntryTable[Index] = SLocEntry::get(0,
471 getFakeContentCacheForRecovery(),
476 return LoadedSLocEntryTable[Index];
479 std::pair<int, unsigned>
481 unsigned TotalSize) {
482 assert(ExternalSLocEntries &&
"Don't have an external sloc source");
484 if (CurrentLoadedOffset - TotalSize < NextLocalOffset)
485 return std::make_pair(0, 0);
486 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
487 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
488 CurrentLoadedOffset -= TotalSize;
489 int ID = LoadedSLocEntryTable.size();
490 return std::make_pair(-ID - 1, CurrentLoadedOffset);
495 llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery()
const {
496 if (!FakeBufferForRecovery)
497 FakeBufferForRecovery =
498 llvm::MemoryBuffer::getMemBuffer(
"<<<INVALID BUFFER>>");
500 return FakeBufferForRecovery.get();
506 SourceManager::getFakeContentCacheForRecovery()
const {
507 if (!FakeContentCacheForRecovery) {
508 FakeContentCacheForRecovery = llvm::make_unique<SrcMgr::ContentCache>();
509 FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(),
512 return FakeContentCacheForRecovery.get();
517 FileID SourceManager::getPreviousFileID(
FileID FID)
const {
528 }
else if (
unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
532 return FileID::get(ID-1);
545 }
else if (ID+1 >= -1) {
549 return FileID::get(ID+1);
562 int LoadedID,
unsigned LoadedOffset) {
564 assert(LoadedID != -1 &&
"Loading sentinel FileID");
565 unsigned Index = unsigned(-LoadedID) - 2;
566 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
567 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
568 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset,
569 FileInfo::get(IncludePos, File, FileCharacter));
570 SLocEntryLoaded[Index] =
true;
571 return FileID::get(LoadedID);
573 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset,
574 FileInfo::get(IncludePos, File,
576 unsigned FileSize = File->
getSize();
577 assert(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
578 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset &&
579 "Ran out of source locations!");
582 NextLocalOffset += FileSize + 1;
586 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
587 return LastFileIDLookup = FID;
593 unsigned TokLength) {
594 ExpansionInfo Info = ExpansionInfo::createForMacroArg(SpellingLoc,
596 return createExpansionLocImpl(Info, TokLength);
604 bool ExpansionIsTokenRange,
606 unsigned LoadedOffset) {
608 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
609 return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
616 "token spans multiple files");
617 return createExpansionLocImpl(
618 ExpansionInfo::createForTokenSplit(Spelling, TokenStart, TokenEnd),
619 TokenEnd.getOffset() - TokenStart.getOffset());
623 SourceManager::createExpansionLocImpl(
const ExpansionInfo &Info,
626 unsigned LoadedOffset) {
628 assert(LoadedID != -1 &&
"Loading sentinel FileID");
629 unsigned Index = unsigned(-LoadedID) - 2;
630 assert(Index < LoadedSLocEntryTable.size() &&
"FileID out of range");
631 assert(!SLocEntryLoaded[Index] &&
"FileID already loaded");
632 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
633 SLocEntryLoaded[Index] =
true;
634 return SourceLocation::getMacroLoc(LoadedOffset);
636 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
637 assert(NextLocalOffset + TokLength + 1 > NextLocalOffset &&
638 NextLocalOffset + TokLength + 1 <= CurrentLoadedOffset &&
639 "Ran out of source locations!");
641 NextLocalOffset += TokLength + 1;
642 return SourceLocation::getMacroLoc(NextLocalOffset - (TokLength + 1));
645 const llvm::MemoryBuffer *
648 assert(IR &&
"getOrCreateContentCache() cannot return NULL");
653 llvm::MemoryBuffer *Buffer,
656 assert(IR &&
"getOrCreateContentCache() cannot return NULL");
661 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
667 "Different sizes, use the FileManager to create a virtual file with " 669 assert(FileInfos.count(SourceFile) == 0 &&
670 "This function should be called at the initialization stage, before " 671 "any parsing occurs.");
672 getOverriddenFilesInfo().OverriddenFiles[SourceFile] = NewFile;
683 assert(OverriddenFilesInfo);
684 OverriddenFilesInfo->OverriddenFiles.erase(File);
685 OverriddenFilesInfo->OverriddenFilesWithBuffer.erase(File);
694 bool MyInvalid =
false;
696 if (!SLoc.
isFile() || MyInvalid) {
699 return "<<<<<INVALID SOURCE LOCATION>>>>>";
705 *Invalid = MyInvalid;
708 return "<<<<<INVALID SOURCE LOCATION>>>>>";
710 return Buf->getBuffer();
722 FileID SourceManager::getFileIDSlow(
unsigned SLocOffset)
const {
724 return FileID::get(0);
728 if (SLocOffset < NextLocalOffset)
729 return getFileIDLocal(SLocOffset);
730 return getFileIDLoaded(SLocOffset);
737 FileID SourceManager::getFileIDLocal(
unsigned SLocOffset)
const {
738 assert(SLocOffset < NextLocalOffset &&
"Bad function choice");
753 if (LastFileIDLookup.ID < 0 ||
754 LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
756 I = LocalSLocEntryTable.end();
759 I = LocalSLocEntryTable.begin()+LastFileIDLookup.ID;
764 unsigned NumProbes = 0;
768 FileID Res = FileID::get(
int(I - LocalSLocEntryTable.begin()));
773 LastFileIDLookup = Res;
774 NumLinearScans += NumProbes+1;
777 if (++NumProbes == 8)
783 unsigned GreaterIndex = I - LocalSLocEntryTable.begin();
787 unsigned LessIndex = 0;
790 bool Invalid =
false;
791 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
794 return FileID::get(0);
800 if (MidOffset > SLocOffset) {
801 GreaterIndex = MiddleIndex;
808 if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
809 FileID Res = FileID::get(MiddleIndex);
813 if (!LocalSLocEntryTable[MiddleIndex].isExpansion())
814 LastFileIDLookup = Res;
815 NumBinaryProbes += NumProbes;
820 LessIndex = MiddleIndex;
828 FileID SourceManager::getFileIDLoaded(
unsigned SLocOffset)
const {
830 if (SLocOffset < CurrentLoadedOffset) {
831 assert(0 &&
"Invalid SLocOffset or bad function choice");
840 int LastID = LastFileIDLookup.ID;
841 if (LastID >= 0 || getLoadedSLocEntryByID(LastID).getOffset() < SLocOffset)
844 I = (-LastID - 2) + 1;
847 for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++I) {
851 FileID Res = FileID::get(-
int(I) - 2);
854 LastFileIDLookup = Res;
855 NumLinearScans += NumProbes + 1;
863 unsigned GreaterIndex = I;
864 unsigned LessIndex = LoadedSLocEntryTable.size();
868 unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex;
877 if (GreaterIndex == MiddleIndex) {
878 assert(0 &&
"binary search missed the entry");
881 GreaterIndex = MiddleIndex;
885 if (isOffsetInFileID(FileID::get(-
int(MiddleIndex) - 2), SLocOffset)) {
886 FileID Res = FileID::get(-
int(MiddleIndex) - 2);
888 LastFileIDLookup = Res;
889 NumBinaryProbes += NumProbes;
894 if (LessIndex == MiddleIndex) {
895 assert(0 &&
"binary search missed the entry");
898 LessIndex = MiddleIndex;
937 std::pair<FileID, unsigned>
938 SourceManager::getDecomposedExpansionLocSlowCase(
952 return std::make_pair(FID, Offset);
955 std::pair<FileID, unsigned>
970 return std::make_pair(FID, Offset);
988 assert(Loc.
isMacroID() &&
"Not a macro expansion loc!");
1045 if (DecompLoc.second > 0)
1048 bool Invalid =
false;
1059 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1071 *MacroBegin = ExpLoc;
1084 bool Invalid =
false;
1094 FileID NextFID = getNextFileID(FID);
1118 bool *Invalid)
const {
1124 bool CharDataInvalid =
false;
1126 if (CharDataInvalid || !Entry.
isFile()) {
1130 return "<<<<INVALID BUFFER>>>>";
1132 const llvm::MemoryBuffer *Buffer =
1136 *Invalid = CharDataInvalid;
1137 return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second);
1143 bool *Invalid)
const {
1144 bool MyInvalid =
false;
1145 const llvm::MemoryBuffer *MemBuf =
getBuffer(FID, &MyInvalid);
1147 *Invalid = MyInvalid;
1153 if (FilePos > MemBuf->getBufferSize()) {
1159 const char *Buf = MemBuf->getBufferStart();
1162 if (LastLineNoFileIDQuery == FID &&
1164 LastLineNoResult < LastLineNoContentCache->NumLines) {
1166 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1167 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1168 if (FilePos >= LineStart && FilePos < LineEnd) {
1173 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1174 if (Buf[FilePos - 1] ==
'\r' || Buf[FilePos - 1] ==
'\n')
1177 return FilePos - LineStart + 1;
1181 unsigned LineStart = FilePos;
1182 while (LineStart && Buf[LineStart-1] !=
'\n' && Buf[LineStart-1] !=
'\r')
1184 return FilePos-LineStart+1;
1189 template<
typename LocType>
1191 bool MyInvalid = Loc.isInvalid();
1193 *Invalid = MyInvalid;
1198 bool *Invalid)
const {
1205 bool *Invalid)
const {
1212 bool *Invalid)
const {
1219 #include <emmintrin.h> 1222 static LLVM_ATTRIBUTE_NOINLINE
void 1224 llvm::BumpPtrAllocator &Alloc,
1227 llvm::BumpPtrAllocator &Alloc,
1230 const MemoryBuffer *Buffer =
1240 LineOffsets.push_back(0);
1242 const unsigned char *Buf = (
const unsigned char *)Buffer->getBufferStart();
1243 const unsigned char *
End = (
const unsigned char *)Buffer->getBufferEnd();
1247 while (Buf[I] !=
'\n' && Buf[I] !=
'\r' && Buf[I] !=
'\0')
1250 if (Buf[I] ==
'\n' || Buf[I] ==
'\r') {
1252 if (Buf[I] ==
'\r' && Buf[I+1] ==
'\n')
1255 LineOffsets.push_back(I);
1258 if (Buf+I == End)
break;
1266 std::copy(LineOffsets.begin(), LineOffsets.end(), FI->
SourceLineCache);
1274 bool *Invalid)
const {
1282 if (LastLineNoFileIDQuery == FID)
1283 Content = LastLineNoContentCache;
1285 bool MyInvalid =
false;
1287 if (MyInvalid || !Entry.
isFile()) {
1299 bool MyInvalid =
false;
1302 *Invalid = MyInvalid;
1311 unsigned *SourceLineCacheStart = SourceLineCache;
1312 unsigned *SourceLineCacheEnd = SourceLineCache + Content->
NumLines;
1314 unsigned QueriedFilePos = FilePos+1;
1329 if (LastLineNoFileIDQuery == FID) {
1330 if (QueriedFilePos >= LastLineNoFilePos) {
1332 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1338 if (SourceLineCache+5 < SourceLineCacheEnd) {
1339 if (SourceLineCache[5] > QueriedFilePos)
1340 SourceLineCacheEnd = SourceLineCache+5;
1341 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1342 if (SourceLineCache[10] > QueriedFilePos)
1343 SourceLineCacheEnd = SourceLineCache+10;
1344 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1345 if (SourceLineCache[20] > QueriedFilePos)
1346 SourceLineCacheEnd = SourceLineCache+20;
1351 if (LastLineNoResult < Content->NumLines)
1352 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1357 = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1358 unsigned LineNo = Pos-SourceLineCacheStart;
1360 LastLineNoFileIDQuery = FID;
1361 LastLineNoContentCache = Content;
1362 LastLineNoFilePos = QueriedFilePos;
1363 LastLineNoResult = LineNo;
1368 bool *Invalid)
const {
1374 bool *Invalid)
const {
1380 bool *Invalid)
const {
1396 assert(Loc.
isValid() &&
"Can't get file characteristic of invalid loc!");
1398 bool Invalid =
false;
1400 if (Invalid || !SEntry.
isFile())
1410 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1413 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1426 bool *Invalid)
const {
1427 if (
isInvalid(Loc, Invalid))
return "<invalid loc>";
1440 bool UseLineDirectives)
const {
1446 bool Invalid =
false;
1448 if (Invalid || !Entry.
isFile())
1457 FileID FID = LocInfo.first;
1462 Filename = C->
getBuffer(Diag, *
this)->getBufferIdentifier();
1464 unsigned LineNo =
getLineNumber(LocInfo.first, LocInfo.second, &Invalid);
1467 unsigned ColNo =
getColumnNumber(LocInfo.first, LocInfo.second, &Invalid);
1476 assert(LineTable &&
"Can't have linetable entries without a LineTable!");
1479 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1481 if (Entry->FilenameID != -1) {
1482 Filename = LineTable->getFilename(Entry->FilenameID);
1485 FID = FileID::get(0);
1492 unsigned MarkerLineNo =
getLineNumber(LocInfo.first, Entry->FileOffset);
1493 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1498 if (Entry->IncludeOffset) {
1505 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1521 bool Invalid =
false;
1523 if (Invalid || !Entry.
isFile())
1531 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1532 if (Entry->IncludeOffset)
1540 bool Invalid =
false;
1546 unsigned NextOffset;
1549 else if (ID+1 == -1)
1550 NextOffset = MaxLoadedOffset;
1554 return NextOffset - Entry.
getOffset() - 1;
1570 llvm::sys::fs::UniqueID
ID;
1571 if (llvm::sys::fs::getUniqueID(File->
getName(),
ID))
1583 unsigned Col)
const {
1584 assert(SourceFile &&
"Null source file!");
1585 assert(Line && Col &&
"Line and column should start from 1!");
1596 assert(SourceFile &&
"Null source file!");
1606 bool Invalid =
false;
1614 if (!MainContentCache || !MainContentCache->
OrigEntry) {
1616 }
else if (MainContentCache->
OrigEntry == SourceFile) {
1617 FirstFID = MainFileID;
1622 SourceFileName = llvm::sys::path::filename(SourceFile->
getName());
1623 if (*SourceFileName == llvm::sys::path::filename(MainFile->
getName())) {
1625 if (SourceFileUID) {
1628 if (*SourceFileUID == *MainFileUID) {
1629 FirstFID = MainFileID;
1630 SourceFile = MainFile;
1643 bool Invalid =
false;
1651 FirstFID = FileID::get(I);
1662 FirstFID = FileID::get(-
int(I) - 2);
1674 (SourceFileName = llvm::sys::path::filename(SourceFile->
getName()))) &&
1676 bool Invalid =
false;
1690 *SourceFileName == llvm::sys::path::filename(Entry->
getName())) {
1693 if (*SourceFileUID == *EntryUID) {
1694 FirstFID = FileID::get(I);
1712 unsigned Col)
const {
1715 assert(Line && Col &&
"Line and column should start from 1!");
1720 bool Invalid =
false;
1730 if (Line == 1 && Col == 1)
1741 bool MyInvalid =
false;
1748 unsigned Size = Content->
getBuffer(Diag, *
this)->getBufferSize();
1754 const llvm::MemoryBuffer *Buffer = Content->
getBuffer(Diag, *
this);
1756 const char *Buf = Buffer->getBufferStart() + FilePos;
1757 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1764 while (i < BufLength-1 && i < Col-1 && Buf[i] !=
'\n' && Buf[i] !=
'\r')
1776 void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
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;
1882 unsigned EndOffs = BeginOffs + ExpansionLength;
1901 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1904 MacroArgsCache[BeginOffs] = ExpansionLoc;
1905 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1928 std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
1929 if (!MacroArgsCache) {
1930 MacroArgsCache = llvm::make_unique<MacroArgsMap>();
1931 computeMacroArgsCache(*MacroArgsCache, FID);
1934 assert(!MacroArgsCache->empty());
1935 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1938 unsigned MacroArgBeginOffs = I->first;
1940 if (MacroArgExpandedLoc.
isValid())
1946 std::pair<FileID, unsigned>
1949 return std::make_pair(
FileID(), 0);
1953 using DecompTy = std::pair<FileID, unsigned>;
1954 auto InsertOp = IncludedLocMap.try_emplace(FID);
1955 DecompTy &DecompLoc = InsertOp.first->second;
1956 if (!InsertOp.second)
1960 bool Invalid =
false;
1982 if (UpperLoc.first.isInvalid())
1996 enum { MagicCacheSize = 300 };
1997 IsBeforeInTUCacheKey Key(LFID, RFID);
2003 if (IBTUCache.size() < MagicCacheSize)
2004 return IBTUCache[Key];
2007 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
2008 if (I != IBTUCache.end())
2012 return IBTUCacheOverflow;
2020 assert(LHS.
isValid() && RHS.
isValid() &&
"Passed invalid source location!");
2030 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
2031 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
2035 return InSameTU.second;
2040 StringRef LB =
getBuffer(LOffs.first)->getBufferIdentifier();
2041 StringRef RB =
getBuffer(ROffs.first)->getBufferIdentifier();
2042 bool LIsBuiltins = LB ==
"<built-in>";
2043 bool RIsBuiltins = RB ==
"<built-in>";
2045 if (LIsBuiltins || RIsBuiltins) {
2046 if (LIsBuiltins != RIsBuiltins)
2050 return LOffs.first < ROffs.first;
2052 bool LIsAsm = LB ==
"<inline asm>";
2053 bool RIsAsm = RB ==
"<inline asm>";
2055 if (LIsAsm || RIsAsm) {
2056 if (LIsAsm != RIsAsm)
2058 assert(LOffs.first == ROffs.first);
2061 bool LIsScratch = LB ==
"<scratch space>";
2062 bool RIsScratch = RB ==
"<scratch space>";
2064 if (LIsScratch || RIsScratch) {
2065 if (LIsScratch != RIsScratch)
2067 return LOffs.second < ROffs.second;
2069 llvm_unreachable(
"Unsortable locations found");
2073 std::pair<FileID, unsigned> &LOffs,
2074 std::pair<FileID, unsigned> &ROffs)
const {
2076 if (LOffs.first == ROffs.first)
2077 return std::make_pair(
true, LOffs.second < ROffs.second);
2082 getInBeforeInTUCache(LOffs.first, ROffs.first);
2086 if (IsBeforeInTUCache.
isCacheValid(LOffs.first, ROffs.first))
2087 return std::make_pair(
2091 IsBeforeInTUCache.
setQueryFIDs(LOffs.first, ROffs.first,
2092 LOffs.first.ID < ROffs.first.ID);
2099 using LocSet = llvm::SmallDenseMap<FileID, unsigned, 16>;
2102 LChain.insert(LOffs);
2107 while((I = LChain.find(ROffs.first)) == LChain.end()) {
2111 if (I != LChain.end())
2116 if (LOffs.first == ROffs.first) {
2117 IsBeforeInTUCache.
setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
2118 return std::make_pair(
2122 IsBeforeInTUCache.
clear();
2123 return std::make_pair(
false,
false);
2127 llvm::errs() <<
"\n*** Source Manager Stats:\n";
2128 llvm::errs() << FileInfos.size() <<
" files mapped, " << MemBufferInfos.size()
2129 <<
" mem buffers mapped.\n";
2130 llvm::errs() << LocalSLocEntryTable.size() <<
" local SLocEntry's allocated (" 2131 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2132 <<
" bytes of capacity), " 2133 << NextLocalOffset <<
"B of Sloc address space used.\n";
2134 llvm::errs() << LoadedSLocEntryTable.size()
2135 <<
" loaded SLocEntries allocated, " 2136 << MaxLoadedOffset - CurrentLoadedOffset
2137 <<
"B of Sloc address space used.\n";
2139 unsigned NumLineNumsComputed = 0;
2140 unsigned NumFileBytesMapped = 0;
2142 NumLineNumsComputed += I->second->SourceLineCache !=
nullptr;
2143 NumFileBytesMapped += I->second->getSizeBytesMapped();
2145 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2147 llvm::errs() << NumFileBytesMapped <<
" bytes of files mapped, " 2148 << NumLineNumsComputed <<
" files with line #'s computed, " 2149 << NumMacroArgsComputed <<
" files with macro args computed.\n";
2150 llvm::errs() <<
"FileID scans: " << NumLinearScans <<
" linear, " 2151 << NumBinaryProbes <<
" binary.\n";
2155 llvm::raw_ostream &out = llvm::errs();
2159 out <<
"SLocEntry <FileID " << ID <<
"> " << (Entry.isFile() ?
"file" :
"expansion")
2160 <<
" <SourceLocation " << Entry.getOffset() <<
":";
2162 out << *NextStart <<
">\n";
2165 if (Entry.isFile()) {
2166 auto &FI = Entry.getFile();
2167 if (FI.NumCreatedFIDs)
2168 out <<
" covers <FileID " << ID <<
":" << int(ID + FI.NumCreatedFIDs)
2170 if (FI.getIncludeLoc().isValid())
2171 out <<
" included from " << FI.getIncludeLoc().getOffset() <<
"\n";
2172 if (
auto *CC = FI.getContentCache()) {
2173 out <<
" for " << (CC->OrigEntry ? CC->OrigEntry->getName() :
"<none>")
2175 if (CC->BufferOverridden)
2176 out <<
" contents overridden\n";
2177 if (CC->ContentsEntry != CC->OrigEntry) {
2178 out <<
" contents from " 2179 << (CC->ContentsEntry ? CC->ContentsEntry->getName() :
"<none>")
2184 auto &EI = Entry.getExpansion();
2185 out <<
" spelling from " << EI.getSpellingLoc().getOffset() <<
"\n";
2186 out <<
" macro " << (EI.isMacroArgExpansion() ?
"arg" :
"body")
2187 <<
" range <" << EI.getExpansionLocStart().getOffset() <<
":" 2188 << EI.getExpansionLocEnd().getOffset() <<
">\n";
2193 for (
unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++
ID) {
2194 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2195 ID == NumIDs - 1 ? NextLocalOffset
2196 : LocalSLocEntryTable[ID + 1].getOffset());
2200 for (
unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2201 int ID = -(int)Index - 2;
2202 if (SLocEntryLoaded[Index]) {
2203 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2204 NextStart = LoadedSLocEntryTable[Index].getOffset();
2216 size_t malloc_bytes = 0;
2217 size_t mmap_bytes = 0;
2219 for (
unsigned i = 0, e = MemBufferInfos.size();
i != e; ++
i)
2220 if (
size_t sized_mapped = MemBufferInfos[
i]->getSizeBytesMapped())
2221 switch (MemBufferInfos[
i]->getMemoryBufferKind()) {
2222 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2223 mmap_bytes += sized_mapped;
2225 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2226 malloc_bytes += sized_mapped;
2234 size_t size = llvm::capacity_in_bytes(MemBufferInfos)
2235 + llvm::capacity_in_bytes(LocalSLocEntryTable)
2236 + llvm::capacity_in_bytes(LoadedSLocEntryTable)
2237 + llvm::capacity_in_bytes(SLocEntryLoaded)
2238 + llvm::capacity_in_bytes(FileInfos);
2240 if (OverriddenFilesInfo)
2241 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2247 StringRef Content) {
2251 new llvm::vfs::InMemoryFileSystem);
2252 InMemoryFileSystem->addFile(
2254 llvm::MemoryBuffer::getMemBuffer(Content, FileName,
2262 Diagnostics = llvm::make_unique<DiagnosticsEngine>(
2265 SourceMgr = llvm::make_unique<SourceManager>(*Diagnostics, *FileMgr);
2268 assert(ID.isValid());
2269 SourceMgr->setMainFileID(ID);
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
const FileEntry * OrigEntry
Reference to the file entry representing this ContentCache.
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.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
This is a discriminated union of FileInfo and ExpansionInfo.
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
static bool MoveUpIncludeHierarchy(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...
Implements support for file system lookup, file system caching, and directory search management...
SourceLocation getSpellingLoc() const
Defines the clang::FileManager interface and associated types.
void setBegin(SourceLocation b)
TypePropertyCache< Private > Cache
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
Defines the SourceManager interface.
fileinfo_iterator fileinfo_end() const
unsigned NumLines
The number of lines in this ContentCache.
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
bool isCacheValid(FileID LHS, FileID RHS) const
Return true if the currently cached values match up with the specified LHS/RHS query.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded...
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.
const llvm::MemoryBuffer * getBuffer(DiagnosticsEngine &Diag, const SourceManager &SM, SourceLocation Loc=SourceLocation(), bool *Invalid=nullptr) const
Returns the memory buffer for the associated content.
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset)
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
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.
unsigned getNextLocalOffset() const
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.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
void disableFileContentsOverride(const FileEntry *File)
Disable overridding the contents of a file, previously enabled with overrideFileContents.
FileManager & getFileManager() const
SourceLocation getBegin() const
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
One instance of this struct is kept for every file loaded or used.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
__DEVICE__ int max(int __a, int __b)
unsigned IsTransient
True if this file may be transient, that is, if it might not exist at some later point in time when t...
void setSourceManager(SourceManager *SrcMgr)
const llvm::MemoryBuffer * getRawBuffer() const
Get the underlying buffer, returning NULL if the buffer is not yet available.
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...
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
const FileInfo & getFile() const
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
Concrete class used by the front-end to report problems and issues.
bool isDiagnosticInFlight() const
Determine whethere there is already a diagnostic in flight.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Defines the Diagnostic-related interfaces.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body. ...
void setTokenRange(bool TR)
SourceLocation getIncludeLoc() const
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
bool isMacroArgExpansion() const
unsigned getSize() const
Returns the size of the content encapsulated by this ContentCache.
unsigned getSizeBytesMapped() const
Returns the number of bytes actually mapped for this ContentCache.
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
void initializeForReplay(const SourceManager &Old)
Initialize this source manager suitably to replay the compilation described by Old.
bool isBufferInvalid() const
Determine whether the buffer itself is invalid.
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
std::pair< FileID, unsigned > getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
virtual ~ExternalSLocEntrySource()
void setFileIsTransient(const FileEntry *SourceFile)
Specify that a file is transient.
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...
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
Represents a character-granular source range.
static Optional< llvm::sys::fs::UniqueID > getActualFileUID(const FileEntry *File)
Retrieve the inode for the given file entry, if possible.
const AnnotatedLine * Line
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.
unsigned getLine() const
Return the presumed line number of this location.
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 FileEntry * ContentsEntry
References the file which the contents were actually loaded from.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
void setEnd(SourceLocation e)
bool shouldFreeBuffer() const
Determine whether the buffer should be freed.
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager...
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
Represents an unpacked "presumed" location which can be presented to the user.
fileinfo_iterator fileinfo_begin() const
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
const ExpansionInfo & getExpansion() const
unsigned getOffset() const
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 isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion...
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache * getContentCache() const
unsigned getColumn() const
Return the presumed column number of this location.
std::pair< FileID, unsigned > getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Encodes a location in the source.
StringRef getName() const
SourceLocation createExpansionLoc(SourceLocation Loc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned TokLength, bool ExpansionIsTokenRange=true, int LoadedID=0, unsigned LoadedOffset=0)
Return a new SourceLocation that encodes the fact that a token from SpellingLoc should actually be re...
Options for controlling the compiler diagnostics engine.
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...
unsigned IsSystemFile
True if this content cache was initially created for a source file considered as a system one...
Cached information about one file (either on disk or in the virtual file system). ...
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a local SLocEntry. This is exposed for indexing.
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.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
unsigned * SourceLineCache
A bump pointer allocated array of offsets for each source line.
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)
llvm::DenseMap< const FileEntry *, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
SourceLocation getExpansionLocStart() const
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache. ...
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
const llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
bool isMacroBodyExpansion() const
static bool isInvalid(LocType Loc, bool *Invalid)
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree=false)
Replace the existing buffer (which will be deleted) with the given buffer.
const llvm::MemoryBuffer * getMemoryBufferForFile(const FileEntry *File, bool *Invalid=nullptr)
Retrieve the memory buffer associated with the given file.
void PrintStats() const
Print statistics to stderr.
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.
Used for handling and querying diagnostic IDs.
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.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
Holds the cache used by isBeforeInTranslationUnit.
SourceManagerForFile(StringRef FileName, StringRef Content)
Creates SourceManager and necessary depdencies (e.g.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
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...
SourceLocation getEnd() const
unsigned loaded_sloc_entry_size() const
Get the number of loaded SLocEntries we have.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
Keeps track of options that affect how file operations are performed.
bool userFilesAreVolatile() const
True if non-system source files should be treated as volatile (likely to change while trying to use t...
Defines the clang::SourceLocation class and associated facilities.
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)
Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...
LineTableInfo & getLineTable()
Retrieve the stored line table.
CharSourceRange getExpansionLocRange() const
A trivial tuple used to represent a source range.
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...
This class handles loading and caching of source files into memory.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const