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");
179 auto File = SourceMgr.getFileManager().getOptionalFileRef(Filename);
186 if (llvm::sys::path::is_absolute(Header.
FileName)) {
187 RelativePathName.clear();
196 SmallString<128> FullPathName(Directory->getName());
199 unsigned FullPathLength = FullPathName.size();
201 unsigned RelativePathLength = RelativePathName.size();
204 llvm::sys::path::append(RelativePathName,
"Headers", Header.
FileName);
205 llvm::sys::path::append(FullPathName, RelativePathName);
206 if (
auto File = GetFile(FullPathName))
216 RelativePathName.clear();
218 RelativePathName.resize(RelativePathLength);
219 FullPathName.resize(FullPathLength);
220 llvm::sys::path::append(RelativePathName,
"PrivateHeaders",
222 llvm::sys::path::append(FullPathName, RelativePathName);
223 return GetFile(FullPathName);
227 return GetFrameworkFile();
230 llvm::sys::path::append(RelativePathName, Header.
FileName);
231 llvm::sys::path::append(FullPathName, RelativePathName);
232 auto NormalHdrFile = GetFile(FullPathName);
234 if (!NormalHdrFile && Directory->getName().ends_with(
".framework")) {
238 FullPathName.assign(Directory->getName());
239 RelativePathName.clear();
240 if (GetFrameworkFile()) {
242 diag::warn_mmap_incomplete_framework_module_declaration)
244 NeedsFramework =
true;
249 return NormalHdrFile;
256 return llvm::StringSwitch<bool>(
FileName)
257 .Case(
"float.h",
true)
258 .Case(
"iso646.h",
true)
259 .Case(
"limits.h",
true)
260 .Case(
"stdalign.h",
true)
261 .Case(
"stdarg.h",
true)
262 .Case(
"stdatomic.h",
true)
263 .Case(
"stdbool.h",
true)
264 .Case(
"stdckdint.h",
true)
265 .Case(
"stdcountof.h",
true)
266 .Case(
"stddef.h",
true)
267 .Case(
"stdint.h",
true)
268 .Case(
"tgmath.h",
true)
269 .Case(
"unwind.h",
true)
276 return llvm::StringSwitch<bool>(ModuleName)
277 .Case(
"_Builtin_float",
true)
278 .Case(
"_Builtin_inttypes",
true)
279 .Case(
"_Builtin_iso646",
true)
280 .Case(
"_Builtin_limits",
true)
281 .Case(
"_Builtin_stdalign",
true)
282 .Case(
"_Builtin_stdarg",
true)
283 .Case(
"_Builtin_stdatomic",
true)
284 .Case(
"_Builtin_stdbool",
true)
285 .Case(
"_Builtin_stddef",
true)
286 .Case(
"_Builtin_stdint",
true)
287 .Case(
"_Builtin_stdnoreturn",
true)
288 .Case(
"_Builtin_tgmath",
true)
289 .Case(
"_Builtin_unwind",
true)
293void ModuleMap::resolveHeader(
Module *Mod,
295 bool &NeedsFramework) {
296 SmallString<128> RelativePathName;
298 findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
300 const DirectoryEntry *UmbrellaDir = &
File->getDir().getDirEntry();
301 if (
Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
302 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
303 << UmbrellaMod->getFullModuleName();
309 Module::Header H = {Header.
FileName, std::string(RelativePathName),
332bool ModuleMap::resolveAsBuiltinHeader(
335 llvm::sys::path::is_absolute(Header.
FileName) ||
337 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->
Directory ||
344 SmallString<128> Path;
345 llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.
FileName);
346 auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
359 : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
360 HeaderInfo(HeaderInfo) {
366 assert((!this->Target || this->Target == &Target) &&
367 "Improper target override");
368 this->Target = &Target;
382 Buffer.push_back(
'_');
383 Buffer.reserve(Buffer.size() + Name.size());
384 for (
unsigned I = 0, N = Name.size(); I != N; ++I) {
386 Buffer.push_back(Name[I]);
388 Buffer.push_back(
'_');
391 Name = StringRef(Buffer.data(), Buffer.size());
394 while (llvm::StringSwitch<bool>(Name)
397#include
"clang/Basic/TokenKinds.def"
399 if (Name.data() != Buffer.data())
400 Buffer.append(Name.begin(), Name.end());
401 Buffer.push_back(
'_');
402 Name = StringRef(Buffer.data(), Buffer.size());
409 return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
415 return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
420ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(
FileEntryRef File) {
422 HeadersMap::iterator Known = Headers.find(
File);
426 return Headers.find(
File);
433 if (UmbrellaDirs.empty())
442 StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
447 auto KnownDir = UmbrellaDirs.find(*Dir);
448 if (KnownDir != UmbrellaDirs.end())
451 IntermediateDirs.push_back(*Dir);
454 DirName = llvm::sys::path::parent_path(DirName);
459 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
472 bool IsPrivate =
false;
476 for (
auto Hs : HeaderList)
477 IsPrivate |= llvm::any_of(
479 assert(IsPrivate &&
"inconsistent headers and roles");
490 bool RequestingModuleIsModuleInterface,
493 if (RequestingModule) {
498 HeadersMap::iterator Known = findKnownHeader(
File);
500 diagnoseDuplicateHeaderOwnership(FilenameLoc, Filename,
File, Known);
506 bool IsPublicForMainPrivateModule =
false;
507 if (TopLevelRequestingModule != TopLevelSourceModule) {
515 if (TopLevelRequestingModule && TopLevelSourceModule &&
516 llvm::StringRef(TopLevelSourceModule->
Name)
518 llvm::StringRef(TopLevelSourceModule->
Name)
520 TopLevelRequestingModule->
Name) {
521 IsPublicForMainPrivateModule =
true;
527 bool Excluded =
false;
528 bool UsedByPrivateModule =
false;
530 Module *NotUsed =
nullptr;
532 if (Known != Headers.end()) {
548 if (RequestingModule && LangOpts.ModulesDeclUse &&
551 if (IsPublicForMainPrivateModule) {
552 UsedByPrivateModule = SourceModule->directlyUses(Header.
getModule());
566 Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
573 if (UsedByPrivateModule) {
574 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_private)
578 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
585 if (Excluded || isHeaderInUmbrellaDirs(
File))
590 if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
591 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
593 }
else if (RequestingModule && RequestingModuleIsModuleInterface &&
594 LangOpts.isCompilingModule()) {
597 diag::warn_non_modular_include_in_framework_module :
598 diag::warn_non_modular_include_in_module;
604void ModuleMap::diagnoseDuplicateHeaderOwnership(
SourceLocation FilenameLoc,
607 HeadersMap::iterator Known) {
608 if (Known == Headers.end())
611 if (Diags.
isIgnored(diag::warn_mmap_duplicate_header_ownership, FilenameLoc))
615 if (!DiagnosedDuplicateHeaders.insert(&
File.getFileEntry()).second)
628 for (
const KnownHeader &H : Known->second) {
632 if (!SeenTopLevel.insert(TopLevel).second)
634 auto It = HeaderOwnerLocs.find({&
File.getFileEntry(), H.getModule()});
635 SourceLocation OwnerLoc =
636 It != HeaderOwnerLocs.end() ? It->second : SourceLocation();
637 OwningModules.push_back({TopLevel, OwnerLoc,
false});
642 if (OwningModules.empty())
650 SmallVector<DirectoryEntryRef, 2> IntermediateDirs;
652 findHeaderInUmbrellaDirs(
File, IntermediateDirs)) {
656 if (SeenTopLevel.insert(TopLevel).second) {
659 llvm::any_of(Known->second, [TopLevel](
const KnownHeader &H) {
660 return H.getModule()->getTopLevelModule() == TopLevel &&
661 H.getRole() == ExcludedHeader;
664 OwningModules.push_back({TopLevel,
671 if (OwningModules.size() < 2)
674 Diags.Report(FilenameLoc, diag::warn_mmap_duplicate_header_ownership)
676 for (
const auto &Owner : OwningModules) {
677 unsigned NoteID = Owner.IsUmbrella
678 ? diag::note_mmap_header_covered_by_umbrella
679 : diag::note_mmap_header_owned_by;
680 Diags.Report(Owner.Loc, NoteID) << Owner.Mod->getFullModuleName();
714 bool AllowExcluded) {
721 HeadersMap::iterator Known = findKnownHeader(
File);
722 if (Known != Headers.end()) {
731 return MakeResult(H);
735 return MakeResult(
Result);
738 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(
File));
742 Module *M, std::string NameAsWritten,
745 Header.
FileName = std::move(NameAsWritten);
748 return findHeader(M, Header, RelativePathName, NeedsFramework);
753 assert(!Headers.count(
File) &&
"already have a module for this header");
756 KnownHeader H = findHeaderInUmbrellaDirs(
File, SkippedDirs);
764 UmbrellaModule = UmbrellaModule->
Parent;
778 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
784 UmbrellaDirs[SkippedDir] =
Result;
795 llvm::sys::path::stem(
File.getName()), NameBuf);
808 for (
unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
809 UmbrellaDirs[SkippedDirs[I]] =
Result;
813 Headers[
File].push_back(Header);
822 HeadersMap::iterator Known = findKnownHeader(
File);
823 if (Known != Headers.end())
824 return Known->second;
826 if (findOrCreateModuleForHeaderInUmbrellaDir(
File))
827 return Headers.find(
File)->second;
836 auto It = Headers.find(
File);
837 if (It == Headers.end())
849 HeadersMap::const_iterator Known = Headers.find(Header);
850 if (Known != Headers.end()) {
852 I = Known->second.begin(),
853 E = Known->second.end();
859 if (I->isAvailable() &&
860 (!RequestingModule ||
877 StringRef DirName = Dir->
getName();
879 auto IsUnavailable = [&](
const Module *M) {
887 auto KnownDir = UmbrellaDirs.find(*Dir);
888 if (KnownDir != UmbrellaDirs.end()) {
890 if (IsUnavailable(
Found))
898 UmbrellaModule = UmbrellaModule->
Parent;
905 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
909 if (IsUnavailable(
Found))
916 llvm::sys::path::stem(Header.
getName()),
923 return IsUnavailable(
Found);
926 SkippedDirs.push_back(*Dir);
929 DirName = llvm::sys::path::parent_path(DirName);
934 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
941 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
942 if (Known != Modules.end())
943 return Known->getValue();
959 if (
Result->InferExportWildcard)
966 for(; Context; Context = Context->Parent) {
979 return Context->findSubmodule(Name);
988 return std::make_pair(Sub.getExisting(),
false);
992 return std::make_pair(M,
true);
996 bool IsFramework,
bool IsExplicit) {
998 "Creating duplicate submodule");
1002 IsFramework, IsExplicit, NumCreatedModules++);
1004 if (LangOpts.CurrentModule == Name)
1007 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1016 true, NumCreatedModules++);
1021 PendingSubmodules.emplace_back(
Result);
1028 assert(Parent &&
"We should only create an implicit global module fragment "
1029 "in a module purview");
1033 auto *
Result =
new (ModulesAlloc.Allocate())
1035 false,
false, NumCreatedModules++);
1045 true, NumCreatedModules++);
1052 auto *
Result =
new (ModulesAlloc.Allocate())
1054 false, NumCreatedModules++);
1058 for (
auto &Submodule : PendingSubmodules)
1059 Submodule->setParent(
Result);
1060 PendingSubmodules.clear();
1066 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1067 assert(!Modules[Name] &&
"redefining existing module");
1071 Modules[Name] = SourceModule =
Result;
1075 auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
1076 assert(MainFile &&
"no input file for module interface");
1084 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1087 "creating implementation module without an interface");
1092 StringRef IName =
".ImplementationUnit";
1093 assert(!Modules[IName] &&
"multiple implementation units?");
1097 Modules[IName] = SourceModule =
Result;
1100 assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
1101 "no input file for module implementation");
1108 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1109 assert(!Modules[Name] &&
"redefining existing module");
1111 auto *
Result =
new (ModulesAlloc.Allocate())
1113 false, NumCreatedModules++);
1115 Modules[Name] = SourceModule =
Result;
1123 assert(Mod->
IsFramework &&
"Can only infer linking for framework modules");
1125 "Can only infer linking for top-level frameworks");
1127 StringRef FrameworkName(Mod->
Name);
1128 FrameworkName.consume_back(
"_Private");
1134 bool IsSystem,
Module *Parent) {
1137 return inferFrameworkModule(FrameworkDir, Attrs, Parent);
1141 Attributes Attrs,
Module *Parent) {
1146 StringRef FrameworkDirName =
1147 SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
1154 llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
1167 bool canInfer =
false;
1168 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
1170 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
1171 if (
auto ParentDir =
FileMgr.getOptionalDirectoryRef(Parent)) {
1174 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1175 inferred = InferredDirectories.find(*ParentDir);
1176 if (inferred == InferredDirectories.end()) {
1179 bool IsFrameworkDir = Parent.ends_with(
".framework");
1187 inferred = InferredDirectories.find(*ParentDir);
1190 if (inferred == InferredDirectories.end())
1191 inferred = InferredDirectories.insert(
1192 std::make_pair(*ParentDir, InferredDirectory())).first;
1195 if (inferred->second.InferModules) {
1198 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1200 !llvm::is_contained(inferred->second.ExcludedModules, Name);
1202 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1203 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1204 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1205 Attrs.NoUndeclaredIncludes |=
1206 inferred->second.Attrs.NoUndeclaredIncludes;
1207 ModuleMapFID = inferred->second.ModuleMapFID;
1220 SmallString<128> UmbrellaName = FrameworkDir.
getName();
1221 llvm::sys::path::append(UmbrellaName,
"Headers", ModuleName +
".h");
1227 if (!UmbrellaHeader)
1231 Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1232 true,
false, NumCreatedModules++);
1235 if (LangOpts.CurrentModule == ModuleName)
1237 Modules[ModuleName] =
Result;
1238 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1241 Result->IsSystem |= Attrs.IsSystem;
1242 Result->IsExternC |= Attrs.IsExternC;
1243 Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1244 Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1245 Result->Directory = FrameworkDir;
1248 StringRef RelativePath = UmbrellaName.str().substr(
1249 Result->getTopLevelModule()->Directory->getName().size());
1250 RelativePath = llvm::sys::path::relative_path(RelativePath);
1260 Result->InferSubmodules =
true;
1261 Result->InferExportWildcard =
true;
1265 SmallString<128> SubframeworksDirName = FrameworkDir.
getName();
1266 llvm::sys::path::append(SubframeworksDirName,
"Frameworks");
1267 llvm::sys::path::native(SubframeworksDirName);
1269 for (llvm::vfs::directory_iterator
1270 Dir = FS.dir_begin(SubframeworksDirName, EC),
1272 Dir != DirEnd && !EC; Dir.increment(EC)) {
1273 if (!StringRef(Dir->path()).ends_with(
".framework"))
1281 StringRef SubframeworkDirName =
1283 bool FoundParent =
false;
1287 = llvm::sys::path::parent_path(SubframeworkDirName);
1288 if (SubframeworkDirName.empty())
1293 if (*SubDir == FrameworkDir) {
1304 inferFrameworkModule(*SubframeworkDir, Attrs,
Result);
1310 if (!
Result->isSubFramework())
1317 Module *ShadowingModule) {
1322 IsFramework,
false, NumCreatedModules++);
1323 Result->ShadowingModule = ShadowingModule;
1324 Result->markUnavailable(
true);
1325 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1326 ShadowModules.push_back(
Result);
1333 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1336 HeaderOwnerLocs[{&UmbrellaHeader.
getFileEntry(), Mod}] = Loc;
1341 PathRelativeToRootModuleDirectory.str();
1342 UmbrellaDirs[UmbrellaHeader.
getDir()] = Mod;
1345 for (
const auto &Cb : Callbacks)
1346 Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1351 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1356 PathRelativeToRootModuleDirectory.str();
1357 UmbrellaDirs[UmbrellaDir] = Mod;
1360void ModuleMap::addUnresolvedHeader(
Module *Mod,
1362 bool &NeedsFramework) {
1365 if (resolveAsBuiltinHeader(Mod, Header)) {
1384 LazyHeadersByModTime[*Header.
ModTime].push_back(Mod);
1386 LazyHeadersBySize[*Header.
Size].push_back(Mod);
1393 resolveHeader(Mod, Header, NeedsFramework);
1397 auto BySize = LazyHeadersBySize.find(
File->getSize());
1398 if (BySize != LazyHeadersBySize.end()) {
1399 for (
auto *M : BySize->second)
1401 LazyHeadersBySize.erase(BySize);
1404 auto ByModTime = LazyHeadersByModTime.find(
File->getModificationTime());
1405 if (ByModTime != LazyHeadersByModTime.end()) {
1406 for (
auto *M : ByModTime->second)
1408 LazyHeadersByModTime.erase(ByModTime);
1413 Module *Mod, std::optional<const FileEntry *>
File)
const {
1414 bool NeedsFramework =
false;
1416 const auto Size =
File ? (*File)->getSize() : 0;
1417 const auto ModTime =
File ? (*File)->getModificationTime() : 0;
1421 (Header.
Size && Header.
Size != Size)))
1422 NewHeaders.push_back(Header);
1426 const_cast<ModuleMap *
>(
this)->resolveHeader(Mod, Header, NeedsFramework);
1441 auto &HeaderList = Headers[HeaderEntry];
1442 if (llvm::is_contained(HeaderList, KH))
1446 HeaderOwnerLocs[{&HeaderEntry.
getFileEntry(), Mod}] = Loc;
1448 HeaderList.push_back(KH);
1451 bool isCompilingModuleHeader = Mod->
isForBuilding(LangOpts);
1452 if (!Imported || isCompilingModuleHeader) {
1455 HeaderInfo.MarkFileModuleHeader(HeaderEntry,
Role, isCompilingModuleHeader);
1459 for (
const auto &Cb : Callbacks)
1460 Cb->moduleMapAddHeader(HeaderEntry.
getName());
1464 bool ImplicitlyDiscovered,
1467 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
1468 Known = ParsedModuleMap.find(
File);
1469 if (Known != ParsedModuleMap.end())
1470 return Known->second ==
nullptr;
1473 if (ID.isInvalid()) {
1474 FileID &LocalFID = ModuleMapLocalFileID[
File];
1476 auto FileCharacter =
1478 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
1483 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
1485 ParsedModuleMap[
File] =
nullptr;
1489 Diags.Report(diag::remark_mmap_parse) <<
File.getName();
1491 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered,
nullptr);
1494 ParsedModuleMap[
File] =
nullptr;
1498 ParsedModuleMaps.push_back(
1499 std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));
1501 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
1504 for (
const auto &
Decl : MD.Decls) {
1505 std::visit(llvm::makeVisitor(
1508 if (SubMD.
Id.front().first ==
"*")
1510 CollectExternDecls(SubMD);
1513 PendingExternalModuleMaps.push_back(&EMD);
1523 std::visit(llvm::makeVisitor(
1529 ParsedModules[StringRef(MD.
Id.front().first)];
1530 ModuleDecls.push_back(std::pair(&MMF, &MD));
1531 CollectExternDecls(MD);
1534 PendingExternalModuleMaps.push_back(&EMD);
1540 StringRef FileNameRef = EMD->Path;
1542 if (llvm::sys::path::is_relative(FileNameRef)) {
1543 ModuleMapFileName += Dir.
getName();
1544 llvm::sys::path::append(ModuleMapFileName, EMD->Path);
1545 FileNameRef = ModuleMapFileName;
1549 SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {
1551 EFile->getDir(),
FileID(), ExternModuleLoc);
1555 ParsedModuleMap[
File] = &MMF;
1557 for (
const auto &Cb : Callbacks)
1564 for (
const auto &Entry : ParsedModules)
1582 assert(InferredModuleAllowedBy.count(M) &&
"missing inferred module map");
1583 return InferredModuleAllowedBy.find(M)->second;
1595 InferredModuleAllowedBy[M] = ModMapFID;
1600 StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1604 if (llvm::sys::path::filename(Dir) ==
"Modules") {
1605 StringRef Parent = llvm::sys::path::parent_path(Dir);
1606 if (Parent.ends_with(
".framework"))
1613 return llvm::errorToErrorCode(DirEntry.takeError());
1617 if (CanonicalDir != Dir)
1618 llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1626 llvm::sys::path::remove_dots(Path);
1628 return std::error_code();
1637 llvm::errs() <<
"Modules:";
1638 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1639 MEnd = Modules.end();
1641 M->getValue()->
print(llvm::errs(), 2);
1643 llvm::errs() <<
"Headers:";
1644 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1646 llvm::errs() <<
" \"" << H->first.getName() <<
"\" -> ";
1648 E = H->second.end();
1650 if (I != H->second.begin())
1651 llvm::errs() <<
",";
1652 llvm::errs() << I->getModule()->getFullModuleName();
1654 llvm::errs() <<
"\n";
1663 if (Export.first || Export.second)
1664 Mod->
Exports.push_back(Export);
1673 auto Unresolved = std::move(Top->UnresolvedDirectUses);
1674 Top->UnresolvedDirectUses.clear();
1676 Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1678 Top->DirectUses.push_back(DirectUse);
1680 Top->UnresolvedDirectUses.push_back(UDU);
1682 return !Top->UnresolvedDirectUses.empty();
1689 if (
Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1691 Conflict.
Other = OtherMod;
1692 Conflict.
Message = UC.Message;
1724 bool ImplicitlyDiscovered;
1727 bool HadError =
false;
1730 Module *ActiveModule =
nullptr;
1761 using Attributes = ModuleMap::Attributes;
1767 bool ImplicitlyDiscovered)
1768 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
1769 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
1770 ImplicitlyDiscovered(ImplicitlyDiscovered) {}
1783void ModuleMapLoader::diagnosePrivateModules(
SourceLocation StartLoc) {
1784 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1785 const Module *M, SourceRange ReplLoc) {
1786 auto D = Diags.Report(ActiveModule->DefinitionLoc,
1787 diag::note_mmap_rename_top_level_private_module);
1788 D << BadName << M->Name;
1792 for (
auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1793 auto const *M = E->getValue();
1794 if (M->Directory != ActiveModule->Directory)
1797 SmallString<128> FullName(ActiveModule->getFullModuleName());
1798 if (!FullName.starts_with(M->Name) && !FullName.ends_with(
"Private"))
1800 SmallString<128> FixedPrivModDecl;
1801 SmallString<128> Canonical(M->Name);
1802 Canonical.append(
"_Private");
1805 if (ActiveModule->Parent && ActiveModule->Name ==
"Private" && !M->Parent &&
1806 M->Name == ActiveModule->Parent->Name) {
1807 Diags.Report(ActiveModule->DefinitionLoc,
1808 diag::warn_mmap_mismatched_private_submodule)
1811 SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1813 FixItInitBegin = StartLoc;
1815 if (ActiveModule->Parent->IsFramework)
1816 FixedPrivModDecl.append(
"framework ");
1817 FixedPrivModDecl.append(
"module ");
1818 FixedPrivModDecl.append(Canonical);
1820 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1821 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1826 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1827 ActiveModule->Name != Canonical) {
1828 Diags.Report(ActiveModule->DefinitionLoc,
1829 diag::warn_mmap_mismatched_private_module_name)
1830 << ActiveModule->Name;
1831 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1832 SourceRange(ActiveModule->DefinitionLoc));
1838 if (MD.
Id.front().first ==
"*")
1839 return handleInferredModuleDecl(MD);
1843 Module *PreviousActiveModule = ActiveModule;
1844 if (MD.
Id.size() > 1) {
1847 ActiveModule =
nullptr;
1848 const Module *TopLevelModule =
nullptr;
1849 for (
unsigned I = 0, N = MD.
Id.size() - 1; I != N; ++I) {
1851 Map.lookupModuleQualified(MD.
Id[I].first, ActiveModule)) {
1853 TopLevelModule =
Next;
1854 ActiveModule =
Next;
1858 Diags.Report(MD.
Id[I].second, diag::err_mmap_missing_parent_module)
1859 << MD.
Id[I].first << (ActiveModule !=
nullptr)
1861 ? ActiveModule->getTopLevelModule()->getFullModuleName()
1866 if (TopLevelModule &&
1867 ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
1868 assert(ModuleMapFID !=
1869 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
1870 "submodule defined in same file as 'module *' that allowed its "
1871 "top-level module");
1872 Map.addAdditionalModuleMapFile(
1873 TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
1877 StringRef ModuleName = MD.
Id.back().first;
1878 SourceLocation ModuleNameLoc = MD.
Id.back().second;
1881 Module *ShadowingModule =
nullptr;
1882 if (
Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1888 bool LoadedFromASTFile = Existing->IsFromModuleFile;
1889 if (LoadedFromASTFile) {
1891 Map.getContainingModuleMapFile(Existing);
1893 SourceMgr.getFileEntryRefForID(ModuleMapFID);
1894 if ((ExistingModMapFile && CurrentModMapFile &&
1895 *ExistingModMapFile == *CurrentModMapFile) ||
1896 Existing->DefinitionLoc.isInvalid()) {
1900 LoadedFromASTFile =
true;
1902 LoadedFromASTFile =
false;
1905 bool Inferred = Existing->IsInferred;
1921 bool PartOfFramework = MD.
Framework || Existing->isPartOfFramework();
1924 bool ParsedAsMainInput =
1926 Map.LangOpts.CurrentModule == ModuleName &&
1927 SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
1928 SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
1931 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
1932 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
1934 ActiveModule = PreviousActiveModule;
1939 if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
1940 ShadowingModule = Existing;
1943 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1945 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1952 if (ShadowingModule) {
1954 Map.createShadowedModule(ModuleName, MD.
Framework, ShadowingModule);
1956 ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
1960 ActiveModule->DefinitionLoc = ModuleNameLoc;
1962 ActiveModule->IsSystem =
true;
1964 ActiveModule->IsExternC =
true;
1966 ActiveModule->NoUndeclaredIncludes =
true;
1967 ActiveModule->Directory = Directory;
1969 StringRef MapFileName(
1970 SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
1971 if (MapFileName.ends_with(
"module.private.modulemap") ||
1972 MapFileName.ends_with(
"module_private.map")) {
1973 ActiveModule->ModuleMapIsPrivate =
true;
1979 SourceLocation StartLoc =
1980 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
1981 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
1982 !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
1984 !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
1986 ActiveModule->ModuleMapIsPrivate)
1987 diagnosePrivateModules(MD.
Location);
1992 [&](
const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
1993 [&](
const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
1994 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1995 handleUmbrellaDirDecl(UDD);
1997 [&](
const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
1998 [&](
const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
1999 [&](
const modulemap::ExportAsDecl &EAD) {
2000 handleExportAsDecl(EAD);
2002 [&](
const modulemap::ExternModuleDecl &EMD) {
2003 handleExternModuleDecl(EMD);
2005 [&](
const modulemap::UseDecl &UD) { handleUseDecl(UD); },
2006 [&](
const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
2007 [&](
const modulemap::ConfigMacrosDecl &CMD) {
2008 handleConfigMacros(CMD);
2010 [&](
const modulemap::ConflictDecl &CD) { handleConflict(CD); },
2011 [&](
const modulemap::ExcludeDecl &ED) {
2012 Diags.Report(ED.Location, diag::err_mmap_expected_member);
2019 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2020 ActiveModule->LinkLibraries.empty())
2025 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2026 ActiveModule->Parent) {
2027 ActiveModule->getTopLevelModule()->markUnavailable(
false);
2028 ActiveModule->getTopLevelModule()->MissingHeaders.append(
2029 ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2033 ActiveModule = PreviousActiveModule;
2036void ModuleMapLoader::handleExternModuleDecl(
2038 StringRef FileNameRef = EMD.
Path;
2039 SmallString<128> ModuleMapFileName;
2040 if (llvm::sys::path::is_relative(FileNameRef)) {
2041 ModuleMapFileName += Directory.getName();
2042 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
2049 llvm::sys::path::remove_dots(ModuleMapFileName,
true);
2050 FileNameRef = ModuleMapFileName;
2052 if (
auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
2053 Map.parseAndLoadModuleMapFile(
2054 *
File, IsSystem, ImplicitlyDiscovered,
2055 Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
2077 bool &IsRequiresExcludedHack) {
2081 IsRequiresExcludedHack =
true;
2092 for (
const modulemap::RequiresFeature &RF : RD.
Features) {
2093 bool IsRequiresExcludedHack =
false;
2094 bool ShouldAddRequirement =
2097 if (IsRequiresExcludedHack)
2098 UsesRequiresExcludedHack.insert(ActiveModule);
2100 if (ShouldAddRequirement) {
2121 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2127 Module::UnresolvedHeaderDirective Header;
2131 Header.
Kind = Map.headerRoleToKind(
Role);
2135 !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2136 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
2137 << ActiveModule->getFullModuleName();
2142 if (ImplicitlyDiscovered) {
2143 SmallString<128> NormalizedPath(HD.
Path);
2144 llvm::sys::path::remove_dots(NormalizedPath,
true);
2145 if (NormalizedPath.starts_with(
".."))
2146 Diags.Report(HD.
PathLoc, diag::warn_mmap_path_outside_directory);
2154 bool NeedsFramework =
false;
2158 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2160 ActiveModule->fullModuleNameIs({
"_Builtin_stddef",
"max_align_t"}))
2161 Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2164 Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2165 << ActiveModule->getFullModuleName()
2174void ModuleMapLoader::handleUmbrellaDirDecl(
2176 std::string DirName = std::string(UDD.
Path);
2177 std::string DirNameAsWritten = DirName;
2180 if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2181 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2182 << ActiveModule->getFullModuleName();
2187 if (ImplicitlyDiscovered) {
2188 SmallString<128> NormalizedPath(UDD.
Path);
2189 llvm::sys::path::remove_dots(NormalizedPath,
true);
2190 if (NormalizedPath.starts_with(
".."))
2191 Diags.Report(UDD.
Location, diag::warn_mmap_path_outside_directory);
2196 if (llvm::sys::path::is_absolute(DirName)) {
2197 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2199 SmallString<128> PathName;
2200 PathName = Directory.getName();
2201 llvm::sys::path::append(PathName, DirName);
2202 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2206 Diags.Report(UDD.
Location, diag::warn_mmap_umbrella_dir_not_found)
2211 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2217 SmallVector<Module::Header, 6> Headers;
2218 llvm::vfs::FileSystem &FS =
2219 SourceMgr.getFileManager().getVirtualFileSystem();
2220 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->
getName(), EC), E;
2221 I != E && !EC; I.increment(EC)) {
2222 if (
auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2223 Module::Header Header = {
"", std::string(I->path()), *FE};
2224 Headers.push_back(std::move(Header));
2231 for (
auto &Header : Headers)
2236 if (
Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2237 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2238 << OwningModule->getFullModuleName();
2244 Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName,
2250 ActiveModule->UnresolvedExports.push_back(
Unresolved);
2254 const auto &ModName = EAD.
Id.front();
2256 if (!ActiveModule->ExportAsModule.empty()) {
2257 if (ActiveModule->ExportAsModule == ModName.first) {
2258 Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)
2259 << ActiveModule->Name << ModName.first;
2261 Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)
2262 << ActiveModule->Name << ActiveModule->ExportAsModule
2267 ActiveModule->ExportAsModule = ModName.first;
2268 Map.addLinkAsDependency(ActiveModule);
2272 if (ActiveModule->Parent)
2273 Diags.Report(UD.
Location, diag::err_mmap_use_decl_submodule);
2275 ActiveModule->UnresolvedDirectUses.push_back(UD.
Id);
2279 ActiveModule->LinkLibraries.push_back(
2283void ModuleMapLoader::handleConfigMacros(
2285 if (ActiveModule->Parent) {
2286 Diags.Report(CMD.
Location, diag::err_mmap_config_macro_submodule);
2293 ActiveModule->ConfigMacrosExhaustive =
true;
2295 ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
2300 Module::UnresolvedConflict Conflict;
2302 Conflict.
Id = CD.
Id;
2306 ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));
2309void ModuleMapLoader::handleInferredModuleDecl(
2311 SourceLocation StarLoc = MD.
Id.front().second;
2315 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2321 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
2322 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2327 if (ActiveModule->InferSubmodules) {
2328 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2329 if (ActiveModule->InferredSubmoduleLoc.isValid())
2330 Diags.Report(ActiveModule->InferredSubmoduleLoc,
2331 diag::note_mmap_prev_definition);
2337 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2341 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2347 ActiveModule->InferSubmodules =
true;
2348 ActiveModule->InferredSubmoduleLoc = StarLoc;
2349 ActiveModule->InferExplicitSubmodules = MD.
Explicit;
2352 auto &InfDir = Map.InferredDirectories[Directory];
2353 InfDir.InferModules =
true;
2354 InfDir.Attrs = MD.
Attrs;
2355 InfDir.ModuleMapFID = ModuleMapFID;
2362 [&](
const auto &
Other) {
2363 Diags.Report(
Other.Location,
2364 diag::err_mmap_expected_inferred_member)
2365 << (ActiveModule !=
nullptr);
2367 [&](
const modulemap::ExcludeDecl &ED) {
2371 diag::err_mmap_expected_inferred_member)
2372 << (ActiveModule !=
nullptr);
2376 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
2379 [&](
const modulemap::ExportDecl &ED) {
2381 if (!ActiveModule) {
2383 diag::err_mmap_expected_inferred_member)
2384 << (ActiveModule !=
nullptr);
2390 ActiveModule->InferExportWildcard =
true;
2392 Diags.Report(ED.
Id.front().second,
2393 diag::err_mmap_expected_export_wildcard);
2400 handleModuleDecl(MD);
2406 handleExternModuleDecl(EMD);
2417 handleExternModuleDecl(EMD);
2425 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
2426 if (Known != Modules.end())
2427 return Known->getValue();
2429 auto ParsedMod = ParsedModules.find(Name);
2430 if (ParsedMod == ParsedModules.end())
2433 Diags.Report(diag::remark_mmap_load_module) << Name;
2435 for (
const auto &ModuleDecl : ParsedMod->second) {
2448 bool ImplicitlyDiscovered,
2452 assert(Target &&
"Missing target information");
2453 llvm::DenseMap<const FileEntry *, bool>::iterator Known =
2454 LoadedModuleMap.find(
File);
2455 if (Known != LoadedModuleMap.end())
2456 return Known->second;
2459 if (ID.isInvalid()) {
2464 FileID &LocalFID = ModuleMapLocalFileID[
File];
2466 auto FileCharacter =
2468 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
2473 assert(Target &&
"Missing target information");
2474 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
2476 return LoadedModuleMap[
File] =
true;
2477 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
2478 "invalid buffer offset");
2481 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
2484 Diags.Report(diag::remark_mmap_load) <<
File.getName();
2486 ImplicitlyDiscovered);
2493 ParsedModuleMap.find(
File);
2494 if (PKnown == ParsedModuleMap.end()) {
2495 ParsedModuleMaps.push_back(
2496 std::make_unique<modulemap::ModuleMapFile>(std::move(*MMF)));
2497 ParsedModuleMap[
File] = &*ParsedModuleMaps.back();
2504 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
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
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.
Top level wrappers for InstallAPI frontend operations.
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...
@ Default
Set to the current date and time.
@ 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