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);
1271 for (llvm::vfs::directory_iterator
1272 Dir = FS.dir_begin(SubframeworksDirName, EC),
1274 Dir != DirEnd && !EC; Dir.increment(EC)) {
1275 if (!StringRef(Dir->path()).ends_with(
".framework"))
1283 StringRef SubframeworkDirName =
1285 bool FoundParent =
false;
1289 = llvm::sys::path::parent_path(SubframeworkDirName);
1290 if (SubframeworkDirName.empty())
1295 if (*SubDir == FrameworkDir) {
1306 inferFrameworkModule(*SubframeworkDir, Attrs,
Result);
1312 if (!
Result->isSubFramework())
1319 Module *ShadowingModule) {
1324 IsFramework,
false, NumCreatedModules++);
1325 Result->ShadowingModule = ShadowingModule;
1326 Result->markUnavailable(
true);
1327 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1328 ShadowModules.push_back(
Result);
1335 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1338 HeaderOwnerLocs[{&UmbrellaHeader.
getFileEntry(), Mod}] = Loc;
1343 PathRelativeToRootModuleDirectory.str();
1344 UmbrellaDirs[UmbrellaHeader.
getDir()] = Mod;
1350 for (
const auto &Cb : Callbacks)
1351 Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1357 FileMgr.getVirtualFileSystem().getDirectoryContentRealSources(Dir, Sources);
1358 for (StringRef Source : Sources) {
1367 FileMgr.makeAbsolutePath(Path);
1368 llvm::sys::path::remove_dots(Path,
true);
1373 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1378 PathRelativeToRootModuleDirectory.str();
1379 UmbrellaDirs[UmbrellaDir] = Mod;
1384void ModuleMap::addUnresolvedHeader(
Module *Mod,
1386 bool &NeedsFramework) {
1389 if (resolveAsBuiltinHeader(Mod, Header)) {
1408 LazyHeadersByModTime[*Header.
ModTime].push_back(Mod);
1410 LazyHeadersBySize[*Header.
Size].push_back(Mod);
1417 resolveHeader(Mod, Header, NeedsFramework);
1421 auto BySize = LazyHeadersBySize.find(
File->getSize());
1422 if (BySize != LazyHeadersBySize.end()) {
1423 for (
auto *M : BySize->second)
1425 LazyHeadersBySize.erase(BySize);
1428 auto ByModTime = LazyHeadersByModTime.find(
File->getModificationTime());
1429 if (ByModTime != LazyHeadersByModTime.end()) {
1430 for (
auto *M : ByModTime->second)
1432 LazyHeadersByModTime.erase(ByModTime);
1437 Module *Mod, std::optional<const FileEntry *>
File)
const {
1438 bool NeedsFramework =
false;
1440 const auto Size =
File ? (*File)->getSize() : 0;
1441 const auto ModTime =
File ? (*File)->getModificationTime() : 0;
1445 (Header.
Size && Header.
Size != Size)))
1446 NewHeaders.push_back(Header);
1450 const_cast<ModuleMap *
>(
this)->resolveHeader(Mod, Header, NeedsFramework);
1465 auto &HeaderList = Headers[HeaderEntry];
1466 if (llvm::is_contained(HeaderList, KH))
1470 HeaderOwnerLocs[{&HeaderEntry.
getFileEntry(), Mod}] = Loc;
1472 HeaderList.push_back(KH);
1475 bool isCompilingModuleHeader = Mod->
isForBuilding(LangOpts);
1476 if (!Imported || isCompilingModuleHeader) {
1479 HeaderInfo.MarkFileModuleHeader(HeaderEntry,
Role, isCompilingModuleHeader);
1483 for (
const auto &Cb : Callbacks)
1484 Cb->moduleMapAddHeader(HeaderEntry.
getName());
1488 bool ImplicitlyDiscovered,
1491 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
1492 Known = ParsedModuleMap.find(
File);
1493 if (Known != ParsedModuleMap.end())
1494 return Known->second ==
nullptr;
1497 if (ID.isInvalid()) {
1498 FileID &LocalFID = ModuleMapLocalFileID[
File];
1500 auto FileCharacter =
1502 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
1507 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
1509 ParsedModuleMap[
File] =
nullptr;
1513 Diags.Report(diag::remark_mmap_parse) <<
File.getName();
1515 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered,
nullptr);
1518 ParsedModuleMap[
File] =
nullptr;
1522 ParsedModuleMaps.push_back(
1523 std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));
1525 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
1528 for (
const auto &
Decl : MD.Decls) {
1529 std::visit(llvm::makeVisitor(
1532 if (SubMD.
Id.front().first ==
"*")
1534 CollectExternDecls(SubMD);
1537 PendingExternalModuleMaps.push_back(&EMD);
1547 std::visit(llvm::makeVisitor(
1553 ParsedModules[StringRef(MD.
Id.front().first)];
1554 ModuleDecls.push_back(std::pair(&MMF, &MD));
1555 CollectExternDecls(MD);
1558 PendingExternalModuleMaps.push_back(&EMD);
1564 StringRef FileNameRef = EMD->Path;
1566 if (llvm::sys::path::is_relative(FileNameRef)) {
1567 ModuleMapFileName += Dir.
getName();
1568 llvm::sys::path::append(ModuleMapFileName, EMD->Path);
1569 FileNameRef = ModuleMapFileName;
1573 SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {
1575 EFile->getDir(),
FileID(), ExternModuleLoc);
1579 ParsedModuleMap[
File] = &MMF;
1581 for (
const auto &Cb : Callbacks)
1588 for (
const auto &Entry : ParsedModules)
1606 assert(InferredModuleAllowedBy.count(M) &&
"missing inferred module map");
1607 return InferredModuleAllowedBy.find(M)->second;
1619 InferredModuleAllowedBy[M] = ModMapFID;
1624 StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1628 if (llvm::sys::path::filename(Dir) ==
"Modules") {
1629 StringRef Parent = llvm::sys::path::parent_path(Dir);
1630 if (Parent.ends_with(
".framework"))
1637 return llvm::errorToErrorCode(DirEntry.takeError());
1641 if (CanonicalDir != Dir)
1642 llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1650 llvm::sys::path::remove_dots(Path);
1652 return std::error_code();
1661 llvm::errs() <<
"Modules:";
1662 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1663 MEnd = Modules.end();
1665 M->getValue()->
print(llvm::errs(), 2);
1667 llvm::errs() <<
"Headers:";
1668 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1670 llvm::errs() <<
" \"" << H->first.getName() <<
"\" -> ";
1672 E = H->second.end();
1674 if (I != H->second.begin())
1675 llvm::errs() <<
",";
1676 llvm::errs() << I->getModule()->getFullModuleName();
1678 llvm::errs() <<
"\n";
1687 if (Export.first || Export.second)
1688 Mod->
Exports.push_back(Export);
1697 auto Unresolved = std::move(Top->UnresolvedDirectUses);
1698 Top->UnresolvedDirectUses.clear();
1700 Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1702 Top->DirectUses.push_back(DirectUse);
1704 Top->UnresolvedDirectUses.push_back(UDU);
1706 return !Top->UnresolvedDirectUses.empty();
1713 if (
Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1715 Conflict.
Other = OtherMod;
1716 Conflict.
Message = UC.Message;
1748 bool ImplicitlyDiscovered;
1751 bool HadError =
false;
1754 Module *ActiveModule =
nullptr;
1785 using Attributes = ModuleMap::Attributes;
1791 bool ImplicitlyDiscovered)
1792 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
1793 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
1794 ImplicitlyDiscovered(ImplicitlyDiscovered) {}
1807void ModuleMapLoader::diagnosePrivateModules(
SourceLocation StartLoc) {
1808 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1809 const Module *M, SourceRange ReplLoc) {
1810 auto D = Diags.Report(ActiveModule->DefinitionLoc,
1811 diag::note_mmap_rename_top_level_private_module);
1812 D << BadName << M->Name;
1816 for (
auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1817 auto const *M = E->getValue();
1818 if (M->Directory != ActiveModule->Directory)
1821 SmallString<128> FullName(ActiveModule->getFullModuleName());
1822 if (!FullName.starts_with(M->Name) && !FullName.ends_with(
"Private"))
1824 SmallString<128> FixedPrivModDecl;
1825 SmallString<128> Canonical(M->Name);
1826 Canonical.append(
"_Private");
1829 if (ActiveModule->Parent && ActiveModule->Name ==
"Private" && !M->Parent &&
1830 M->Name == ActiveModule->Parent->Name) {
1831 Diags.Report(ActiveModule->DefinitionLoc,
1832 diag::warn_mmap_mismatched_private_submodule)
1835 SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1837 FixItInitBegin = StartLoc;
1839 if (ActiveModule->Parent->IsFramework)
1840 FixedPrivModDecl.append(
"framework ");
1841 FixedPrivModDecl.append(
"module ");
1842 FixedPrivModDecl.append(Canonical);
1844 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1845 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1850 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1851 ActiveModule->Name != Canonical) {
1852 Diags.Report(ActiveModule->DefinitionLoc,
1853 diag::warn_mmap_mismatched_private_module_name)
1854 << ActiveModule->Name;
1855 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1856 SourceRange(ActiveModule->DefinitionLoc));
1862 if (MD.
Id.front().first ==
"*")
1863 return handleInferredModuleDecl(MD);
1867 Module *PreviousActiveModule = ActiveModule;
1868 if (MD.
Id.size() > 1) {
1871 ActiveModule =
nullptr;
1872 const Module *TopLevelModule =
nullptr;
1873 for (
unsigned I = 0, N = MD.
Id.size() - 1; I != N; ++I) {
1875 Map.lookupModuleQualified(MD.
Id[I].first, ActiveModule)) {
1877 TopLevelModule =
Next;
1878 ActiveModule =
Next;
1882 Diags.Report(MD.
Id[I].second, diag::err_mmap_missing_parent_module)
1883 << MD.
Id[I].first << (ActiveModule !=
nullptr)
1885 ? ActiveModule->getTopLevelModule()->getFullModuleName()
1890 if (TopLevelModule &&
1891 ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
1892 assert(ModuleMapFID !=
1893 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
1894 "submodule defined in same file as 'module *' that allowed its "
1895 "top-level module");
1896 Map.addAdditionalModuleMapFile(
1897 TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
1901 StringRef ModuleName = MD.
Id.back().first;
1902 SourceLocation ModuleNameLoc = MD.
Id.back().second;
1905 Module *ShadowingModule =
nullptr;
1906 if (
Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1912 bool LoadedFromASTFile = Existing->IsFromModuleFile;
1913 if (LoadedFromASTFile) {
1915 Map.getContainingModuleMapFile(Existing);
1917 SourceMgr.getFileEntryRefForID(ModuleMapFID);
1918 if ((ExistingModMapFile && CurrentModMapFile &&
1919 *ExistingModMapFile == *CurrentModMapFile) ||
1920 Existing->DefinitionLoc.isInvalid()) {
1924 LoadedFromASTFile =
true;
1926 LoadedFromASTFile =
false;
1929 bool Inferred = Existing->IsInferred;
1945 bool PartOfFramework = MD.
Framework || Existing->isPartOfFramework();
1948 bool ParsedAsMainInput =
1950 Map.LangOpts.CurrentModule == ModuleName &&
1951 SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
1952 SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
1955 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
1956 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
1958 ActiveModule = PreviousActiveModule;
1963 if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
1964 ShadowingModule = Existing;
1967 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1969 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1976 if (ShadowingModule) {
1978 Map.createShadowedModule(ModuleName, MD.
Framework, ShadowingModule);
1980 ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
1984 ActiveModule->DefinitionLoc = ModuleNameLoc;
1986 ActiveModule->IsSystem =
true;
1988 ActiveModule->IsExternC =
true;
1990 ActiveModule->NoUndeclaredIncludes =
true;
1991 ActiveModule->Directory = Directory;
1993 StringRef MapFileName(
1994 SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
1995 if (MapFileName.ends_with(
"module.private.modulemap") ||
1996 MapFileName.ends_with(
"module_private.map")) {
1997 ActiveModule->ModuleMapIsPrivate =
true;
2003 SourceLocation StartLoc =
2004 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
2005 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
2006 !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
2008 !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
2010 ActiveModule->ModuleMapIsPrivate)
2011 diagnosePrivateModules(MD.
Location);
2016 [&](
const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
2017 [&](
const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
2018 [&](
const modulemap::UmbrellaDirDecl &UDD) {
2019 handleUmbrellaDirDecl(UDD);
2021 [&](
const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
2022 [&](
const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
2023 [&](
const modulemap::ExportAsDecl &EAD) {
2024 handleExportAsDecl(EAD);
2026 [&](
const modulemap::ExternModuleDecl &EMD) {
2027 handleExternModuleDecl(EMD);
2029 [&](
const modulemap::UseDecl &UD) { handleUseDecl(UD); },
2030 [&](
const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
2031 [&](
const modulemap::ConfigMacrosDecl &CMD) {
2032 handleConfigMacros(CMD);
2034 [&](
const modulemap::ConflictDecl &CD) { handleConflict(CD); },
2035 [&](
const modulemap::ExcludeDecl &ED) {
2036 Diags.Report(ED.Location, diag::err_mmap_expected_member);
2043 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2044 ActiveModule->LinkLibraries.empty())
2049 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2050 ActiveModule->Parent) {
2051 ActiveModule->getTopLevelModule()->markUnavailable(
false);
2052 ActiveModule->getTopLevelModule()->MissingHeaders.append(
2053 ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2057 ActiveModule = PreviousActiveModule;
2060void ModuleMapLoader::handleExternModuleDecl(
2062 StringRef FileNameRef = EMD.
Path;
2063 SmallString<128> ModuleMapFileName;
2064 if (llvm::sys::path::is_relative(FileNameRef)) {
2065 ModuleMapFileName += Directory.getName();
2066 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
2073 llvm::sys::path::remove_dots(ModuleMapFileName,
true);
2074 FileNameRef = ModuleMapFileName;
2076 if (
auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
2077 Map.parseAndLoadModuleMapFile(
2078 *
File, IsSystem, ImplicitlyDiscovered,
2079 Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
2101 bool &IsRequiresExcludedHack) {
2105 IsRequiresExcludedHack =
true;
2116 for (
const modulemap::RequiresFeature &RF : RD.
Features) {
2117 bool IsRequiresExcludedHack =
false;
2118 bool ShouldAddRequirement =
2121 if (IsRequiresExcludedHack)
2122 UsesRequiresExcludedHack.insert(ActiveModule);
2124 if (ShouldAddRequirement) {
2145 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2151 Module::UnresolvedHeaderDirective Header;
2155 Header.
Kind = Map.headerRoleToKind(
Role);
2159 !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2160 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
2161 << ActiveModule->getFullModuleName();
2166 if (ImplicitlyDiscovered) {
2167 SmallString<128> NormalizedPath(HD.
Path);
2168 llvm::sys::path::remove_dots(NormalizedPath,
true);
2169 if (NormalizedPath.starts_with(
".."))
2170 Diags.Report(HD.
PathLoc, diag::warn_mmap_path_outside_directory);
2178 bool NeedsFramework =
false;
2182 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2184 ActiveModule->fullModuleNameIs({
"_Builtin_stddef",
"max_align_t"}))
2185 Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2188 Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2189 << ActiveModule->getFullModuleName()
2198void ModuleMapLoader::handleUmbrellaDirDecl(
2200 std::string DirName = std::string(UDD.
Path);
2201 std::string DirNameAsWritten = DirName;
2204 if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2205 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2206 << ActiveModule->getFullModuleName();
2211 if (ImplicitlyDiscovered) {
2212 SmallString<128> NormalizedPath(UDD.
Path);
2213 llvm::sys::path::remove_dots(NormalizedPath,
true);
2214 if (NormalizedPath.starts_with(
".."))
2215 Diags.Report(UDD.
Location, diag::warn_mmap_path_outside_directory);
2220 if (llvm::sys::path::is_absolute(DirName)) {
2221 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2223 SmallString<128> PathName;
2224 PathName = Directory.getName();
2225 llvm::sys::path::append(PathName, DirName);
2226 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2230 Diags.Report(UDD.
Location, diag::warn_mmap_umbrella_dir_not_found)
2235 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2241 SmallVector<Module::Header, 6> Headers;
2242 llvm::vfs::FileSystem &FS =
2243 SourceMgr.getFileManager().getVirtualFileSystem();
2244 Map.recordDirectoryDependencies(ActiveModule, Dir->
getName());
2245 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->
getName(), EC), E;
2246 I != E && !EC; I.increment(EC)) {
2247 if (
auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2248 Module::Header Header = {
"", std::string(I->path()), *FE};
2249 Headers.push_back(std::move(Header));
2256 for (
auto &Header : Headers)
2261 if (
Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2262 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2263 << OwningModule->getFullModuleName();
2269 Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName,
2275 ActiveModule->UnresolvedExports.push_back(
Unresolved);
2279 const auto &ModName = EAD.
Id.front();
2281 if (!ActiveModule->ExportAsModule.empty()) {
2282 if (ActiveModule->ExportAsModule == ModName.first) {
2283 Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)
2284 << ActiveModule->Name << ModName.first;
2286 Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)
2287 << ActiveModule->Name << ActiveModule->ExportAsModule
2292 ActiveModule->ExportAsModule = ModName.first;
2293 Map.addLinkAsDependency(ActiveModule);
2297 if (ActiveModule->Parent)
2298 Diags.Report(UD.
Location, diag::err_mmap_use_decl_submodule);
2300 ActiveModule->UnresolvedDirectUses.push_back(UD.
Id);
2304 ActiveModule->LinkLibraries.push_back(
2308void ModuleMapLoader::handleConfigMacros(
2310 if (ActiveModule->Parent) {
2311 Diags.Report(CMD.
Location, diag::err_mmap_config_macro_submodule);
2318 ActiveModule->ConfigMacrosExhaustive =
true;
2320 ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
2325 Module::UnresolvedConflict Conflict;
2327 Conflict.
Id = CD.
Id;
2331 ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));
2334void ModuleMapLoader::handleInferredModuleDecl(
2336 SourceLocation StarLoc = MD.
Id.front().second;
2340 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2346 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
2347 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2352 if (ActiveModule->InferSubmodules) {
2353 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2354 if (ActiveModule->InferredSubmoduleLoc.isValid())
2355 Diags.Report(ActiveModule->InferredSubmoduleLoc,
2356 diag::note_mmap_prev_definition);
2362 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2366 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2372 ActiveModule->InferSubmodules =
true;
2373 ActiveModule->InferredSubmoduleLoc = StarLoc;
2374 ActiveModule->InferExplicitSubmodules = MD.
Explicit;
2377 auto &InfDir = Map.InferredDirectories[Directory];
2378 InfDir.InferModules =
true;
2379 InfDir.Attrs = MD.
Attrs;
2380 InfDir.ModuleMapFID = ModuleMapFID;
2387 [&](
const auto &
Other) {
2388 Diags.Report(
Other.Location,
2389 diag::err_mmap_expected_inferred_member)
2390 << (ActiveModule !=
nullptr);
2392 [&](
const modulemap::ExcludeDecl &ED) {
2396 diag::err_mmap_expected_inferred_member)
2397 << (ActiveModule !=
nullptr);
2401 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
2404 [&](
const modulemap::ExportDecl &ED) {
2406 if (!ActiveModule) {
2408 diag::err_mmap_expected_inferred_member)
2409 << (ActiveModule !=
nullptr);
2415 ActiveModule->InferExportWildcard =
true;
2417 Diags.Report(ED.
Id.front().second,
2418 diag::err_mmap_expected_export_wildcard);
2425 handleModuleDecl(MD);
2431 handleExternModuleDecl(EMD);
2442 handleExternModuleDecl(EMD);
2450 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
2451 if (Known != Modules.end())
2452 return Known->getValue();
2454 auto ParsedMod = ParsedModules.find(Name);
2455 if (ParsedMod == ParsedModules.end())
2458 Diags.Report(diag::remark_mmap_load_module) << Name;
2460 for (
const auto &ModuleDecl : ParsedMod->second) {
2473 bool ImplicitlyDiscovered,
2477 assert(Target &&
"Missing target information");
2478 llvm::DenseMap<const FileEntry *, bool>::iterator Known =
2479 LoadedModuleMap.find(
File);
2480 if (Known != LoadedModuleMap.end())
2481 return Known->second;
2484 if (ID.isInvalid()) {
2489 FileID &LocalFID = ModuleMapLocalFileID[
File];
2491 auto FileCharacter =
2493 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
2498 assert(Target &&
"Missing target information");
2499 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
2501 return LoadedModuleMap[
File] =
true;
2502 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
2503 "invalid buffer offset");
2506 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
2509 Diags.Report(diag::remark_mmap_load) <<
File.getName();
2511 ImplicitlyDiscovered);
2518 ParsedModuleMap.find(
File);
2519 if (PKnown == ParsedModuleMap.end()) {
2520 ParsedModuleMaps.push_back(
2521 std::make_unique<modulemap::ModuleMapFile>(std::move(*MMF)));
2522 ParsedModuleMap[
File] = &*ParsedModuleMaps.back();
2529 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.
void recordDirectoryDependencies(Module *Mod, StringRef Dir)
Record that Mod depends on the listing of Dir. Dir is a VFS path.
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.
static void canonicalizeDirectoryDependency(const FileManager &FileMgr, SmallVectorImpl< char > &Path)
Spell Path the way directory dependencies are recorded: absolute, with dots removed.
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.
void addDirectoryDependency(StringRef Path)
Record that this module depends on the listing of Path, which must name a location in an underlying f...
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