28#include "llvm/ADT/DenseMap.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/SmallPtrSet.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringMap.h"
33#include "llvm/ADT/StringRef.h"
34#include "llvm/ADT/StringSwitch.h"
35#include "llvm/Support/Compiler.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/Path.h"
38#include "llvm/Support/VirtualFileSystem.h"
39#include "llvm/Support/raw_ostream.h"
44#include <system_error>
51void ModuleMapCallbacks::anchor() {}
54 auto PendingLinkAs = PendingLinkAsModule.find(Mod->
Name);
55 if (PendingLinkAs != PendingLinkAsModule.end()) {
56 for (
auto &Name : PendingLinkAs->second) {
59 M->UseExportAsModuleLinkName =
true;
84 llvm_unreachable(
"unknown header role");
101 llvm_unreachable(
"unknown header kind");
109ModuleMap::resolveExport(
Module *Mod,
111 bool Complain)
const {
114 assert(
Unresolved.Wildcard &&
"Invalid unresolved export");
127 bool Complain)
const {
132 Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
139 for (
unsigned I = 1, N = Id.size(); I != N; ++I) {
143 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
144 << Id[I].first << Context->getFullModuleName()
145 << SourceRange(Id[0].second, Id[I-1].second);
162 for (; Mod; Mod = Mod->
Parent) {
164 Paths.push_back(Mod->
Name);
171 for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
172 llvm::sys::path::append(Path,
"Frameworks", Framework +
".framework");
180 SmallString<128> FullPathName(Directory->getName());
184 expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
192 unsigned FullPathLength = FullPathName.size();
194 unsigned RelativePathLength = RelativePathName.size();
197 llvm::sys::path::append(RelativePathName,
"Headers", Header.
FileName);
198 llvm::sys::path::append(FullPathName, RelativePathName);
199 if (
auto File = GetFile(FullPathName))
209 RelativePathName.clear();
211 RelativePathName.resize(RelativePathLength);
212 FullPathName.resize(FullPathLength);
213 llvm::sys::path::append(RelativePathName,
"PrivateHeaders",
215 llvm::sys::path::append(FullPathName, RelativePathName);
216 return GetFile(FullPathName);
219 if (llvm::sys::path::is_absolute(Header.
FileName)) {
220 RelativePathName.clear();
226 return GetFrameworkFile();
229 llvm::sys::path::append(RelativePathName, Header.
FileName);
230 llvm::sys::path::append(FullPathName, RelativePathName);
231 auto NormalHdrFile = GetFile(FullPathName);
233 if (!NormalHdrFile && Directory->getName().ends_with(
".framework")) {
237 FullPathName.assign(Directory->getName());
238 RelativePathName.clear();
239 if (GetFrameworkFile()) {
241 diag::warn_mmap_incomplete_framework_module_declaration)
243 NeedsFramework =
true;
248 return NormalHdrFile;
255 return llvm::StringSwitch<bool>(
FileName)
256 .Case(
"float.h",
true)
257 .Case(
"iso646.h",
true)
258 .Case(
"limits.h",
true)
259 .Case(
"stdalign.h",
true)
260 .Case(
"stdarg.h",
true)
261 .Case(
"stdatomic.h",
true)
262 .Case(
"stdbool.h",
true)
263 .Case(
"stdckdint.h",
true)
264 .Case(
"stdcountof.h",
true)
265 .Case(
"stddef.h",
true)
266 .Case(
"stdint.h",
true)
267 .Case(
"tgmath.h",
true)
268 .Case(
"unwind.h",
true)
275 return llvm::StringSwitch<bool>(ModuleName)
276 .Case(
"_Builtin_float",
true)
277 .Case(
"_Builtin_inttypes",
true)
278 .Case(
"_Builtin_iso646",
true)
279 .Case(
"_Builtin_limits",
true)
280 .Case(
"_Builtin_stdalign",
true)
281 .Case(
"_Builtin_stdarg",
true)
282 .Case(
"_Builtin_stdatomic",
true)
283 .Case(
"_Builtin_stdbool",
true)
284 .Case(
"_Builtin_stddef",
true)
285 .Case(
"_Builtin_stdint",
true)
286 .Case(
"_Builtin_stdnoreturn",
true)
287 .Case(
"_Builtin_tgmath",
true)
288 .Case(
"_Builtin_unwind",
true)
292void ModuleMap::resolveHeader(
Module *Mod,
294 bool &NeedsFramework) {
295 SmallString<128> RelativePathName;
297 findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
299 const DirectoryEntry *UmbrellaDir = &
File->getDir().getDirEntry();
300 if (
Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
301 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
302 << UmbrellaMod->getFullModuleName();
308 Module::Header H = {Header.
FileName, std::string(RelativePathName),
331bool ModuleMap::resolveAsBuiltinHeader(
334 llvm::sys::path::is_absolute(Header.
FileName) ||
336 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->
Directory ||
343 SmallString<128> Path;
344 llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.
FileName);
345 auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
358 : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
359 HeaderInfo(HeaderInfo) {
365 assert((!this->Target || this->Target == &Target) &&
366 "Improper target override");
367 this->Target = &Target;
381 Buffer.push_back(
'_');
382 Buffer.reserve(Buffer.size() + Name.size());
383 for (
unsigned I = 0, N = Name.size(); I != N; ++I) {
385 Buffer.push_back(Name[I]);
387 Buffer.push_back(
'_');
390 Name = StringRef(Buffer.data(), Buffer.size());
393 while (llvm::StringSwitch<bool>(Name)
396#include
"clang/Basic/TokenKinds.def"
398 if (Name.data() != Buffer.data())
399 Buffer.append(Name.begin(), Name.end());
400 Buffer.push_back(
'_');
401 Name = StringRef(Buffer.data(), Buffer.size());
408 return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
414 return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
419ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(
FileEntryRef File) {
421 HeadersMap::iterator Known = Headers.find(
File);
425 return Headers.find(
File);
432 if (UmbrellaDirs.empty())
441 StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
446 auto KnownDir = UmbrellaDirs.find(*Dir);
447 if (KnownDir != UmbrellaDirs.end())
450 IntermediateDirs.push_back(*Dir);
453 DirName = llvm::sys::path::parent_path(DirName);
458 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
471 bool IsPrivate =
false;
475 for (
auto Hs : HeaderList)
476 IsPrivate |= llvm::any_of(
478 assert(IsPrivate &&
"inconsistent headers and roles");
489 bool RequestingModuleIsModuleInterface,
492 if (RequestingModule) {
497 HeadersMap::iterator Known = findKnownHeader(
File);
499 diagnoseDuplicateHeaderOwnership(FilenameLoc, Filename,
File, Known);
505 bool IsPublicForMainPrivateModule =
false;
506 if (TopLevelRequestingModule != TopLevelSourceModule) {
514 if (TopLevelRequestingModule && TopLevelSourceModule &&
515 llvm::StringRef(TopLevelSourceModule->
Name)
517 llvm::StringRef(TopLevelSourceModule->
Name)
519 TopLevelRequestingModule->
Name) {
520 IsPublicForMainPrivateModule =
true;
526 bool Excluded =
false;
527 bool UsedByPrivateModule =
false;
529 Module *NotUsed =
nullptr;
531 if (Known != Headers.end()) {
547 if (RequestingModule && LangOpts.ModulesDeclUse &&
550 if (IsPublicForMainPrivateModule) {
551 UsedByPrivateModule = SourceModule->directlyUses(Header.
getModule());
565 Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
572 if (UsedByPrivateModule) {
573 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_private)
577 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
584 if (Excluded || isHeaderInUmbrellaDirs(
File))
589 if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
590 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
592 }
else if (RequestingModule && RequestingModuleIsModuleInterface &&
593 LangOpts.isCompilingModule()) {
596 diag::warn_non_modular_include_in_framework_module :
597 diag::warn_non_modular_include_in_module;
603void ModuleMap::diagnoseDuplicateHeaderOwnership(
SourceLocation FilenameLoc,
606 HeadersMap::iterator Known) {
607 if (Known == Headers.end())
610 if (Diags.
isIgnored(diag::warn_mmap_duplicate_header_ownership, FilenameLoc))
614 if (!DiagnosedDuplicateHeaders.insert(&
File.getFileEntry()).second)
627 for (
const KnownHeader &H : Known->second) {
631 if (!SeenTopLevel.insert(TopLevel).second)
633 auto It = HeaderOwnerLocs.find({&
File.getFileEntry(), H.getModule()});
634 SourceLocation OwnerLoc =
635 It != HeaderOwnerLocs.end() ? It->second : SourceLocation();
636 OwningModules.push_back({TopLevel, OwnerLoc,
false});
641 if (OwningModules.empty())
649 SmallVector<DirectoryEntryRef, 2> IntermediateDirs;
651 findHeaderInUmbrellaDirs(
File, IntermediateDirs)) {
655 if (SeenTopLevel.insert(TopLevel).second) {
658 llvm::any_of(Known->second, [TopLevel](
const KnownHeader &H) {
659 return H.getModule()->getTopLevelModule() == TopLevel &&
660 H.getRole() == ExcludedHeader;
663 OwningModules.push_back({TopLevel,
670 if (OwningModules.size() < 2)
673 Diags.Report(FilenameLoc, diag::warn_mmap_duplicate_header_ownership)
675 for (
const auto &Owner : OwningModules) {
676 unsigned NoteID = Owner.IsUmbrella
677 ? diag::note_mmap_header_covered_by_umbrella
678 : diag::note_mmap_header_owned_by;
679 Diags.Report(Owner.Loc, NoteID) << Owner.Mod->getFullModuleName();
713 bool AllowExcluded) {
720 HeadersMap::iterator Known = findKnownHeader(
File);
721 if (Known != Headers.end()) {
730 return MakeResult(H);
734 return MakeResult(
Result);
737 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(
File));
741 Module *M, std::string NameAsWritten,
744 Header.
FileName = std::move(NameAsWritten);
747 return findHeader(M, Header, RelativePathName, NeedsFramework);
752 assert(!Headers.count(
File) &&
"already have a module for this header");
755 KnownHeader H = findHeaderInUmbrellaDirs(
File, SkippedDirs);
763 UmbrellaModule = UmbrellaModule->
Parent;
777 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
783 UmbrellaDirs[SkippedDir] =
Result;
794 llvm::sys::path::stem(
File.getName()), NameBuf);
807 for (
unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
808 UmbrellaDirs[SkippedDirs[I]] =
Result;
812 Headers[
File].push_back(Header);
821 HeadersMap::iterator Known = findKnownHeader(
File);
822 if (Known != Headers.end())
823 return Known->second;
825 if (findOrCreateModuleForHeaderInUmbrellaDir(
File))
826 return Headers.find(
File)->second;
835 auto It = Headers.find(
File);
836 if (It == Headers.end())
848 HeadersMap::const_iterator Known = Headers.find(Header);
849 if (Known != Headers.end()) {
851 I = Known->second.begin(),
852 E = Known->second.end();
858 if (I->isAvailable() &&
859 (!RequestingModule ||
876 StringRef DirName = Dir->
getName();
878 auto IsUnavailable = [&](
const Module *M) {
886 auto KnownDir = UmbrellaDirs.find(*Dir);
887 if (KnownDir != UmbrellaDirs.end()) {
889 if (IsUnavailable(
Found))
897 UmbrellaModule = UmbrellaModule->
Parent;
904 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
908 if (IsUnavailable(
Found))
915 llvm::sys::path::stem(Header.
getName()),
922 return IsUnavailable(
Found);
925 SkippedDirs.push_back(*Dir);
928 DirName = llvm::sys::path::parent_path(DirName);
933 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
940 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
941 if (Known != Modules.end())
942 return Known->getValue();
958 if (
Result->InferExportWildcard)
965 for(; Context; Context = Context->Parent) {
978 return Context->findSubmodule(Name);
987 return std::make_pair(Sub.getExisting(),
false);
991 return std::make_pair(M,
true);
995 bool IsFramework,
bool IsExplicit) {
997 "Creating duplicate submodule");
1001 IsFramework, IsExplicit, NumCreatedModules++);
1003 if (LangOpts.CurrentModule == Name)
1006 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1015 true, NumCreatedModules++);
1020 PendingSubmodules.emplace_back(
Result);
1027 assert(Parent &&
"We should only create an implicit global module fragment "
1028 "in a module purview");
1032 auto *
Result =
new (ModulesAlloc.Allocate())
1034 false,
false, NumCreatedModules++);
1044 true, NumCreatedModules++);
1051 auto *
Result =
new (ModulesAlloc.Allocate())
1053 false, NumCreatedModules++);
1057 for (
auto &Submodule : PendingSubmodules)
1058 Submodule->setParent(
Result);
1059 PendingSubmodules.clear();
1065 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1066 assert(!Modules[Name] &&
"redefining existing module");
1070 Modules[Name] = SourceModule =
Result;
1074 auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
1075 assert(MainFile &&
"no input file for module interface");
1083 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1086 "creating implementation module without an interface");
1091 StringRef IName =
".ImplementationUnit";
1092 assert(!Modules[IName] &&
"multiple implementation units?");
1096 Modules[IName] = SourceModule =
Result;
1099 assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
1100 "no input file for module implementation");
1107 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1108 assert(!Modules[Name] &&
"redefining existing module");
1110 auto *
Result =
new (ModulesAlloc.Allocate())
1112 false, NumCreatedModules++);
1114 Modules[Name] = SourceModule =
Result;
1122 assert(Mod->
IsFramework &&
"Can only infer linking for framework modules");
1124 "Can only infer linking for top-level frameworks");
1126 StringRef FrameworkName(Mod->
Name);
1127 FrameworkName.consume_back(
"_Private");
1133 bool IsSystem,
Module *Parent) {
1136 return inferFrameworkModule(FrameworkDir, Attrs, Parent);
1140 Attributes Attrs,
Module *Parent) {
1145 StringRef FrameworkDirName =
1146 SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
1153 llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
1166 bool canInfer =
false;
1167 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
1169 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
1170 if (
auto ParentDir =
FileMgr.getOptionalDirectoryRef(Parent)) {
1173 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1174 inferred = InferredDirectories.find(*ParentDir);
1175 if (inferred == InferredDirectories.end()) {
1178 bool IsFrameworkDir = Parent.ends_with(
".framework");
1186 inferred = InferredDirectories.find(*ParentDir);
1189 if (inferred == InferredDirectories.end())
1190 inferred = InferredDirectories.insert(
1191 std::make_pair(*ParentDir, InferredDirectory())).first;
1194 if (inferred->second.InferModules) {
1197 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1199 !llvm::is_contained(inferred->second.ExcludedModules, Name);
1201 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1202 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1203 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1204 Attrs.NoUndeclaredIncludes |=
1205 inferred->second.Attrs.NoUndeclaredIncludes;
1206 ModuleMapFID = inferred->second.ModuleMapFID;
1219 SmallString<128> UmbrellaName = FrameworkDir.
getName();
1220 llvm::sys::path::append(UmbrellaName,
"Headers", ModuleName +
".h");
1226 if (!UmbrellaHeader)
1230 Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1231 true,
false, NumCreatedModules++);
1234 if (LangOpts.CurrentModule == ModuleName)
1236 Modules[ModuleName] =
Result;
1237 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1240 Result->IsSystem |= Attrs.IsSystem;
1241 Result->IsExternC |= Attrs.IsExternC;
1242 Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1243 Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1244 Result->Directory = FrameworkDir;
1247 StringRef RelativePath = UmbrellaName.str().substr(
1248 Result->getTopLevelModule()->Directory->getName().size());
1249 RelativePath = llvm::sys::path::relative_path(RelativePath);
1259 Result->InferSubmodules =
true;
1260 Result->InferExportWildcard =
true;
1264 SmallString<128> SubframeworksDirName = FrameworkDir.
getName();
1265 llvm::sys::path::append(SubframeworksDirName,
"Frameworks");
1266 llvm::sys::path::native(SubframeworksDirName);
1268 for (llvm::vfs::directory_iterator
1269 Dir = FS.dir_begin(SubframeworksDirName, EC),
1271 Dir != DirEnd && !EC; Dir.increment(EC)) {
1272 if (!StringRef(Dir->path()).ends_with(
".framework"))
1280 StringRef SubframeworkDirName =
1282 bool FoundParent =
false;
1286 = llvm::sys::path::parent_path(SubframeworkDirName);
1287 if (SubframeworkDirName.empty())
1292 if (*SubDir == FrameworkDir) {
1303 inferFrameworkModule(*SubframeworkDir, Attrs,
Result);
1309 if (!
Result->isSubFramework())
1316 Module *ShadowingModule) {
1321 IsFramework,
false, NumCreatedModules++);
1322 Result->ShadowingModule = ShadowingModule;
1323 Result->markUnavailable(
true);
1324 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1325 ShadowModules.push_back(
Result);
1332 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1335 HeaderOwnerLocs[{&UmbrellaHeader.
getFileEntry(), Mod}] = Loc;
1340 PathRelativeToRootModuleDirectory.str();
1341 UmbrellaDirs[UmbrellaHeader.
getDir()] = Mod;
1344 for (
const auto &Cb : Callbacks)
1345 Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1350 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1355 PathRelativeToRootModuleDirectory.str();
1356 UmbrellaDirs[UmbrellaDir] = Mod;
1359void ModuleMap::addUnresolvedHeader(
Module *Mod,
1361 bool &NeedsFramework) {
1364 if (resolveAsBuiltinHeader(Mod, Header)) {
1383 LazyHeadersByModTime[*Header.
ModTime].push_back(Mod);
1385 LazyHeadersBySize[*Header.
Size].push_back(Mod);
1392 resolveHeader(Mod, Header, NeedsFramework);
1396 auto BySize = LazyHeadersBySize.find(
File->getSize());
1397 if (BySize != LazyHeadersBySize.end()) {
1398 for (
auto *M : BySize->second)
1400 LazyHeadersBySize.erase(BySize);
1403 auto ByModTime = LazyHeadersByModTime.find(
File->getModificationTime());
1404 if (ByModTime != LazyHeadersByModTime.end()) {
1405 for (
auto *M : ByModTime->second)
1407 LazyHeadersByModTime.erase(ByModTime);
1412 Module *Mod, std::optional<const FileEntry *>
File)
const {
1413 bool NeedsFramework =
false;
1415 const auto Size =
File ? (*File)->getSize() : 0;
1416 const auto ModTime =
File ? (*File)->getModificationTime() : 0;
1420 (Header.
Size && Header.
Size != Size)))
1421 NewHeaders.push_back(Header);
1425 const_cast<ModuleMap *
>(
this)->resolveHeader(Mod, Header, NeedsFramework);
1440 auto &HeaderList = Headers[HeaderEntry];
1441 if (llvm::is_contained(HeaderList, KH))
1445 HeaderOwnerLocs[{&HeaderEntry.
getFileEntry(), Mod}] = Loc;
1447 HeaderList.push_back(KH);
1450 bool isCompilingModuleHeader = Mod->
isForBuilding(LangOpts);
1451 if (!Imported || isCompilingModuleHeader) {
1454 HeaderInfo.MarkFileModuleHeader(HeaderEntry,
Role, isCompilingModuleHeader);
1458 for (
const auto &Cb : Callbacks)
1459 Cb->moduleMapAddHeader(HeaderEntry.
getName());
1463 bool ImplicitlyDiscovered,
1466 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
1467 Known = ParsedModuleMap.find(
File);
1468 if (Known != ParsedModuleMap.end())
1469 return Known->second ==
nullptr;
1472 if (ID.isInvalid()) {
1473 FileID &LocalFID = ModuleMapLocalFileID[
File];
1475 auto FileCharacter =
1477 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
1482 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
1484 ParsedModuleMap[
File] =
nullptr;
1488 Diags.Report(diag::remark_mmap_parse) <<
File.getName();
1490 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered,
nullptr);
1493 ParsedModuleMap[
File] =
nullptr;
1497 ParsedModuleMaps.push_back(
1498 std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));
1500 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
1503 for (
const auto &
Decl : MD.Decls) {
1504 std::visit(llvm::makeVisitor(
1507 if (SubMD.
Id.front().first ==
"*")
1509 CollectExternDecls(SubMD);
1512 PendingExternalModuleMaps.push_back(&EMD);
1522 std::visit(llvm::makeVisitor(
1528 ParsedModules[StringRef(MD.
Id.front().first)];
1529 ModuleDecls.push_back(std::pair(&MMF, &MD));
1530 CollectExternDecls(MD);
1533 PendingExternalModuleMaps.push_back(&EMD);
1539 StringRef FileNameRef = EMD->Path;
1541 if (llvm::sys::path::is_relative(FileNameRef)) {
1542 ModuleMapFileName += Dir.
getName();
1543 llvm::sys::path::append(ModuleMapFileName, EMD->Path);
1544 FileNameRef = ModuleMapFileName;
1548 SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {
1550 EFile->getDir(),
FileID(), ExternModuleLoc);
1554 ParsedModuleMap[
File] = &MMF;
1556 for (
const auto &Cb : Callbacks)
1563 for (
const auto &Entry : ParsedModules)
1581 assert(InferredModuleAllowedBy.count(M) &&
"missing inferred module map");
1582 return InferredModuleAllowedBy.find(M)->second;
1594 InferredModuleAllowedBy[M] = ModMapFID;
1599 StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1603 if (llvm::sys::path::filename(Dir) ==
"Modules") {
1604 StringRef Parent = llvm::sys::path::parent_path(Dir);
1605 if (Parent.ends_with(
".framework"))
1612 return llvm::errorToErrorCode(DirEntry.takeError());
1616 if (CanonicalDir != Dir)
1617 llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1625 llvm::sys::path::remove_dots(Path);
1627 return std::error_code();
1636 llvm::errs() <<
"Modules:";
1637 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1638 MEnd = Modules.end();
1640 M->getValue()->
print(llvm::errs(), 2);
1642 llvm::errs() <<
"Headers:";
1643 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1645 llvm::errs() <<
" \"" << H->first.getName() <<
"\" -> ";
1647 E = H->second.end();
1649 if (I != H->second.begin())
1650 llvm::errs() <<
",";
1651 llvm::errs() << I->getModule()->getFullModuleName();
1653 llvm::errs() <<
"\n";
1662 if (Export.first || Export.second)
1663 Mod->
Exports.push_back(Export);
1672 auto Unresolved = std::move(Top->UnresolvedDirectUses);
1673 Top->UnresolvedDirectUses.clear();
1675 Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1677 Top->DirectUses.push_back(DirectUse);
1679 Top->UnresolvedDirectUses.push_back(UDU);
1681 return !Top->UnresolvedDirectUses.empty();
1688 if (
Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1690 Conflict.
Other = OtherMod;
1691 Conflict.
Message = UC.Message;
1723 bool ImplicitlyDiscovered;
1726 bool HadError =
false;
1729 Module *ActiveModule =
nullptr;
1760 using Attributes = ModuleMap::Attributes;
1766 bool ImplicitlyDiscovered)
1767 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
1768 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
1769 ImplicitlyDiscovered(ImplicitlyDiscovered) {}
1782void ModuleMapLoader::diagnosePrivateModules(
SourceLocation StartLoc) {
1783 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1784 const Module *M, SourceRange ReplLoc) {
1785 auto D = Diags.Report(ActiveModule->DefinitionLoc,
1786 diag::note_mmap_rename_top_level_private_module);
1787 D << BadName << M->Name;
1791 for (
auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1792 auto const *M = E->getValue();
1793 if (M->Directory != ActiveModule->Directory)
1796 SmallString<128> FullName(ActiveModule->getFullModuleName());
1797 if (!FullName.starts_with(M->Name) && !FullName.ends_with(
"Private"))
1799 SmallString<128> FixedPrivModDecl;
1800 SmallString<128> Canonical(M->Name);
1801 Canonical.append(
"_Private");
1804 if (ActiveModule->Parent && ActiveModule->Name ==
"Private" && !M->Parent &&
1805 M->Name == ActiveModule->Parent->Name) {
1806 Diags.Report(ActiveModule->DefinitionLoc,
1807 diag::warn_mmap_mismatched_private_submodule)
1810 SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1812 FixItInitBegin = StartLoc;
1814 if (ActiveModule->Parent->IsFramework)
1815 FixedPrivModDecl.append(
"framework ");
1816 FixedPrivModDecl.append(
"module ");
1817 FixedPrivModDecl.append(Canonical);
1819 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1820 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1825 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1826 ActiveModule->Name != Canonical) {
1827 Diags.Report(ActiveModule->DefinitionLoc,
1828 diag::warn_mmap_mismatched_private_module_name)
1829 << ActiveModule->Name;
1830 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1831 SourceRange(ActiveModule->DefinitionLoc));
1837 if (MD.
Id.front().first ==
"*")
1838 return handleInferredModuleDecl(MD);
1842 Module *PreviousActiveModule = ActiveModule;
1843 if (MD.
Id.size() > 1) {
1846 ActiveModule =
nullptr;
1847 const Module *TopLevelModule =
nullptr;
1848 for (
unsigned I = 0, N = MD.
Id.size() - 1; I != N; ++I) {
1850 Map.lookupModuleQualified(MD.
Id[I].first, ActiveModule)) {
1852 TopLevelModule =
Next;
1853 ActiveModule =
Next;
1857 Diags.Report(MD.
Id[I].second, diag::err_mmap_missing_parent_module)
1858 << MD.
Id[I].first << (ActiveModule !=
nullptr)
1860 ? ActiveModule->getTopLevelModule()->getFullModuleName()
1865 if (TopLevelModule &&
1866 ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
1867 assert(ModuleMapFID !=
1868 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
1869 "submodule defined in same file as 'module *' that allowed its "
1870 "top-level module");
1871 Map.addAdditionalModuleMapFile(
1872 TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
1876 StringRef ModuleName = MD.
Id.back().first;
1877 SourceLocation ModuleNameLoc = MD.
Id.back().second;
1880 Module *ShadowingModule =
nullptr;
1881 if (
Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1887 bool LoadedFromASTFile = Existing->IsFromModuleFile;
1888 if (LoadedFromASTFile) {
1890 Map.getContainingModuleMapFile(Existing);
1892 SourceMgr.getFileEntryRefForID(ModuleMapFID);
1893 if ((ExistingModMapFile && CurrentModMapFile &&
1894 *ExistingModMapFile == *CurrentModMapFile) ||
1895 Existing->DefinitionLoc.isInvalid()) {
1899 LoadedFromASTFile =
true;
1901 LoadedFromASTFile =
false;
1904 bool Inferred = Existing->IsInferred;
1920 bool PartOfFramework = MD.
Framework || Existing->isPartOfFramework();
1923 bool ParsedAsMainInput =
1925 Map.LangOpts.CurrentModule == ModuleName &&
1926 SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
1927 SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
1930 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
1931 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
1933 ActiveModule = PreviousActiveModule;
1938 if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
1939 ShadowingModule = Existing;
1942 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1944 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1951 if (ShadowingModule) {
1953 Map.createShadowedModule(ModuleName, MD.
Framework, ShadowingModule);
1955 ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
1959 ActiveModule->DefinitionLoc = ModuleNameLoc;
1961 ActiveModule->IsSystem =
true;
1963 ActiveModule->IsExternC =
true;
1965 ActiveModule->NoUndeclaredIncludes =
true;
1966 ActiveModule->Directory = Directory;
1968 StringRef MapFileName(
1969 SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
1970 if (MapFileName.ends_with(
"module.private.modulemap") ||
1971 MapFileName.ends_with(
"module_private.map")) {
1972 ActiveModule->ModuleMapIsPrivate =
true;
1978 SourceLocation StartLoc =
1979 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
1980 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
1981 !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
1983 !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
1985 ActiveModule->ModuleMapIsPrivate)
1986 diagnosePrivateModules(MD.
Location);
1991 [&](
const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
1992 [&](
const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
1993 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1994 handleUmbrellaDirDecl(UDD);
1996 [&](
const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
1997 [&](
const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
1998 [&](
const modulemap::ExportAsDecl &EAD) {
1999 handleExportAsDecl(EAD);
2001 [&](
const modulemap::ExternModuleDecl &EMD) {
2002 handleExternModuleDecl(EMD);
2004 [&](
const modulemap::UseDecl &UD) { handleUseDecl(UD); },
2005 [&](
const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
2006 [&](
const modulemap::ConfigMacrosDecl &CMD) {
2007 handleConfigMacros(CMD);
2009 [&](
const modulemap::ConflictDecl &CD) { handleConflict(CD); },
2010 [&](
const modulemap::ExcludeDecl &ED) {
2011 Diags.Report(ED.Location, diag::err_mmap_expected_member);
2018 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2019 ActiveModule->LinkLibraries.empty())
2024 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2025 ActiveModule->Parent) {
2026 ActiveModule->getTopLevelModule()->markUnavailable(
false);
2027 ActiveModule->getTopLevelModule()->MissingHeaders.append(
2028 ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2032 ActiveModule = PreviousActiveModule;
2035void ModuleMapLoader::handleExternModuleDecl(
2037 StringRef FileNameRef = EMD.
Path;
2038 SmallString<128> ModuleMapFileName;
2039 if (llvm::sys::path::is_relative(FileNameRef)) {
2040 ModuleMapFileName += Directory.getName();
2041 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
2048 llvm::sys::path::remove_dots(ModuleMapFileName,
true);
2049 FileNameRef = ModuleMapFileName;
2051 if (
auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
2052 Map.parseAndLoadModuleMapFile(
2053 *
File, IsSystem, ImplicitlyDiscovered,
2054 Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
2076 bool &IsRequiresExcludedHack) {
2080 IsRequiresExcludedHack =
true;
2091 for (
const modulemap::RequiresFeature &RF : RD.
Features) {
2092 bool IsRequiresExcludedHack =
false;
2093 bool ShouldAddRequirement =
2096 if (IsRequiresExcludedHack)
2097 UsesRequiresExcludedHack.insert(ActiveModule);
2099 if (ShouldAddRequirement) {
2120 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2126 Module::UnresolvedHeaderDirective Header;
2130 Header.
Kind = Map.headerRoleToKind(
Role);
2134 !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2135 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
2136 << ActiveModule->getFullModuleName();
2141 if (ImplicitlyDiscovered) {
2142 SmallString<128> NormalizedPath(HD.
Path);
2143 llvm::sys::path::remove_dots(NormalizedPath,
true);
2144 if (NormalizedPath.starts_with(
".."))
2145 Diags.Report(HD.
PathLoc, diag::warn_mmap_path_outside_directory);
2153 bool NeedsFramework =
false;
2157 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2159 ActiveModule->fullModuleNameIs({
"_Builtin_stddef",
"max_align_t"}))
2160 Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2163 Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2164 << ActiveModule->getFullModuleName()
2173void ModuleMapLoader::handleUmbrellaDirDecl(
2175 std::string DirName = std::string(UDD.
Path);
2176 std::string DirNameAsWritten = DirName;
2179 if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2180 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2181 << ActiveModule->getFullModuleName();
2186 if (ImplicitlyDiscovered) {
2187 SmallString<128> NormalizedPath(UDD.
Path);
2188 llvm::sys::path::remove_dots(NormalizedPath,
true);
2189 if (NormalizedPath.starts_with(
".."))
2190 Diags.Report(UDD.
Location, diag::warn_mmap_path_outside_directory);
2195 if (llvm::sys::path::is_absolute(DirName)) {
2196 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2198 SmallString<128> PathName;
2199 PathName = Directory.getName();
2200 llvm::sys::path::append(PathName, DirName);
2201 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2205 Diags.Report(UDD.
Location, diag::warn_mmap_umbrella_dir_not_found)
2210 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2216 SmallVector<Module::Header, 6> Headers;
2217 llvm::vfs::FileSystem &FS =
2218 SourceMgr.getFileManager().getVirtualFileSystem();
2219 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->
getName(), EC), E;
2220 I != E && !EC; I.increment(EC)) {
2221 if (
auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2222 Module::Header Header = {
"", std::string(I->path()), *FE};
2223 Headers.push_back(std::move(Header));
2230 for (
auto &Header : Headers)
2235 if (
Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2236 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2237 << OwningModule->getFullModuleName();
2243 Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName,
2249 ActiveModule->UnresolvedExports.push_back(
Unresolved);
2253 const auto &ModName = EAD.
Id.front();
2255 if (!ActiveModule->ExportAsModule.empty()) {
2256 if (ActiveModule->ExportAsModule == ModName.first) {
2257 Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)
2258 << ActiveModule->Name << ModName.first;
2260 Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)
2261 << ActiveModule->Name << ActiveModule->ExportAsModule
2266 ActiveModule->ExportAsModule = ModName.first;
2267 Map.addLinkAsDependency(ActiveModule);
2271 if (ActiveModule->Parent)
2272 Diags.Report(UD.
Location, diag::err_mmap_use_decl_submodule);
2274 ActiveModule->UnresolvedDirectUses.push_back(UD.
Id);
2278 ActiveModule->LinkLibraries.push_back(
2282void ModuleMapLoader::handleConfigMacros(
2284 if (ActiveModule->Parent) {
2285 Diags.Report(CMD.
Location, diag::err_mmap_config_macro_submodule);
2292 ActiveModule->ConfigMacrosExhaustive =
true;
2294 ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
2299 Module::UnresolvedConflict Conflict;
2301 Conflict.
Id = CD.
Id;
2305 ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));
2308void ModuleMapLoader::handleInferredModuleDecl(
2310 SourceLocation StarLoc = MD.
Id.front().second;
2314 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2320 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
2321 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2326 if (ActiveModule->InferSubmodules) {
2327 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2328 if (ActiveModule->InferredSubmoduleLoc.isValid())
2329 Diags.Report(ActiveModule->InferredSubmoduleLoc,
2330 diag::note_mmap_prev_definition);
2336 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2340 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2346 ActiveModule->InferSubmodules =
true;
2347 ActiveModule->InferredSubmoduleLoc = StarLoc;
2348 ActiveModule->InferExplicitSubmodules = MD.
Explicit;
2351 auto &InfDir = Map.InferredDirectories[Directory];
2352 InfDir.InferModules =
true;
2353 InfDir.Attrs = MD.
Attrs;
2354 InfDir.ModuleMapFID = ModuleMapFID;
2361 [&](
const auto &
Other) {
2362 Diags.Report(
Other.Location,
2363 diag::err_mmap_expected_inferred_member)
2364 << (ActiveModule !=
nullptr);
2366 [&](
const modulemap::ExcludeDecl &ED) {
2370 diag::err_mmap_expected_inferred_member)
2371 << (ActiveModule !=
nullptr);
2375 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
2378 [&](
const modulemap::ExportDecl &ED) {
2380 if (!ActiveModule) {
2382 diag::err_mmap_expected_inferred_member)
2383 << (ActiveModule !=
nullptr);
2389 ActiveModule->InferExportWildcard =
true;
2391 Diags.Report(ED.
Id.front().second,
2392 diag::err_mmap_expected_export_wildcard);
2399 handleModuleDecl(MD);
2405 handleExternModuleDecl(EMD);
2416 handleExternModuleDecl(EMD);
2424 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
2425 if (Known != Modules.end())
2426 return Known->getValue();
2428 auto ParsedMod = ParsedModules.find(Name);
2429 if (ParsedMod == ParsedModules.end())
2432 Diags.Report(diag::remark_mmap_load_module) << Name;
2434 for (
const auto &ModuleDecl : ParsedMod->second) {
2447 bool ImplicitlyDiscovered,
2451 assert(Target &&
"Missing target information");
2452 llvm::DenseMap<const FileEntry *, bool>::iterator Known =
2453 LoadedModuleMap.find(
File);
2454 if (Known != LoadedModuleMap.end())
2455 return Known->second;
2458 if (ID.isInvalid()) {
2463 FileID &LocalFID = ModuleMapLocalFileID[
File];
2465 auto FileCharacter =
2467 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
2472 assert(Target &&
"Missing target information");
2473 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
2475 return LoadedModuleMap[
File] =
true;
2476 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
2477 "invalid buffer offset");
2480 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
2483 Diags.Report(diag::remark_mmap_load) <<
File.getName();
2485 ImplicitlyDiscovered);
2492 ParsedModuleMap.find(
File);
2493 if (PKnown == ParsedModuleMap.end()) {
2494 ParsedModuleMaps.push_back(
2495 std::make_unique<modulemap::ModuleMapFile>(std::move(*MMF)));
2496 ParsedModuleMap[
File] = &*ParsedModuleMaps.back();
2503 for (
const auto &Cb : Callbacks)
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
#define ALIAS(NAME, TOK, FLAGS)
#define KEYWORD(NAME, FLAGS)
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
static bool isBuiltinHeaderName(StringRef FileName)
Determine whether the given file name is the name of a builtin header, supplied by Clang to replace,...
static bool isBuiltInModuleName(StringRef ModuleName)
Determine whether the given module name is the name of a builtin module that is cyclic with a system ...
static Module * getTopLevelOrNull(Module *M)
static bool violatesPrivateInclude(Module *RequestingModule, const FileEntry *IncFileEnt, ModuleMap::KnownHeader Header)
static void inferFrameworkLink(Module *Mod)
For a framework module, infer the framework against which we should link.
static StringRef sanitizeFilenameAsIdentifier(StringRef Name, SmallVectorImpl< char > &Buffer)
"Sanitize" a filename so that it can be used as an identifier.
static constexpr llvm::StringRef kPrivateModuleSuffix
static void appendSubframeworkPaths(Module *Mod, SmallVectorImpl< char > &Path)
Append to Paths the set of paths needed to get to the subframework in which the given module lives.
static bool shouldAddRequirement(Module *M, StringRef Feature, bool &IsRequiresExcludedHack)
Whether to add the requirement Feature to the module M.
static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, const ModuleMap::KnownHeader &Old)
static bool compareModuleHeaders(const Module::Header &A, const Module::Header &B)
Defines the clang::Module class, which describes a module in the source code.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Concrete class used by the front-end to report problems and issues.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
const FileEntry & getFileEntry() const
StringRef getName() const
The name of this FileEntry.
DirectoryEntryRef getDir() const
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::vfs::FileSystem & getVirtualFileSystem() const
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Get a FileEntryRef if it exists, without doing anything on error.
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
@ CMK_ModuleMap
Compiling a module from a module map.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Required to construct a Module.
ModuleMapLoader(SourceManager &SourceMgr, DiagnosticsEngine &Diags, ModuleMap &Map, FileID ModuleMapFID, DirectoryEntryRef Directory, bool IsSystem, bool ImplicitlyDiscovered)
bool loadExternModuleDecl(const modulemap::ExternModuleDecl &EMD)
bool parseAndLoadModuleMapFile(const modulemap::ModuleMapFile &MMF)
bool loadModuleDecl(const modulemap::ModuleDecl &MD)
Module * createShadowedModule(StringRef Name, bool IsFramework, Module *ShadowingModule)
Create a new top-level module that is shadowed by ShadowingModule.
bool resolveExports(Module *Mod, bool Complain)
Resolve all of the unresolved exports in the given module.
void addLinkAsDependency(Module *Mod)
Make module to use export_as as the link dependency name if enough information is available or add it...
friend class ModuleMapLoader
bool parseModuleMapFile(FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered, DirectoryEntryRef Dir, FileID ID=FileID(), SourceLocation ExternModuleLoc=SourceLocation())
Parse a module map without creating clang::Module instances.
void dump()
Dump the contents of the module map, for debugging purposes.
std::pair< Module *, bool > findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit)
Find a new module or submodule, or create it if it does not already exist.
void diagnoseHeaderInclusion(Module *RequestingModule, bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, FileEntryRef File)
Reports errors if a module must not include a specific file.
void addAdditionalModuleMapFile(const Module *M, FileEntryRef ModuleMap)
ModuleRef lookupModuleQualified(StringRef Name, Module *Context) const
Retrieve a module with the given name within the given context, using direct (qualified) name lookup.
OptionalFileEntryRef getContainingModuleMapFile(const Module *Module) const
static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role)
Convert a header role to a kind.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
Module * createHeaderUnit(SourceLocation Loc, StringRef Name, Module::Header H)
Create a C++20 header unit.
void setUmbrellaHeaderAsWritten(Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory, SourceLocation Loc=SourceLocation())
Sets the umbrella header of the given module to the given header.
void addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role, bool Imported=false, SourceLocation Loc=SourceLocation())
Adds this header to the given module.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
bool resolveConflicts(Module *Mod, bool Complain)
Resolve all of the unresolved conflicts in the given module.
bool isHeaderUnavailableInModule(FileEntryRef Header, const Module *RequestingModule) const
Determine whether the given header is unavailable as part of the specified module.
void resolveHeaderDirectives(const FileEntry *File) const
Resolve all lazy header directives for the specified file.
ArrayRef< KnownHeader > findResolvedModulesForHeader(FileEntryRef File) const
Like findAllModulesForHeader, but do not attempt to infer module ownership from umbrella headers if w...
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool shouldImportRelativeToBuiltinIncludeDir(StringRef FileName, Module *Module) const
bool parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Load the given module map file, and record any modules we encounter.
Module * createModuleForImplementationUnit(SourceLocation Loc, StringRef Name)
Create a new module for a C++ module implementation unit.
ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo)
Construct a new module map.
std::error_code canonicalizeModuleMapPath(SmallVectorImpl< char > &Path)
Canonicalize Path in a manner suitable for a module map file.
OptionalFileEntryRef findUmbrellaHeaderForModule(Module *M, std::string NameAsWritten, SmallVectorImpl< char > &RelativePathName)
Find the FileEntry for an umbrella header in a module as if it was written in the module map as a hea...
FileID getModuleMapFileIDForUniquing(const Module *M) const
Get the module map file that (along with the module name) uniquely identifies this module.
void setInferredModuleAllowedBy(Module *M, FileID ModMapFID)
void setUmbrellaDirAsWritten(Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory, SourceLocation Loc=SourceLocation())
Sets the umbrella directory of the given module to the given directory.
Module * findOrCreateModuleFirst(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit)
Call ModuleMap::findOrCreateModule and throw away the information whether the module was found or cre...
Module * lookupModuleUnqualified(StringRef Name, Module *Context) const
Retrieve a module with the given name using lexical name lookup, starting at the given context.
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
Module * createModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit)
Create new submodule, assuming it does not exist.
bool isHeaderInUnavailableModule(FileEntryRef Header) const
Determine whether the given header is part of a module marked 'unavailable'.
FileID getContainingModuleMapFileID(const Module *Module) const
Retrieve the module map file containing the definition of the given module.
~ModuleMap()
Destroy the module map.
Module * createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module *Parent=nullptr)
Create a global module fragment for a C++ module unit.
void setTarget(const TargetInfo &Target)
Set the target information.
void resolveLinkAsDependencies(Module *Mod)
Use PendingLinkAsModule information to mark top level link names that are going to be replaced by exp...
ModuleHeaderRole
Flags describing the role of a module header.
@ PrivateHeader
This header is included but private.
@ ExcludedHeader
This header is explicitly excluded from the module.
@ NormalHeader
This header is normally included in the module.
@ TextualHeader
This header is part of the module (for layering purposes) but should be textually included.
Module * createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name)
Create a new module for a C++ module interface unit.
Module * createPrivateModuleFragmentForInterfaceUnit(Module *Parent, SourceLocation Loc)
Create a global module fragment for a C++ module interface unit.
Module * findOrInferSubmodule(Module *Parent, StringRef Name)
ArrayRef< KnownHeader > findAllModulesForHeader(FileEntryRef File)
Retrieve all the modules that contain the given header file.
Module * createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module *Parent)
void loadAllParsedModules()
Module * createModuleUnitWithKind(SourceLocation Loc, StringRef Name, Module::ModuleKind Kind)
Create a new C++ module with the specified kind, and reparent any pending global module fragment(s) t...
Module * findOrLoadModule(StringRef Name)
static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind)
Convert a header kind to a role. Requires Kind to not be HK_Excluded.
bool resolveUses(Module *Mod, bool Complain)
Resolve all of the unresolved uses in the given module.
Reference to a module that consists of either an existing/materialized Module object,...
Describes a module or submodule.
SmallVector< ExportDecl, 2 > Exports
The set of export declarations.
bool isForBuilding(const LangOptions &LangOpts) const
Determine whether this module can be built in this compilation.
std::variant< std::monostate, FileEntryRef, DirectoryEntryRef > Umbrella
The umbrella header or directory.
unsigned InferSubmodules
Whether we should infer submodules for this module based on the headers.
SourceLocation UmbrellaDeclLoc
The location of the umbrella header or directory declaration.
bool directlyUses(const Module *Requested)
Determine whether this module has declared its intention to directly use another module.
std::pair< ModuleRef, bool > ExportDecl
Describes an exported module.
void print(raw_ostream &OS, unsigned Indent=0, bool Dump=false) const
Print the module map for this module to the given stream.
SourceLocation DefinitionLoc
The location of the module definition.
SmallVector< UnresolvedHeaderDirective, 1 > MissingHeaders
Headers that are mentioned in the module map file but could not be found on the file system.
Module * Parent
The parent of this module.
void markUnavailable(bool Unimportable)
Mark this module and all of its submodules as unavailable.
SmallVector< UnresolvedHeaderDirective, 1 > UnresolvedHeaders
Headers that are mentioned in the module map file but that we have not yet attempted to resolve to a ...
bool fullModuleNameIs(ArrayRef< StringRef > nameParts) const
Whether the full name of this module is equal to joining nameParts with "."s.
unsigned IsInferred
Whether this is an inferred submodule (module * { ... }).
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
std::string Name
The name of this module.
bool isSubFramework() const
Determine whether this module is a subframework of another framework.
llvm::SmallVector< LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used.
SmallVector< UnresolvedExportDecl, 2 > UnresolvedExports
The set of export declarations that have yet to be resolved.
void addHeader(HeaderKind HK, Header H)
std::string UmbrellaRelativeToRootModuleDirectory
OptionalDirectoryEntryRef Directory
The build directory of this module.
ModuleRef findSubmodule(StringRef Name) const
Find the submodule with the given name.
ArrayRef< Header > getHeaders(HeaderKind HK) const
unsigned InferExportWildcard
Whether, when inferring submodules, the inferr submodules should export all modules they import (e....
std::vector< UnresolvedConflict > UnresolvedConflicts
The list of conflicts for which the module-id has not yet been resolved.
bool isSubModuleOf(const Module *Other) const
Check if this module is a (possibly transitive) submodule of Other.
bool isPartOfFramework() const
Determine whether this module is a part of a framework, either because it is a framework module or be...
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
@ ModuleImplementationUnit
This is a C++20 module implementation unit.
@ ImplicitGlobalModuleFragment
This is an implicit fragment of the global module which contains only language linkage declarations (...
@ ModuleInterfaceUnit
This is a C++20 module interface unit.
@ ModuleHeaderUnit
This is a C++20 header unit.
@ PrivateModuleFragment
This is the private module fragment within some C++ module.
@ ExplicitGlobalModuleFragment
This is the explicit Global Module Fragment of a modular TU.
unsigned IsFramework
Whether this is a framework module.
std::string ExportAsModule
The module through which entities defined in this module will eventually be exposed,...
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
std::string UmbrellaAsWritten
The name of the umbrella entry, as written in the module map.
unsigned InferExplicitSubmodules
Whether, when inferring submodules, the inferred submodules should be explicit.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
OptionalDirectoryEntryRef getEffectiveUmbrellaDir() const
Get the effective umbrella directory for this module: either the one explicitly written in the module...
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
std::vector< Conflict > Conflicts
The list of conflicts.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
Exposes information about the current target.
Defines the clang::TargetInfo interface.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
bool Sub(InterpState &S, CodePtr OpPC)
std::optional< ModuleMapFile > parseModuleMap(FileID ID, clang::DirectoryEntryRef Dir, SourceManager &SM, DiagnosticsEngine &Diags, bool IsSystem, bool ImplicitlyDiscovered, unsigned *Offset)
Parse a module map file into an in memory representation.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)
SmallVector< std::pair< std::string, SourceLocation >, 2 > ModuleId
Describes the name of a module.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
@ Keyword
The name has been typo-corrected to a keyword.
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
@ Other
Other implicit parameter.
int const char * function
unsigned IsExternC
Whether this is an extern "C" module.
unsigned IsSystem
Whether this is a system module.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules.
A conflict between two modules.
std::string Message
The message provided to the user when there is a conflict.
ModuleRef Other
The module that this module conflicts with.
A library or framework to link against when an entity from this module is used.
std::string Message
The message provided to the user when there is a conflict.
ModuleId Id
The (unresolved) module id.
Describes an exported module that has not yet been resolved (perhaps because the module it refers to ...
std::vector< StringRef > Macros
ModuleAttributes Attrs
Points to the first keyword in the decl.
std::vector< Decl > Decls
Represents the parsed form of a module map file.
std::vector< TopLevelDecl > Decls
FileID ID
The FileID used to parse this module map. This is always a local ID.
OptionalDirectoryEntryRef Dir
The directory in which the module map was discovered.
bool ImplicitlyDiscovered
std::vector< RequiresFeature > Features