28#include "llvm/ADT/DenseMap.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/SmallPtrSet.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringMap.h"
33#include "llvm/ADT/StringRef.h"
34#include "llvm/ADT/StringSwitch.h"
35#include "llvm/Support/Compiler.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/Path.h"
38#include "llvm/Support/VirtualFileSystem.h"
39#include "llvm/Support/raw_ostream.h"
44#include <system_error>
51void ModuleMapCallbacks::anchor() {}
54 auto PendingLinkAs = PendingLinkAsModule.find(Mod->
Name);
55 if (PendingLinkAs != PendingLinkAsModule.end()) {
56 for (
auto &Name : PendingLinkAs->second) {
59 M->UseExportAsModuleLinkName =
true;
84 llvm_unreachable(
"unknown header role");
101 llvm_unreachable(
"unknown header kind");
109ModuleMap::resolveExport(
Module *Mod,
111 bool Complain)
const {
114 assert(
Unresolved.Wildcard &&
"Invalid unresolved export");
127 bool Complain)
const {
132 Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
139 for (
unsigned I = 1, N = Id.size(); I != N; ++I) {
143 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
144 << Id[I].first << Context->getFullModuleName()
145 << SourceRange(Id[0].second, Id[I-1].second);
162 for (; Mod; Mod = Mod->
Parent) {
164 Paths.push_back(Mod->
Name);
171 for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
172 llvm::sys::path::append(Path,
"Frameworks", Framework +
".framework");
180 SmallString<128> FullPathName(Directory->getName());
184 expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
192 unsigned FullPathLength = FullPathName.size();
194 unsigned RelativePathLength = RelativePathName.size();
197 llvm::sys::path::append(RelativePathName,
"Headers", Header.
FileName);
198 llvm::sys::path::append(FullPathName, RelativePathName);
199 if (
auto File = GetFile(FullPathName))
209 RelativePathName.clear();
211 RelativePathName.resize(RelativePathLength);
212 FullPathName.resize(FullPathLength);
213 llvm::sys::path::append(RelativePathName,
"PrivateHeaders",
215 llvm::sys::path::append(FullPathName, RelativePathName);
216 return GetFile(FullPathName);
219 if (llvm::sys::path::is_absolute(Header.
FileName)) {
220 RelativePathName.clear();
226 return GetFrameworkFile();
229 llvm::sys::path::append(RelativePathName, Header.
FileName);
230 llvm::sys::path::append(FullPathName, RelativePathName);
231 auto NormalHdrFile = GetFile(FullPathName);
233 if (!NormalHdrFile && Directory->getName().ends_with(
".framework")) {
237 FullPathName.assign(Directory->getName());
238 RelativePathName.clear();
239 if (GetFrameworkFile()) {
241 diag::warn_mmap_incomplete_framework_module_declaration)
243 NeedsFramework =
true;
248 return NormalHdrFile;
255 return llvm::StringSwitch<bool>(
FileName)
256 .Case(
"float.h",
true)
257 .Case(
"iso646.h",
true)
258 .Case(
"limits.h",
true)
259 .Case(
"stdalign.h",
true)
260 .Case(
"stdarg.h",
true)
261 .Case(
"stdatomic.h",
true)
262 .Case(
"stdbool.h",
true)
263 .Case(
"stdckdint.h",
true)
264 .Case(
"stdcountof.h",
true)
265 .Case(
"stddef.h",
true)
266 .Case(
"stdint.h",
true)
267 .Case(
"tgmath.h",
true)
268 .Case(
"unwind.h",
true)
275 return llvm::StringSwitch<bool>(ModuleName)
276 .Case(
"_Builtin_float",
true)
277 .Case(
"_Builtin_inttypes",
true)
278 .Case(
"_Builtin_iso646",
true)
279 .Case(
"_Builtin_limits",
true)
280 .Case(
"_Builtin_stdalign",
true)
281 .Case(
"_Builtin_stdarg",
true)
282 .Case(
"_Builtin_stdatomic",
true)
283 .Case(
"_Builtin_stdbool",
true)
284 .Case(
"_Builtin_stddef",
true)
285 .Case(
"_Builtin_stdint",
true)
286 .Case(
"_Builtin_stdnoreturn",
true)
287 .Case(
"_Builtin_tgmath",
true)
288 .Case(
"_Builtin_unwind",
true)
292void ModuleMap::resolveHeader(
Module *Mod,
294 bool &NeedsFramework) {
295 SmallString<128> RelativePathName;
297 findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
299 const DirectoryEntry *UmbrellaDir = &
File->getDir().getDirEntry();
300 if (
Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
301 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
302 << UmbrellaMod->getFullModuleName();
308 Module::Header H = {Header.
FileName, std::string(RelativePathName),
331bool ModuleMap::resolveAsBuiltinHeader(
334 llvm::sys::path::is_absolute(Header.
FileName) ||
336 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->
Directory ||
343 SmallString<128> Path;
344 llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.
FileName);
345 auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
358 : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
359 HeaderInfo(HeaderInfo) {
365 assert((!this->Target || this->Target == &Target) &&
366 "Improper target override");
367 this->Target = &Target;
381 Buffer.push_back(
'_');
382 Buffer.reserve(Buffer.size() + Name.size());
383 for (
unsigned I = 0, N = Name.size(); I != N; ++I) {
385 Buffer.push_back(Name[I]);
387 Buffer.push_back(
'_');
390 Name = StringRef(Buffer.data(), Buffer.size());
393 while (llvm::StringSwitch<bool>(Name)
396#include
"clang/Basic/TokenKinds.def"
398 if (Name.data() != Buffer.data())
399 Buffer.append(Name.begin(), Name.end());
400 Buffer.push_back(
'_');
401 Name = StringRef(Buffer.data(), Buffer.size());
408 return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
414 return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
419ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(
FileEntryRef File) {
421 HeadersMap::iterator Known = Headers.find(
File);
425 return Headers.find(
File);
432 if (UmbrellaDirs.empty())
441 StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
446 auto KnownDir = UmbrellaDirs.find(*Dir);
447 if (KnownDir != UmbrellaDirs.end())
450 IntermediateDirs.push_back(*Dir);
453 DirName = llvm::sys::path::parent_path(DirName);
458 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
471 bool IsPrivate =
false;
475 for (
auto Hs : HeaderList)
476 IsPrivate |= llvm::any_of(
478 assert(IsPrivate &&
"inconsistent headers and roles");
489 bool RequestingModuleIsModuleInterface,
492 if (RequestingModule) {
497 HeadersMap::iterator Known = findKnownHeader(
File);
499 diagnoseDuplicateHeaderOwnership(FilenameLoc, Filename,
File, Known);
505 bool IsPublicForMainPrivateModule =
false;
506 if (TopLevelRequestingModule != TopLevelSourceModule) {
514 if (TopLevelRequestingModule && TopLevelSourceModule &&
515 llvm::StringRef(TopLevelSourceModule->
Name)
517 llvm::StringRef(TopLevelSourceModule->
Name)
519 TopLevelRequestingModule->
Name) {
520 IsPublicForMainPrivateModule =
true;
526 bool Excluded =
false;
527 bool UsedByPrivateModule =
false;
529 Module *NotUsed =
nullptr;
531 if (Known != Headers.end()) {
547 if (RequestingModule && LangOpts.ModulesDeclUse &&
550 if (IsPublicForMainPrivateModule) {
551 UsedByPrivateModule = SourceModule->directlyUses(Header.
getModule());
565 Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
572 if (UsedByPrivateModule) {
573 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_private)
577 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
584 if (Excluded || isHeaderInUmbrellaDirs(
File))
589 if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
590 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
592 }
else if (RequestingModule && RequestingModuleIsModuleInterface &&
593 LangOpts.isCompilingModule()) {
596 diag::warn_non_modular_include_in_framework_module :
597 diag::warn_non_modular_include_in_module;
603void ModuleMap::diagnoseDuplicateHeaderOwnership(
SourceLocation FilenameLoc,
606 HeadersMap::iterator Known) {
607 if (Known == Headers.end())
610 if (Diags.
isIgnored(diag::warn_mmap_duplicate_header_ownership, FilenameLoc))
614 if (!DiagnosedDuplicateHeaders.insert(&
File.getFileEntry()).second)
627 for (
const KnownHeader &H : Known->second) {
631 if (!SeenTopLevel.insert(TopLevel).second)
633 auto It = HeaderOwnerLocs.find({&
File.getFileEntry(), H.getModule()});
634 SourceLocation OwnerLoc =
635 It != HeaderOwnerLocs.end() ? It->second : SourceLocation();
636 OwningModules.push_back({TopLevel, OwnerLoc,
false});
641 if (OwningModules.empty())
649 SmallVector<DirectoryEntryRef, 2> IntermediateDirs;
651 findHeaderInUmbrellaDirs(
File, IntermediateDirs)) {
655 if (SeenTopLevel.insert(TopLevel).second) {
658 llvm::any_of(Known->second, [TopLevel](
const KnownHeader &H) {
659 return H.getModule()->getTopLevelModule() == TopLevel &&
660 H.getRole() == ExcludedHeader;
663 OwningModules.push_back({TopLevel,
670 if (OwningModules.size() < 2)
673 Diags.Report(FilenameLoc, diag::warn_mmap_duplicate_header_ownership)
675 for (
const auto &Owner : OwningModules) {
676 unsigned NoteID = Owner.IsUmbrella
677 ? diag::note_mmap_header_covered_by_umbrella
678 : diag::note_mmap_header_owned_by;
679 Diags.Report(Owner.Loc, NoteID) << Owner.Mod->getFullModuleName();
713 bool AllowExcluded) {
720 HeadersMap::iterator Known = findKnownHeader(
File);
721 if (Known != Headers.end()) {
730 return MakeResult(H);
734 return MakeResult(
Result);
737 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(
File));
741 Module *M, std::string NameAsWritten,
744 Header.
FileName = std::move(NameAsWritten);
747 return findHeader(M, Header, RelativePathName, NeedsFramework);
752 assert(!Headers.count(
File) &&
"already have a module for this header");
755 KnownHeader H = findHeaderInUmbrellaDirs(
File, SkippedDirs);
763 UmbrellaModule = UmbrellaModule->
Parent;
777 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
783 UmbrellaDirs[SkippedDir] =
Result;
794 llvm::sys::path::stem(
File.getName()), NameBuf);
807 for (
unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
808 UmbrellaDirs[SkippedDirs[I]] =
Result;
812 Headers[
File].push_back(Header);
821 HeadersMap::iterator Known = findKnownHeader(
File);
822 if (Known != Headers.end())
823 return Known->second;
825 if (findOrCreateModuleForHeaderInUmbrellaDir(
File))
826 return Headers.find(
File)->second;
835 auto It = Headers.find(
File);
836 if (It == Headers.end())
848 HeadersMap::const_iterator Known = Headers.find(Header);
849 if (Known != Headers.end()) {
851 I = Known->second.begin(),
852 E = Known->second.end();
858 if (I->isAvailable() &&
859 (!RequestingModule ||
876 StringRef DirName = Dir->
getName();
878 auto IsUnavailable = [&](
const Module *M) {
886 auto KnownDir = UmbrellaDirs.find(*Dir);
887 if (KnownDir != UmbrellaDirs.end()) {
889 if (IsUnavailable(
Found))
897 UmbrellaModule = UmbrellaModule->
Parent;
904 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
908 if (IsUnavailable(
Found))
915 llvm::sys::path::stem(Header.
getName()),
922 return IsUnavailable(
Found);
925 SkippedDirs.push_back(*Dir);
928 DirName = llvm::sys::path::parent_path(DirName);
933 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
940 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
941 if (Known != Modules.end())
942 return Known->getValue();
958 if (
Result->InferExportWildcard)
965 for(; Context; Context = Context->Parent) {
977 return Context->findSubmodule(Name);
986 return std::make_pair(Sub,
false);
990 return std::make_pair(M,
true);
994 bool IsFramework,
bool IsExplicit) {
996 "Creating duplicate submodule");
1000 IsFramework, IsExplicit, NumCreatedModules++);
1002 if (LangOpts.CurrentModule == Name)
1005 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1014 true, NumCreatedModules++);
1019 PendingSubmodules.emplace_back(
Result);
1026 assert(Parent &&
"We should only create an implicit global module fragment "
1027 "in a module purview");
1031 auto *
Result =
new (ModulesAlloc.Allocate())
1033 false,
false, NumCreatedModules++);
1043 true, NumCreatedModules++);
1050 auto *
Result =
new (ModulesAlloc.Allocate())
1052 false, NumCreatedModules++);
1056 for (
auto &Submodule : PendingSubmodules)
1057 Submodule->setParent(
Result);
1058 PendingSubmodules.clear();
1064 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1065 assert(!Modules[Name] &&
"redefining existing module");
1069 Modules[Name] = SourceModule =
Result;
1073 auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
1074 assert(MainFile &&
"no input file for module interface");
1082 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1085 "creating implementation module without an interface");
1090 StringRef IName =
".ImplementationUnit";
1091 assert(!Modules[IName] &&
"multiple implementation units?");
1095 Modules[IName] = SourceModule =
Result;
1098 assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
1099 "no input file for module implementation");
1106 assert(LangOpts.CurrentModule == Name &&
"module name mismatch");
1107 assert(!Modules[Name] &&
"redefining existing module");
1109 auto *
Result =
new (ModulesAlloc.Allocate())
1111 false, NumCreatedModules++);
1113 Modules[Name] = SourceModule =
Result;
1121 assert(Mod->
IsFramework &&
"Can only infer linking for framework modules");
1123 "Can only infer linking for top-level frameworks");
1125 StringRef FrameworkName(Mod->
Name);
1126 FrameworkName.consume_back(
"_Private");
1132 bool IsSystem,
Module *Parent) {
1135 return inferFrameworkModule(FrameworkDir, Attrs, Parent);
1139 Attributes Attrs,
Module *Parent) {
1144 StringRef FrameworkDirName =
1145 SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
1152 llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
1165 bool canInfer =
false;
1166 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
1168 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
1169 if (
auto ParentDir =
FileMgr.getOptionalDirectoryRef(Parent)) {
1172 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1173 inferred = InferredDirectories.find(*ParentDir);
1174 if (inferred == InferredDirectories.end()) {
1177 bool IsFrameworkDir = Parent.ends_with(
".framework");
1185 inferred = InferredDirectories.find(*ParentDir);
1188 if (inferred == InferredDirectories.end())
1189 inferred = InferredDirectories.insert(
1190 std::make_pair(*ParentDir, InferredDirectory())).first;
1193 if (inferred->second.InferModules) {
1196 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1198 !llvm::is_contained(inferred->second.ExcludedModules, Name);
1200 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1201 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1202 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1203 Attrs.NoUndeclaredIncludes |=
1204 inferred->second.Attrs.NoUndeclaredIncludes;
1205 ModuleMapFID = inferred->second.ModuleMapFID;
1218 SmallString<128> UmbrellaName = FrameworkDir.
getName();
1219 llvm::sys::path::append(UmbrellaName,
"Headers", ModuleName +
".h");
1225 if (!UmbrellaHeader)
1229 Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1230 true,
false, NumCreatedModules++);
1233 if (LangOpts.CurrentModule == ModuleName)
1235 Modules[ModuleName] =
Result;
1236 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1239 Result->IsSystem |= Attrs.IsSystem;
1240 Result->IsExternC |= Attrs.IsExternC;
1241 Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1242 Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1243 Result->Directory = FrameworkDir;
1246 StringRef RelativePath = UmbrellaName.str().substr(
1247 Result->getTopLevelModule()->Directory->getName().size());
1248 RelativePath = llvm::sys::path::relative_path(RelativePath);
1258 Result->InferSubmodules =
true;
1259 Result->InferExportWildcard =
true;
1263 SmallString<128> SubframeworksDirName = FrameworkDir.
getName();
1264 llvm::sys::path::append(SubframeworksDirName,
"Frameworks");
1265 llvm::sys::path::native(SubframeworksDirName);
1267 for (llvm::vfs::directory_iterator
1268 Dir = FS.dir_begin(SubframeworksDirName, EC),
1270 Dir != DirEnd && !EC; Dir.increment(EC)) {
1271 if (!StringRef(Dir->path()).ends_with(
".framework"))
1279 StringRef SubframeworkDirName =
1281 bool FoundParent =
false;
1285 = llvm::sys::path::parent_path(SubframeworkDirName);
1286 if (SubframeworkDirName.empty())
1291 if (*SubDir == FrameworkDir) {
1302 inferFrameworkModule(*SubframeworkDir, Attrs,
Result);
1308 if (!
Result->isSubFramework())
1315 Module *ShadowingModule) {
1320 IsFramework,
false, NumCreatedModules++);
1321 Result->ShadowingModule = ShadowingModule;
1322 Result->markUnavailable(
true);
1323 ModuleScopeIDs[
Result] = CurrentModuleScopeID;
1324 ShadowModules.push_back(
Result);
1331 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1334 HeaderOwnerLocs[{&UmbrellaHeader.
getFileEntry(), Mod}] = Loc;
1339 PathRelativeToRootModuleDirectory.str();
1340 UmbrellaDirs[UmbrellaHeader.
getDir()] = Mod;
1343 for (
const auto &Cb : Callbacks)
1344 Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1349 const Twine &PathRelativeToRootModuleDirectory,
SourceLocation Loc) {
1354 PathRelativeToRootModuleDirectory.str();
1355 UmbrellaDirs[UmbrellaDir] = Mod;
1358void ModuleMap::addUnresolvedHeader(
Module *Mod,
1360 bool &NeedsFramework) {
1363 if (resolveAsBuiltinHeader(Mod, Header)) {
1382 LazyHeadersByModTime[*Header.
ModTime].push_back(Mod);
1384 LazyHeadersBySize[*Header.
Size].push_back(Mod);
1391 resolveHeader(Mod, Header, NeedsFramework);
1395 auto BySize = LazyHeadersBySize.find(
File->getSize());
1396 if (BySize != LazyHeadersBySize.end()) {
1397 for (
auto *M : BySize->second)
1399 LazyHeadersBySize.erase(BySize);
1402 auto ByModTime = LazyHeadersByModTime.find(
File->getModificationTime());
1403 if (ByModTime != LazyHeadersByModTime.end()) {
1404 for (
auto *M : ByModTime->second)
1406 LazyHeadersByModTime.erase(ByModTime);
1411 Module *Mod, std::optional<const FileEntry *>
File)
const {
1412 bool NeedsFramework =
false;
1414 const auto Size =
File ? (*File)->getSize() : 0;
1415 const auto ModTime =
File ? (*File)->getModificationTime() : 0;
1419 (Header.
Size && Header.
Size != Size)))
1420 NewHeaders.push_back(Header);
1424 const_cast<ModuleMap *
>(
this)->resolveHeader(Mod, Header, NeedsFramework);
1439 auto &HeaderList = Headers[HeaderEntry];
1440 if (llvm::is_contained(HeaderList, KH))
1444 HeaderOwnerLocs[{&HeaderEntry.
getFileEntry(), Mod}] = Loc;
1446 HeaderList.push_back(KH);
1449 bool isCompilingModuleHeader = Mod->
isForBuilding(LangOpts);
1450 if (!Imported || isCompilingModuleHeader) {
1453 HeaderInfo.MarkFileModuleHeader(HeaderEntry,
Role, isCompilingModuleHeader);
1457 for (
const auto &Cb : Callbacks)
1458 Cb->moduleMapAddHeader(HeaderEntry.
getName());
1462 bool ImplicitlyDiscovered,
1465 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
1466 Known = ParsedModuleMap.find(
File);
1467 if (Known != ParsedModuleMap.end())
1468 return Known->second ==
nullptr;
1471 if (ID.isInvalid()) {
1472 FileID &LocalFID = ModuleMapLocalFileID[
File];
1474 auto FileCharacter =
1476 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
1481 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
1483 ParsedModuleMap[
File] =
nullptr;
1487 Diags.Report(diag::remark_mmap_parse) <<
File.getName();
1489 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered,
nullptr);
1492 ParsedModuleMap[
File] =
nullptr;
1496 ParsedModuleMaps.push_back(
1497 std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));
1499 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
1502 for (
const auto &
Decl : MD.Decls) {
1503 std::visit(llvm::makeVisitor(
1506 if (SubMD.
Id.front().first ==
"*")
1508 CollectExternDecls(SubMD);
1511 PendingExternalModuleMaps.push_back(&EMD);
1521 std::visit(llvm::makeVisitor(
1527 ParsedModules[StringRef(MD.
Id.front().first)];
1528 ModuleDecls.push_back(std::pair(&MMF, &MD));
1529 CollectExternDecls(MD);
1532 PendingExternalModuleMaps.push_back(&EMD);
1538 StringRef FileNameRef = EMD->Path;
1540 if (llvm::sys::path::is_relative(FileNameRef)) {
1541 ModuleMapFileName += Dir.
getName();
1542 llvm::sys::path::append(ModuleMapFileName, EMD->Path);
1543 FileNameRef = ModuleMapFileName;
1547 SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {
1549 EFile->getDir(),
FileID(), ExternModuleLoc);
1553 ParsedModuleMap[
File] = &MMF;
1555 for (
const auto &Cb : Callbacks)
1562 for (
const auto &Entry : ParsedModules)
1580 assert(InferredModuleAllowedBy.count(M) &&
"missing inferred module map");
1581 return InferredModuleAllowedBy.find(M)->second;
1593 InferredModuleAllowedBy[M] = ModMapFID;
1598 StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1602 if (llvm::sys::path::filename(Dir) ==
"Modules") {
1603 StringRef Parent = llvm::sys::path::parent_path(Dir);
1604 if (Parent.ends_with(
".framework"))
1611 return llvm::errorToErrorCode(DirEntry.takeError());
1615 if (CanonicalDir != Dir)
1616 llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1624 llvm::sys::path::remove_dots(Path);
1626 return std::error_code();
1635 llvm::errs() <<
"Modules:";
1636 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1637 MEnd = Modules.end();
1639 M->getValue()->
print(llvm::errs(), 2);
1641 llvm::errs() <<
"Headers:";
1642 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1644 llvm::errs() <<
" \"" << H->first.getName() <<
"\" -> ";
1646 E = H->second.end();
1648 if (I != H->second.begin())
1649 llvm::errs() <<
",";
1650 llvm::errs() << I->getModule()->getFullModuleName();
1652 llvm::errs() <<
"\n";
1661 if (Export.first || Export.second)
1662 Mod->
Exports.push_back(Export);
1671 auto Unresolved = std::move(Top->UnresolvedDirectUses);
1672 Top->UnresolvedDirectUses.clear();
1674 Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1676 Top->DirectUses.push_back(DirectUse);
1678 Top->UnresolvedDirectUses.push_back(UDU);
1680 return !Top->UnresolvedDirectUses.empty();
1687 if (
Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1689 Conflict.
Other = OtherMod;
1690 Conflict.
Message = UC.Message;
1722 bool ImplicitlyDiscovered;
1725 bool HadError =
false;
1728 Module *ActiveModule =
nullptr;
1759 using Attributes = ModuleMap::Attributes;
1765 bool ImplicitlyDiscovered)
1766 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
1767 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
1768 ImplicitlyDiscovered(ImplicitlyDiscovered) {}
1781void ModuleMapLoader::diagnosePrivateModules(
SourceLocation StartLoc) {
1782 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1783 const Module *M, SourceRange ReplLoc) {
1784 auto D = Diags.Report(ActiveModule->DefinitionLoc,
1785 diag::note_mmap_rename_top_level_private_module);
1786 D << BadName << M->Name;
1790 for (
auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1791 auto const *M = E->getValue();
1792 if (M->Directory != ActiveModule->Directory)
1795 SmallString<128> FullName(ActiveModule->getFullModuleName());
1796 if (!FullName.starts_with(M->Name) && !FullName.ends_with(
"Private"))
1798 SmallString<128> FixedPrivModDecl;
1799 SmallString<128> Canonical(M->Name);
1800 Canonical.append(
"_Private");
1803 if (ActiveModule->Parent && ActiveModule->Name ==
"Private" && !M->Parent &&
1804 M->Name == ActiveModule->Parent->Name) {
1805 Diags.Report(ActiveModule->DefinitionLoc,
1806 diag::warn_mmap_mismatched_private_submodule)
1809 SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1811 FixItInitBegin = StartLoc;
1813 if (ActiveModule->Parent->IsFramework)
1814 FixedPrivModDecl.append(
"framework ");
1815 FixedPrivModDecl.append(
"module ");
1816 FixedPrivModDecl.append(Canonical);
1818 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1819 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1824 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1825 ActiveModule->Name != Canonical) {
1826 Diags.Report(ActiveModule->DefinitionLoc,
1827 diag::warn_mmap_mismatched_private_module_name)
1828 << ActiveModule->Name;
1829 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1830 SourceRange(ActiveModule->DefinitionLoc));
1836 if (MD.
Id.front().first ==
"*")
1837 return handleInferredModuleDecl(MD);
1841 Module *PreviousActiveModule = ActiveModule;
1842 if (MD.
Id.size() > 1) {
1845 ActiveModule =
nullptr;
1846 const Module *TopLevelModule =
nullptr;
1847 for (
unsigned I = 0, N = MD.
Id.size() - 1; I != N; ++I) {
1849 Map.lookupModuleQualified(MD.
Id[I].first, ActiveModule)) {
1851 TopLevelModule =
Next;
1852 ActiveModule =
Next;
1856 Diags.Report(MD.
Id[I].second, diag::err_mmap_missing_parent_module)
1857 << MD.
Id[I].first << (ActiveModule !=
nullptr)
1859 ? ActiveModule->getTopLevelModule()->getFullModuleName()
1864 if (TopLevelModule &&
1865 ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
1866 assert(ModuleMapFID !=
1867 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
1868 "submodule defined in same file as 'module *' that allowed its "
1869 "top-level module");
1870 Map.addAdditionalModuleMapFile(
1871 TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
1875 StringRef ModuleName = MD.
Id.back().first;
1876 SourceLocation ModuleNameLoc = MD.
Id.back().second;
1879 Module *ShadowingModule =
nullptr;
1880 if (
Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1886 bool LoadedFromASTFile = Existing->IsFromModuleFile;
1887 if (LoadedFromASTFile) {
1889 Map.getContainingModuleMapFile(Existing);
1891 SourceMgr.getFileEntryRefForID(ModuleMapFID);
1892 if ((ExistingModMapFile && CurrentModMapFile &&
1893 *ExistingModMapFile == *CurrentModMapFile) ||
1894 Existing->DefinitionLoc.isInvalid()) {
1898 LoadedFromASTFile =
true;
1900 LoadedFromASTFile =
false;
1903 bool Inferred = Existing->IsInferred;
1919 bool PartOfFramework = MD.
Framework || Existing->isPartOfFramework();
1922 bool ParsedAsMainInput =
1924 Map.LangOpts.CurrentModule == ModuleName &&
1925 SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
1926 SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
1929 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
1930 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
1932 ActiveModule = PreviousActiveModule;
1937 if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
1938 ShadowingModule = Existing;
1941 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1943 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1950 if (ShadowingModule) {
1952 Map.createShadowedModule(ModuleName, MD.
Framework, ShadowingModule);
1954 ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,
1958 ActiveModule->DefinitionLoc = ModuleNameLoc;
1960 ActiveModule->IsSystem =
true;
1962 ActiveModule->IsExternC =
true;
1964 ActiveModule->NoUndeclaredIncludes =
true;
1965 ActiveModule->Directory = Directory;
1967 StringRef MapFileName(
1968 SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
1969 if (MapFileName.ends_with(
"module.private.modulemap") ||
1970 MapFileName.ends_with(
"module_private.map")) {
1971 ActiveModule->ModuleMapIsPrivate =
true;
1977 SourceLocation StartLoc =
1978 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
1979 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
1980 !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
1982 !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
1984 ActiveModule->ModuleMapIsPrivate)
1985 diagnosePrivateModules(MD.
Location);
1990 [&](
const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
1991 [&](
const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
1992 [&](
const modulemap::UmbrellaDirDecl &UDD) {
1993 handleUmbrellaDirDecl(UDD);
1995 [&](
const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
1996 [&](
const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
1997 [&](
const modulemap::ExportAsDecl &EAD) {
1998 handleExportAsDecl(EAD);
2000 [&](
const modulemap::ExternModuleDecl &EMD) {
2001 handleExternModuleDecl(EMD);
2003 [&](
const modulemap::UseDecl &UD) { handleUseDecl(UD); },
2004 [&](
const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
2005 [&](
const modulemap::ConfigMacrosDecl &CMD) {
2006 handleConfigMacros(CMD);
2008 [&](
const modulemap::ConflictDecl &CD) { handleConflict(CD); },
2009 [&](
const modulemap::ExcludeDecl &ED) {
2010 Diags.Report(ED.Location, diag::err_mmap_expected_member);
2017 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2018 ActiveModule->LinkLibraries.empty())
2023 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2024 ActiveModule->Parent) {
2025 ActiveModule->getTopLevelModule()->markUnavailable(
false);
2026 ActiveModule->getTopLevelModule()->MissingHeaders.append(
2027 ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2031 ActiveModule = PreviousActiveModule;
2034void ModuleMapLoader::handleExternModuleDecl(
2036 StringRef FileNameRef = EMD.
Path;
2037 SmallString<128> ModuleMapFileName;
2038 if (llvm::sys::path::is_relative(FileNameRef)) {
2039 ModuleMapFileName += Directory.getName();
2040 llvm::sys::path::append(ModuleMapFileName, EMD.
Path);
2047 llvm::sys::path::remove_dots(ModuleMapFileName,
true);
2048 FileNameRef = ModuleMapFileName;
2050 if (
auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
2051 Map.parseAndLoadModuleMapFile(
2052 *
File, IsSystem, ImplicitlyDiscovered,
2053 Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
2075 bool &IsRequiresExcludedHack) {
2079 IsRequiresExcludedHack =
true;
2090 for (
const modulemap::RequiresFeature &RF : RD.
Features) {
2091 bool IsRequiresExcludedHack =
false;
2092 bool ShouldAddRequirement =
2095 if (IsRequiresExcludedHack)
2096 UsesRequiresExcludedHack.insert(ActiveModule);
2098 if (ShouldAddRequirement) {
2119 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2125 Module::UnresolvedHeaderDirective Header;
2129 Header.
Kind = Map.headerRoleToKind(
Role);
2133 !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2134 Diags.Report(Header.
FileNameLoc, diag::err_mmap_umbrella_clash)
2135 << ActiveModule->getFullModuleName();
2140 if (ImplicitlyDiscovered) {
2141 SmallString<128> NormalizedPath(HD.
Path);
2142 llvm::sys::path::remove_dots(NormalizedPath,
true);
2143 if (NormalizedPath.starts_with(
".."))
2144 Diags.Report(HD.
PathLoc, diag::warn_mmap_path_outside_directory);
2152 bool NeedsFramework =
false;
2156 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2158 ActiveModule->fullModuleNameIs({
"_Builtin_stddef",
"max_align_t"}))
2159 Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2162 Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2163 << ActiveModule->getFullModuleName()
2172void ModuleMapLoader::handleUmbrellaDirDecl(
2174 std::string DirName = std::string(UDD.
Path);
2175 std::string DirNameAsWritten = DirName;
2178 if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2179 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2180 << ActiveModule->getFullModuleName();
2185 if (ImplicitlyDiscovered) {
2186 SmallString<128> NormalizedPath(UDD.
Path);
2187 llvm::sys::path::remove_dots(NormalizedPath,
true);
2188 if (NormalizedPath.starts_with(
".."))
2189 Diags.Report(UDD.
Location, diag::warn_mmap_path_outside_directory);
2194 if (llvm::sys::path::is_absolute(DirName)) {
2195 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2197 SmallString<128> PathName;
2198 PathName = Directory.getName();
2199 llvm::sys::path::append(PathName, DirName);
2200 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2204 Diags.Report(UDD.
Location, diag::warn_mmap_umbrella_dir_not_found)
2209 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2215 SmallVector<Module::Header, 6> Headers;
2216 llvm::vfs::FileSystem &FS =
2217 SourceMgr.getFileManager().getVirtualFileSystem();
2218 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->
getName(), EC), E;
2219 I != E && !EC; I.increment(EC)) {
2220 if (
auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2221 Module::Header Header = {
"", std::string(I->path()), *FE};
2222 Headers.push_back(std::move(Header));
2229 for (
auto &Header : Headers)
2234 if (
Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2235 Diags.Report(UDD.
Location, diag::err_mmap_umbrella_clash)
2236 << OwningModule->getFullModuleName();
2242 Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName,
2248 ActiveModule->UnresolvedExports.push_back(
Unresolved);
2252 const auto &ModName = EAD.
Id.front();
2254 if (!ActiveModule->ExportAsModule.empty()) {
2255 if (ActiveModule->ExportAsModule == ModName.first) {
2256 Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)
2257 << ActiveModule->Name << ModName.first;
2259 Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)
2260 << ActiveModule->Name << ActiveModule->ExportAsModule
2265 ActiveModule->ExportAsModule = ModName.first;
2266 Map.addLinkAsDependency(ActiveModule);
2270 if (ActiveModule->Parent)
2271 Diags.Report(UD.
Location, diag::err_mmap_use_decl_submodule);
2273 ActiveModule->UnresolvedDirectUses.push_back(UD.
Id);
2277 ActiveModule->LinkLibraries.push_back(
2281void ModuleMapLoader::handleConfigMacros(
2283 if (ActiveModule->Parent) {
2284 Diags.Report(CMD.
Location, diag::err_mmap_config_macro_submodule);
2291 ActiveModule->ConfigMacrosExhaustive =
true;
2293 ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),
2298 Module::UnresolvedConflict Conflict;
2300 Conflict.
Id = CD.
Id;
2304 ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));
2307void ModuleMapLoader::handleInferredModuleDecl(
2309 SourceLocation StarLoc = MD.
Id.front().second;
2313 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2319 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
2320 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2325 if (ActiveModule->InferSubmodules) {
2326 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2327 if (ActiveModule->InferredSubmoduleLoc.isValid())
2328 Diags.Report(ActiveModule->InferredSubmoduleLoc,
2329 diag::note_mmap_prev_definition);
2335 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2339 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2345 ActiveModule->InferSubmodules =
true;
2346 ActiveModule->InferredSubmoduleLoc = StarLoc;
2347 ActiveModule->InferExplicitSubmodules = MD.
Explicit;
2350 auto &InfDir = Map.InferredDirectories[Directory];
2351 InfDir.InferModules =
true;
2352 InfDir.Attrs = MD.
Attrs;
2353 InfDir.ModuleMapFID = ModuleMapFID;
2360 [&](
const auto &
Other) {
2361 Diags.Report(
Other.Location,
2362 diag::err_mmap_expected_inferred_member)
2363 << (ActiveModule !=
nullptr);
2365 [&](
const modulemap::ExcludeDecl &ED) {
2369 diag::err_mmap_expected_inferred_member)
2370 << (ActiveModule !=
nullptr);
2374 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
2377 [&](
const modulemap::ExportDecl &ED) {
2379 if (!ActiveModule) {
2381 diag::err_mmap_expected_inferred_member)
2382 << (ActiveModule !=
nullptr);
2388 ActiveModule->InferExportWildcard =
true;
2390 Diags.Report(ED.
Id.front().second,
2391 diag::err_mmap_expected_export_wildcard);
2398 handleModuleDecl(MD);
2404 handleExternModuleDecl(EMD);
2415 handleExternModuleDecl(EMD);
2423 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
2424 if (Known != Modules.end())
2425 return Known->getValue();
2427 auto ParsedMod = ParsedModules.find(Name);
2428 if (ParsedMod == ParsedModules.end())
2431 Diags.Report(diag::remark_mmap_load_module) << Name;
2433 for (
const auto &ModuleDecl : ParsedMod->second) {
2446 bool ImplicitlyDiscovered,
2450 assert(Target &&
"Missing target information");
2451 llvm::DenseMap<const FileEntry *, bool>::iterator Known =
2452 LoadedModuleMap.find(
File);
2453 if (Known != LoadedModuleMap.end())
2454 return Known->second;
2457 if (ID.isInvalid()) {
2462 FileID &LocalFID = ModuleMapLocalFileID[
File];
2464 auto FileCharacter =
2466 LocalFID = SourceMgr.createFileID(
File, ExternModuleLoc, FileCharacter);
2471 assert(Target &&
"Missing target information");
2472 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
2474 return LoadedModuleMap[
File] =
true;
2475 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
2476 "invalid buffer offset");
2479 ID, Dir, SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
2482 Diags.Report(diag::remark_mmap_load) <<
File.getName();
2484 ImplicitlyDiscovered);
2491 ParsedModuleMap.find(
File);
2492 if (PKnown == ParsedModuleMap.end()) {
2493 ParsedModuleMaps.push_back(
2494 std::make_unique<modulemap::ModuleMapFile>(std::move(*MMF)));
2495 ParsedModuleMap[
File] = &*ParsedModuleMaps.back();
2502 for (
const auto &Cb : Callbacks)
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
#define ALIAS(NAME, TOK, FLAGS)
#define KEYWORD(NAME, FLAGS)
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
static bool isBuiltinHeaderName(StringRef FileName)
Determine whether the given file name is the name of a builtin header, supplied by Clang to replace,...
static bool isBuiltInModuleName(StringRef ModuleName)
Determine whether the given module name is the name of a builtin module that is cyclic with a system ...
static Module * getTopLevelOrNull(Module *M)
static bool violatesPrivateInclude(Module *RequestingModule, const FileEntry *IncFileEnt, ModuleMap::KnownHeader Header)
static void inferFrameworkLink(Module *Mod)
For a framework module, infer the framework against which we should link.
static StringRef sanitizeFilenameAsIdentifier(StringRef Name, SmallVectorImpl< char > &Buffer)
"Sanitize" a filename so that it can be used as an identifier.
static constexpr llvm::StringRef kPrivateModuleSuffix
static void appendSubframeworkPaths(Module *Mod, SmallVectorImpl< char > &Path)
Append to Paths the set of paths needed to get to the subframework in which the given module lives.
static bool shouldAddRequirement(Module *M, StringRef Feature, bool &IsRequiresExcludedHack)
Whether to add the requirement Feature to the module M.
static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, const ModuleMap::KnownHeader &Old)
static bool compareModuleHeaders(const Module::Header &A, const Module::Header &B)
Defines the clang::Module class, which describes a module in the source code.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Concrete class used by the front-end to report problems and issues.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
const FileEntry & getFileEntry() const
StringRef getName() const
The name of this FileEntry.
DirectoryEntryRef getDir() const
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::vfs::FileSystem & getVirtualFileSystem() const
StringRef getCanonicalName(DirectoryEntryRef Dir)
Retrieve the canonical name for a given directory.
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Get a FileEntryRef if it exists, without doing anything on error.
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
@ CMK_ModuleMap
Compiling a module from a module map.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Required to construct a Module.
ModuleMapLoader(SourceManager &SourceMgr, DiagnosticsEngine &Diags, ModuleMap &Map, FileID ModuleMapFID, DirectoryEntryRef Directory, bool IsSystem, bool ImplicitlyDiscovered)
bool loadExternModuleDecl(const modulemap::ExternModuleDecl &EMD)
bool parseAndLoadModuleMapFile(const modulemap::ModuleMapFile &MMF)
bool loadModuleDecl(const modulemap::ModuleDecl &MD)
Module * createShadowedModule(StringRef Name, bool IsFramework, Module *ShadowingModule)
Create a new top-level module that is shadowed by ShadowingModule.
bool resolveExports(Module *Mod, bool Complain)
Resolve all of the unresolved exports in the given module.
void addLinkAsDependency(Module *Mod)
Make module to use export_as as the link dependency name if enough information is available or add it...
friend class ModuleMapLoader
bool parseModuleMapFile(FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered, DirectoryEntryRef Dir, FileID ID=FileID(), SourceLocation ExternModuleLoc=SourceLocation())
Parse a module map without creating clang::Module instances.
void dump()
Dump the contents of the module map, for debugging purposes.
std::pair< Module *, bool > findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit)
Find a new module or submodule, or create it if it does not already exist.
void diagnoseHeaderInclusion(Module *RequestingModule, bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, FileEntryRef File)
Reports errors if a module must not include a specific file.
void addAdditionalModuleMapFile(const Module *M, FileEntryRef ModuleMap)
OptionalFileEntryRef getContainingModuleMapFile(const Module *Module) const
static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role)
Convert a header role to a kind.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
Module * createHeaderUnit(SourceLocation Loc, StringRef Name, Module::Header H)
Create a C++20 header unit.
void setUmbrellaHeaderAsWritten(Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory, SourceLocation Loc=SourceLocation())
Sets the umbrella header of the given module to the given header.
void addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role, bool Imported=false, SourceLocation Loc=SourceLocation())
Adds this header to the given module.
static bool isModular(ModuleHeaderRole Role)
Check if the header with the given role is a modular one.
bool resolveConflicts(Module *Mod, bool Complain)
Resolve all of the unresolved conflicts in the given module.
bool isHeaderUnavailableInModule(FileEntryRef Header, const Module *RequestingModule) const
Determine whether the given header is unavailable as part of the specified module.
void resolveHeaderDirectives(const FileEntry *File) const
Resolve all lazy header directives for the specified file.
ArrayRef< KnownHeader > findResolvedModulesForHeader(FileEntryRef File) const
Like findAllModulesForHeader, but do not attempt to infer module ownership from umbrella headers if w...
OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const
bool shouldImportRelativeToBuiltinIncludeDir(StringRef FileName, Module *Module) const
bool parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem, bool ImplicitlyDiscovered, DirectoryEntryRef HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Load the given module map file, and record any modules we encounter.
Module * createModuleForImplementationUnit(SourceLocation Loc, StringRef Name)
Create a new module for a C++ module implementation unit.
ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo)
Construct a new module map.
std::error_code canonicalizeModuleMapPath(SmallVectorImpl< char > &Path)
Canonicalize Path in a manner suitable for a module map file.
OptionalFileEntryRef findUmbrellaHeaderForModule(Module *M, std::string NameAsWritten, SmallVectorImpl< char > &RelativePathName)
Find the FileEntry for an umbrella header in a module as if it was written in the module map as a hea...
FileID getModuleMapFileIDForUniquing(const Module *M) const
Get the module map file that (along with the module name) uniquely identifies this module.
void setInferredModuleAllowedBy(Module *M, FileID ModMapFID)
void setUmbrellaDirAsWritten(Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten, const Twine &PathRelativeToRootModuleDirectory, SourceLocation Loc=SourceLocation())
Sets the umbrella directory of the given module to the given directory.
Module * findOrCreateModuleFirst(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit)
Call ModuleMap::findOrCreateModule and throw away the information whether the module was found or cre...
Module * lookupModuleUnqualified(StringRef Name, Module *Context) const
Retrieve a module with the given name using lexical name lookup, starting at the given context.
bool isBuiltinHeader(FileEntryRef File)
Is this a compiler builtin header?
Module * createModule(StringRef Name, Module *Parent, bool IsFramework, bool IsExplicit)
Create new submodule, assuming it does not exist.
bool isHeaderInUnavailableModule(FileEntryRef Header) const
Determine whether the given header is part of a module marked 'unavailable'.
FileID getContainingModuleMapFileID(const Module *Module) const
Retrieve the module map file containing the definition of the given module.
~ModuleMap()
Destroy the module map.
Module * createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module *Parent=nullptr)
Create a global module fragment for a C++ module unit.
void setTarget(const TargetInfo &Target)
Set the target information.
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.
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.
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.
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::pair< Module *, bool > ExportDecl
Describes an exported module.
std::vector< UnresolvedConflict > UnresolvedConflicts
The list of conflicts for which the module-id has not yet been resolved.
bool isSubModuleOf(const Module *Other) const
Check if this module is a (possibly transitive) submodule of Other.
bool isPartOfFramework() const
Determine whether this module is a part of a framework, either because it is a framework module or be...
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
@ ModuleImplementationUnit
This is a C++20 module implementation unit.
@ ImplicitGlobalModuleFragment
This is an implicit fragment of the global module which contains only language linkage declarations (...
@ ModuleInterfaceUnit
This is a C++20 module interface unit.
@ ModuleHeaderUnit
This is a C++20 header unit.
@ PrivateModuleFragment
This is the private module fragment within some C++ module.
@ ExplicitGlobalModuleFragment
This is the explicit Global Module Fragment of a modular TU.
unsigned IsFramework
Whether this is a framework module.
std::string ExportAsModule
The module through which entities defined in this module will eventually be exposed,...
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
std::string UmbrellaAsWritten
The name of the umbrella entry, as written in the module map.
unsigned InferExplicitSubmodules
Whether, when inferring submodules, the inferred submodules should be explicit.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
OptionalDirectoryEntryRef getEffectiveUmbrellaDir() const
Get the effective umbrella directory for this module: either the one explicitly written in the module...
bool UseExportAsModuleLinkName
Autolinking uses the framework name for linking purposes when this is false and the export_as name ot...
std::vector< Conflict > Conflicts
The list of conflicts.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
Exposes information about the current target.
Defines the clang::TargetInfo interface.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
bool Sub(InterpState &S, CodePtr OpPC)
std::optional< ModuleMapFile > parseModuleMap(FileID ID, clang::DirectoryEntryRef Dir, SourceManager &SM, DiagnosticsEngine &Diags, bool IsSystem, bool ImplicitlyDiscovered, unsigned *Offset)
Parse a module map file into an in memory representation.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)
SmallVector< std::pair< std::string, SourceLocation >, 2 > ModuleId
Describes the name of a module.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Result
The result type of a method or function.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
@ Keyword
The name has been typo-corrected to a keyword.
CustomizableOptional< DirectoryEntryRef > OptionalDirectoryEntryRef
@ Other
Other implicit parameter.
int const char * function
unsigned IsExternC
Whether this is an extern "C" module.
unsigned IsSystem
Whether this is a system module.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules.
A conflict between two modules.
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