File indexing completed on 2026-05-10 08:36:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_BASIC_MODULE_H
0016 #define LLVM_CLANG_BASIC_MODULE_H
0017
0018 #include "clang/Basic/DirectoryEntry.h"
0019 #include "clang/Basic/FileEntry.h"
0020 #include "clang/Basic/SourceLocation.h"
0021 #include "llvm/ADT/ArrayRef.h"
0022 #include "llvm/ADT/DenseSet.h"
0023 #include "llvm/ADT/PointerIntPair.h"
0024 #include "llvm/ADT/STLExtras.h"
0025 #include "llvm/ADT/SetVector.h"
0026 #include "llvm/ADT/SmallVector.h"
0027 #include "llvm/ADT/StringMap.h"
0028 #include "llvm/ADT/StringRef.h"
0029 #include "llvm/ADT/iterator_range.h"
0030 #include <array>
0031 #include <cassert>
0032 #include <cstdint>
0033 #include <ctime>
0034 #include <iterator>
0035 #include <optional>
0036 #include <string>
0037 #include <utility>
0038 #include <variant>
0039 #include <vector>
0040
0041 namespace llvm {
0042
0043 class raw_ostream;
0044
0045 }
0046
0047 namespace clang {
0048
0049 class FileManager;
0050 class LangOptions;
0051 class ModuleMap;
0052 class TargetInfo;
0053
0054
0055 using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
0056
0057
0058 struct ASTFileSignature : std::array<uint8_t, 20> {
0059 using BaseT = std::array<uint8_t, 20>;
0060
0061 static constexpr size_t size = std::tuple_size<BaseT>::value;
0062
0063 ASTFileSignature(BaseT S = {{0}}) : BaseT(std::move(S)) {}
0064
0065 explicit operator bool() const { return *this != BaseT({{0}}); }
0066
0067
0068 uint64_t truncatedValue() const {
0069 uint64_t Value = 0;
0070 static_assert(sizeof(*this) >= sizeof(uint64_t), "No need to truncate.");
0071 for (unsigned I = 0; I < sizeof(uint64_t); ++I)
0072 Value |= static_cast<uint64_t>((*this)[I]) << (I * 8);
0073 return Value;
0074 }
0075
0076 static ASTFileSignature create(std::array<uint8_t, 20> Bytes) {
0077 return ASTFileSignature(std::move(Bytes));
0078 }
0079
0080 static ASTFileSignature createDISentinel() {
0081 ASTFileSignature Sentinel;
0082 Sentinel.fill(0xFF);
0083 return Sentinel;
0084 }
0085
0086 static ASTFileSignature createDummy() {
0087 ASTFileSignature Dummy;
0088 Dummy.fill(0x00);
0089 return Dummy;
0090 }
0091
0092 template <typename InputIt>
0093 static ASTFileSignature create(InputIt First, InputIt Last) {
0094 assert(std::distance(First, Last) == size &&
0095 "Wrong amount of bytes to create an ASTFileSignature");
0096
0097 ASTFileSignature Signature;
0098 std::copy(First, Last, Signature.begin());
0099 return Signature;
0100 }
0101 };
0102
0103
0104
0105
0106
0107 class ModuleConstructorTag {
0108 explicit ModuleConstructorTag() = default;
0109 friend ModuleMap;
0110 };
0111
0112
0113
0114
0115 class alignas(8) Module {
0116 public:
0117
0118 std::string Name;
0119
0120
0121 SourceLocation DefinitionLoc;
0122
0123
0124
0125
0126 enum ModuleKind {
0127
0128
0129 ModuleMapModule,
0130
0131
0132 ModuleHeaderUnit,
0133
0134
0135 ModuleInterfaceUnit,
0136
0137
0138 ModuleImplementationUnit,
0139
0140
0141 ModulePartitionInterface,
0142
0143
0144 ModulePartitionImplementation,
0145
0146
0147
0148 ExplicitGlobalModuleFragment,
0149
0150
0151 PrivateModuleFragment,
0152
0153
0154
0155
0156 ImplicitGlobalModuleFragment,
0157 };
0158
0159
0160 ModuleKind Kind = ModuleMapModule;
0161
0162
0163
0164 Module *Parent;
0165
0166
0167
0168
0169 OptionalDirectoryEntryRef Directory;
0170
0171
0172
0173 std::string PresumedModuleMapFile;
0174
0175
0176 std::variant<std::monostate, FileEntryRef, DirectoryEntryRef> Umbrella;
0177
0178
0179 ASTFileSignature Signature;
0180
0181
0182 std::string UmbrellaAsWritten;
0183
0184
0185 std::string UmbrellaRelativeToRootModuleDirectory;
0186
0187
0188
0189 std::string ExportAsModule;
0190
0191
0192 std::string APINotesFile;
0193
0194
0195 bool isNamedModule() const {
0196 switch (Kind) {
0197 case ModuleInterfaceUnit:
0198 case ModuleImplementationUnit:
0199 case ModulePartitionInterface:
0200 case ModulePartitionImplementation:
0201 case PrivateModuleFragment:
0202 return true;
0203 default:
0204 return false;
0205 }
0206 }
0207
0208
0209
0210 bool isGlobalModule() const {
0211 return isExplicitGlobalModule() || isImplicitGlobalModule();
0212 }
0213 bool isExplicitGlobalModule() const {
0214 return Kind == ExplicitGlobalModuleFragment;
0215 }
0216 bool isImplicitGlobalModule() const {
0217 return Kind == ImplicitGlobalModuleFragment;
0218 }
0219
0220 bool isPrivateModule() const { return Kind == PrivateModuleFragment; }
0221
0222 bool isModuleMapModule() const { return Kind == ModuleMapModule; }
0223
0224 private:
0225
0226 std::vector<Module *> SubModules;
0227
0228
0229
0230 mutable llvm::StringMap<unsigned> SubModuleIndex;
0231
0232
0233
0234 OptionalFileEntryRef ASTFile;
0235
0236
0237 llvm::SmallSetVector<FileEntryRef, 2> TopHeaders;
0238
0239
0240 std::vector<std::string> TopHeaderNames;
0241
0242
0243 mutable llvm::DenseSet<const Module*> VisibleModulesCache;
0244
0245
0246 unsigned VisibilityID;
0247
0248 public:
0249 enum HeaderKind {
0250 HK_Normal,
0251 HK_Textual,
0252 HK_Private,
0253 HK_PrivateTextual,
0254 HK_Excluded
0255 };
0256
0257
0258 struct Header {
0259 std::string NameAsWritten;
0260 std::string PathRelativeToRootModuleDirectory;
0261 FileEntryRef Entry;
0262 };
0263
0264 private:
0265 static const int NumHeaderKinds = HK_Excluded + 1;
0266
0267
0268 unsigned HeaderKindBeginIndex[NumHeaderKinds + 1] = {};
0269 SmallVector<Header, 2> HeadersStorage;
0270
0271 public:
0272 ArrayRef<Header> getAllHeaders() const { return HeadersStorage; }
0273 ArrayRef<Header> getHeaders(HeaderKind HK) const {
0274 assert(HK < NumHeaderKinds && "Invalid Module::HeaderKind");
0275 auto BeginIt = HeadersStorage.begin() + HeaderKindBeginIndex[HK];
0276 auto EndIt = HeadersStorage.begin() + HeaderKindBeginIndex[HK + 1];
0277 return {BeginIt, EndIt};
0278 }
0279 void addHeader(HeaderKind HK, Header H) {
0280 assert(HK < NumHeaderKinds && "Invalid Module::HeaderKind");
0281 auto EndIt = HeadersStorage.begin() + HeaderKindBeginIndex[HK + 1];
0282 HeadersStorage.insert(EndIt, std::move(H));
0283 for (unsigned HKI = HK + 1; HKI != NumHeaderKinds + 1; ++HKI)
0284 ++HeaderKindBeginIndex[HKI];
0285 }
0286
0287
0288 struct DirectoryName {
0289 std::string NameAsWritten;
0290 std::string PathRelativeToRootModuleDirectory;
0291 DirectoryEntryRef Entry;
0292 };
0293
0294
0295
0296 struct UnresolvedHeaderDirective {
0297 HeaderKind Kind = HK_Normal;
0298 SourceLocation FileNameLoc;
0299 std::string FileName;
0300 bool IsUmbrella = false;
0301 bool HasBuiltinHeader = false;
0302 std::optional<off_t> Size;
0303 std::optional<time_t> ModTime;
0304 };
0305
0306
0307
0308 SmallVector<UnresolvedHeaderDirective, 1> UnresolvedHeaders;
0309
0310
0311
0312 SmallVector<UnresolvedHeaderDirective, 1> MissingHeaders;
0313
0314 struct Requirement {
0315 std::string FeatureName;
0316 bool RequiredState;
0317 };
0318
0319
0320
0321
0322
0323 SmallVector<Requirement, 2> Requirements;
0324
0325
0326 Module *ShadowingModule = nullptr;
0327
0328
0329
0330
0331 LLVM_PREFERRED_TYPE(bool)
0332 unsigned IsUnimportable : 1;
0333
0334
0335 LLVM_PREFERRED_TYPE(bool)
0336 unsigned HasIncompatibleModuleFile : 1;
0337
0338
0339
0340
0341
0342 LLVM_PREFERRED_TYPE(bool)
0343 unsigned IsAvailable : 1;
0344
0345
0346 LLVM_PREFERRED_TYPE(bool)
0347 unsigned IsFromModuleFile : 1;
0348
0349
0350 LLVM_PREFERRED_TYPE(bool)
0351 unsigned IsFramework : 1;
0352
0353
0354 LLVM_PREFERRED_TYPE(bool)
0355 unsigned IsExplicit : 1;
0356
0357
0358
0359 LLVM_PREFERRED_TYPE(bool)
0360 unsigned IsSystem : 1;
0361
0362
0363
0364
0365 LLVM_PREFERRED_TYPE(bool)
0366 unsigned IsExternC : 1;
0367
0368
0369 LLVM_PREFERRED_TYPE(bool)
0370 unsigned IsInferred : 1;
0371
0372
0373
0374
0375
0376 LLVM_PREFERRED_TYPE(bool)
0377 unsigned InferSubmodules : 1;
0378
0379
0380
0381 LLVM_PREFERRED_TYPE(bool)
0382 unsigned InferExplicitSubmodules : 1;
0383
0384
0385
0386 LLVM_PREFERRED_TYPE(bool)
0387 unsigned InferExportWildcard : 1;
0388
0389
0390
0391
0392
0393
0394 LLVM_PREFERRED_TYPE(bool)
0395 unsigned ConfigMacrosExhaustive : 1;
0396
0397
0398
0399 LLVM_PREFERRED_TYPE(bool)
0400 unsigned NoUndeclaredIncludes : 1;
0401
0402
0403
0404 LLVM_PREFERRED_TYPE(bool)
0405 unsigned ModuleMapIsPrivate : 1;
0406
0407
0408
0409 LLVM_PREFERRED_TYPE(bool)
0410 unsigned NamedModuleHasInit : 1;
0411
0412
0413
0414 enum NameVisibilityKind {
0415
0416 Hidden,
0417
0418 AllVisible
0419 };
0420
0421
0422 NameVisibilityKind NameVisibility;
0423
0424
0425 SourceLocation InferredSubmoduleLoc;
0426
0427
0428
0429 llvm::SmallSetVector<Module *, 2> Imports;
0430
0431
0432
0433 llvm::SmallSetVector<Module *, 2> AffectingClangModules;
0434
0435
0436
0437
0438
0439 using ExportDecl = llvm::PointerIntPair<Module *, 1, bool>;
0440
0441
0442 SmallVector<ExportDecl, 2> Exports;
0443
0444
0445
0446 struct UnresolvedExportDecl {
0447
0448 SourceLocation ExportLoc;
0449
0450
0451 ModuleId Id;
0452
0453
0454
0455
0456 bool Wildcard;
0457 };
0458
0459
0460 SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;
0461
0462
0463 SmallVector<Module *, 2> DirectUses;
0464
0465
0466 SmallVector<ModuleId, 2> UnresolvedDirectUses;
0467
0468
0469
0470 llvm::SmallSetVector<const Module *, 2> UndeclaredUses;
0471
0472
0473
0474 struct LinkLibrary {
0475 LinkLibrary() = default;
0476 LinkLibrary(const std::string &Library, bool IsFramework)
0477 : Library(Library), IsFramework(IsFramework) {}
0478
0479
0480
0481
0482
0483 std::string Library;
0484
0485
0486 bool IsFramework = false;
0487 };
0488
0489
0490
0491 llvm::SmallVector<LinkLibrary, 2> LinkLibraries;
0492
0493
0494
0495 bool UseExportAsModuleLinkName = false;
0496
0497
0498
0499 std::vector<std::string> ConfigMacros;
0500
0501
0502 struct UnresolvedConflict {
0503
0504 ModuleId Id;
0505
0506
0507 std::string Message;
0508 };
0509
0510
0511
0512 std::vector<UnresolvedConflict> UnresolvedConflicts;
0513
0514
0515 struct Conflict {
0516
0517 Module *Other;
0518
0519
0520 std::string Message;
0521 };
0522
0523
0524 std::vector<Conflict> Conflicts;
0525
0526
0527 Module(ModuleConstructorTag, StringRef Name, SourceLocation DefinitionLoc,
0528 Module *Parent, bool IsFramework, bool IsExplicit,
0529 unsigned VisibilityID);
0530
0531 ~Module();
0532
0533
0534 bool isUnimportable() const { return IsUnimportable; }
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549 bool isUnimportable(const LangOptions &LangOpts, const TargetInfo &Target,
0550 Requirement &Req, Module *&ShadowingModule) const;
0551
0552
0553 bool isForBuilding(const LangOptions &LangOpts) const;
0554
0555
0556
0557 bool isAvailable() const { return IsAvailable; }
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576 bool isAvailable(const LangOptions &LangOpts,
0577 const TargetInfo &Target,
0578 Requirement &Req,
0579 UnresolvedHeaderDirective &MissingHeader,
0580 Module *&ShadowingModule) const;
0581
0582
0583 bool isSubModule() const { return Parent != nullptr; }
0584
0585
0586
0587
0588
0589
0590
0591 bool isSubModuleOf(const Module *Other) const;
0592
0593
0594
0595
0596 bool isPartOfFramework() const {
0597 for (const Module *Mod = this; Mod; Mod = Mod->Parent)
0598 if (Mod->IsFramework)
0599 return true;
0600
0601 return false;
0602 }
0603
0604
0605
0606 bool isSubFramework() const {
0607 return IsFramework && Parent && Parent->isPartOfFramework();
0608 }
0609
0610
0611
0612 void setParent(Module *M) {
0613 assert(!Parent);
0614 Parent = M;
0615 Parent->SubModules.push_back(this);
0616 }
0617
0618
0619 bool isHeaderLikeModule() const {
0620 return isModuleMapModule() || isHeaderUnit();
0621 }
0622
0623
0624 bool isModulePartition() const {
0625 return Kind == ModulePartitionInterface ||
0626 Kind == ModulePartitionImplementation;
0627 }
0628
0629
0630 bool isModulePartitionImplementation() const {
0631 return Kind == ModulePartitionImplementation;
0632 }
0633
0634
0635 bool isModuleImplementation() const {
0636 return Kind == ModuleImplementationUnit;
0637 }
0638
0639
0640 bool isHeaderUnit() const { return Kind == ModuleHeaderUnit; }
0641
0642 bool isInterfaceOrPartition() const {
0643 return Kind == ModuleInterfaceUnit || isModulePartition();
0644 }
0645
0646
0647 bool isNamedModuleUnit() const {
0648 return isInterfaceOrPartition() || isModuleImplementation();
0649 }
0650
0651 bool isModuleInterfaceUnit() const {
0652 return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface;
0653 }
0654
0655 bool isNamedModuleInterfaceHasInit() const { return NamedModuleHasInit; }
0656
0657
0658 StringRef getPrimaryModuleInterfaceName() const {
0659
0660
0661
0662
0663
0664
0665 if (isGlobalModule())
0666 return "<global>";
0667
0668 if (isModulePartition()) {
0669 auto pos = Name.find(':');
0670 return StringRef(Name.data(), pos);
0671 }
0672
0673 if (isPrivateModule())
0674 return getTopLevelModuleName();
0675
0676 return Name;
0677 }
0678
0679
0680
0681
0682
0683 std::string getFullModuleName(bool AllowStringLiterals = false) const;
0684
0685
0686
0687
0688
0689 bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const;
0690
0691
0692
0693 Module *getTopLevelModule() {
0694 return const_cast<Module *>(
0695 const_cast<const Module *>(this)->getTopLevelModule());
0696 }
0697
0698
0699
0700 const Module *getTopLevelModule() const;
0701
0702
0703 StringRef getTopLevelModuleName() const {
0704 return getTopLevelModule()->Name;
0705 }
0706
0707
0708 OptionalFileEntryRef getASTFile() const {
0709 return getTopLevelModule()->ASTFile;
0710 }
0711
0712
0713 void setASTFile(OptionalFileEntryRef File) {
0714 assert((!getASTFile() || getASTFile() == File) && "file path changed");
0715 getTopLevelModule()->ASTFile = File;
0716 }
0717
0718
0719 std::optional<DirectoryName> getUmbrellaDirAsWritten() const {
0720 if (const auto *Dir = std::get_if<DirectoryEntryRef>(&Umbrella))
0721 return DirectoryName{UmbrellaAsWritten,
0722 UmbrellaRelativeToRootModuleDirectory, *Dir};
0723 return std::nullopt;
0724 }
0725
0726
0727 std::optional<Header> getUmbrellaHeaderAsWritten() const {
0728 if (const auto *Hdr = std::get_if<FileEntryRef>(&Umbrella))
0729 return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory,
0730 *Hdr};
0731 return std::nullopt;
0732 }
0733
0734
0735
0736
0737 OptionalDirectoryEntryRef getEffectiveUmbrellaDir() const;
0738
0739
0740 void addTopHeader(FileEntryRef File);
0741
0742
0743 void addTopHeaderFilename(StringRef Filename) {
0744 TopHeaderNames.push_back(std::string(Filename));
0745 }
0746
0747
0748 ArrayRef<FileEntryRef> getTopHeaders(FileManager &FileMgr);
0749
0750
0751
0752 bool directlyUses(const Module *Requested);
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768 void addRequirement(StringRef Feature, bool RequiredState,
0769 const LangOptions &LangOpts,
0770 const TargetInfo &Target);
0771
0772
0773 void markUnavailable(bool Unimportable);
0774
0775
0776
0777
0778 Module *findSubmodule(StringRef Name) const;
0779
0780
0781
0782
0783
0784 Module *getGlobalModuleFragment() const;
0785
0786
0787
0788
0789
0790 Module *getPrivateModuleFragment() const;
0791
0792
0793
0794
0795
0796
0797
0798 bool isModuleVisible(const Module *M) const {
0799 if (VisibleModulesCache.empty())
0800 buildVisibleModulesCache();
0801 return VisibleModulesCache.count(M);
0802 }
0803
0804 unsigned getVisibilityID() const { return VisibilityID; }
0805
0806 using submodule_iterator = std::vector<Module *>::iterator;
0807 using submodule_const_iterator = std::vector<Module *>::const_iterator;
0808
0809 llvm::iterator_range<submodule_iterator> submodules() {
0810 return llvm::make_range(SubModules.begin(), SubModules.end());
0811 }
0812 llvm::iterator_range<submodule_const_iterator> submodules() const {
0813 return llvm::make_range(SubModules.begin(), SubModules.end());
0814 }
0815
0816
0817
0818
0819
0820 void getExportedModules(SmallVectorImpl<Module *> &Exported) const;
0821
0822 static StringRef getModuleInputBufferName() {
0823 return "<module-includes>";
0824 }
0825
0826
0827 void print(raw_ostream &OS, unsigned Indent = 0, bool Dump = false) const;
0828
0829
0830 void dump() const;
0831
0832 private:
0833 void buildVisibleModulesCache() const;
0834 };
0835
0836
0837 class VisibleModuleSet {
0838 public:
0839 VisibleModuleSet() = default;
0840 VisibleModuleSet(VisibleModuleSet &&O)
0841 : ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) {
0842 O.ImportLocs.clear();
0843 ++O.Generation;
0844 }
0845
0846
0847
0848 VisibleModuleSet &operator=(VisibleModuleSet &&O) {
0849 ImportLocs = std::move(O.ImportLocs);
0850 O.ImportLocs.clear();
0851 ++O.Generation;
0852 ++Generation;
0853 return *this;
0854 }
0855
0856
0857
0858 unsigned getGeneration() const { return Generation; }
0859
0860
0861 bool isVisible(const Module *M) const {
0862 return getImportLoc(M).isValid();
0863 }
0864
0865
0866 SourceLocation getImportLoc(const Module *M) const {
0867 return M->getVisibilityID() < ImportLocs.size()
0868 ? ImportLocs[M->getVisibilityID()]
0869 : SourceLocation();
0870 }
0871
0872
0873
0874 using VisibleCallback = llvm::function_ref<void(Module *M)>;
0875
0876
0877
0878
0879 using ConflictCallback =
0880 llvm::function_ref<void(ArrayRef<Module *> Path, Module *Conflict,
0881 StringRef Message)>;
0882
0883
0884 void setVisible(Module *M, SourceLocation Loc,
0885 VisibleCallback Vis = [](Module *) {},
0886 ConflictCallback Cb = [](ArrayRef<Module *>, Module *,
0887 StringRef) {});
0888 private:
0889
0890
0891 std::vector<SourceLocation> ImportLocs;
0892
0893
0894 unsigned Generation = 0;
0895 };
0896
0897 }
0898
0899 #endif