File indexing completed on 2026-05-10 08:36:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H
0035 #define LLVM_CLANG_BASIC_SOURCEMANAGER_H
0036
0037 #include "clang/Basic/Diagnostic.h"
0038 #include "clang/Basic/FileEntry.h"
0039 #include "clang/Basic/FileManager.h"
0040 #include "clang/Basic/SourceLocation.h"
0041 #include "llvm/ADT/ArrayRef.h"
0042 #include "llvm/ADT/BitVector.h"
0043 #include "llvm/ADT/DenseMap.h"
0044 #include "llvm/ADT/DenseSet.h"
0045 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0046 #include "llvm/ADT/PagedVector.h"
0047 #include "llvm/ADT/PointerIntPair.h"
0048 #include "llvm/ADT/SmallVector.h"
0049 #include "llvm/ADT/StringRef.h"
0050 #include "llvm/Support/Allocator.h"
0051 #include "llvm/Support/Compiler.h"
0052 #include "llvm/Support/MemoryBuffer.h"
0053 #include <cassert>
0054 #include <cstddef>
0055 #include <map>
0056 #include <memory>
0057 #include <optional>
0058 #include <string>
0059 #include <utility>
0060 #include <vector>
0061
0062 namespace clang {
0063
0064 class ASTReader;
0065 class ASTWriter;
0066 class FileManager;
0067 class LineTableInfo;
0068 class SourceManager;
0069
0070
0071
0072 namespace SrcMgr {
0073
0074
0075
0076
0077
0078
0079
0080
0081 enum CharacteristicKind {
0082 C_User,
0083 C_System,
0084 C_ExternCSystem,
0085 C_User_ModuleMap,
0086 C_System_ModuleMap
0087 };
0088
0089
0090 inline bool isSystem(CharacteristicKind CK) {
0091 return CK != C_User && CK != C_User_ModuleMap;
0092 }
0093
0094
0095 inline bool isModuleMap(CharacteristicKind CK) {
0096 return CK == C_User_ModuleMap || CK == C_System_ModuleMap;
0097 }
0098
0099
0100
0101 class LineOffsetMapping {
0102 public:
0103 explicit operator bool() const { return Storage; }
0104 unsigned size() const {
0105 assert(Storage);
0106 return Storage[0];
0107 }
0108 ArrayRef<unsigned> getLines() const {
0109 assert(Storage);
0110 return ArrayRef<unsigned>(Storage + 1, Storage + 1 + size());
0111 }
0112 const unsigned *begin() const { return getLines().begin(); }
0113 const unsigned *end() const { return getLines().end(); }
0114 const unsigned &operator[](int I) const { return getLines()[I]; }
0115
0116 static LineOffsetMapping get(llvm::MemoryBufferRef Buffer,
0117 llvm::BumpPtrAllocator &Alloc);
0118
0119 LineOffsetMapping() = default;
0120 LineOffsetMapping(ArrayRef<unsigned> LineOffsets,
0121 llvm::BumpPtrAllocator &Alloc);
0122
0123 private:
0124
0125 unsigned *Storage = nullptr;
0126 };
0127
0128
0129
0130
0131 class alignas(8) ContentCache {
0132
0133
0134 mutable std::unique_ptr<llvm::MemoryBuffer> Buffer;
0135
0136 public:
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 OptionalFileEntryRef OrigEntry;
0147
0148
0149
0150
0151
0152 OptionalFileEntryRef ContentsEntry;
0153
0154
0155
0156
0157 StringRef Filename;
0158
0159
0160
0161
0162
0163 mutable LineOffsetMapping SourceLineCache;
0164
0165
0166
0167
0168
0169
0170 LLVM_PREFERRED_TYPE(bool)
0171 unsigned BufferOverridden : 1;
0172
0173
0174
0175 LLVM_PREFERRED_TYPE(bool)
0176 unsigned IsFileVolatile : 1;
0177
0178
0179
0180
0181 LLVM_PREFERRED_TYPE(bool)
0182 unsigned IsTransient : 1;
0183
0184 LLVM_PREFERRED_TYPE(bool)
0185 mutable unsigned IsBufferInvalid : 1;
0186
0187 ContentCache()
0188 : OrigEntry(std::nullopt), ContentsEntry(std::nullopt),
0189 BufferOverridden(false), IsFileVolatile(false), IsTransient(false),
0190 IsBufferInvalid(false) {}
0191
0192 ContentCache(FileEntryRef Ent) : ContentCache(Ent, Ent) {}
0193
0194 ContentCache(FileEntryRef Ent, FileEntryRef contentEnt)
0195 : OrigEntry(Ent), ContentsEntry(contentEnt), BufferOverridden(false),
0196 IsFileVolatile(false), IsTransient(false), IsBufferInvalid(false) {}
0197
0198
0199
0200
0201 ContentCache(const ContentCache &RHS)
0202 : BufferOverridden(false), IsFileVolatile(false), IsTransient(false),
0203 IsBufferInvalid(false) {
0204 OrigEntry = RHS.OrigEntry;
0205 ContentsEntry = RHS.ContentsEntry;
0206
0207 assert(!RHS.Buffer && !RHS.SourceLineCache &&
0208 "Passed ContentCache object cannot own a buffer.");
0209 }
0210
0211 ContentCache &operator=(const ContentCache &RHS) = delete;
0212
0213
0214
0215
0216
0217
0218
0219
0220 std::optional<llvm::MemoryBufferRef>
0221 getBufferOrNone(DiagnosticsEngine &Diag, FileManager &FM,
0222 SourceLocation Loc = SourceLocation()) const;
0223
0224
0225
0226
0227
0228
0229
0230 unsigned getSize() const;
0231
0232
0233
0234
0235
0236 unsigned getSizeBytesMapped() const;
0237
0238
0239
0240 llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;
0241
0242
0243 std::optional<llvm::MemoryBufferRef> getBufferIfLoaded() const {
0244 if (Buffer)
0245 return Buffer->getMemBufferRef();
0246 return std::nullopt;
0247 }
0248
0249
0250
0251 std::optional<StringRef> getBufferDataIfLoaded() const {
0252 if (Buffer)
0253 return Buffer->getBuffer();
0254 return std::nullopt;
0255 }
0256
0257
0258 void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) {
0259 IsBufferInvalid = false;
0260 Buffer = std::move(B);
0261 }
0262
0263
0264
0265
0266 void setUnownedBuffer(std::optional<llvm::MemoryBufferRef> B) {
0267 assert(!Buffer && "Expected to be called right after construction");
0268 if (B)
0269 setBuffer(llvm::MemoryBuffer::getMemBuffer(*B));
0270 }
0271
0272
0273
0274 static const char *getInvalidBOM(StringRef BufStr);
0275 };
0276
0277
0278
0279 static_assert(alignof(ContentCache) >= 8,
0280 "ContentCache must be 8-byte aligned.");
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 class FileInfo {
0296 friend class clang::SourceManager;
0297 friend class clang::ASTWriter;
0298 friend class clang::ASTReader;
0299
0300
0301
0302
0303 SourceLocation IncludeLoc;
0304
0305
0306
0307
0308
0309 unsigned NumCreatedFIDs : 31;
0310
0311
0312 LLVM_PREFERRED_TYPE(bool)
0313 unsigned HasLineDirectives : 1;
0314
0315
0316 llvm::PointerIntPair<const ContentCache *, 3, CharacteristicKind>
0317 ContentAndKind;
0318
0319 public:
0320
0321 static FileInfo get(SourceLocation IL, ContentCache &Con,
0322 CharacteristicKind FileCharacter, StringRef Filename) {
0323 FileInfo X;
0324 X.IncludeLoc = IL;
0325 X.NumCreatedFIDs = 0;
0326 X.HasLineDirectives = false;
0327 X.ContentAndKind.setPointer(&Con);
0328 X.ContentAndKind.setInt(FileCharacter);
0329 Con.Filename = Filename;
0330 return X;
0331 }
0332
0333 SourceLocation getIncludeLoc() const {
0334 return IncludeLoc;
0335 }
0336
0337 const ContentCache &getContentCache() const {
0338 return *ContentAndKind.getPointer();
0339 }
0340
0341
0342 CharacteristicKind getFileCharacteristic() const {
0343 return ContentAndKind.getInt();
0344 }
0345
0346
0347 bool hasLineDirectives() const { return HasLineDirectives; }
0348
0349
0350
0351 void setHasLineDirectives() { HasLineDirectives = true; }
0352
0353
0354
0355 StringRef getName() const { return getContentCache().Filename; }
0356 };
0357
0358
0359
0360
0361 class ExpansionInfo {
0362
0363
0364
0365 SourceLocation SpellingLoc;
0366
0367
0368
0369
0370
0371
0372
0373 SourceLocation ExpansionLocStart, ExpansionLocEnd;
0374
0375
0376 bool ExpansionIsTokenRange;
0377
0378 public:
0379 SourceLocation getSpellingLoc() const {
0380 return SpellingLoc.isInvalid() ? getExpansionLocStart() : SpellingLoc;
0381 }
0382
0383 SourceLocation getExpansionLocStart() const {
0384 return ExpansionLocStart;
0385 }
0386
0387 SourceLocation getExpansionLocEnd() const {
0388 return ExpansionLocEnd.isInvalid() ? getExpansionLocStart()
0389 : ExpansionLocEnd;
0390 }
0391
0392 bool isExpansionTokenRange() const { return ExpansionIsTokenRange; }
0393
0394 CharSourceRange getExpansionLocRange() const {
0395 return CharSourceRange(
0396 SourceRange(getExpansionLocStart(), getExpansionLocEnd()),
0397 isExpansionTokenRange());
0398 }
0399
0400 bool isMacroArgExpansion() const {
0401
0402 return getExpansionLocStart().isValid() && ExpansionLocEnd.isInvalid();
0403 }
0404
0405 bool isMacroBodyExpansion() const {
0406 return getExpansionLocStart().isValid() && ExpansionLocEnd.isValid();
0407 }
0408
0409 bool isFunctionMacroExpansion() const {
0410 return getExpansionLocStart().isValid() &&
0411 getExpansionLocStart() != getExpansionLocEnd();
0412 }
0413
0414
0415
0416
0417
0418
0419
0420 static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start,
0421 SourceLocation End,
0422 bool ExpansionIsTokenRange = true) {
0423 ExpansionInfo X;
0424 X.SpellingLoc = SpellingLoc;
0425 X.ExpansionLocStart = Start;
0426 X.ExpansionLocEnd = End;
0427 X.ExpansionIsTokenRange = ExpansionIsTokenRange;
0428 return X;
0429 }
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450 static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc,
0451 SourceLocation ExpansionLoc) {
0452
0453
0454
0455 return create(SpellingLoc, ExpansionLoc, SourceLocation());
0456 }
0457
0458
0459
0460
0461
0462
0463 static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc,
0464 SourceLocation Start,
0465 SourceLocation End) {
0466 return create(SpellingLoc, Start, End, false);
0467 }
0468 };
0469
0470
0471
0472
0473
0474 static_assert(sizeof(FileInfo) <= sizeof(ExpansionInfo),
0475 "FileInfo must be no larger than ExpansionInfo.");
0476
0477
0478
0479
0480
0481 class SLocEntry {
0482 static constexpr int OffsetBits = 8 * sizeof(SourceLocation::UIntTy) - 1;
0483 SourceLocation::UIntTy Offset : OffsetBits;
0484 LLVM_PREFERRED_TYPE(bool)
0485 SourceLocation::UIntTy IsExpansion : 1;
0486 union {
0487 FileInfo File;
0488 ExpansionInfo Expansion;
0489 };
0490
0491 public:
0492 SLocEntry() : Offset(), IsExpansion(), File() {}
0493
0494 SourceLocation::UIntTy getOffset() const { return Offset; }
0495
0496 bool isExpansion() const { return IsExpansion; }
0497 bool isFile() const { return !isExpansion(); }
0498
0499 const FileInfo &getFile() const {
0500 return const_cast<SLocEntry *>(this)->getFile();
0501 }
0502
0503 FileInfo &getFile() {
0504 assert(isFile() && "Not a file SLocEntry!");
0505 return File;
0506 }
0507
0508 const ExpansionInfo &getExpansion() const {
0509 assert(isExpansion() && "Not a macro expansion SLocEntry!");
0510 return Expansion;
0511 }
0512
0513
0514 static SLocEntry getOffsetOnly(SourceLocation::UIntTy Offset) {
0515 assert(!(Offset & (1ULL << OffsetBits)) && "Offset is too large");
0516 SLocEntry E;
0517 E.Offset = Offset;
0518 return E;
0519 }
0520
0521 static SLocEntry get(SourceLocation::UIntTy Offset, const FileInfo &FI) {
0522 assert(!(Offset & (1ULL << OffsetBits)) && "Offset is too large");
0523 SLocEntry E;
0524 E.Offset = Offset;
0525 E.IsExpansion = false;
0526 E.File = FI;
0527 return E;
0528 }
0529
0530 static SLocEntry get(SourceLocation::UIntTy Offset,
0531 const ExpansionInfo &Expansion) {
0532 assert(!(Offset & (1ULL << OffsetBits)) && "Offset is too large");
0533 SLocEntry E;
0534 E.Offset = Offset;
0535 E.IsExpansion = true;
0536 new (&E.Expansion) ExpansionInfo(Expansion);
0537 return E;
0538 }
0539 };
0540
0541 }
0542
0543
0544 class ExternalSLocEntrySource {
0545 public:
0546 virtual ~ExternalSLocEntrySource();
0547
0548
0549
0550
0551
0552
0553 virtual bool ReadSLocEntry(int ID) = 0;
0554
0555
0556
0557
0558
0559 virtual int getSLocEntryID(SourceLocation::UIntTy SLocOffset) = 0;
0560
0561
0562
0563
0564 virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0;
0565 };
0566
0567
0568
0569
0570
0571 class InBeforeInTUCacheEntry {
0572
0573
0574
0575 FileID LQueryFID, RQueryFID;
0576
0577
0578
0579
0580 bool LChildBeforeRChild;
0581
0582
0583
0584 FileID CommonFID;
0585
0586
0587
0588
0589
0590
0591 unsigned LCommonOffset, RCommonOffset;
0592
0593 public:
0594 InBeforeInTUCacheEntry() = default;
0595 InBeforeInTUCacheEntry(FileID L, FileID R) : LQueryFID(L), RQueryFID(R) {
0596 assert(L != R);
0597 }
0598
0599
0600
0601
0602
0603 bool isCacheValid() const {
0604 return CommonFID.isValid();
0605 }
0606
0607
0608
0609 bool getCachedResult(unsigned LOffset, unsigned ROffset) const {
0610
0611
0612 if (LQueryFID != CommonFID) LOffset = LCommonOffset;
0613 if (RQueryFID != CommonFID) ROffset = RCommonOffset;
0614
0615
0616
0617
0618
0619
0620 if (LOffset == ROffset)
0621 return LChildBeforeRChild;
0622
0623 return LOffset < ROffset;
0624 }
0625
0626
0627
0628 void setQueryFIDs(FileID LHS, FileID RHS) {
0629 assert(LHS != RHS);
0630 if (LQueryFID != LHS || RQueryFID != RHS) {
0631 LQueryFID = LHS;
0632 RQueryFID = RHS;
0633 CommonFID = FileID();
0634 }
0635 }
0636
0637 void setCommonLoc(FileID commonFID, unsigned lCommonOffset,
0638 unsigned rCommonOffset, bool LParentBeforeRParent) {
0639 CommonFID = commonFID;
0640 LCommonOffset = lCommonOffset;
0641 RCommonOffset = rCommonOffset;
0642 LChildBeforeRChild = LParentBeforeRParent;
0643 }
0644 };
0645
0646
0647
0648
0649 using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>;
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663 class SourceManager : public RefCountedBase<SourceManager> {
0664
0665 DiagnosticsEngine &Diag;
0666
0667 FileManager &FileMgr;
0668
0669 mutable llvm::BumpPtrAllocator ContentCacheAlloc;
0670
0671
0672
0673
0674
0675
0676
0677 llvm::DenseMap<FileEntryRef, SrcMgr::ContentCache*> FileInfos;
0678
0679
0680
0681 bool OverridenFilesKeepOriginalName = true;
0682
0683
0684
0685 bool UserFilesAreVolatile;
0686
0687
0688
0689
0690 bool FilesAreTransient = false;
0691
0692 struct OverriddenFilesInfoTy {
0693
0694
0695 llvm::DenseMap<const FileEntry *, FileEntryRef> OverriddenFiles;
0696
0697
0698 llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
0699 };
0700
0701
0702
0703 std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo;
0704
0705 OverriddenFilesInfoTy &getOverriddenFilesInfo() {
0706 if (!OverriddenFilesInfo)
0707 OverriddenFilesInfo.reset(new OverriddenFilesInfoTy);
0708 return *OverriddenFilesInfo;
0709 }
0710
0711
0712
0713
0714
0715 std::vector<SrcMgr::ContentCache*> MemBufferInfos;
0716
0717
0718
0719
0720
0721 SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable;
0722
0723
0724
0725
0726
0727 llvm::PagedVector<SrcMgr::SLocEntry, 32> LoadedSLocEntryTable;
0728
0729
0730
0731
0732 SmallVector<FileID, 0> LoadedSLocEntryAllocBegin;
0733
0734
0735
0736
0737 SourceLocation::UIntTy NextLocalOffset;
0738
0739
0740
0741
0742
0743 SourceLocation::UIntTy CurrentLoadedOffset;
0744
0745
0746
0747 static const SourceLocation::UIntTy MaxLoadedOffset =
0748 1ULL << (8 * sizeof(SourceLocation::UIntTy) - 1);
0749
0750
0751
0752
0753
0754 llvm::BitVector SLocEntryLoaded;
0755
0756
0757
0758
0759
0760 llvm::BitVector SLocEntryOffsetLoaded;
0761
0762
0763 ExternalSLocEntrySource *ExternalSLocEntries = nullptr;
0764
0765
0766
0767
0768
0769 mutable FileID LastFileIDLookup;
0770
0771
0772
0773
0774 std::unique_ptr<LineTableInfo> LineTable;
0775
0776
0777
0778 mutable FileID LastLineNoFileIDQuery;
0779 mutable const SrcMgr::ContentCache *LastLineNoContentCache;
0780 mutable unsigned LastLineNoFilePos;
0781 mutable unsigned LastLineNoResult;
0782
0783
0784 FileID MainFileID;
0785
0786
0787 FileID PreambleFileID;
0788
0789
0790 mutable unsigned NumLinearScans = 0;
0791 mutable unsigned NumBinaryProbes = 0;
0792
0793
0794
0795
0796
0797
0798 mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned>> IncludedLocMap;
0799
0800
0801 using IsBeforeInTUCacheKey = std::pair<FileID, FileID>;
0802
0803
0804
0805 using InBeforeInTUCache =
0806 llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>;
0807
0808
0809 mutable InBeforeInTUCache IBTUCache;
0810 mutable InBeforeInTUCacheEntry IBTUCacheOverflow;
0811
0812
0813
0814 InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const;
0815
0816
0817 mutable std::unique_ptr<llvm::MemoryBuffer> FakeBufferForRecovery;
0818
0819 mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery;
0820
0821 mutable std::unique_ptr<SrcMgr::SLocEntry> FakeSLocEntryForRecovery;
0822
0823
0824
0825 using MacroArgsMap = std::map<unsigned, SourceLocation>;
0826
0827 mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>>
0828 MacroArgsCacheMap;
0829
0830
0831
0832
0833
0834
0835
0836
0837 SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack;
0838
0839 public:
0840 SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
0841 bool UserFilesAreVolatile = false);
0842 explicit SourceManager(const SourceManager &) = delete;
0843 SourceManager &operator=(const SourceManager &) = delete;
0844 ~SourceManager();
0845
0846 void clearIDTables();
0847
0848
0849
0850 void initializeForReplay(const SourceManager &Old);
0851
0852 DiagnosticsEngine &getDiagnostics() const { return Diag; }
0853
0854 FileManager &getFileManager() const { return FileMgr; }
0855
0856
0857
0858
0859 void setOverridenFilesKeepOriginalName(bool value) {
0860 OverridenFilesKeepOriginalName = value;
0861 }
0862
0863
0864
0865 bool userFilesAreVolatile() const { return UserFilesAreVolatile; }
0866
0867
0868 ModuleBuildStack getModuleBuildStack() const {
0869 return StoredModuleBuildStack;
0870 }
0871
0872
0873 void setModuleBuildStack(ModuleBuildStack stack) {
0874 StoredModuleBuildStack.clear();
0875 StoredModuleBuildStack.append(stack.begin(), stack.end());
0876 }
0877
0878
0879 void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) {
0880 StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc));
0881 }
0882
0883
0884
0885
0886
0887
0888 FileID getMainFileID() const { return MainFileID; }
0889
0890
0891 void setMainFileID(FileID FID) {
0892 MainFileID = FID;
0893 }
0894
0895
0896
0897
0898 bool isMainFile(const FileEntry &SourceFile);
0899
0900
0901 void setPreambleFileID(FileID Preamble) {
0902 assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
0903 PreambleFileID = Preamble;
0904 }
0905
0906
0907 FileID getPreambleFileID() const { return PreambleFileID; }
0908
0909
0910
0911
0912
0913
0914
0915 FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos,
0916 SrcMgr::CharacteristicKind FileCharacter,
0917 int LoadedID = 0,
0918 SourceLocation::UIntTy LoadedOffset = 0);
0919
0920
0921
0922
0923
0924 FileID createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
0925 SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
0926 int LoadedID = 0, SourceLocation::UIntTy LoadedOffset = 0,
0927 SourceLocation IncludeLoc = SourceLocation());
0928
0929
0930
0931
0932
0933 FileID createFileID(const llvm::MemoryBufferRef &Buffer,
0934 SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
0935 int LoadedID = 0, SourceLocation::UIntTy LoadedOffset = 0,
0936 SourceLocation IncludeLoc = SourceLocation());
0937
0938
0939
0940 FileID getOrCreateFileID(FileEntryRef SourceFile,
0941 SrcMgr::CharacteristicKind FileCharacter);
0942
0943
0944
0945
0946
0947
0948 SourceLocation createMacroArgExpansionLoc(SourceLocation SpellingLoc,
0949 SourceLocation ExpansionLoc,
0950 unsigned Length);
0951
0952
0953
0954
0955
0956 SourceLocation createExpansionLoc(SourceLocation SpellingLoc,
0957 SourceLocation ExpansionLocStart,
0958 SourceLocation ExpansionLocEnd,
0959 unsigned Length,
0960 bool ExpansionIsTokenRange = true,
0961 int LoadedID = 0,
0962 SourceLocation::UIntTy LoadedOffset = 0);
0963
0964
0965
0966 SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc,
0967 SourceLocation TokenStart,
0968 SourceLocation TokenEnd);
0969
0970
0971
0972
0973 std::optional<llvm::MemoryBufferRef>
0974 getMemoryBufferForFileOrNone(FileEntryRef File);
0975
0976
0977
0978
0979 llvm::MemoryBufferRef getMemoryBufferForFileOrFake(FileEntryRef File) {
0980 if (auto B = getMemoryBufferForFileOrNone(File))
0981 return *B;
0982 return getFakeBufferForRecovery();
0983 }
0984
0985
0986
0987
0988
0989
0990
0991
0992 void overrideFileContents(FileEntryRef SourceFile,
0993 const llvm::MemoryBufferRef &Buffer) {
0994 overrideFileContents(SourceFile, llvm::MemoryBuffer::getMemBuffer(Buffer));
0995 }
0996
0997
0998
0999
1000
1001
1002
1003
1004 void overrideFileContents(FileEntryRef SourceFile,
1005 std::unique_ptr<llvm::MemoryBuffer> Buffer);
1006
1007
1008
1009
1010
1011
1012
1013 void overrideFileContents(const FileEntry *SourceFile, FileEntryRef NewFile);
1014
1015
1016 bool isFileOverridden(const FileEntry *File) const {
1017 if (OverriddenFilesInfo) {
1018 if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File))
1019 return true;
1020 if (OverriddenFilesInfo->OverriddenFiles.contains(File))
1021 return true;
1022 }
1023 return false;
1024 }
1025
1026
1027
1028
1029
1030
1031 OptionalFileEntryRef bypassFileContentsOverride(FileEntryRef File);
1032
1033
1034 void setFileIsTransient(FileEntryRef SourceFile);
1035
1036
1037
1038 void setAllFilesAreTransient(bool Transient) {
1039 FilesAreTransient = Transient;
1040 }
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050 std::optional<llvm::MemoryBufferRef>
1051 getBufferOrNone(FileID FID, SourceLocation Loc = SourceLocation()) const {
1052 if (auto *Entry = getSLocEntryForFile(FID))
1053 return Entry->getFile().getContentCache().getBufferOrNone(
1054 Diag, getFileManager(), Loc);
1055 return std::nullopt;
1056 }
1057
1058
1059
1060
1061
1062 llvm::MemoryBufferRef
1063 getBufferOrFake(FileID FID, SourceLocation Loc = SourceLocation()) const {
1064 if (auto B = getBufferOrNone(FID, Loc))
1065 return *B;
1066 return getFakeBufferForRecovery();
1067 }
1068
1069
1070 const FileEntry *getFileEntryForID(FileID FID) const {
1071 if (auto FE = getFileEntryRefForID(FID))
1072 return *FE;
1073 return nullptr;
1074 }
1075
1076
1077 OptionalFileEntryRef getFileEntryRefForID(FileID FID) const {
1078 if (auto *Entry = getSLocEntryForFile(FID))
1079 return Entry->getFile().getContentCache().OrigEntry;
1080 return std::nullopt;
1081 }
1082
1083
1084
1085
1086
1087 std::optional<StringRef> getNonBuiltinFilenameForID(FileID FID) const;
1088
1089
1090 const FileEntry *
1091 getFileEntryForSLocEntry(const SrcMgr::SLocEntry &SLocEntry) const {
1092 if (auto FE = SLocEntry.getFile().getContentCache().OrigEntry)
1093 return *FE;
1094 return nullptr;
1095 }
1096
1097
1098
1099
1100
1101
1102 StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const;
1103
1104
1105
1106
1107
1108 std::optional<StringRef> getBufferDataOrNone(FileID FID) const;
1109
1110
1111
1112
1113
1114 std::optional<StringRef> getBufferDataIfLoaded(FileID FID) const;
1115
1116
1117
1118 unsigned getNumCreatedFIDsForFileID(FileID FID) const {
1119 if (auto *Entry = getSLocEntryForFile(FID))
1120 return Entry->getFile().NumCreatedFIDs;
1121 return 0;
1122 }
1123
1124
1125
1126 void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs,
1127 bool Force = false) {
1128 auto *Entry = getSLocEntryForFile(FID);
1129 if (!Entry)
1130 return;
1131 assert((Force || Entry->getFile().NumCreatedFIDs == 0) && "Already set!");
1132 Entry->getFile().NumCreatedFIDs = NumFIDs;
1133 }
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145 FileID getFileID(SourceLocation SpellingLoc) const {
1146 return getFileID(SpellingLoc.getOffset());
1147 }
1148
1149
1150 StringRef getFilename(SourceLocation SpellingLoc) const;
1151
1152
1153
1154 SourceLocation getLocForStartOfFile(FileID FID) const {
1155 if (auto *Entry = getSLocEntryForFile(FID))
1156 return SourceLocation::getFileLoc(Entry->getOffset());
1157 return SourceLocation();
1158 }
1159
1160
1161
1162 SourceLocation getLocForEndOfFile(FileID FID) const {
1163 if (auto *Entry = getSLocEntryForFile(FID))
1164 return SourceLocation::getFileLoc(Entry->getOffset() +
1165 getFileIDSize(FID));
1166 return SourceLocation();
1167 }
1168
1169
1170
1171 SourceLocation getIncludeLoc(FileID FID) const {
1172 if (auto *Entry = getSLocEntryForFile(FID))
1173 return Entry->getFile().getIncludeLoc();
1174 return SourceLocation();
1175 }
1176
1177
1178
1179
1180 std::pair<SourceLocation, StringRef>
1181 getModuleImportLoc(SourceLocation Loc) const {
1182 FileID FID = getFileID(Loc);
1183
1184
1185
1186 if (FID.ID >= -1)
1187 return std::make_pair(SourceLocation(), "");
1188
1189 return ExternalSLocEntries->getModuleImportLoc(FID.ID);
1190 }
1191
1192
1193
1194 SourceLocation getExpansionLoc(SourceLocation Loc) const {
1195
1196
1197 if (Loc.isFileID()) return Loc;
1198 return getExpansionLocSlowCase(Loc);
1199 }
1200
1201
1202
1203
1204 SourceLocation getFileLoc(SourceLocation Loc) const {
1205 if (Loc.isFileID()) return Loc;
1206 return getFileLocSlowCase(Loc);
1207 }
1208
1209
1210
1211
1212
1213 CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const;
1214
1215
1216
1217 CharSourceRange getExpansionRange(SourceLocation Loc) const;
1218
1219
1220
1221 CharSourceRange getExpansionRange(SourceRange Range) const {
1222 SourceLocation Begin = getExpansionRange(Range.getBegin()).getBegin();
1223 CharSourceRange End = getExpansionRange(Range.getEnd());
1224 return CharSourceRange(SourceRange(Begin, End.getEnd()),
1225 End.isTokenRange());
1226 }
1227
1228
1229
1230 CharSourceRange getExpansionRange(CharSourceRange Range) const {
1231 CharSourceRange Expansion = getExpansionRange(Range.getAsRange());
1232 if (Expansion.getEnd() == Range.getEnd())
1233 Expansion.setTokenRange(Range.isTokenRange());
1234 return Expansion;
1235 }
1236
1237
1238
1239
1240
1241
1242 SourceLocation getSpellingLoc(SourceLocation Loc) const {
1243
1244
1245 if (Loc.isFileID()) return Loc;
1246 return getSpellingLocSlowCase(Loc);
1247 }
1248
1249
1250
1251
1252
1253
1254
1255 SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;
1256
1257
1258 SourceLocation getComposedLoc(FileID FID, unsigned Offset) const {
1259 auto *Entry = getSLocEntryOrNull(FID);
1260 if (!Entry)
1261 return SourceLocation();
1262
1263 SourceLocation::UIntTy GlobalOffset = Entry->getOffset() + Offset;
1264 return Entry->isFile() ? SourceLocation::getFileLoc(GlobalOffset)
1265 : SourceLocation::getMacroLoc(GlobalOffset);
1266 }
1267
1268
1269
1270
1271
1272 std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
1273 FileID FID = getFileID(Loc);
1274 auto *Entry = getSLocEntryOrNull(FID);
1275 if (!Entry)
1276 return std::make_pair(FileID(), 0);
1277 return std::make_pair(FID, Loc.getOffset() - Entry->getOffset());
1278 }
1279
1280
1281
1282
1283
1284 std::pair<FileID, unsigned>
1285 getDecomposedExpansionLoc(SourceLocation Loc) const {
1286 FileID FID = getFileID(Loc);
1287 auto *E = getSLocEntryOrNull(FID);
1288 if (!E)
1289 return std::make_pair(FileID(), 0);
1290
1291 unsigned Offset = Loc.getOffset()-E->getOffset();
1292 if (Loc.isFileID())
1293 return std::make_pair(FID, Offset);
1294
1295 return getDecomposedExpansionLocSlowCase(E);
1296 }
1297
1298
1299
1300
1301
1302 std::pair<FileID, unsigned>
1303 getDecomposedSpellingLoc(SourceLocation Loc) const {
1304 FileID FID = getFileID(Loc);
1305 auto *E = getSLocEntryOrNull(FID);
1306 if (!E)
1307 return std::make_pair(FileID(), 0);
1308
1309 unsigned Offset = Loc.getOffset()-E->getOffset();
1310 if (Loc.isFileID())
1311 return std::make_pair(FID, Offset);
1312 return getDecomposedSpellingLocSlowCase(E, Offset);
1313 }
1314
1315
1316
1317 std::pair<FileID, unsigned> getDecomposedIncludedLoc(FileID FID) const;
1318
1319
1320
1321
1322
1323 unsigned getFileOffset(SourceLocation SpellingLoc) const {
1324 return getDecomposedLoc(SpellingLoc).second;
1325 }
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 bool isMacroArgExpansion(SourceLocation Loc,
1337 SourceLocation *StartLoc = nullptr) const;
1338
1339
1340
1341
1342
1343
1344 bool isMacroBodyExpansion(SourceLocation Loc) const;
1345
1346
1347
1348
1349
1350
1351 bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
1352 SourceLocation *MacroBegin = nullptr) const;
1353
1354
1355
1356
1357
1358
1359 bool
1360 isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
1361 SourceLocation *MacroEnd = nullptr) const;
1362
1363
1364
1365
1366
1367
1368 bool
1369 isInSLocAddrSpace(SourceLocation Loc, SourceLocation Start, unsigned Length,
1370 SourceLocation::UIntTy *RelativeOffset = nullptr) const {
1371 assert(((Start.getOffset() < NextLocalOffset &&
1372 Start.getOffset()+Length <= NextLocalOffset) ||
1373 (Start.getOffset() >= CurrentLoadedOffset &&
1374 Start.getOffset()+Length < MaxLoadedOffset)) &&
1375 "Chunk is not valid SLoc address space");
1376 SourceLocation::UIntTy LocOffs = Loc.getOffset();
1377 SourceLocation::UIntTy BeginOffs = Start.getOffset();
1378 SourceLocation::UIntTy EndOffs = BeginOffs + Length;
1379 if (LocOffs >= BeginOffs && LocOffs < EndOffs) {
1380 if (RelativeOffset)
1381 *RelativeOffset = LocOffs - BeginOffs;
1382 return true;
1383 }
1384
1385 return false;
1386 }
1387
1388
1389
1390
1391
1392
1393 bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS,
1394 SourceLocation::IntTy *RelativeOffset) const {
1395 SourceLocation::UIntTy LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset();
1396 bool LHSLoaded = LHSOffs >= CurrentLoadedOffset;
1397 bool RHSLoaded = RHSOffs >= CurrentLoadedOffset;
1398
1399 if (LHSLoaded == RHSLoaded) {
1400 if (RelativeOffset)
1401 *RelativeOffset = RHSOffs - LHSOffs;
1402 return true;
1403 }
1404
1405 return false;
1406 }
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416 const char *getCharacterData(SourceLocation SL,
1417 bool *Invalid = nullptr) const;
1418
1419
1420
1421
1422
1423
1424
1425 unsigned getColumnNumber(FileID FID, unsigned FilePos,
1426 bool *Invalid = nullptr) const;
1427 unsigned getSpellingColumnNumber(SourceLocation Loc,
1428 bool *Invalid = nullptr) const;
1429 unsigned getExpansionColumnNumber(SourceLocation Loc,
1430 bool *Invalid = nullptr) const;
1431 unsigned getPresumedColumnNumber(SourceLocation Loc,
1432 bool *Invalid = nullptr) const;
1433
1434
1435
1436
1437
1438
1439
1440 unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = nullptr) const;
1441 unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
1442 unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
1443 unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
1444
1445
1446
1447
1448
1449
1450 StringRef getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const;
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462 SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477 PresumedLoc getPresumedLoc(SourceLocation Loc,
1478 bool UseLineDirectives = true) const;
1479
1480
1481
1482
1483
1484
1485
1486
1487 bool isInMainFile(SourceLocation Loc) const;
1488
1489
1490
1491
1492
1493 bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
1494 return getFileID(Loc1) == getFileID(Loc2);
1495 }
1496
1497
1498
1499
1500
1501 bool isWrittenInMainFile(SourceLocation Loc) const {
1502 return getFileID(Loc) == getMainFileID();
1503 }
1504
1505
1506 bool isWrittenInBuiltinFile(SourceLocation Loc) const {
1507 PresumedLoc Presumed = getPresumedLoc(Loc);
1508 if (Presumed.isInvalid())
1509 return false;
1510 StringRef Filename(Presumed.getFilename());
1511 return Filename == "<built-in>";
1512 }
1513
1514
1515 bool isWrittenInCommandLineFile(SourceLocation Loc) const {
1516 PresumedLoc Presumed = getPresumedLoc(Loc);
1517 if (Presumed.isInvalid())
1518 return false;
1519 StringRef Filename(Presumed.getFilename());
1520 return Filename == "<command line>";
1521 }
1522
1523
1524 bool isWrittenInScratchSpace(SourceLocation Loc) const {
1525 PresumedLoc Presumed = getPresumedLoc(Loc);
1526 if (Presumed.isInvalid())
1527 return false;
1528 StringRef Filename(Presumed.getFilename());
1529 return Filename == "<scratch space>";
1530 }
1531
1532
1533 bool isInSystemHeader(SourceLocation Loc) const {
1534 if (Loc.isInvalid())
1535 return false;
1536 return isSystem(getFileCharacteristic(Loc));
1537 }
1538
1539
1540 bool isInExternCSystemHeader(SourceLocation Loc) const {
1541 return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
1542 }
1543
1544
1545 bool isInSystemMacro(SourceLocation loc) const {
1546 if (!loc.isMacroID())
1547 return false;
1548
1549
1550
1551
1552 if (isWrittenInScratchSpace(getSpellingLoc(loc))) {
1553 do {
1554 loc = getImmediateMacroCallerLoc(loc);
1555 } while (isWrittenInScratchSpace(getSpellingLoc(loc)));
1556 return isInSystemMacro(loc);
1557 }
1558
1559 return isInSystemHeader(getSpellingLoc(loc));
1560 }
1561
1562
1563 unsigned getFileIDSize(FileID FID) const;
1564
1565
1566
1567
1568 bool isInFileID(SourceLocation Loc, FileID FID,
1569 unsigned *RelativeOffset = nullptr) const {
1570 SourceLocation::UIntTy Offs = Loc.getOffset();
1571 if (isOffsetInFileID(FID, Offs)) {
1572 if (RelativeOffset)
1573 *RelativeOffset = Offs - getSLocEntry(FID).getOffset();
1574 return true;
1575 }
1576
1577 return false;
1578 }
1579
1580
1581
1582
1583
1584
1585 unsigned getLineTableFilenameID(StringRef Str);
1586
1587
1588
1589
1590
1591 void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
1592 bool IsFileEntry, bool IsFileExit,
1593 SrcMgr::CharacteristicKind FileKind);
1594
1595
1596 bool hasLineTable() const { return LineTable != nullptr; }
1597
1598
1599 LineTableInfo &getLineTable();
1600
1601
1602
1603
1604
1605
1606
1607 size_t getContentCacheSize() const {
1608 return ContentCacheAlloc.getTotalMemory();
1609 }
1610
1611 struct MemoryBufferSizes {
1612 const size_t malloc_bytes;
1613 const size_t mmap_bytes;
1614
1615 MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
1616 : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
1617 };
1618
1619
1620
1621 MemoryBufferSizes getMemoryBufferSizes() const;
1622
1623
1624
1625 size_t getDataStructureSizes() const;
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635 SourceLocation translateFileLineCol(const FileEntry *SourceFile,
1636 unsigned Line, unsigned Col) const;
1637
1638
1639
1640
1641
1642 FileID translateFile(const FileEntry *SourceFile) const;
1643 FileID translateFile(FileEntryRef SourceFile) const {
1644 return translateFile(&SourceFile.getFileEntry());
1645 }
1646
1647
1648
1649 SourceLocation translateLineCol(FileID FID,
1650 unsigned Line, unsigned Col) const;
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661 SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const;
1662
1663
1664
1665
1666 bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
1667
1668
1669
1670
1671
1672
1673
1674
1675 std::pair<bool, bool>
1676 isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs,
1677 std::pair<FileID, unsigned> &ROffs) const;
1678
1679
1680
1681
1682 FileID getUniqueLoadedASTFileID(SourceLocation Loc) const;
1683
1684
1685 bool isInTheSameTranslationUnitImpl(
1686 const std::pair<FileID, unsigned> &LOffs,
1687 const std::pair<FileID, unsigned> &ROffs) const;
1688
1689
1690
1691 bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
1692 return isBeforeInSLocAddrSpace(LHS, RHS.getOffset());
1693 }
1694
1695
1696
1697
1698
1699 bool isBeforeInSLocAddrSpace(SourceLocation LHS,
1700 SourceLocation::UIntTy RHS) const {
1701 SourceLocation::UIntTy LHSOffset = LHS.getOffset();
1702 bool LHSLoaded = LHSOffset >= CurrentLoadedOffset;
1703 bool RHSLoaded = RHS >= CurrentLoadedOffset;
1704 if (LHSLoaded == RHSLoaded)
1705 return LHSOffset < RHS;
1706
1707 return LHSLoaded;
1708 }
1709
1710
1711 bool isPointWithin(SourceLocation Location, SourceLocation Start,
1712 SourceLocation End) const {
1713 return Location == Start || Location == End ||
1714 (isBeforeInTranslationUnit(Start, Location) &&
1715 isBeforeInTranslationUnit(Location, End));
1716 }
1717
1718
1719 using fileinfo_iterator =
1720 llvm::DenseMap<FileEntryRef, SrcMgr::ContentCache *>::const_iterator;
1721
1722 fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
1723 fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
1724 bool hasFileInfo(const FileEntry *File) const {
1725 return FileInfos.find_as(File) != FileInfos.end();
1726 }
1727
1728
1729 void PrintStats() const;
1730
1731 void dump() const;
1732
1733
1734 void noteSLocAddressSpaceUsage(DiagnosticsEngine &Diag,
1735 std::optional<unsigned> MaxNotes = 32) const;
1736
1737
1738 unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }
1739
1740
1741 const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index) const {
1742 return const_cast<SourceManager *>(this)->getLocalSLocEntry(Index);
1743 }
1744
1745
1746 SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index) {
1747 assert(Index < LocalSLocEntryTable.size() && "Invalid index");
1748 return LocalSLocEntryTable[Index];
1749 }
1750
1751
1752 unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();}
1753
1754
1755 const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index,
1756 bool *Invalid = nullptr) const {
1757 return const_cast<SourceManager *>(this)->getLoadedSLocEntry(Index,
1758 Invalid);
1759 }
1760
1761
1762 SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index,
1763 bool *Invalid = nullptr) {
1764 assert(Index < LoadedSLocEntryTable.size() && "Invalid index");
1765 if (SLocEntryLoaded[Index])
1766 return LoadedSLocEntryTable[Index];
1767 return loadSLocEntry(Index, Invalid);
1768 }
1769
1770 const SrcMgr::SLocEntry &getSLocEntry(FileID FID,
1771 bool *Invalid = nullptr) const {
1772 return const_cast<SourceManager *>(this)->getSLocEntry(FID, Invalid);
1773 }
1774
1775 SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = nullptr) {
1776 if (FID.ID == 0 || FID.ID == -1) {
1777 if (Invalid) *Invalid = true;
1778 return LocalSLocEntryTable[0];
1779 }
1780 return getSLocEntryByID(FID.ID, Invalid);
1781 }
1782
1783 SourceLocation::UIntTy getNextLocalOffset() const { return NextLocalOffset; }
1784
1785 void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) {
1786 assert(LoadedSLocEntryTable.empty() &&
1787 "Invalidating existing loaded entries");
1788 ExternalSLocEntries = Source;
1789 }
1790
1791
1792
1793
1794
1795
1796
1797 std::pair<int, SourceLocation::UIntTy>
1798 AllocateLoadedSLocEntries(unsigned NumSLocEntries,
1799 SourceLocation::UIntTy TotalSize);
1800
1801
1802 bool isLoadedSourceLocation(SourceLocation Loc) const {
1803 return isLoadedOffset(Loc.getOffset());
1804 }
1805
1806
1807 bool isLocalSourceLocation(SourceLocation Loc) const {
1808 return isLocalOffset(Loc.getOffset());
1809 }
1810
1811
1812 bool isLoadedFileID(FileID FID) const {
1813 assert(FID.ID != -1 && "Using FileID sentinel value");
1814 return FID.ID < 0;
1815 }
1816
1817
1818 bool isLocalFileID(FileID FID) const {
1819 return !isLoadedFileID(FID);
1820 }
1821
1822
1823
1824 SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const {
1825 if (!Loc.isMacroID()) return Loc;
1826
1827
1828
1829
1830 if (isMacroArgExpansion(Loc))
1831 return getImmediateSpellingLoc(Loc);
1832
1833
1834
1835 return getImmediateExpansionRange(Loc).getBegin();
1836 }
1837
1838
1839 SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const;
1840
1841 private:
1842 friend class ASTReader;
1843 friend class ASTWriter;
1844
1845 llvm::MemoryBufferRef getFakeBufferForRecovery() const;
1846 SrcMgr::ContentCache &getFakeContentCacheForRecovery() const;
1847
1848 const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const;
1849 SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid);
1850
1851 const SrcMgr::SLocEntry *getSLocEntryOrNull(FileID FID) const {
1852 return const_cast<SourceManager *>(this)->getSLocEntryOrNull(FID);
1853 }
1854
1855 SrcMgr::SLocEntry *getSLocEntryOrNull(FileID FID) {
1856 bool Invalid = false;
1857 SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
1858 return Invalid ? nullptr : &Entry;
1859 }
1860
1861 const SrcMgr::SLocEntry *getSLocEntryForFile(FileID FID) const {
1862 return const_cast<SourceManager *>(this)->getSLocEntryForFile(FID);
1863 }
1864
1865 SrcMgr::SLocEntry *getSLocEntryForFile(FileID FID) {
1866 if (auto *Entry = getSLocEntryOrNull(FID))
1867 if (Entry->isFile())
1868 return Entry;
1869 return nullptr;
1870 }
1871
1872
1873
1874 const SrcMgr::SLocEntry &getSLocEntryByID(int ID,
1875 bool *Invalid = nullptr) const {
1876 return const_cast<SourceManager *>(this)->getSLocEntryByID(ID, Invalid);
1877 }
1878
1879 SrcMgr::SLocEntry &getSLocEntryByID(int ID, bool *Invalid = nullptr) {
1880 assert(ID != -1 && "Using FileID sentinel value");
1881 if (ID < 0)
1882 return getLoadedSLocEntryByID(ID, Invalid);
1883 return getLocalSLocEntry(static_cast<unsigned>(ID));
1884 }
1885
1886 const SrcMgr::SLocEntry &
1887 getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const {
1888 return const_cast<SourceManager *>(this)->getLoadedSLocEntryByID(ID,
1889 Invalid);
1890 }
1891
1892 SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) {
1893 return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid);
1894 }
1895
1896 FileID getFileID(SourceLocation::UIntTy SLocOffset) const {
1897
1898 if (isOffsetInFileID(LastFileIDLookup, SLocOffset))
1899 return LastFileIDLookup;
1900
1901 return getFileIDSlow(SLocOffset);
1902 }
1903
1904 bool isLocalOffset(SourceLocation::UIntTy SLocOffset) const {
1905 return SLocOffset < CurrentLoadedOffset;
1906 }
1907
1908 bool isLoadedOffset(SourceLocation::UIntTy SLocOffset) const {
1909 return SLocOffset >= CurrentLoadedOffset;
1910 }
1911
1912
1913
1914 SourceLocation
1915 createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion,
1916 unsigned Length, int LoadedID = 0,
1917 SourceLocation::UIntTy LoadedOffset = 0);
1918
1919
1920
1921 inline bool isOffsetInFileID(FileID FID,
1922 SourceLocation::UIntTy SLocOffset) const {
1923 const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
1924
1925 if (SLocOffset < Entry.getOffset()) return false;
1926
1927
1928 if (FID.ID == -2)
1929 return true;
1930
1931
1932 if (FID.ID+1 == static_cast<int>(LocalSLocEntryTable.size()))
1933 return SLocOffset < NextLocalOffset;
1934
1935
1936
1937 return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset();
1938 }
1939
1940
1941
1942 FileID getPreviousFileID(FileID FID) const;
1943
1944
1945
1946 FileID getNextFileID(FileID FID) const;
1947
1948
1949
1950
1951
1952
1953 FileID createFileIDImpl(SrcMgr::ContentCache &File, StringRef Filename,
1954 SourceLocation IncludePos,
1955 SrcMgr::CharacteristicKind DirCharacter, int LoadedID,
1956 SourceLocation::UIntTy LoadedOffset);
1957
1958 SrcMgr::ContentCache &getOrCreateContentCache(FileEntryRef SourceFile,
1959 bool isSystemFile = false);
1960
1961
1962 SrcMgr::ContentCache &
1963 createMemBufferContentCache(std::unique_ptr<llvm::MemoryBuffer> Buf);
1964
1965 FileID getFileIDSlow(SourceLocation::UIntTy SLocOffset) const;
1966 FileID getFileIDLocal(SourceLocation::UIntTy SLocOffset) const;
1967 FileID getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const;
1968
1969 SourceLocation getExpansionLocSlowCase(SourceLocation Loc) const;
1970 SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const;
1971 SourceLocation getFileLocSlowCase(SourceLocation Loc) const;
1972
1973 std::pair<FileID, unsigned>
1974 getDecomposedExpansionLocSlowCase(const SrcMgr::SLocEntry *E) const;
1975 std::pair<FileID, unsigned>
1976 getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
1977 unsigned Offset) const;
1978 void computeMacroArgsCache(MacroArgsMap &MacroArgsCache, FileID FID) const;
1979 void associateFileChunkWithMacroArgExp(MacroArgsMap &MacroArgsCache,
1980 FileID FID,
1981 SourceLocation SpellLoc,
1982 SourceLocation ExpansionLoc,
1983 unsigned ExpansionLength) const;
1984 void updateSlocUsageStats() const;
1985 };
1986
1987
1988 template<typename T>
1989 class BeforeThanCompare;
1990
1991
1992 template<>
1993 class BeforeThanCompare<SourceLocation> {
1994 SourceManager &SM;
1995
1996 public:
1997 explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {}
1998
1999 bool operator()(SourceLocation LHS, SourceLocation RHS) const {
2000 return SM.isBeforeInTranslationUnit(LHS, RHS);
2001 }
2002 };
2003
2004
2005 template<>
2006 class BeforeThanCompare<SourceRange> {
2007 SourceManager &SM;
2008
2009 public:
2010 explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {}
2011
2012 bool operator()(SourceRange LHS, SourceRange RHS) const {
2013 return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin());
2014 }
2015 };
2016
2017
2018
2019 class SourceManagerForFile {
2020 public:
2021
2022
2023 SourceManagerForFile(StringRef FileName, StringRef Content);
2024
2025 SourceManager &get() {
2026 assert(SourceMgr);
2027 return *SourceMgr;
2028 }
2029
2030 private:
2031
2032
2033
2034 std::unique_ptr<FileManager> FileMgr;
2035 std::unique_ptr<DiagnosticsEngine> Diagnostics;
2036 std::unique_ptr<SourceManager> SourceMgr;
2037 };
2038
2039 }
2040
2041 #endif