clang: lib/Basic/SourceManager.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/ADT/StringSwitch.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/AutoConvert.h"
28#include "llvm/Support/Capacity.h"
29#include "llvm/Support/Compiler.h"
30#include "llvm/Support/Endian.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/MemoryBuffer.h"
33#include "llvm/Support/raw_ostream.h"
34#include
35#include
36#include
37#include
38#include
39#include
40#include
41#include
42#include
43
44using namespace clang;
45using namespace SrcMgr;
46using llvm::MemoryBuffer;
47
48#define DEBUG_TYPE "source-manager"
49
50
51
52STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations "
53 "(both loaded and local).");
54
55
56
57
58
59
60
62 return Buffer ? Buffer->getBufferSize() : 0;
63}
64
65
66
68 if (Buffer == nullptr) {
69 assert(0 && "Buffer should never be null");
70 return llvm::MemoryBuffer::MemoryBuffer_Malloc;
71 }
72 return Buffer->getBufferKind();
73}
74
75
76
77
78
80 return Buffer ? (unsigned)Buffer->getBufferSize()
82}
83
85
86
87
88 const char *InvalidBOM =
89 llvm::StringSwitch<const char *>(BufStr)
90 .StartsWith(llvm::StringLiteral::withInnerNUL("\x00\x00\xFE\xFF"),
91 "UTF-32 (BE)")
92 .StartsWith(llvm::StringLiteral::withInnerNUL("\xFF\xFE\x00\x00"),
93 "UTF-32 (LE)")
94 .StartsWith("\xFE\xFF", "UTF-16 (BE)")
95 .StartsWith("\xFF\xFE", "UTF-16 (LE)")
96 .StartsWith("\x2B\x2F\x76", "UTF-7")
97 .StartsWith("\xF7\x64\x4C", "UTF-1")
98 .StartsWith("\xDD\x73\x66\x73", "UTF-EBCDIC")
99 .StartsWith("\x0E\xFE\xFF", "SCSU")
100 .StartsWith("\xFB\xEE\x28", "BOCU-1")
101 .StartsWith("\x84\x31\x95\x33", "GB-18030")
102 .Default(nullptr);
103
104 return InvalidBOM;
105}
106
107std::optionalllvm::MemoryBufferRef
110
111
113 return std::nullopt;
114 if (Buffer)
115 return Buffer->getMemBufferRef();
117 return std::nullopt;
118
119
120
122
124
125
126
127
128
129
130 if (!BufferOrError) {
131 Diag.Report(Loc, diag::err_cannot_open_file)
132 << ContentsEntry->getName() << BufferOrError.getError().message();
133
134 return std::nullopt;
135 }
136
137 Buffer = std::move(*BufferOrError);
138
139
140
141
142
143
144
145
146
147
148 if (Buffer->getBufferSize() >= std::numeric_limits::max()) {
149 Diag.Report(Loc, diag::err_file_too_large) << ContentsEntry->getName();
150
151 return std::nullopt;
152 }
153
154
155
156
157
158
159 assert(Buffer->getBufferSize() >= (size_t)ContentsEntry->getSize());
161 Buffer->getBufferSize() < (size_t)ContentsEntry->getSize()) {
162 Diag.Report(Loc, diag::err_file_modified) << ContentsEntry->getName();
163
164 return std::nullopt;
165 }
166
167
168
169
170 StringRef BufStr = Buffer->getBuffer();
172
173 if (InvalidBOM) {
174 Diag.Report(Loc, diag::err_unsupported_bom)
176 return std::nullopt;
177 }
178
179
181 return Buffer->getMemBufferRef();
182}
183
185 auto IterBool = FilenameIDs.try_emplace(Name, FilenamesByID.size());
186 if (IterBool.second)
187 FilenamesByID.push_back(&*IterBool.first);
188 return IterBool.first->second;
189}
190
191
192
193
194
195
196
198 int FilenameID, unsigned EntryExit,
200 std::vector &Entries = LineEntries[FID];
201
202 assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
203 "Adding line entries out of order!");
204
205 unsigned IncludeOffset = 0;
206 if (EntryExit == 1) {
207
208 IncludeOffset = Offset-1;
209 } else {
210 const auto *PrevEntry = Entries.empty() ? nullptr : &Entries.back();
211 if (EntryExit == 2) {
212
213 assert(PrevEntry && PrevEntry->IncludeOffset &&
214 "PPDirectives should have caught case when popping empty include "
215 "stack");
217 }
218 if (PrevEntry) {
219 IncludeOffset = PrevEntry->IncludeOffset;
220 if (FilenameID == -1) {
221
222
223 FilenameID = PrevEntry->FilenameID;
224 }
225 }
226 }
227
228 Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID, FileKind,
229 IncludeOffset));
230}
231
232
233
235 unsigned Offset) {
236 const std::vector &Entries = LineEntries[FID];
237 assert(!Entries.empty() && "No #line entries for this FID after all!");
238
239
240
241 if (Entries.back().FileOffset <= Offset)
242 return &Entries.back();
243
244
245 std::vector::const_iterator I = llvm::upper_bound(Entries, Offset);
246 if (I == Entries.begin())
247 return nullptr;
248 return &*--I;
249}
250
251
252
254 const std::vector &Entries) {
255 LineEntries[FID] = Entries;
256}
257
258
260 return getLineTable().getLineTableFilenameID(Name);
261}
262
263
264
265
267 int FilenameID, bool IsFileEntry,
268 bool IsFileExit,
271
275 return;
276
278
279
281
283
284 unsigned EntryExit = 0;
285 if (IsFileEntry)
286 EntryExit = 1;
287 else if (IsFileExit)
288 EntryExit = 2;
289
290 LineTable->AddLineNote(LocInfo.first, LocInfo.second, LineNo, FilenameID,
291 EntryExit, FileKind);
292}
293
295 if (!LineTable)
297 return *LineTable;
298}
299
300
301
302
303
305 bool UserFilesAreVolatile)
306 : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) {
308 Diag.setSourceManager(this);
309}
310
312
313
314
315 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
316 if (MemBufferInfos[i]) {
317 MemBufferInfos[i]->~ContentCache();
318 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
319 }
320 }
321 for (auto I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
322 if (I->second) {
323 I->second->~ContentCache();
324 ContentCacheAlloc.Deallocate(I->second);
325 }
326 }
327}
328
330 MainFileID = FileID();
331 LocalSLocEntryTable.clear();
332 LocalLocOffsetTable.clear();
333 LoadedSLocEntryTable.clear();
334 SLocEntryLoaded.clear();
335 SLocEntryOffsetLoaded.clear();
336 LastLineNoFileIDQuery = FileID();
337 LastLineNoContentCache = nullptr;
338 LastFileIDLookup = FileID();
339 LastLookupStartOffset = LastLookupEndOffset = 0;
340
341 IncludedLocMap.clear();
342 if (LineTable)
343 LineTable->clear();
344
345
346 NextLocalOffset = 0;
347 CurrentLoadedOffset = MaxLoadedOffset;
349
350
351 Diag.ResetPragmas();
352}
353
355 assert(MainFileID.isValid() && "expected initialized SourceManager");
357 return FE->getUID() == SourceFile.getUID();
358 return false;
359}
360
362 assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
363
367 Clone->ContentsEntry = Cache->ContentsEntry;
368 Clone->BufferOverridden = Cache->BufferOverridden;
369 Clone->IsFileVolatile = Cache->IsFileVolatile;
370 Clone->IsTransient = Cache->IsTransient;
371 Clone->setUnownedBuffer(Cache->getBufferIfLoaded());
372 return Clone;
373 };
374
375
376 for (unsigned I = 0, N = Old.LoadedSLocEntryTable.size(); I != N; ++I)
377 if (!Old.SLocEntryLoaded[I])
378 Old.loadSLocEntry(I, nullptr);
379
380
381 for (auto &FileInfo : Old.FileInfos) {
383 if (Slot)
384 continue;
385 Slot = CloneContentCache(FileInfo.second);
386 }
387}
388
390 bool isSystemFile) {
391
393 if (Entry)
394 return *Entry;
395
396
397 Entry = ContentCacheAlloc.Allocate<ContentCache>();
398
399 if (OverriddenFilesInfo) {
400
401
402 auto overI = OverriddenFilesInfo->OverriddenFiles.find(FileEnt);
403 if (overI == OverriddenFilesInfo->OverriddenFiles.end())
405 else
406 new (Entry) ContentCache(OverridenFilesKeepOriginalName ? FileEnt
407 : overI->second,
408 overI->second);
409 } else {
411 }
412
413 Entry->IsFileVolatile = UserFilesAreVolatile && !isSystemFile;
416
417 return *Entry;
418}
419
420
421
422ContentCache &SourceManager::createMemBufferContentCache(
423 std::unique_ptrllvm::MemoryBuffer Buffer) {
424
425 ContentCache *Entry = ContentCacheAlloc.Allocate();
426 new (Entry) ContentCache();
427 MemBufferInfos.push_back(Entry);
428 Entry->setBuffer(std::move(Buffer));
429 return *Entry;
430}
431
432const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index,
435}
436
438 assert(!SLocEntryLoaded[Index]);
439 if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) {
442
443 if (!SLocEntryLoaded[Index]) {
444
445 if (!FakeSLocEntryForRecovery)
446 FakeSLocEntryForRecovery = std::make_unique(SLocEntry::get(
447 0, FileInfo::get(SourceLocation(), getFakeContentCacheForRecovery(),
449 return *FakeSLocEntryForRecovery;
450 }
451 }
452
453 return LoadedSLocEntryTable[Index];
454}
455
456std::pair<int, SourceLocation::UIntTy>
459 assert(ExternalSLocEntries && "Don't have an external sloc source");
460
461 if (CurrentLoadedOffset < TotalSize ||
462 CurrentLoadedOffset - TotalSize < NextLocalOffset) {
463 return std::make_pair(0, 0);
464 }
465 LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
466 SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
467 SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size());
468 CurrentLoadedOffset -= TotalSize;
469 updateSlocUsageStats();
470 int BaseID = -int(LoadedSLocEntryTable.size()) - 1;
471 LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID));
472 return std::make_pair(BaseID, CurrentLoadedOffset);
473}
474
475
476
477llvm::MemoryBufferRef SourceManager::getFakeBufferForRecovery() const {
478 if (!FakeBufferForRecovery)
479 FakeBufferForRecovery =
480 llvm::MemoryBuffer::getMemBuffer("<<>");
481
482 return *FakeBufferForRecovery;
483}
484
485
486
488 if (!FakeContentCacheForRecovery) {
489 FakeContentCacheForRecovery = std::make_uniqueSrcMgr::ContentCache();
490 FakeContentCacheForRecovery->setUnownedBuffer(getFakeBufferForRecovery());
491 }
492 return *FakeContentCacheForRecovery;
493}
494
495
496
497FileID SourceManager::getPreviousFileID(FileID FID) const {
499 return FileID();
500
501 int ID = FID.ID;
502 if (ID == -1)
503 return FileID();
504
505 if (ID > 0) {
506 if (ID-1 == 0)
507 return FileID();
508 } else if (unsigned(-(ID-1) - 2) >= LoadedSLocEntryTable.size()) {
509 return FileID();
510 }
511
512 return FileID::get(ID-1);
513}
514
515
516
517FileID SourceManager::getNextFileID(FileID FID) const {
519 return FileID();
520
521 int ID = FID.ID;
522 if (ID > 0) {
524 return FileID();
525 } else if (ID+1 >= -1) {
526 return FileID();
527 }
528
529 return FileID::get(ID+1);
530}
531
532
533
534
535
536
537
541 int LoadedID,
545
546
547
550
551 return createFileIDImpl(IR, SourceFile.getName(), IncludePos, FileCharacter,
552 LoadedID, LoadedOffset);
553}
554
555
556
557
558
561 int LoadedID,
564 StringRef Name = Buffer->getBufferIdentifier();
565 return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
566 IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
567}
568
569
570
571
572
575 int LoadedID,
578 return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
579 LoadedID, LoadedOffset, IncludeLoc);
580}
581
582
583
591
592
593
594
598 int LoadedID,
600 if (LoadedID < 0) {
601 assert(LoadedID != -1 && "Loading sentinel FileID");
602 unsigned Index = unsigned(-LoadedID) - 2;
603 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
604 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
606 LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename));
607 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
608 return FileID::get(LoadedID);
609 }
610 unsigned FileSize = File.getSize();
611 llvm::ErrorOr NeedConversion = llvm::needConversion(Filename);
612 if (NeedConversion && *NeedConversion) {
613
614
615 if (std::optionalllvm::MemoryBufferRef Buffer =
617 unsigned BufSize = Buffer->getBufferSize();
618 if (BufSize > FileSize) {
619 if (File.ContentsEntry.has_value())
620 File.ContentsEntry->updateFileEntryBufferSize(BufSize);
621 FileSize = BufSize;
622 }
623 }
624 }
625 if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
626 NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
627 Diag.Report(IncludePos, diag::err_sloc_space_too_large);
629 return FileID();
630 }
631 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
632 LocalSLocEntryTable.push_back(
635 LocalLocOffsetTable.push_back(NextLocalOffset);
636 LastLookupStartOffset = NextLocalOffset;
637
638
639 NextLocalOffset += FileSize + 1;
640 LastLookupEndOffset = NextLocalOffset;
641 updateSlocUsageStats();
642
643
644
645 FileID FID = FileID::get(LocalSLocEntryTable.size()-1);
646 return LastFileIDLookup = FID;
647}
648
652 ExpansionLoc);
653 return createExpansionLocImpl(Info, Length);
654}
655
659 bool ExpansionIsTokenRange, int LoadedID,
662 SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
663 return createExpansionLocImpl(Info, Length, LoadedID, LoadedOffset);
664}
665
670 "token spans multiple files");
671 return createExpansionLocImpl(
673 TokenEnd.getOffset() - TokenStart.getOffset());
674}
675
677SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
678 unsigned Length, int LoadedID,
680 if (LoadedID < 0) {
681 assert(LoadedID != -1 && "Loading sentinel FileID");
682 unsigned Index = unsigned(-LoadedID) - 2;
683 assert(Index < LoadedSLocEntryTable.size() && "FileID out of range");
684 assert(!SLocEntryLoaded[Index] && "FileID already loaded");
685 LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info);
686 SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
687 return SourceLocation::getMacroLoc(LoadedOffset);
688 }
689 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
690 LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
691 LocalLocOffsetTable.push_back(NextLocalOffset);
692 if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
693 NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
694 Diag.Report(diag::err_sloc_space_too_large);
695
696
697
698
699
700 llvm::report_fatal_error("ran out of source locations");
701 }
702
703 NextLocalOffset += Length + 1;
704 updateSlocUsageStats();
705 return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));
706}
707
708std::optionalllvm::MemoryBufferRef
713
715 FileEntryRef SourceFile, std::unique_ptrllvm::MemoryBuffer Buffer) {
717
720
721 getOverriddenFilesInfo().OverriddenFilesWithBuffer.insert(SourceFile);
722}
723
727 "Different sizes, use the FileManager to create a virtual file with "
728 "the correct size");
729 assert(FileInfos.find_as(SourceFile) == FileInfos.end() &&
730 "This function should be called at the initialization stage, before "
731 "any parsing occurs.");
732
733 auto Pair = getOverriddenFilesInfo().OverriddenFiles.insert(
734 std::make_pair(SourceFile, NewFile));
735 if (!Pair.second)
736 Pair.first->second = NewFile;
737}
738
743
744
745 if (!BypassFile)
746 return std::nullopt;
747
748 (void)getOrCreateContentCache(*BypassFile);
749 return BypassFile;
750}
751
753 getOrCreateContentCache(File).IsTransient = true;
754}
755
756std::optional
759 if (Entry->getFile().getContentCache().OrigEntry)
760 return Entry->getFile().getName();
761 return std::nullopt;
762}
763
768 return B ? *B : "<<<<>>>>";
769}
770
771std::optional
775 return std::nullopt;
776}
777
780 if (auto B = Entry->getFile().getContentCache().getBufferOrNone(
782 return B->getBuffer();
783 return std::nullopt;
784}
785
786
787
788
789
790
791
792
793
794
796 if (!SLocOffset)
797 return FileID::get(0);
798
799
800
801 if (SLocOffset < NextLocalOffset)
802 return getFileIDLocal(SLocOffset);
803 return getFileIDLoaded(SLocOffset);
804}
805
806
807
808
809
811 assert(SLocOffset < NextLocalOffset && "Bad function choice");
812 assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
813 "Invalid SLocOffset");
814 assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
815 assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832 unsigned LessIndex = 0;
833
834 unsigned GreaterIndex = LocalLocOffsetTable.size();
835
836 if (LastLookupStartOffset < SLocOffset)
837 LessIndex = LastFileIDLookup.ID;
838 else
839 GreaterIndex = LastFileIDLookup.ID;
840
841
842 unsigned NumProbes = 0;
843 while (true) {
844 --GreaterIndex;
845 assert(GreaterIndex < LocalLocOffsetTable.size());
846 if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
847 FileID Res = FileID::get(int(GreaterIndex));
848
849 LastFileIDLookup = Res;
850 LastLookupStartOffset = LocalLocOffsetTable[GreaterIndex];
851 LastLookupEndOffset =
852 GreaterIndex + 1 >= LocalLocOffsetTable.size()
853 ? NextLocalOffset
854 : LocalLocOffsetTable[GreaterIndex + 1];
855 NumLinearScans += NumProbes + 1;
856 return Res;
857 }
858 if (++NumProbes == 8)
859 break;
860 }
861
862 while (LessIndex < GreaterIndex) {
863 ++NumBinaryProbes;
864
865 unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
866 if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
867 LessIndex = MiddleIndex + 1;
868 else
869 GreaterIndex = MiddleIndex;
870 }
871
872
873
874
875 LastLookupStartOffset = LocalLocOffsetTable[LessIndex - 1];
876 LastLookupEndOffset = LocalLocOffsetTable[LessIndex];
877 return LastFileIDLookup = FileID::get(LessIndex - 1);
878}
879
880
881
882
883
885 if (SLocOffset < CurrentLoadedOffset) {
886 assert(0 && "Invalid SLocOffset or bad function choice");
887 return FileID();
888 }
889
890 return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset));
891}
892
895 do {
896
897
898
899
900
901
904
905 return Loc;
906}
907
909 do {
912 Loc.getOffset() - Entry.getOffset());
914 return Loc;
915}
916
918 do {
920 const ExpansionInfo &ExpInfo = Entry.getExpansion();
924 } else {
926 }
928 return Loc;
929}
930
931
932
933
934
936 if (Loc.isFileID()) return Loc;
940}
941
942
945 return F->getName();
946 return StringRef();
947}
948
949
950
953 assert(Loc.isMacroID() && "Not a macro expansion loc!");
956}
957
963
964
965
969
971
972
973
980 }
981 return Res;
982}
983
986 if (!Loc.isMacroID()) return false;
987
991
992 if (StartLoc)
994 return true;
995}
996
998 if (!Loc.isMacroID()) return false;
999
1003}
1004
1007 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1008
1010 if (DecompLoc.second > 0)
1011 return false;
1012
1017 return false;
1019
1021
1022
1023
1024 FileID PrevFID = getPreviousFileID(DecompLoc.first);
1028 return false;
1031 return false;
1032 }
1033 }
1034
1035 if (MacroBegin)
1036 *MacroBegin = ExpLoc;
1037 return true;
1038}
1039
1042 assert(Loc.isValid() && Loc.isMacroID() && "Expected a valid macro loc");
1043
1047 return false;
1048
1053 return false;
1054
1056
1057
1058
1059 FileID NextFID = getNextFileID(FID);
1063 return false;
1067 return false;
1068 }
1069 }
1070
1071 if (MacroEnd)
1073 return true;
1074}
1075
1076
1077
1078
1079
1080
1081
1084
1085
1087
1088
1089 bool CharDataInvalid = false;
1091 if (CharDataInvalid || !Entry.isFile()) {
1094
1095 return "<<<>>>";
1096 }
1097 std::optionalllvm::MemoryBufferRef Buffer =
1102 return Buffer ? Buffer->getBufferStart() + LocInfo.second
1103 : "<<<>>>";
1104}
1105
1106
1107
1110 std::optionalllvm::MemoryBufferRef MemBuf = getBufferOrNone(FID);
1113
1114 if (!MemBuf)
1115 return 1;
1116
1117
1118 if (FilePos > MemBuf->getBufferSize()) {
1121 return 1;
1122 }
1123
1124 const char *Buf = MemBuf->getBufferStart();
1125
1126
1127 if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache &&
1128 LastLineNoResult < LastLineNoContentCache->SourceLineCache.size()) {
1129 const unsigned *SourceLineCache =
1130 LastLineNoContentCache->SourceLineCache.begin();
1131 unsigned LineStart = SourceLineCache[LastLineNoResult - 1];
1132 unsigned LineEnd = SourceLineCache[LastLineNoResult];
1133 if (FilePos >= LineStart && FilePos < LineEnd) {
1134
1135
1136
1137
1138 if (FilePos + 1 == LineEnd && FilePos > LineStart) {
1139 if (Buf[FilePos - 1] == '\r' || Buf[FilePos - 1] == '\n')
1140 --FilePos;
1141 }
1142 return (FilePos - LineStart) + 1;
1143 }
1144 }
1145
1146 unsigned LineStart = FilePos;
1147 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
1148 --LineStart;
1149 return (FilePos - LineStart) + 1;
1150}
1151
1152
1153
1154template
1156 bool MyInvalid = Loc.isInvalid();
1159 return MyInvalid;
1160}
1161
1169
1176
1177
1178
1179
1180
1181template
1183 unsigned char n) {
1184 return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
1185 ((x & ~static_cast<T>(0) / 255 * 127) +
1186 (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
1187 ~static_cast(0) / 255 * 128;
1188}
1189
1191 llvm::BumpPtrAllocator &Alloc) {
1192
1193
1194
1196
1197
1198 LineOffsets.push_back(0);
1199
1200 const unsigned char *Start = (const unsigned char *)Buffer.getBufferStart();
1201 const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
1202 const unsigned char *Buf = Start;
1203
1204 uint64_t Word;
1205
1206
1207
1208 if ((unsigned long)(End - Start) > sizeof(Word)) {
1209 do {
1210 Word = llvm::support::endian::read64(Buf, llvm::endianness::little);
1211
1213 if (!Mask) {
1214 Buf += sizeof(Word);
1215 continue;
1216 }
1217
1218
1219
1220
1221
1222 unsigned N = llvm::countr_zero(Mask) - 7;
1223 Word >>= N;
1224 Buf += N / 8 + 1;
1225 unsigned char Byte = Word;
1226 switch (Byte) {
1227 case '\r':
1228
1229 if (*Buf == '\n') {
1230 ++Buf;
1231 }
1232 [[fallthrough]];
1233 case '\n':
1234 LineOffsets.push_back(Buf - Start);
1235 };
1236 } while (Buf < End - sizeof(Word) - 1);
1237 }
1238
1239
1240 while (Buf < End) {
1241 if (*Buf == '\n') {
1242 LineOffsets.push_back(Buf - Start + 1);
1243 } else if (*Buf == '\r') {
1244
1245 if (Buf + 1 < End && Buf[1] == '\n') {
1246 ++Buf;
1247 }
1248 LineOffsets.push_back(Buf - Start + 1);
1249 }
1250 ++Buf;
1251 }
1252
1254}
1255
1257 llvm::BumpPtrAllocator &Alloc)
1258 : Storage(Alloc.Allocate<unsigned>(LineOffsets.size() + 1)) {
1259 Storage[0] = LineOffsets.size();
1260 std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1);
1261}
1262
1263
1264
1265
1266
1272 return 1;
1273 }
1274
1276 if (LastLineNoFileIDQuery == FID)
1277 Content = LastLineNoContentCache;
1278 else {
1279 bool MyInvalid = false;
1281 if (MyInvalid || !Entry.isFile()) {
1284 return 1;
1285 }
1286
1288 }
1289
1290
1291
1293 std::optionalllvm::MemoryBufferRef Buffer =
1297 if (!Buffer)
1298 return 1;
1299
1304
1305
1306
1308 const unsigned *SourceLineCacheStart = SourceLineCache;
1309 const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end();
1310
1311 unsigned QueriedFilePos = FilePos+1;
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326 if (LastLineNoFileIDQuery == FID) {
1327 if (QueriedFilePos >= LastLineNoFilePos) {
1328
1329 SourceLineCache = SourceLineCache+LastLineNoResult-1;
1330
1331
1332
1333
1334
1335 if (SourceLineCache+5 < SourceLineCacheEnd) {
1336 if (SourceLineCache[5] > QueriedFilePos)
1337 SourceLineCacheEnd = SourceLineCache+5;
1338 else if (SourceLineCache+10 < SourceLineCacheEnd) {
1339 if (SourceLineCache[10] > QueriedFilePos)
1340 SourceLineCacheEnd = SourceLineCache+10;
1341 else if (SourceLineCache+20 < SourceLineCacheEnd) {
1342 if (SourceLineCache[20] > QueriedFilePos)
1343 SourceLineCacheEnd = SourceLineCache+20;
1344 }
1345 }
1346 }
1347 } else {
1348 if (LastLineNoResult < Content->SourceLineCache.size())
1349 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
1350 }
1351 }
1352
1353 const unsigned *Pos =
1354 std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
1355 unsigned LineNo = Pos-SourceLineCacheStart;
1356
1357 LastLineNoFileIDQuery = FID;
1358 LastLineNoContentCache = Content;
1359 LastLineNoFilePos = QueriedFilePos;
1360 LastLineNoResult = LineNo;
1361 return LineNo;
1362}
1363
1370
1377
1378
1379
1380
1381
1382
1383
1384
1385
1388 assert(Loc.isValid() && "Can't get file characteristic of invalid loc!");
1390 const SLocEntry *SEntry = getSLocEntryForFile(LocInfo.first);
1391 if (!SEntry)
1393
1395
1396
1397
1400
1401 assert(LineTable && "Can't have linetable entries without a LineTable!");
1402
1404 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second);
1405
1406
1407 if (!Entry)
1409
1411}
1412
1413
1414
1415
1419
1423 return B ? B->getBufferIdentifier() : "";
1424}
1425
1426
1427
1428
1429
1430
1431
1432
1434 bool UseLineDirectives) const {
1436
1437
1439
1444
1447
1448
1449
1450
1451 FileID FID = LocInfo.first;
1452 StringRef Filename;
1453 if (C->OrigEntry)
1454 Filename = C->OrigEntry->getName();
1455 else if (auto Buffer = C->getBufferOrNone(Diag, getFileManager()))
1456 Filename = Buffer->getBufferIdentifier();
1457
1464
1466
1467
1468
1470 assert(LineTable && "Can't have linetable entries without a LineTable!");
1471
1473 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second)) {
1474
1475 if (Entry->FilenameID != -1) {
1476 Filename = LineTable->getFilename(Entry->FilenameID);
1477
1478
1479 FID = FileID::get(0);
1480 }
1481
1482
1483
1484
1485
1486 unsigned MarkerLineNo = getLineNumber(LocInfo.first, Entry->FileOffset);
1487 LineNo = Entry->LineNo + (LineNo-MarkerLineNo-1);
1488
1489
1490
1491
1492 if (Entry->IncludeOffset) {
1494 IncludeLoc = IncludeLoc.getLocWithOffset(Entry->IncludeOffset);
1495 }
1496 }
1497 }
1498
1499 return PresumedLoc(Filename.data(), FID, LineNo, ColNo, IncludeLoc);
1500}
1501
1502
1503
1504
1505
1506
1507
1508
1510 if (Loc.isInvalid()) return false;
1511
1512
1514
1515 const SLocEntry *Entry = getSLocEntryForFile(LocInfo.first);
1516 if (!Entry)
1517 return false;
1518
1520
1521
1524 LineTable->FindNearestLineEntry(LocInfo.first, LocInfo.second))
1525 if (Entry->IncludeOffset)
1526 return false;
1527
1529}
1530
1531
1536 return 0;
1537
1538 int ID = FID.ID;
1542 else if (ID+1 == -1)
1543 NextOffset = MaxLoadedOffset;
1544 else
1545 NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
1546
1547 return NextOffset - Entry.getOffset() - 1;
1548}
1549
1550
1551
1552
1553
1554
1555
1556
1557
1559 unsigned Line,
1560 unsigned Col) const {
1561 assert(SourceFile && "Null source file!");
1562 assert(Line && Col && "Line and column should start from 1!");
1563
1566}
1567
1568
1569
1570
1571
1573 assert(SourceFile && "Null source file!");
1574
1575
1576
1577 if (MainFileID.isValid()) {
1582
1583 if (MainSLoc.isFile()) {
1585 return MainFileID;
1586 }
1587 }
1588
1589
1590
1593 if (SLoc.isFile() &&
1595 return FileID::get(I);
1596 }
1597
1598
1601 if (SLoc.isFile() &&
1603 return FileID::get(-int(I) - 2);
1604 }
1605
1607}
1608
1609
1610
1612 unsigned Line,
1613 unsigned Col) const {
1614
1615
1616 assert(Line && Col && "Line and column should start from 1!");
1617
1620
1625
1626 if (!Entry.isFile())
1628
1630
1631 if (Line == 1 && Col == 1)
1632 return FileLoc;
1633
1635
1636
1637
1638 std::optionalllvm::MemoryBufferRef Buffer =
1640 if (!Buffer)
1645
1647 unsigned Size = Buffer->getBufferSize();
1648 if (Size > 0)
1649 --Size;
1651 }
1652
1654 const char *Buf = Buffer->getBufferStart() + FilePos;
1655 unsigned BufLength = Buffer->getBufferSize() - FilePos;
1656 if (BufLength == 0)
1658
1659 unsigned i = 0;
1660
1661
1662 while (i < BufLength-1 && i < Col-1 && Buf[i] != '\n' && Buf[i] != '\r')
1663 ++i;
1665}
1666
1667
1668
1669
1670
1671
1672
1673
1674void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
1677
1678
1679 MacroArgsCache.try_emplace(0);
1680
1681 int ID = FID.ID;
1682 while (true) {
1683 ++ID;
1684
1685 if (ID > 0) {
1686 if (unsigned(ID) >= local_sloc_entry_size())
1687 return;
1688 } else if (ID == -1) {
1689 return;
1690 }
1691
1693 const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID, &Invalid);
1695 return;
1696 if (Entry.isFile()) {
1700 continue;
1701
1703 bool IncludedInFID =
1704 (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) ||
1705
1706
1707
1708 (FID == MainFileID && Entry.getFile().getName() == "");
1709 if (IncludedInFID) {
1710
1711
1712 if (Entry.getFile().NumCreatedFIDs)
1713 ID += Entry.getFile().NumCreatedFIDs - 1 ;
1714 continue;
1715 }
1716
1717
1718 if (IncludeLoc.isValid())
1719 return;
1720 continue;
1721 }
1722
1724
1727 return;
1728 }
1729
1731 continue;
1732
1733 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1735 SourceLocation::getMacroLoc(Entry.getOffset()),
1736 getFileIDSize(FileID::get(ID)));
1737 }
1738}
1739
1740void SourceManager::associateFileChunkWithMacroArgExp(
1741 MacroArgsMap &MacroArgsCache,
1742 FileID FID,
1743 SourceLocation SpellLoc,
1744 SourceLocation ExpansionLoc,
1745 unsigned ExpansionLength) const {
1749
1750
1751
1752
1753
1754
1755
1756 auto [SpellFID, SpellRelativeOffs] = getDecomposedLoc(SpellLoc);
1757 while (true) {
1758 const SLocEntry &Entry = getSLocEntry(SpellFID);
1760 unsigned SpellFIDSize = getFileIDSize(SpellFID);
1764 unsigned CurrSpellLength;
1765 if (SpellFIDEndOffs < SpellEndOffs)
1766 CurrSpellLength = SpellFIDSize - SpellRelativeOffs;
1767 else
1768 CurrSpellLength = ExpansionLength;
1769 associateFileChunkWithMacroArgExp(MacroArgsCache, FID,
1771 ExpansionLoc, CurrSpellLength);
1772 }
1773
1774 if (SpellFIDEndOffs >= SpellEndOffs)
1775 return;
1776
1777
1778 unsigned advance = SpellFIDSize - SpellRelativeOffs + 1;
1780 ExpansionLength -= advance;
1781 ++SpellFID.ID;
1782 SpellRelativeOffs = 0;
1783 }
1784 }
1785
1786 assert(SpellLoc.isFileID());
1787
1788 unsigned BeginOffs;
1789 if (!isInFileID(SpellLoc, FID, &BeginOffs))
1790 return;
1791
1792 unsigned EndOffs = BeginOffs + ExpansionLength;
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811 MacroArgsMap::iterator I = MacroArgsCache.upper_bound(EndOffs);
1812 --I;
1813 SourceLocation EndOffsMappedLoc = I->second;
1814 MacroArgsCache[BeginOffs] = ExpansionLoc;
1815 MacroArgsCache[EndOffs] = EndOffsMappedLoc;
1816}
1817
1818void SourceManager::updateSlocUsageStats() const {
1820 NextLocalOffset + (MaxLoadedOffset - CurrentLoadedOffset);
1821 MaxUsedSLocBytes.updateMax(UsedBytes);
1822}
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833SourceLocation
1836 return Loc;
1837
1840 return Loc;
1841
1842 std::unique_ptr &MacroArgsCache = MacroArgsCacheMap[FID];
1843 if (!MacroArgsCache) {
1844 MacroArgsCache = std::make_unique();
1845 computeMacroArgsCache(*MacroArgsCache, FID);
1846 }
1847
1848 assert(!MacroArgsCache->empty());
1849 MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
1850
1851
1852 if (I == MacroArgsCache->begin())
1853 return Loc;
1854
1855 --I;
1856
1859 if (MacroArgExpandedLoc.isValid())
1860 return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
1861
1862 return Loc;
1863}
1864
1867 return std::make_pair(FileID(), 0);
1868
1869
1870
1872 auto InsertOp = IncludedLocMap.try_emplace(FID);
1873 DecompTy &DecompLoc = InsertOp.first->second;
1874 if (!InsertOp.second)
1875 return DecompLoc;
1876
1883 else
1885 }
1886
1889
1890 return DecompLoc;
1891}
1892
1895 "Must be a source location in a loaded PCH/Module file");
1896
1898
1899
1900
1901
1902 const FileID *FirstFID =
1903 llvm::lower_bound(LoadedSLocEntryAllocBegin, FID, std::greater{});
1904
1905 assert(FirstFID &&
1906 "The failure to find the first FileID of a "
1907 "loaded AST from a loaded source location was unexpected.");
1908 return *FirstFID;
1909}
1910
1913
1915 return false;
1916
1918 auto FindSLocEntryAlloc = [this](FileID FID) {
1919
1920
1921 return llvm::lower_bound(LoadedSLocEntryAllocBegin, FID,
1922 std::greater{});
1923 };
1924
1925
1926 if (FindSLocEntryAlloc(LOffs.first) != FindSLocEntryAlloc(ROffs.first))
1927 return false;
1928 }
1929
1930 return true;
1931}
1932
1933
1934
1935
1936
1939 FileIDAndOffset UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
1940 if (UpperLoc.first.isInvalid() ||
1941 .isInTheSameTranslationUnitImpl(UpperLoc, Loc))
1942 return true;
1943
1944 Loc = UpperLoc;
1945 return false;
1946}
1947
1948
1949
1950InBeforeInTUCacheEntry &SourceManager::getInBeforeInTUCache(FileID LFID,
1951 FileID RFID) const {
1952
1953
1954
1955
1956 enum { MagicCacheSize = 300 };
1957 IsBeforeInTUCacheKey Key(LFID, RFID);
1958
1959
1960
1961
1962
1963 if (IBTUCache.size() < MagicCacheSize)
1964 return IBTUCache.try_emplace(Key, LFID, RFID).first->second;
1965
1966
1967 InBeforeInTUCache::iterator I = IBTUCache.find(Key);
1968 if (I != IBTUCache.end())
1969 return I->second;
1970
1971
1972 IBTUCacheOverflow.setQueryFIDs(LFID, RFID);
1973 return IBTUCacheOverflow;
1974}
1975
1976
1977
1978
1981 assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
1982 if (LHS == RHS)
1983 return false;
1984
1987
1988
1989
1990
1991 if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
1992 return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
1993
1995 if (InSameTU.first)
1996 return InSameTU.second;
1997
1998 return LOffs.first < ROffs.first;
1999}
2000
2001std::pair<bool, bool>
2004
2006 return std::make_pair(false, false);
2007
2008
2009 if (LOffs.first == ROffs.first)
2010 return std::make_pair(true, LOffs.second < ROffs.second);
2011
2012
2013
2015 getInBeforeInTUCache(LOffs.first, ROffs.first);
2016
2017
2018
2020 return std::make_pair(
2021 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2022
2023
2024
2025
2026
2027
2028
2029 struct Entry {
2030 FileIDAndOffset DecomposedLoc;
2031 FileID ChildFID;
2032 };
2033 llvm::SmallDenseMap<FileID, Entry, 16> LChain;
2034
2036 do {
2037 LChain.try_emplace(LOffs.first, Entry{LOffs, LChild});
2038
2039
2040 if (LOffs.first == ROffs.first)
2041 break;
2042 LChild = LOffs.first;
2044
2046 do {
2047 auto LIt = LChain.find(ROffs.first);
2048 if (LIt != LChain.end()) {
2049
2050 LOffs = LIt->second.DecomposedLoc;
2051 LChild = LIt->second.ChildFID;
2052
2053
2054
2055
2056
2057
2058
2059
2060 unsigned LChildID = LChild.ID;
2061 unsigned RChildID = RChild.ID;
2062 assert(((LOffs.second != ROffs.second) ||
2063 (LChildID == 0 || RChildID == 0) ||
2066 "Mixed local/loaded FileIDs with same include location?");
2067 IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second,
2068 LChildID < RChildID);
2069 return std::make_pair(
2070 true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
2071 }
2072 RChild = ROffs.first;
2074
2075
2076
2077
2078 StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2079 StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2080
2081 bool LIsBuiltins = LB == "";
2082 bool RIsBuiltins = RB == "";
2083
2084 if (LIsBuiltins || RIsBuiltins) {
2085 if (LIsBuiltins != RIsBuiltins)
2086 return std::make_pair(true, LIsBuiltins);
2087
2088
2089 return std::make_pair(true, LOffs.first < ROffs.first);
2090 }
2091
2092 bool LIsAsm = LB == "";
2093 bool RIsAsm = RB == "";
2094
2095 if (LIsAsm || RIsAsm) {
2096 if (LIsAsm != RIsAsm)
2097 return std::make_pair(true, RIsAsm);
2098 assert(LOffs.first == ROffs.first);
2099 return std::make_pair(true, false);
2100 }
2101
2102 bool LIsScratch = LB == "";
2103 bool RIsScratch = RB == "";
2104
2105 if (LIsScratch || RIsScratch) {
2106 if (LIsScratch != RIsScratch)
2107 return std::make_pair(true, LIsScratch);
2108 return std::make_pair(true, LOffs.second < ROffs.second);
2109 }
2110
2111 llvm_unreachable("Unsortable locations found");
2112}
2113
2115 llvm::errs() << "\n*** Source Manager Stats:\n";
2116 llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
2117 << " mem buffers mapped.\n";
2118 llvm::errs() << LocalSLocEntryTable.size() << " local SLocEntries allocated ("
2119 << llvm::capacity_in_bytes(LocalSLocEntryTable)
2120 << " bytes of capacity), " << NextLocalOffset
2121 << "B of SLoc address space used.\n";
2122 llvm::errs() << LoadedSLocEntryTable.size()
2123 << " loaded SLocEntries allocated ("
2124 << llvm::capacity_in_bytes(LoadedSLocEntryTable)
2125 << " bytes of capacity), "
2126 << MaxLoadedOffset - CurrentLoadedOffset
2127 << "B of SLoc address space used.\n";
2128
2129 unsigned NumLineNumsComputed = 0;
2130 unsigned NumFileBytesMapped = 0;
2132 NumLineNumsComputed += bool(I->second->SourceLineCache);
2133 NumFileBytesMapped += I->second->getSizeBytesMapped();
2134 }
2135 unsigned NumMacroArgsComputed = MacroArgsCacheMap.size();
2136
2137 llvm::errs() << NumFileBytesMapped << " bytes of files mapped, "
2138 << NumLineNumsComputed << " files with line #'s computed, "
2139 << NumMacroArgsComputed << " files with macro args computed.\n";
2140 llvm::errs() << "FileID scans: " << NumLinearScans << " linear, "
2141 << NumBinaryProbes << " binary.\n";
2142}
2143
2145 llvm::raw_ostream &out = llvm::errs();
2146
2147 auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
2148 std::optionalSourceLocation::UIntTy NextStart) {
2149 out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
2150 << " <SourceLocation " << Entry.getOffset() << ":";
2151 if (NextStart)
2152 out << *NextStart << ">\n";
2153 else
2154 out << "???\?>\n";
2155 if (Entry.isFile()) {
2156 auto &FI = Entry.getFile();
2157 if (FI.NumCreatedFIDs)
2158 out << " covers <FileID " << ID << ":" << int(ID + FI.NumCreatedFIDs)
2159 << ">\n";
2160 if (FI.getIncludeLoc().isValid())
2161 out << " included from " << FI.getIncludeLoc().getOffset() << "\n";
2162 auto &CC = FI.getContentCache();
2163 out << " for " << (CC.OrigEntry ? CC.OrigEntry->getName() : "")
2164 << "\n";
2165 if (CC.BufferOverridden)
2166 out << " contents overridden\n";
2167 if (CC.ContentsEntry != CC.OrigEntry) {
2168 out << " contents from "
2169 << (CC.ContentsEntry ? CC.ContentsEntry->getName() : "")
2170 << "\n";
2171 }
2172 } else {
2173 auto &EI = Entry.getExpansion();
2174 out << " spelling from " << EI.getSpellingLoc().getOffset() << "\n";
2175 out << " macro " << (EI.isMacroArgExpansion() ? "arg" : "body")
2176 << " range <" << EI.getExpansionLocStart().getOffset() << ":"
2177 << EI.getExpansionLocEnd().getOffset() << ">\n";
2178 }
2179 };
2180
2181
2182 for (unsigned ID = 0, NumIDs = LocalSLocEntryTable.size(); ID != NumIDs; ++ID) {
2183 DumpSLocEntry(ID, LocalSLocEntryTable[ID],
2184 ID == NumIDs - 1 ? NextLocalOffset
2185 : LocalSLocEntryTable[ID + 1].getOffset());
2186 }
2187
2188 std::optionalSourceLocation::UIntTy NextStart;
2189 for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2190 int ID = -(int)Index - 2;
2191 if (SLocEntryLoaded[Index]) {
2192 DumpSLocEntry(ID, LoadedSLocEntryTable[Index], NextStart);
2193 NextStart = LoadedSLocEntryTable[Index].getOffset();
2194 } else {
2195 NextStart = std::nullopt;
2196 }
2197 }
2198}
2199
2201 DiagnosticsEngine &Diag, std::optional MaxNotes) const {
2202 struct Info {
2203
2205
2206 unsigned Inclusions = 0;
2207
2208 uint64_t DirectSize = 0;
2209
2210 uint64_t TotalSize = 0;
2211 };
2212 using UsageMap = llvm::MapVector<const FileEntry*, Info>;
2213
2214 UsageMap Usage;
2215 uint64_t CountedSize = 0;
2216
2217 auto AddUsageForFileID = [&](FileID ID) {
2218
2219
2221
2222
2223
2227
2228 Info &EntryInfo = Usage[Entry];
2229 if (EntryInfo.Loc.isInvalid())
2230 EntryInfo.Loc = FileStart;
2231 if (ID == FileLocID) {
2232 ++EntryInfo.Inclusions;
2233 EntryInfo.DirectSize += Size;
2234 }
2235 EntryInfo.TotalSize += Size;
2236 CountedSize += Size;
2237 };
2238
2239
2240 for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
2241 AddUsageForFileID(FileID::get(-2 - Index));
2242 }
2243
2244 for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) {
2245 AddUsageForFileID(FileID::get(Index));
2246 }
2247
2248
2249
2250 auto SortedUsage = Usage.takeVector();
2251 auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) {
2252 return A.second.TotalSize > B.second.TotalSize ||
2253 (A.second.TotalSize == B.second.TotalSize &&
2254 A.second.Loc < B.second.Loc);
2255 };
2256 auto SortedEnd = SortedUsage.end();
2257 if (MaxNotes && SortedUsage.size() > *MaxNotes) {
2258 SortedEnd = SortedUsage.begin() + *MaxNotes;
2259 std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp);
2260 }
2261 std::sort(SortedUsage.begin(), SortedEnd, Cmp);
2262
2263
2264 uint64_t LocalUsage = NextLocalOffset;
2265 uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset;
2266 int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
2267 MaxLoadedOffset);
2268 Diag.Report(diag::note_total_sloc_usage)
2269 << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage)
2270 << UsagePercent;
2271
2272
2273 uint64_t ReportedSize = 0;
2274 for (auto &[Entry, FileInfo] :
2275 llvm::make_range(SortedUsage.begin(), SortedEnd)) {
2276 Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage)
2279 ReportedSize += FileInfo.TotalSize;
2280 }
2281
2282
2283 if (ReportedSize != CountedSize) {
2284 Diag.Report(diag::note_file_misc_sloc_usage)
2285 << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
2286 }
2287}
2288
2290
2291
2292
2294 size_t malloc_bytes = 0;
2295 size_t mmap_bytes = 0;
2296
2297 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i)
2298 if (size_t sized_mapped = MemBufferInfos[i]->getSizeBytesMapped())
2299 switch (MemBufferInfos[i]->getMemoryBufferKind()) {
2300 case llvm::MemoryBuffer::MemoryBuffer_MMap:
2301 mmap_bytes += sized_mapped;
2302 break;
2303 case llvm::MemoryBuffer::MemoryBuffer_Malloc:
2304 malloc_bytes += sized_mapped;
2305 break;
2306 }
2307
2309}
2310
2312 size_t size = llvm::capacity_in_bytes(MemBufferInfos) +
2313 llvm::capacity_in_bytes(LocalSLocEntryTable) +
2314 llvm::capacity_in_bytes(LoadedSLocEntryTable) +
2315 llvm::capacity_in_bytes(SLocEntryLoaded) +
2316 llvm::capacity_in_bytes(FileInfos);
2317
2318 if (OverriddenFilesInfo)
2319 size += llvm::capacity_in_bytes(OverriddenFilesInfo->OverriddenFiles);
2320
2321 return size;
2322}
2323
2325 StringRef Content) {
2326 auto InMemoryFileSystem =
2327 llvm::makeIntrusiveRefCntllvm::vfs::InMemoryFileSystem();
2328 InMemoryFileSystem->addFile(
2330 llvm::MemoryBuffer::getMemBuffer(Content, FileName,
2331 false));
2332
2333
2335 std::move(InMemoryFileSystem));
2336 DiagOpts = std::make_unique();
2337
2338
2339 Diagnostics =
2341 SourceMgr = std::make_unique(*Diagnostics, *FileMgr);
2345 assert(ID.isValid());
2346 SourceMgr->setMainFileID(ID);
2347}
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)
Definition SourceManager.cpp:1182
static bool isInvalid(LocType Loc, bool *Invalid)
Definition SourceManager.cpp:1155
STATISTIC(MaxUsedSLocBytes, "Maximum number of bytes used by source locations " "(both loaded and local).")
static bool MoveUpTranslationUnitIncludeHierarchy(FileIDAndOffset &Loc, const SourceManager &SM)
Given a decomposed source location, move it up the include/expansion stack to the parent source locat...
Definition SourceManager.cpp:1937
Defines the SourceManager interface.
Represents a character-granular source range.
void setEnd(SourceLocation e)
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setTokenRange(bool TR)
static llvm::IntrusiveRefCntPtr< DiagnosticIDs > create()
Concrete class used by the front-end to report problems and issues.
virtual ~ExternalSLocEntrySource()
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(FileEntryRef Entry, bool isVolatile=false, bool RequiresNullTerminator=true, std::optional< int64_t > MaybeLimit=std::nullopt, bool IsText=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Keeps track of options that affect how file operations are performed.
Holds the cache used by isBeforeInTranslationUnit.
void setCommonLoc(FileID commonFID, unsigned lCommonOffset, unsigned rCommonOffset, bool LParentBeforeRParent)
bool getCachedResult(unsigned LOffset, unsigned ROffset) const
If the cache is valid, compute the result given the specified offsets in the LHS/RHS FileID's.
bool isCacheValid() const
Return true if the currently cached values match up with the specified LHS/RHS query.
Used to hold and unique data used to represent #line information.
const LineEntry * FindNearestLineEntry(FileID FID, unsigned Offset)
Find the line entry nearest to FID that is before it.
Definition SourceManager.cpp:234
unsigned getLineTableFilenameID(StringRef Str)
Definition SourceManager.cpp:184
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...
Definition SourceManager.cpp:253
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...
Definition SourceManager.cpp:197
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.
Definition SourceManager.cpp:2324
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...
Definition SourceManager.cpp:757
FileIDAndOffset getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body.
Definition SourceManager.cpp:997
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Definition SourceManager.cpp:1371
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...
Definition SourceManager.cpp:1040
~SourceManager()
Definition SourceManager.cpp:311
SourceLocation::UIntTy getNextLocalOffset() const
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
Definition SourceManager.cpp:1108
void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag, std::optional< unsigned > MaxNotes=32) const
Definition SourceManager.cpp:2200
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
Definition SourceManager.cpp:1509
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.
Definition SourceManager.cpp:266
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile=false)
Definition SourceManager.cpp:304
SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, SourceLocation TokenStart, SourceLocation TokenEnd)
Return a new SourceLocation that encodes that the token starting at TokenStart ends prematurely at To...
Definition SourceManager.cpp:666
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Definition SourceManager.cpp:1433
bool isInTheSameTranslationUnitImpl(const FileIDAndOffset &LOffs, const FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same TU.
Definition SourceManager.cpp:1911
MemoryBufferSizes getMemoryBufferSizes() const
Return the amount of memory used by memory buffers, breaking down by heap-backed versus mmap'ed memor...
Definition SourceManager.cpp:2293
void setFileIsTransient(FileEntryRef SourceFile)
Specify that a file is transient.
Definition SourceManager.cpp:752
bool isFileOverridden(const FileEntry *File) const
Returns true if the file contents have been overridden.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
Definition SourceManager.cpp:1611
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
Definition SourceManager.cpp:1416
SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const
Definition SourceManager.cpp:958
std::optional< StringRef > getBufferDataOrNone(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if inva...
Definition SourceManager.cpp:778
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
Definition SourceManager.cpp:1572
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
Definition SourceManager.cpp:764
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...
Definition SourceManager.cpp:538
void PrintStats() const
Print statistics to stderr.
Definition SourceManager.cpp:2114
FileID getUniqueLoadedASTFileID(SourceLocation Loc) const
Definition SourceManager.cpp:1893
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
Definition SourceManager.cpp:354
size_t getDataStructureSizes() const
Return the amount of memory used for various side tables and data structures in the SourceManager.
Definition SourceManager.cpp:2311
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
Definition SourceManager.cpp:984
void clearIDTables()
Definition SourceManager.cpp:329
const SrcMgr::SLocEntry & getLocalSLocEntry(unsigned Index) const
Get a local SLocEntry. This is exposed for indexing.
SourceLocation getComposedLoc(FileID FID, unsigned Offset) const
Form a SourceLocation from a FileID and Offset pair.
OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File)
Bypass the overridden contents of a file.
Definition SourceManager.cpp:740
const SrcMgr::SLocEntry & getLoadedSLocEntry(unsigned Index, bool *Invalid=nullptr) const
Get a loaded SLocEntry. This is exposed for indexing.
llvm::DenseMap< FileEntryRef, SrcMgr::ContentCache * >::const_iterator fileinfo_iterator
FileManager & getFileManager() const
fileinfo_iterator fileinfo_end() const
unsigned local_sloc_entry_size() const
Get the number of local SLocEntries we have.
std::optional< StringRef > getBufferDataIfLoaded(FileID FID) const
Return a StringRef to the source buffer data for the specified FileID, returning std::nullopt if it's...
Definition SourceManager.cpp:772
FileIDAndOffset getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
Definition SourceManager.cpp:1082
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...
Definition SourceManager.cpp:457
void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
Definition SourceManager.cpp:1532
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
Definition SourceManager.cpp:1267
void dump() const
Definition SourceManager.cpp:2144
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
Definition SourceManager.cpp:952
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
Definition SourceManager.cpp:966
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.
Definition SourceManager.cpp:259
void initializeForReplay(const SourceManager &Old)
Initialize this source manager suitably to replay the compilation described by Old.
Definition SourceManager.cpp:361
FileIDAndOffset getDecomposedIncludedLoc(FileID FID) const
Returns the "included/expanded in" decomposed location of the given FileID.
Definition SourceManager.cpp:1865
bool isLoadedSourceLocation(SourceLocation Loc) const
Returns true if Loc came from a PCH/Module.
unsigned loaded_sloc_entry_size() const
Get the number of loaded SLocEntries we have.
FileID getOrCreateFileID(FileEntryRef SourceFile, SrcMgr::CharacteristicKind FileCharacter)
Get the FileID for SourceFile if it exists.
Definition SourceManager.cpp:585
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
Definition SourceManager.cpp:1558
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, SourceLocation::IntTy *RelativeOffset) const
Return true if both LHS and RHS are in the local source location address space or the loaded one.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion.
Definition SourceManager.cpp:1005
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
Definition SourceManager.cpp:1387
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.
Definition SourceManager.cpp:656
unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Definition SourceManager.cpp:1170
std::pair< bool, bool > isInTheSameTranslationUnit(FileIDAndOffset &LOffs, FileIDAndOffset &ROffs) const
Determines whether the two decomposed source location is in the same translation unit.
Definition SourceManager.cpp:2002
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
Definition SourceManager.cpp:943
SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const
If Loc points inside a function macro argument, the returned location will be the macro location in w...
Definition SourceManager.cpp:1834
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
Definition SourceManager.cpp:1979
std::optional< llvm::MemoryBufferRef > getBufferOrNone(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
fileinfo_iterator fileinfo_begin() const
LineTableInfo & getLineTable()
Retrieve the stored line table.
Definition SourceManager.cpp:294
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
Definition SourceManager.cpp:935
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
Definition SourceManager.cpp:709
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.
Definition SourceManager.cpp:649
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.
Definition SourceManager.cpp:61
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.
Definition SourceManager.cpp:79
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const
Returns the kind of memory used to back the memory buffer for this content cache.
Definition SourceManager.cpp:67
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.
Definition SourceManager.cpp:108
static const char * getInvalidBOM(StringRef BufStr)
Definition SourceManager.cpp:84
unsigned BufferOverridden
Indicates whether the buffer itself was provided to override the actual file contents.
OptionalFileEntryRef OrigEntry
Reference to the file entry representing this ContentCache.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End, bool ExpansionIsTokenRange=true)
Return a ExpansionInfo for an expansion.
bool isMacroBodyExpansion() const
SourceLocation getSpellingLoc() const
CharSourceRange getExpansionLocRange() const
bool isMacroArgExpansion() const
static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc)
Return a special ExpansionInfo for the expansion of a macro argument into a function-like macro's bod...
static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End)
Return a special ExpansionInfo representing a token that ends prematurely.
SourceLocation getExpansionLocEnd() const
Information about a FileID, basically just the logical file that it represents and include stack info...
const ContentCache & getContentCache() const
CharacteristicKind getFileCharacteristic() const
Return whether this is a system header or not.
static FileInfo get(SourceLocation IL, ContentCache &Con, CharacteristicKind FileCharacter, StringRef Filename)
Return a FileInfo object.
bool hasLineDirectives() const
Return true if this FileID has #line directives in it.
void setHasLineDirectives()
Set the flag that indicates that this FileID has line table entries associated with it.
SourceLocation getIncludeLoc() const
const unsigned * begin() const
LineOffsetMapping()=default
const unsigned * end() const
static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, llvm::BumpPtrAllocator &Alloc)
Definition SourceManager.cpp:1190
This is a discriminated union of FileInfo and ExpansionInfo.
SourceLocation::UIntTy getOffset() const
static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI)
const FileInfo & getFile() const
const ExpansionInfo & getExpansion() const
Public enums and private classes that are part of the SourceManager implementation.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
StringRef getName(const HeaderType T)
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
std::pair< FileID, unsigned > FileIDAndOffset
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
const FunctionProtoType * T
SrcMgr::CharacteristicKind FileKind
Set the 0 if no flags, 1 if a system header,.
static LineEntry get(unsigned Offs, unsigned Line, int Filename, SrcMgr::CharacteristicKind FileKind, unsigned IncludeOffset)