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>
49void ModuleMapCallbacks::anchor() {}
52 auto PendingLinkAs = PendingLinkAsModule.find(Mod->
Name);
53 if (PendingLinkAs != PendingLinkAsModule.end()) {
54 for (
auto &Name : PendingLinkAs->second) {
57 M->UseExportAsModuleLinkName =
true;
82 llvm_unreachable(
"unknown header role");
99 llvm_unreachable(
"unknown header kind");
107ModuleMap::resolveExport(
Module *Mod,
109 bool Complain)
const {
112 assert(
Unresolved.Wildcard &&
"Invalid unresolved export");
125 bool Complain)
const {
130 Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
137 for (
unsigned I = 1, N = Id.size(); I != N; ++I) {
141 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
142 << Id[I].first << Context->getFullModuleName()
143 << SourceRange(Id[0].second, Id[I-1].second);
160 for (; Mod; Mod = Mod->
Parent) {
162 Paths.push_back(Mod->
Name);
169 for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
170 llvm::sys::path::append(Path,
"Frameworks", Framework +
".framework");
178 SmallString<128> FullPathName(Directory->getName());
182 expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190 unsigned FullPathLength = FullPathName.size();
192 unsigned RelativePathLength = RelativePathName.size();
195 llvm::sys::path::append(RelativePathName,
"Headers", Header.
FileName);
196 llvm::sys::path::append(FullPathName, RelativePathName);
197 if (
auto File = GetFile(FullPathName))
207 RelativePathName.clear();
209 RelativePathName.resize(RelativePathLength);
210 FullPathName.resize(FullPathLength);
211 llvm::sys::path::append(RelativePathName,
"PrivateHeaders",
213 llvm::sys::path::append(FullPathName, RelativePathName);
214 return GetFile(FullPathName);
217 if (llvm::sys::path::is_absolute(Header.
FileName)) {
218 RelativePathName.clear();
224 return GetFrameworkFile();
227 llvm::sys::path::append(RelativePathName, Header.
FileName);
228 llvm::sys::path::append(FullPathName, RelativePathName);
229 auto NormalHdrFile = GetFile(FullPathName);
231 if (!NormalHdrFile && Directory->getName().ends_with(
".framework")) {
235 FullPathName.assign(Directory->getName());
236 RelativePathName.clear();
237 if (GetFrameworkFile()) {
239 diag::warn_mmap_incomplete_framework_module_declaration)
241 NeedsFramework =
true;
246 return NormalHdrFile;
253 return llvm::StringSwitch<bool>(
FileName)
254 .Case(
"float.h",
true)
255 .Case(
"iso646.h",
true)
256 .Case(
"limits.h",
true)
257 .Case(
"stdalign.h",
true)
258 .Case(
"stdarg.h",
true)
259 .Case(
"stdatomic.h",
true)
260 .Case(
"stdbool.h",
true)
261 .Case(
"stdckdint.h",
true)
262 .Case(
"stdcountof.h",
true)
263 .Case(
"stddef.h",
true)
264 .Case(
"stdint.h",
true)
265 .Case(
"tgmath.h",
true)
266 .Case(
"unwind.h",
true)
273 return llvm::StringSwitch<bool>(ModuleName)
274 .Case(
"_Builtin_float",
true)
275 .Case(
"_Builtin_inttypes",
true)
276 .Case(
"_Builtin_iso646",
true)
277 .Case(
"_Builtin_limits",
true)
278 .Case(
"_Builtin_stdalign",
true)
279 .Case(
"_Builtin_stdarg",
true)
280 .Case(
"_Builtin_stdatomic",
true)
281 .Case(
"_Builtin_stdbool",
true)
282 .Case(
"_Builtin_stddef",
true)
283 .Case(
"_Builtin_stdint",
true)
284 .Case(
"_Builtin_stdnoreturn",
true)
285 .Case(
"_Builtin_tgmath",
true)
286 .Case(
"_Builtin_unwind",
true)
290void ModuleMap::resolveHeader(
Module *Mod,
292 bool &NeedsFramework) {
293 SmallString<128> RelativePathName;
295 findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
297 const DirectoryEntry *UmbrellaDir = &
File->getDir().getDirEntry();
298 if (
Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
299 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
300 << UmbrellaMod->getFullModuleName();
304 RelativePathName.str());
306 Module::Header H = {Header.
FileName, std::string(RelativePathName),
328bool ModuleMap::resolveAsBuiltinHeader(
331 llvm::sys::path::is_absolute(Header.
FileName) ||
333 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->
Directory ||
340 SmallString<128> Path;
341 llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.
FileName);
342 auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
355 : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
356 HeaderInfo(HeaderInfo) {
362 assert((!this->Target || this->Target == &Target) &&
363 "Improper target override");
364 this->Target = &Target;
378 Buffer.push_back(
'_');
379 Buffer.reserve(Buffer.size() + Name.size());
380 for (
unsigned I = 0, N = Name.size(); I != N; ++I) {
382 Buffer.push_back(Name[I]);
384 Buffer.push_back(
'_');
387 Name = StringRef(Buffer.data(), Buffer.size());
390 while (llvm::StringSwitch<bool>(Name)
393#include
"clang/Basic/TokenKinds.def"
395 if (Name.data() != Buffer.data())
396 Buffer.append(Name.begin(), Name.end());
397 Buffer.push_back(
'_');
398 Name = StringRef(Buffer.data(), Buffer.size());
405 return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
411 return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
416ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(
FileEntryRef File) {
418 HeadersMap::iterator Known = Headers.find(
File);
422 return Headers.find(
File);
429 if (UmbrellaDirs.empty())
438 StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
443 auto KnownDir = UmbrellaDirs.find(*Dir);
444 if (KnownDir != UmbrellaDirs.end())
447 IntermediateDirs.push_back(*Dir);
450 DirName = llvm::sys::path::parent_path(DirName);
455 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
468 bool IsPrivate =
false;
472 for (
auto Hs : HeaderList)
473 IsPrivate |= llvm::any_of(
475 assert(IsPrivate &&
"inconsistent headers and roles");
486 bool RequestingModuleIsModuleInterface,
494 if (RequestingModule) {
499 bool Excluded =
false;
501 Module *NotUsed =
nullptr;
503 HeadersMap::iterator Known = findKnownHeader(
File);
504 if (Known != Headers.end()) {
520 if (RequestingModule && LangOpts.ModulesDeclUse &&
535 Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
542 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
548 if (Excluded || isHeaderInUmbrellaDirs(
File))
553 if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
554 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
556 }
else if (RequestingModule && RequestingModuleIsModuleInterface &&
557 LangOpts.isCompilingModule()) {
560 diag::warn_non_modular_include_in_framework_module :
561 diag::warn_non_modular_include_in_module;
597 bool AllowExcluded) {
604 HeadersMap::iterator Known = findKnownHeader(
File);
605 if (Known != Headers.end()) {
614 return MakeResult(H);
618 return MakeResult(
Result);
621 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(
File));
625 Module *M, std::string NameAsWritten,
628 Header.
FileName = std::move(NameAsWritten);
631 return findHeader(M, Header, RelativePathName, NeedsFramework);
636 assert(!Headers.count(
File) &&
"already have a module for this header");
639 KnownHeader H = findHeaderInUmbrellaDirs(
File, SkippedDirs);
647 UmbrellaModule = UmbrellaModule->
Parent;
661 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
667 UmbrellaDirs[SkippedDir] =
Result;
678 llvm::sys::path::stem(
File.getName()), NameBuf);
682 Result->addTopHeader(
File);
691 for (
unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
692 UmbrellaDirs[SkippedDirs[I]] =
Result;
696 Headers[
File].push_back(Header);
705 HeadersMap::iterator Known = findKnownHeader(
File);
706 if (Known != Headers.end())
707 return Known->second;
709 if (findOrCreateModuleForHeaderInUmbrellaDir(
File))
710 return Headers.find(
File)->second;
719 auto It = Headers.find(
File);
720 if (It == Headers.end())
732 HeadersMap::const_iterator Known = Headers.find(Header);
733 if (Known != Headers.end()) {
735 I = Known->second.begin(),
736 E = Known->second.end();
742 if (I->isAvailable() &&
743 (!RequestingModule ||
760 StringRef DirName = Dir->
getName();
762 auto IsUnavailable = [&](
const Module *M) {
770 auto KnownDir = UmbrellaDirs.find(*Dir);
771 if (KnownDir != UmbrellaDirs.end()) {
773 if (IsUnavailable(
Found))
781 UmbrellaModule = UmbrellaModule->
Parent;
788 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
792 if (IsUnavailable(
Found))
799 llvm::sys::path::stem(Header.
getName()),
806 return IsUnavailable(
Found);
809 SkippedDirs.push_back(*Dir);
812 DirName = llvm::sys::path::parent_path(DirName);
817 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
824 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
825 if (Known != Modules.end())
826 return Known->getValue();
842 if (
Result->InferExportWildcard)
849 for(; Context; Context = Context->Parent) {
861 return Context->findSubmodule(Name);
870 return std::make_pair(Sub,
false);
874 return std::make_pair(M,
true);
878 bool IsFramework,
bool IsExplicit) {
880 "Creating duplicate submodule");
884 IsFramework, IsExplicit, NumCreatedModules++);
886 if (LangOpts.CurrentModule == Name)
889 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
898 true, NumCreatedModules++);
903 PendingSubmodules.emplace_back(
Result);
910 assert(Parent &&
"We should only create an implicit global module fragment "
911 "in a module purview");
915 auto *
Result =
new (ModulesAlloc.Allocate())
917 false,
false, NumCreatedModules++);
927 true, NumCreatedModules++);
934 auto *
Result =
new (ModulesAlloc.Allocate())
936 false, NumCreatedModules++);
940 for (
auto &Submodule : PendingSubmodules)
941 Submodule->setParent(
Result);
942 PendingSubmodules.clear();
948 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
949 assert(!Modules[Name] &&
"redefining existing module");
953 Modules[Name] = SourceModule =
Result;
957 auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
958 assert(MainFile &&
"no input file for module interface");
966 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
969 "creating implementation module without an interface");
974 StringRef IName =
".ImplementationUnit";
975 assert(!Modules[IName] &&
"multiple implementation units?");
979 Modules[IName] = SourceModule =
Result;
982 assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
983 "no input file for module implementation");
990 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
991 assert(!Modules[Name] &&
"redefining existing module");
993 auto *
Result =
new (ModulesAlloc.Allocate())
995 false, NumCreatedModules++);
997 Modules[Name] = SourceModule =
Result;
1005 assert(Mod->
IsFramework &&
"Can only infer linking for framework modules");
1007 "Can only infer linking for top-level frameworks");
1009 StringRef FrameworkName(Mod->
Name);
1010 FrameworkName.consume_back(
"_Private");
1016 bool IsSystem,
Module *Parent) {
1019 return inferFrameworkModule(FrameworkDir, Attrs, Parent);
1023 Attributes Attrs,
Module *Parent) {
1028 StringRef FrameworkDirName =
1029 SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
1036 llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
1049 bool canInfer =
false;
1050 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
1052 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
1053 if (
auto ParentDir =
FileMgr.getOptionalDirectoryRef(Parent)) {
1056 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1057 inferred = InferredDirectories.find(*ParentDir);
1058 if (inferred == InferredDirectories.end()) {
1061 bool IsFrameworkDir = Parent.ends_with(
".framework");
1069 inferred = InferredDirectories.find(*ParentDir);
1072 if (inferred == InferredDirectories.end())
1073 inferred = InferredDirectories.insert(
1074 std::make_pair(*ParentDir, InferredDirectory())).first;
1077 if (inferred->second.InferModules) {
1080 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1082 !llvm::is_contained(inferred->second.ExcludedModules, Name);
1084 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1085 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1086 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1087 Attrs.NoUndeclaredIncludes |=
1088 inferred->second.Attrs.NoUndeclaredIncludes;
1089 ModuleMapFID = inferred->second.ModuleMapFID;
1102 SmallString<128> UmbrellaName = FrameworkDir.
getName();
1103 llvm::sys::path::append(UmbrellaName,
"Headers", ModuleName +
".h");
1109 if (!UmbrellaHeader)
1113 Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1114 true,
false, NumCreatedModules++);
1117 if (LangOpts.CurrentModule == ModuleName)
1119 Modules[ModuleName] =
Result;
1120 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1123 Result->IsSystem |= Attrs.IsSystem;
1124 Result->IsExternC |= Attrs.IsExternC;
1125 Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1126 Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1127 Result->Directory = FrameworkDir;
1130 StringRef RelativePath = UmbrellaName.str().substr(
1131 Result->getTopLevelModule()->Directory->getName().size());
1132 RelativePath = llvm::sys::path::relative_path(RelativePath);
1142 Result->InferSubmodules =
true;
1143 Result->InferExportWildcard =
true;
1147 SmallString<128> SubframeworksDirName = FrameworkDir.
getName();
1148 llvm::sys::path::append(SubframeworksDirName,
"Frameworks");
1149 llvm::sys::path::native(SubframeworksDirName);
1151 for (llvm::vfs::directory_iterator
1152 Dir = FS.dir_begin(SubframeworksDirName, EC),
1154 Dir != DirEnd && !EC; Dir.increment(EC)) {
1155 if (!StringRef(Dir->path()).ends_with(
".framework"))
1163 StringRef SubframeworkDirName =
1165 bool FoundParent =
false;
1169 = llvm::sys::path::parent_path(SubframeworkDirName);
1170 if (SubframeworkDirName.empty())
1175 if (*SubDir == FrameworkDir) {
1186 inferFrameworkModule(*SubframeworkDir, Attrs,
Result);
1192 if (!
Result->isSubFramework())
1199 Module *ShadowingModule) {
1204 IsFramework,
false, NumCreatedModules++);
1205 Result->ShadowingModule = ShadowingModule;
1206 Result->markUnavailable(
true);
1207 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1208 ShadowModules.push_back(
Result);
1215 const Twine &PathRelativeToRootModuleDirectory) {
1220 PathRelativeToRootModuleDirectory.str();
1221 UmbrellaDirs[UmbrellaHeader.
getDir()] = Mod;
1224 for (
const auto &Cb : Callbacks)
1225 Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1230 const Twine &PathRelativeToRootModuleDirectory) {
1234 PathRelativeToRootModuleDirectory.str();
1235 UmbrellaDirs[UmbrellaDir] = Mod;
1238void ModuleMap::addUnresolvedHeader(
Module *Mod,
1240 bool &NeedsFramework) {
1243 if (resolveAsBuiltinHeader(Mod, Header)) {
1262 LazyHeadersByModTime[*Header.
ModTime].push_back(Mod);
1264 LazyHeadersBySize[*Header.
Size].push_back(Mod);
1271 resolveHeader(Mod, Header, NeedsFramework);
1275 auto BySize = LazyHeadersBySize.find(
File->getSize());
1276 if (BySize != LazyHeadersBySize.end()) {
1277 for (
auto *M : BySize->second)
1279 LazyHeadersBySize.erase(BySize);
1282 auto ByModTime = LazyHeadersByModTime.find(
File->getModificationTime());
1283 if (ByModTime != LazyHeadersByModTime.end()) {
1284 for (
auto *M : ByModTime->second)
1286 LazyHeadersByModTime.erase(ByModTime);
1291 Module *Mod, std::optional<const FileEntry *>
File)
const {
1292 bool NeedsFramework =
false;
1294 const auto Size =
File ? (*File)->getSize() : 0;
1295 const auto ModTime =
File ? (*File)->getModificationTime() : 0;
1299 (Header.
Size && Header.
Size != Size)))
1300 NewHeaders.push_back(Header);
1304 const_cast<ModuleMap *
>(
this)->resolveHeader(Mod, Header, NeedsFramework);
1318 auto &HeaderList = Headers[HeaderEntry];
1319 if (llvm::is_contained(HeaderList, KH))
1322 HeaderList.push_back(KH);
1325 bool isCompilingModuleHeader = Mod->
isForBuilding(LangOpts);
1326 if (!Imported || isCompilingModuleHeader) {
1329 HeaderInfo.MarkFileModuleHeader(HeaderEntry,
Role, isCompilingModuleHeader);
1333 for (
const auto &Cb : Callbacks)
1334 Cb->moduleMapAddHeader(HeaderEntry.
getName());
1338 bool ImplicitlyDiscovered,
1341 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
1342 Known = ParsedModuleMap.find(
File);
1343 if (Known != ParsedModuleMap.end())
1344 return Known->second ==
nullptr;
1347 if (ID.isInvalid()) {
1348 FileID &LocalFID = ModuleMapLocalFileID[
File];
1350 auto FileCharacter =
1352 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
1357 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
1359 ParsedModuleMap[
File] =
nullptr;
1363 Diags.Report(diag::remark_mmap_parse) <<
File.getName();
1365 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered,
nullptr);
1368 ParsedModuleMap[
File] =
nullptr;
1372 ParsedModuleMaps.push_back(
1373 std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));
1375 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
1378 for (
const auto &
Decl : MD.Decls) {
1379 std::visit(llvm::makeVisitor(
1382 if (SubMD.
Id.front().first ==
"*")
1384 CollectExternDecls(SubMD);
1387 PendingExternalModuleMaps.push_back(&EMD);
1397 std::visit(llvm::makeVisitor(
1403 ParsedModules[StringRef(MD.
Id.front().first)];
1404 ModuleDecls.push_back(std::pair(&MMF, &MD));
1405 CollectExternDecls(MD);
1408 PendingExternalModuleMaps.push_back(&EMD);
1414 StringRef FileNameRef = EMD->Path;
1416 if (llvm::sys::path::is_relative(FileNameRef)) {
1417 ModuleMapFileName += Dir.
getName();
1418 llvm::sys::path::append(ModuleMapFileName, EMD->Path);
1419 FileNameRef = ModuleMapFileName;
1423 SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {
1425 EFile->getDir(),
FileID(), ExternModuleLoc);
1429 ParsedModuleMap[
File] = &MMF;
1431 for (
const auto &Cb : Callbacks)
1438 for (
const auto &Entry : ParsedModules)
1456 assert(InferredModuleAllowedBy.count(M) &&
"missing inferred module map");
1457 return InferredModuleAllowedBy.find(M)->second;
1469 InferredModuleAllowedBy[M] = ModMapFID;
1474 StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1478 if (llvm::sys::path::filename(Dir) ==
"Modules") {
1479 StringRef Parent = llvm::sys::path::parent_path(Dir);
1480 if (Parent.ends_with(
".framework"))
1487 return llvm::errorToErrorCode(DirEntry.takeError());
1491 if (CanonicalDir != Dir)
1492 llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1500 llvm::sys::path::remove_dots(Path);
1502 return std::error_code();
1511 llvm::errs() <<
"Modules:";
1512 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1513 MEnd = Modules.end();
1515 M->getValue()->
print(llvm::errs(), 2);
1517 llvm::errs() <<
"Headers:";
1518 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1520 llvm::errs() <<
" \"" << H->first.getName() <<
"\" -> ";
1522 E = H->second.end();
1524 if (I != H->second.begin())
1525 llvm::errs() <<
",";
1526 llvm::errs() << I->getModule()->getFullModuleName();
1528 llvm::errs() <<
"\n";
1537 if (Export.getPointer() || Export.getInt())
1538 Mod->
Exports.push_back(Export);
1547 auto Unresolved = std::move(Top->UnresolvedDirectUses);
1548 Top->UnresolvedDirectUses.clear();
1550 Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1552 Top->DirectUses.push_back(DirectUse);
1554 Top->UnresolvedDirectUses.push_back(UDU);
1556 return !Top->UnresolvedDirectUses.empty();
1563 if (
Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1565 Conflict.
Other = OtherMod;
1566 Conflict.
Message = UC.Message;
1598 bool ImplicitlyDiscovered;
1601 bool HadError =
false;
1604 Module *ActiveModule =
nullptr;
1635 using Attributes = ModuleMap::Attributes;
1641 bool ImplicitlyDiscovered)
1642 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
1643 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
1644 ImplicitlyDiscovered(ImplicitlyDiscovered) {}
1657void ModuleMapLoader::diagnosePrivateModules(
SourceLocation StartLoc) {
1658 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1659 const Module *M, SourceRange ReplLoc) {
1660 auto D = Diags.Report(ActiveModule->DefinitionLoc,
1661 diag::note_mmap_rename_top_level_private_module);
1662 D << BadName << M->Name;
1666 for (
auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1667 auto const *M = E->getValue();
1668 if (M->Directory != ActiveModule->Directory)
1671 SmallString<128> FullName(ActiveModule->getFullModuleName());
1672 if (!FullName.starts_with(M->Name) && !FullName.ends_with(
"Private"))
1674 SmallString<128> FixedPrivModDecl;
1675 SmallString<128> Canonical(M->Name);
1676 Canonical.append(
"_Private");
1679 if (ActiveModule->Parent && ActiveModule->Name ==
"Private" && !M->Parent &&
1680 M->Name == ActiveModule->Parent->Name) {
1681 Diags.Report(ActiveModule->DefinitionLoc,
1682 diag::warn_mmap_mismatched_private_submodule)
1685 SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1687 FixItInitBegin = StartLoc;
1689 if (ActiveModule->Parent->IsFramework)
1690 FixedPrivModDecl.append(
"framework ");
1691 FixedPrivModDecl.append(
"module ");
1692 FixedPrivModDecl.append(Canonical);
1694 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1695 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1700 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1701 ActiveModule->Name != Canonical) {
1702 Diags.Report(ActiveModule->DefinitionLoc,
1703 diag::warn_mmap_mismatched_private_module_name)
1704 << ActiveModule->Name;
1705 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1706 SourceRange(ActiveModule->DefinitionLoc));
1712 if (MD.
Id.front().first ==
"*")
1713 return handleInferredModuleDecl(MD);
1717 Module *PreviousActiveModule = ActiveModule;
1718 if (MD.
Id.size() > 1) {
1721 ActiveModule =
nullptr;
1722 const Module *TopLevelModule =
nullptr;
1723 for (
unsigned I = 0, N = MD.
Id.size() - 1; I != N; ++I) {
1725 Map.lookupModuleQualified(MD.
Id[I].first, ActiveModule)) {
1727 TopLevelModule =
Next;
1728 ActiveModule =
Next;
1732 Diags.Report(MD.
Id[I].second, diag::err_mmap_missing_parent_module)
1733 << MD.
Id[I].first << (ActiveModule !=
nullptr)
1735 ? ActiveModule->getTopLevelModule()->getFullModuleName()
1740 if (TopLevelModule &&
1741 ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
1742 assert(ModuleMapFID !=
1743 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
1744 "submodule defined in same file as 'module *' that allowed its "
1745 "top-level module");
1746 Map.addAdditionalModuleMapFile(
1747 TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
1751 StringRef ModuleName = MD.
Id.back().first;
1752 SourceLocation ModuleNameLoc = MD.
Id.back().second;
1755 Module *ShadowingModule =
nullptr;
1756 if (
Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1761 bool LoadedFromASTFile = Existing->IsFromModuleFile;
1762 if (LoadedFromASTFile) {
1764 Map.getContainingModuleMapFile(Existing);
1766 SourceMgr.getFileEntryRefForID(ModuleMapFID);
1767 if (ExistingModMapFile && CurrentModMapFile &&
1768 *ExistingModMapFile == *CurrentModMapFile)
1769 LoadedFromASTFile =
true;
1771 LoadedFromASTFile =
false;
1774 bool Inferred = Existing->IsInferred;
1790 bool PartOfFramework = MD.
Framework || Existing->isPartOfFramework();
1793 bool ParsedAsMainInput =
1795 Map.LangOpts.CurrentModule == ModuleName &&
1796 SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
1797 SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
1800 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
1801 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
1803 ActiveModule = PreviousActiveModule;
1808 if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
1809 ShadowingModule = Existing;
1812 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1814 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1821 if (ShadowingModule) {
1823 Map.createShadowedModule(ModuleName, MD.
Framework, ShadowingModule);
1825 ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
1829 ActiveModule->DefinitionLoc = ModuleNameLoc;
1831 ActiveModule->IsSystem =
true;
1833 ActiveModule->IsExternC =
true;
1835 ActiveModule->NoUndeclaredIncludes =
true;
1836 ActiveModule->Directory = Directory;
1838 StringRef MapFileName(
1839 SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
1840 if (MapFileName.ends_with(
"module.private.modulemap") ||
1841 MapFileName.ends_with(
"module_private.map")) {
1842 ActiveModule->ModuleMapIsPrivate =
true;
1848 SourceLocation StartLoc =
1849 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
1850 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
1851 !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
1853 !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
1855 ActiveModule->ModuleMapIsPrivate)
1856 diagnosePrivateModules(MD.
Location);
1861 [&](
const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
1862 [&](
const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
1863 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1864 handleUmbrellaDirDecl(UDD);
1866 [&](
const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
1867 [&](
const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
1868 [&](
const modulemap::ExportAsDecl &EAD) {
1869 handleExportAsDecl(EAD);
1871 [&](
const modulemap::ExternModuleDecl &EMD) {
1872 handleExternModuleDecl(EMD);
1874 [&](
const modulemap::UseDecl &UD) { handleUseDecl(UD); },
1875 [&](
const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
1876 [&](
const modulemap::ConfigMacrosDecl &CMD) {
1877 handleConfigMacros(CMD);
1879 [&](
const modulemap::ConflictDecl &CD) { handleConflict(CD); },
1880 [&](
const modulemap::ExcludeDecl &ED) {
1881 Diags.Report(ED.Location, diag::err_mmap_expected_member);
1888 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
1889 ActiveModule->LinkLibraries.empty())
1894 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
1895 ActiveModule->Parent) {
1896 ActiveModule->getTopLevelModule()->markUnavailable(
false);
1897 ActiveModule->getTopLevelModule()->MissingHeaders.append(
1898 ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
1902 ActiveModule = PreviousActiveModule;
1905void ModuleMapLoader::handleExternModuleDecl(
1907 StringRef FileNameRef = EMD.
Path;
1908 SmallString<128> ModuleMapFileName;
1909 if (llvm::sys::path::is_relative(FileNameRef)) {
1910 ModuleMapFileName += Directory.getName();
1911 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
1912 FileNameRef = ModuleMapFileName;
1914 if (
auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
1915 Map.parseAndLoadModuleMapFile(
1916 *
File, IsSystem, ImplicitlyDiscovered,
1917 Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
1939 bool &IsRequiresExcludedHack) {
1943 IsRequiresExcludedHack =
true;
1954 for (
const modulemap::RequiresFeature &RF : RD.
Features) {
1955 bool IsRequiresExcludedHack =
false;
1956 bool ShouldAddRequirement =
1959 if (IsRequiresExcludedHack)
1960 UsesRequiresExcludedHack.insert(ActiveModule);
1962 if (ShouldAddRequirement) {
1983 if (UsesRequiresExcludedHack.count(ActiveModule)) {
1989 Module::UnresolvedHeaderDirective Header;
1993 Header.
Kind = Map.headerRoleToKind(
Role);
1997 !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
1998 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
1999 << ActiveModule->getFullModuleName();
2004 if (ImplicitlyDiscovered) {
2005 SmallString<128> NormalizedPath(HD.
Path);
2006 llvm::sys::path::remove_dots(NormalizedPath,
true);
2007 if (NormalizedPath.starts_with(
".."))
2008 Diags.Report(HD.
PathLoc, diag::warn_mmap_path_outside_directory);
2016 bool NeedsFramework =
false;
2020 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2022 ActiveModule->fullModuleNameIs({
"_Builtin_stddef",
"max_align_t"}))
2023 Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2026 Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2027 << ActiveModule->getFullModuleName()
2036void ModuleMapLoader::handleUmbrellaDirDecl(
2038 std::string DirName = std::string(UDD.
Path);
2039 std::string DirNameAsWritten = DirName;
2042 if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2043 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2044 << ActiveModule->getFullModuleName();
2049 if (ImplicitlyDiscovered) {
2050 SmallString<128> NormalizedPath(UDD.
Path);
2051 llvm::sys::path::remove_dots(NormalizedPath,
true);
2052 if (NormalizedPath.starts_with(
".."))
2053 Diags.Report(UDD.
Location, diag::warn_mmap_path_outside_directory);
2058 if (llvm::sys::path::is_absolute(DirName)) {
2059 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2061 SmallString<128> PathName;
2062 PathName = Directory.getName();
2063 llvm::sys::path::append(PathName, DirName);
2064 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2068 Diags.Report(UDD.
Location, diag::warn_mmap_umbrella_dir_not_found)
2073 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2079 SmallVector<Module::Header, 6> Headers;
2080 llvm::vfs::FileSystem &FS =
2081 SourceMgr.getFileManager().getVirtualFileSystem();
2082 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->
getName(), EC), E;
2083 I != E && !EC; I.increment(EC)) {
2084 if (
auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2085 Module::Header Header = {
"", std::string(I->path()), *FE};
2086 Headers.push_back(std::move(Header));
2093 for (
auto &Header : Headers)
2098 if (
Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2099 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2100 << OwningModule->getFullModuleName();
2106 Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);
2111 ActiveModule->UnresolvedExports.push_back(
Unresolved);
2115 const auto &ModName = EAD.
Id.front();
2117 if (!ActiveModule->ExportAsModule.empty()) {
2118 if (ActiveModule->ExportAsModule == ModName.first) {
2119 Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)
2120 << ActiveModule->Name << ModName.first;
2122 Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)
2123 << ActiveModule->Name << ActiveModule->ExportAsModule
2128 ActiveModule->ExportAsModule = ModName.first;
2129 Map.addLinkAsDependency(ActiveModule);
2133 if (ActiveModule->Parent)
2134 Diags.Report(UD.
Location, diag::err_mmap_use_decl_submodule);
2136 ActiveModule->UnresolvedDirectUses.push_back(UD.
Id);
2140 ActiveModule->LinkLibraries.push_back(
2144void ModuleMapLoader::handleConfigMacros(
2146 if (ActiveModule->Parent) {
2147 Diags.Report(CMD.
Location, diag::err_mmap_config_macro_submodule);
2154 ActiveModule->ConfigMacrosExhaustive =
true;
2156 ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
2161 Module::UnresolvedConflict Conflict;
2163 Conflict.
Id = CD.
Id;
2167 ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));
2170void ModuleMapLoader::handleInferredModuleDecl(
2172 SourceLocation StarLoc = MD.
Id.front().second;
2176 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2182 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
2183 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2188 if (ActiveModule->InferSubmodules) {
2189 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2190 if (ActiveModule->InferredSubmoduleLoc.isValid())
2191 Diags.Report(ActiveModule->InferredSubmoduleLoc,
2192 diag::note_mmap_prev_definition);
2198 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2202 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2208 ActiveModule->InferSubmodules =
true;
2209 ActiveModule->InferredSubmoduleLoc = StarLoc;
2210 ActiveModule->InferExplicitSubmodules = MD.
Explicit;
2213 auto &InfDir = Map.InferredDirectories[Directory];
2214 InfDir.InferModules =
true;
2215 InfDir.Attrs = MD.
Attrs;
2216 InfDir.ModuleMapFID = ModuleMapFID;
2223 [&](
const auto &
Other) {
2224 Diags.Report(
Other.Location,
2225 diag::err_mmap_expected_inferred_member)
2226 << (ActiveModule !=
nullptr);
2228 [&](
const modulemap::ExcludeDecl &ED) {
2232 diag::err_mmap_expected_inferred_member)
2233 << (ActiveModule !=
nullptr);
2237 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
2240 [&](
const modulemap::ExportDecl &ED) {
2242 if (!ActiveModule) {
2244 diag::err_mmap_expected_inferred_member)
2245 << (ActiveModule !=
nullptr);
2251 ActiveModule->InferExportWildcard =
true;
2253 Diags.Report(ED.
Id.front().second,
2254 diag::err_mmap_expected_export_wildcard);
2261 handleModuleDecl(MD);
2267 handleExternModuleDecl(EMD);
2278 handleExternModuleDecl(EMD);
2286 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
2287 if (Known != Modules.end())
2288 return Known->getValue();
2290 auto ParsedMod = ParsedModules.find(Name);
2291 if (ParsedMod == ParsedModules.end())
2294 Diags.Report(diag::remark_mmap_load_module) << Name;
2296 for (
const auto &ModuleDecl : ParsedMod->second) {
2309 bool ImplicitlyDiscovered,
2313 assert(Target &&
"Missing target information");
2314 llvm::DenseMap<const FileEntry *, bool>::iterator Known =
2315 LoadedModuleMap.find(
File);
2316 if (Known != LoadedModuleMap.end())
2317 return Known->second;
2320 if (ID.isInvalid()) {
2325 FileID &LocalFID = ModuleMapLocalFileID[
File];
2327 auto FileCharacter =
2329 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
2334 assert(Target &&
"Missing target information");
2335 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
2337 return LoadedModuleMap[
File] =
true;
2338 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
2339 "invalid buffer offset");
2342 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
2345 Diags.Report(diag::remark_mmap_load) <<
File.getName();
2347 ImplicitlyDiscovered);
2354 ParsedModuleMap.find(
File);
2355 if (PKnown == ParsedModuleMap.end()) {
2356 ParsedModuleMaps.push_back(
2357 std::make_unique<modulemap::ModuleMapFile>(std::move(*MMF)));
2358 ParsedModuleMap[
File] = &*ParsedModuleMaps.back();
2365 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)
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 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.
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...
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
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
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 setUmbrellaDirAsWritten(Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory)
Sets the umbrella directory of the given module to the given directory.
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)
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.
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 setUmbrellaHeaderAsWritten(Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory)
Sets the umbrella header of the given module to the given header.
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.
Module * lookupModuleQualified(StringRef Name, Module *Context) const
Retrieve a module with the given name within the given context, using direct (qualified) name lookup.
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.
void addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role, bool Imported=false)
Adds this header to the given module.
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.
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.
Module * findSubmodule(StringRef Name) const
Find the submodule with the given name.
bool directlyUses(const Module *Requested)
Determine whether this module has declared its intention to directly use another 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.
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.
llvm::PointerIntPair< Module *, 1, bool > ExportDecl
Describes an exported module.
@ ModuleImplementationUnit
This is a C++20 module implementation unit.
@ ImplicitGlobalModuleFragment
This is an implicit fragment of the global module which contains only language linkage declarations (...
@ ModuleInterfaceUnit
This is a C++20 module interface unit.
@ ModuleHeaderUnit
This is a C++20 header unit.
@ PrivateModuleFragment
This is the private module fragment within some C++ module.
@ ExplicitGlobalModuleFragment
This is the explicit Global Module Fragment of a modular TU.
unsigned IsFramework
Whether this is a framework module.
std::string ExportAsModule
The module through which entities defined in this module will eventually be exposed,...
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
std::string UmbrellaAsWritten
The name of the umbrella entry, as written in the module map.
unsigned InferExplicitSubmodules
Whether, when inferring submodules, the inferred submodules should be explicit.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
OptionalDirectoryEntryRef getEffectiveUmbrellaDir() const
Get the effective umbrella directory for this module: either the one explicitly written in the module...
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
std::vector< Conflict > Conflicts
The list of conflicts.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
Exposes information about the current target.
Defines the clang::TargetInfo interface.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
bool Sub(InterpState &S, CodePtr OpPC)
std::optional< ModuleMapFile > parseModuleMap(FileID ID, clang::DirectoryEntryRef Dir, SourceManager &SM, DiagnosticsEngine &Diags, bool IsSystem, bool ImplicitlyDiscovered, unsigned *Offset)
Parse a module map file into an in memory representation.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)
SmallVector< std::pair< std::string, SourceLocation >, 2 > ModuleId
Describes the name of a module.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
@ Keyword
The name has been typo-corrected to a keyword.
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
@ Other
Other implicit parameter.
int const char * function
unsigned IsExternC
Whether this is an extern "C" module.
unsigned IsSystem
Whether this is a system module.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules.
A conflict between two modules.
Module * Other
The module that this module conflicts with.
std::string Message
The message provided to the user when there is a conflict.
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