26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/ADT/StringSwitch.h"
28 #include "llvm/Support/Allocator.h"
29 #include "llvm/Support/FileSystem.h"
30 #include "llvm/Support/Host.h"
31 #include "llvm/Support/Path.h"
32 #include "llvm/Support/raw_ostream.h"
34 #if defined(LLVM_ON_UNIX)
37 using namespace clang;
41 default: llvm_unreachable(
"unknown header role");
65 llvm_unreachable(
"unexpected header kind");
67 llvm_unreachable(
"unknown header kind");
71 ModuleMap::resolveExport(
Module *Mod,
73 bool Complain)
const {
75 if (Unresolved.
Id.empty()) {
76 assert(Unresolved.
Wildcard &&
"Invalid unresolved export");
89 bool Complain)
const {
94 Diags.
Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
101 for (
unsigned I = 1, N = Id.size();
I != N; ++
I) {
105 Diags.
Report(Id[
I].second, diag::err_mmap_missing_module_qualified)
124 for (; Mod; Mod = Mod->
Parent) {
126 Paths.push_back(Mod->
Name);
133 for (
unsigned I = Paths.size() - 1;
I != 0; --
I)
134 llvm::sys::path::append(Path,
"Frameworks", Paths[
I-1] +
".framework");
138 ModuleMap::findHeader(
Module *M,
144 (Header.
Size && File->getSize() != *Header.
Size) ||
145 (Header.
ModTime && File->getModificationTime() != *Header.
ModTime))
150 if (llvm::sys::path::is_absolute(Header.
FileName)) {
151 RelativePathName.clear();
159 unsigned FullPathLength = FullPathName.size();
163 unsigned RelativePathLength = RelativePathName.size();
166 llvm::sys::path::append(RelativePathName,
"Headers", Header.
FileName);
167 llvm::sys::path::append(FullPathName, RelativePathName);
168 if (
auto *File = GetFile(FullPathName))
178 RelativePathName.clear();
180 RelativePathName.resize(RelativePathLength);
181 FullPathName.resize(FullPathLength);
182 llvm::sys::path::append(RelativePathName,
"PrivateHeaders",
184 llvm::sys::path::append(FullPathName, RelativePathName);
185 return GetFile(FullPathName);
189 llvm::sys::path::append(RelativePathName, Header.
FileName);
190 llvm::sys::path::append(FullPathName, RelativePathName);
191 return GetFile(FullPathName);
194 void ModuleMap::resolveHeader(
Module *Mod,
197 if (
const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
200 if (
Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
202 << UmbrellaMod->getFullModuleName();
231 bool ModuleMap::resolveAsBuiltinHeader(
234 llvm::sys::path::is_absolute(Header.
FileName) ||
236 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->
Directory ||
244 llvm::sys::path::append(Path, BuiltinIncludeDir->
getName(), Header.
FileName);
258 : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
259 HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
260 SourceModule(nullptr), NumCreatedModules(0) {
261 MMapLangOpts.LineComment =
true;
265 for (
auto &M : Modules)
270 assert((!this->Target || this->Target == &Target) &&
271 "Improper target override");
272 this->Target = &Target;
286 Buffer.push_back(
'_');
287 Buffer.reserve(Buffer.size() + Name.size());
288 for (
unsigned I = 0, N = Name.size();
I != N; ++
I) {
290 Buffer.push_back(Name[I]);
292 Buffer.push_back(
'_');
295 Name = StringRef(Buffer.data(), Buffer.size());
298 while (llvm::StringSwitch<bool>(Name)
299 #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
300 #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
301 #include "clang/Basic/TokenKinds.def"
303 if (Name.data() != Buffer.data())
304 Buffer.append(Name.begin(), Name.end());
305 Buffer.push_back(
'_');
306 Name = StringRef(Buffer.data(), Buffer.size());
316 return llvm::StringSwitch<bool>(
FileName)
317 .Case(
"float.h",
true)
318 .Case(
"iso646.h",
true)
319 .Case(
"limits.h",
true)
320 .Case(
"stdalign.h",
true)
321 .Case(
"stdarg.h",
true)
322 .Case(
"stdatomic.h",
true)
323 .Case(
"stdbool.h",
true)
324 .Case(
"stddef.h",
true)
325 .Case(
"stdint.h",
true)
326 .Case(
"tgmath.h",
true)
327 .Case(
"unwind.h",
true)
331 ModuleMap::HeadersMap::iterator
332 ModuleMap::findKnownHeader(
const FileEntry *File) {
334 HeadersMap::iterator Known = Headers.find(File);
336 Known == Headers.end() && File->
getDir() == BuiltinIncludeDir &&
339 return Headers.find(File);
345 ModuleMap::findHeaderInUmbrellaDirs(
const FileEntry *File,
347 if (UmbrellaDirs.empty())
348 return KnownHeader();
351 assert(Dir &&
"file in no directory");
362 auto KnownDir = UmbrellaDirs.find(Dir);
363 if (KnownDir != UmbrellaDirs.end())
366 IntermediateDirs.push_back(Dir);
369 DirName = llvm::sys::path::parent_path(DirName);
376 return KnownHeader();
387 bool IsPrivate =
false;
391 for (
auto *Hs : HeaderList)
393 std::find_if(Hs->begin(), Hs->end(), [&](
const Module::Header &H) {
394 return H.
Entry == IncFileEnt;
396 assert(IsPrivate &&
"inconsistent headers and roles");
407 bool RequestingModuleIsModuleInterface,
416 if (RequestingModule) {
421 bool Excluded =
false;
422 Module *Private =
nullptr;
423 Module *NotUsed =
nullptr;
425 HeadersMap::iterator Known = findKnownHeader(File);
426 if (Known != Headers.end()) {
436 if (RequestingModule && LangOpts.ModulesDeclUse &&
451 Diags.
Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
458 Diags.
Report(FilenameLoc, diag::err_undeclared_use_of_module)
463 if (Excluded || isHeaderInUmbrellaDirs(File))
468 if (LangOpts.ModulesStrictDeclUse) {
469 Diags.
Report(FilenameLoc, diag::err_undeclared_use_of_module)
471 }
else if (RequestingModule && RequestingModuleIsModuleInterface &&
475 diag::warn_non_modular_include_in_framework_module :
476 diag::warn_non_modular_include_in_module;
510 HeadersMap::iterator Known = findKnownHeader(File);
511 if (Known != Headers.end()) {
517 return MakeResult(H);
521 return MakeResult(Result);
524 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
528 ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(
const FileEntry *File) {
529 assert(!Headers.count(File) &&
"already have a module for this header");
532 KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
540 UmbrellaModule = UmbrellaModule->
Parent;
551 for (
unsigned I = SkippedDirs.size();
I != 0; --
I) {
555 llvm::sys::path::stem(SkippedDirs[
I-1]->getName()), NameBuf);
558 InferredModuleAllowedBy[
Result] = UmbrellaModuleMap;
562 UmbrellaDirs[SkippedDirs[
I-1]] =
Result;
573 llvm::sys::path::stem(File->
getName()), NameBuf);
576 InferredModuleAllowedBy[
Result] = UmbrellaModuleMap;
587 for (
unsigned I = 0, N = SkippedDirs.size();
I != N; ++
I)
588 UmbrellaDirs[SkippedDirs[
I]] = Result;
592 Headers[File].push_back(Header);
596 return KnownHeader();
599 ArrayRef<ModuleMap::KnownHeader>
602 auto It = Headers.find(File);
603 if (It == Headers.end())
614 const Module *RequestingModule)
const {
616 HeadersMap::const_iterator Known = Headers.find(Header);
617 if (Known != Headers.end()) {
619 I = Known->second.begin(),
620 E = Known->second.end();
623 if (
I->isAvailable() &&
624 (!RequestingModule ||
625 I->getModule()->isSubModuleOf(RequestingModule))) {
641 StringRef DirName = Dir->
getName();
643 auto IsUnavailable = [&](
const Module *M) {
651 llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
652 = UmbrellaDirs.find(Dir);
653 if (KnownDir != UmbrellaDirs.end()) {
654 Module *Found = KnownDir->second;
655 if (IsUnavailable(Found))
660 Module *UmbrellaModule = Found;
662 UmbrellaModule = UmbrellaModule->
Parent;
665 for (
unsigned I = SkippedDirs.size();
I != 0; --
I) {
669 llvm::sys::path::stem(SkippedDirs[
I-1]->getName()),
674 if (IsUnavailable(Found))
681 llvm::sys::path::stem(Header->
getName()),
688 return IsUnavailable(Found);
691 SkippedDirs.push_back(Dir);
694 DirName = llvm::sys::path::parent_path(DirName);
706 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
707 if (Known != Modules.end())
708 return Known->getValue();
736 return std::make_pair(Sub,
false);
740 IsExplicit, NumCreatedModules++);
746 return std::make_pair(Result,
true);
751 assert(LangOpts.
CurrentModule == Name &&
"module name mismatch");
752 assert(!Modules[Name] &&
"redefining existing module");
755 new Module(Name, Loc,
nullptr,
false,
756 false, NumCreatedModules++);
763 assert(MainFile &&
"no input file for module interface");
773 assert(Mod->
IsFramework &&
"Can only infer linking for framework modules");
775 "Can only infer linking for top-level frameworks");
778 LibName += FrameworkDir->
getName();
779 llvm::sys::path::append(LibName, Mod->
Name);
784 for (
const char *extension : {
"",
".tbd"}) {
785 llvm::sys::path::replace_extension(LibName, extension);
786 if (FileMgr.
getFile(LibName)) {
795 bool IsSystem,
Module *Parent) {
798 return inferFrameworkModule(FrameworkDir, Attrs, Parent);
802 Attributes Attrs,
Module *Parent) {
807 StringRef FrameworkDirName =
815 llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
825 const FileEntry *ModuleMapFile =
nullptr;
828 bool canInfer =
false;
829 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
831 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
835 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
836 inferred = InferredDirectories.find(ParentDir);
837 if (inferred == InferredDirectories.end()) {
840 bool IsFrameworkDir = Parent.endswith(
".framework");
844 inferred = InferredDirectories.find(ParentDir);
847 if (inferred == InferredDirectories.end())
848 inferred = InferredDirectories.insert(
849 std::make_pair(ParentDir, InferredDirectory())).first;
852 if (inferred->second.InferModules) {
855 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
856 canInfer = std::find(inferred->second.ExcludedModules.begin(),
857 inferred->second.ExcludedModules.end(),
858 Name) == inferred->second.ExcludedModules.end();
860 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
861 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
862 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
863 Attrs.NoUndeclaredIncludes |=
864 inferred->second.Attrs.NoUndeclaredIncludes;
865 ModuleMapFile = inferred->second.ModuleMapFile;
879 llvm::sys::path::append(UmbrellaName,
"Headers", ModuleName +
".h");
890 NumCreatedModules++);
891 InferredModuleAllowedBy[
Result] = ModuleMapFile;
896 Modules[ModuleName] =
Result;
921 = StringRef(FrameworkDir->
getName());
922 llvm::sys::path::append(SubframeworksDirName,
"Frameworks");
923 llvm::sys::path::native(SubframeworksDirName);
927 Dir != DirEnd && !EC; Dir.increment(EC)) {
928 if (!StringRef(Dir->
getName()).endswith(
".framework"))
938 bool FoundParent =
false;
942 = llvm::sys::path::parent_path(SubframeworkDirName);
943 if (SubframeworkDirName.empty())
946 if (FileMgr.
getDirectory(SubframeworkDirName) == FrameworkDir) {
956 inferFrameworkModule(SubframeworkDir, Attrs, Result);
970 Twine NameAsWritten) {
974 UmbrellaDirs[UmbrellaHeader->
getDir()] = Mod;
977 for (
const auto &Cb : Callbacks)
978 Cb->moduleMapAddUmbrellaHeader(&SourceMgr.
getFileManager(), UmbrellaHeader);
982 Twine NameAsWritten) {
985 UmbrellaDirs[UmbrellaDir] = Mod;
988 void ModuleMap::addUnresolvedHeader(
Module *Mod,
992 if (resolveAsBuiltinHeader(Mod, Header)) {
1011 LazyHeadersByModTime[*Header.
ModTime].push_back(Mod);
1013 LazyHeadersBySize[*Header.
Size].push_back(Mod);
1020 resolveHeader(Mod, Header);
1024 auto BySize = LazyHeadersBySize.find(File->
getSize());
1025 if (BySize != LazyHeadersBySize.end()) {
1026 for (
auto *M : BySize->second)
1028 LazyHeadersBySize.erase(BySize);
1032 if (ByModTime != LazyHeadersByModTime.end()) {
1033 for (
auto *M : ByModTime->second)
1035 LazyHeadersByModTime.erase(ByModTime);
1043 const_cast<ModuleMap*
>(
this)->resolveHeader(Mod, Header);
1054 auto &HeaderList = Headers[Header.
Entry];
1055 for (
auto H : HeaderList)
1059 HeaderList.push_back(KH);
1062 bool isCompilingModuleHeader =
1064 if (!Imported || isCompilingModuleHeader) {
1068 isCompilingModuleHeader);
1072 for (
const auto &Cb : Callbacks)
1081 (void) Headers[Header.
Entry];
1097 assert(InferredModuleAllowedBy.count(M) &&
"missing inferred module map");
1098 return InferredModuleAllowedBy.find(M)->second;
1104 assert(M->
IsInferred &&
"module not inferred");
1105 InferredModuleAllowedBy[M] = ModMap;
1109 llvm::errs() <<
"Modules:";
1110 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1111 MEnd = Modules.end();
1113 M->getValue()->
print(llvm::errs(), 2);
1115 llvm::errs() <<
"Headers:";
1116 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1118 llvm::errs() <<
" \"" << H->first->getName() <<
"\" -> ";
1120 E = H->second.end();
1122 if (
I != H->second.begin())
1123 llvm::errs() <<
",";
1124 llvm::errs() <<
I->getModule()->getFullModuleName();
1126 llvm::errs() <<
"\n";
1133 for (
auto &UE : Unresolved) {
1135 if (Export.getPointer() || Export.getInt())
1136 Mod->
Exports.push_back(Export);
1146 for (
auto &UDU : Unresolved) {
1147 Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1159 for (
auto &UC : Unresolved) {
1160 if (
Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1162 Conflict.
Other = OtherMod;
1163 Conflict.
Message = UC.Message;
1266 llvm::BumpPtrAllocator StringData;
1282 llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
1292 bool parseModuleId(ModuleId &Id);
1293 void parseModuleDecl();
1294 void parseExternModuleDecl();
1295 void parseRequiresDecl();
1299 void parseExportDecl();
1300 void parseUseDecl();
1301 void parseLinkDecl();
1302 void parseConfigMacros();
1303 void parseConflict();
1304 void parseInferredModuleDecl(
bool Framework,
bool Explicit);
1306 typedef ModuleMap::Attributes Attributes;
1307 bool parseOptionalAttributes(Attributes &Attrs);
1317 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1318 ModuleMapFile(ModuleMapFile), Directory(Directory),
1319 IsSystem(IsSystem), HadError(
false), ActiveModule(nullptr)
1341 case tok::raw_identifier: {
1345 Tok.
Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1401 case tok::string_literal: {
1416 char *Saved = StringData.Allocate<
char>(Length + 1);
1427 case tok::numeric_constant: {
1430 SpellingBuffer.resize(LToken.
getLength() + 1);
1431 const char *Start = SpellingBuffer.data();
1435 if (StringRef(Start, Length).getAsInteger(0, Value)) {
1455 auto NextIsIdent = [&](StringRef Str) ->
bool {
1460 if (NextIsIdent(
"pragma") && NextIsIdent(
"clang") &&
1461 NextIsIdent(
"module") && NextIsIdent(
"contents")) {
1478 unsigned braceDepth = 0;
1479 unsigned squareDepth = 0;
1486 if (Tok.
is(K) && braceDepth == 0 && squareDepth == 0)
1493 if (Tok.
is(K) && braceDepth == 0 && squareDepth == 0)
1507 if (squareDepth > 0)
1514 if (braceDepth == 0 && squareDepth == 0 && Tok.
is(K))
1530 bool ModuleMapParser::parseModuleId(
ModuleId &Id) {
1562 AT_no_undeclared_includes
1583 void ModuleMapParser::parseModuleDecl() {
1587 parseExternModuleDecl();
1593 bool Explicit =
false;
1594 bool Framework =
false;
1598 ExplicitLoc = consumeToken();
1620 return parseInferredModuleDecl(Framework, Explicit);
1624 if (parseModuleId(Id)) {
1630 if (Id.size() > 1) {
1631 Diags.
Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1632 <<
SourceRange(Id.front().second, Id.back().second);
1637 }
else if (Id.size() == 1 && Explicit) {
1639 Diags.
Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1645 Module *PreviousActiveModule = ActiveModule;
1646 if (Id.size() > 1) {
1649 ActiveModule =
nullptr;
1650 const Module *TopLevelModule =
nullptr;
1651 for (
unsigned I = 0, N = Id.size() - 1;
I != N; ++
I) {
1654 TopLevelModule =
Next;
1655 ActiveModule =
Next;
1660 Diags.
Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1664 Diags.
Report(Id[I].second, diag::err_mmap_expected_module_name);
1672 "submodule defined in same file as 'module *' that allowed its "
1673 "top-level module");
1678 StringRef ModuleName = Id.back().first;
1683 if (parseOptionalAttributes(Attrs))
1702 bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
1705 bool ParsedAsMainInput =
1710 if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1717 Diags.
Report(LBraceLoc, diag::note_mmap_lbrace_match);
1723 Diags.
Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1725 Diags.
Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1740 if (Attrs.IsSystem || IsSystem)
1742 if (Attrs.IsExternC)
1744 if (Attrs.NoUndeclaredIncludes ||
1745 (!ActiveModule->
Parent && ModuleName ==
"Darwin"))
1749 if (!ActiveModule->
Parent) {
1750 StringRef MapFileName(ModuleMapFile->
getName());
1751 if (MapFileName.endswith(
"module.private.modulemap") ||
1752 MapFileName.endswith(
"module_private.map")) {
1758 auto const *M =
E->getValue();
1763 diag::warn_mmap_mismatched_top_level_private)
1770 diag::note_mmap_rename_top_level_private_as_submodule);
1771 D << ActiveModule->
Name << M->
Name;
1772 StringRef Bad(ActiveModule->
Name);
1773 if (Bad.consume_back(
"Private")) {
1775 Fixed.append(
".Private");
1794 parseConfigMacros();
1817 parseRequiresDecl();
1829 parseUmbrellaDirDecl(UmbrellaLoc);
1860 Diags.
Report(LBraceLoc, diag::note_mmap_lbrace_match);
1881 ActiveModule = PreviousActiveModule;
1888 void ModuleMapParser::parseExternModuleDecl() {
1903 if (parseModuleId(Id)) {
1919 if (llvm::sys::path::is_relative(FileNameRef)) {
1920 ModuleMapFileName += Directory->
getName();
1921 llvm::sys::path::append(ModuleMapFileName, FileName);
1922 FileNameRef = ModuleMapFileName;
1930 FileID(),
nullptr, ExternLoc);
1949 bool &IsRequiresExcludedHack) {
1950 if (Feature ==
"excluded" &&
1953 IsRequiresExcludedHack =
true;
1955 }
else if (Feature ==
"cplusplus" && M->
fullModuleNameIs({
"IOKit",
"avc"})) {
1973 void ModuleMapParser::parseRequiresDecl() {
1981 bool RequiredState =
true;
1983 RequiredState =
false;
1997 bool IsRequiresExcludedHack =
false;
1998 bool ShouldAddRequirement =
2001 if (IsRequiresExcludedHack)
2002 UsesRequiresExcludedHack.insert(ActiveModule);
2004 if (ShouldAddRequirement) {
2006 ActiveModule->
addRequirement(Feature, RequiredState, Map.LangOpts,
2035 LeadingToken = Tok.
Kind;
2043 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2089 enum Attribute { Size, ModTime,
Unknown };
2092 switch (llvm::StringSwitch<Attribute>(Str)
2094 .Case(
"mtime", ModTime)
2098 Diags.
Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2101 diag::err_mmap_invalid_header_attribute_value) << Str;
2111 Diags.
Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2114 diag::err_mmap_invalid_header_attribute_value) << Str;
2123 Diags.
Report(Loc, diag::err_mmap_expected_header_attribute);
2133 Diags.
Report(LBraceLoc, diag::note_mmap_lbrace_match);
2138 Map.addUnresolvedHeader(ActiveModule, std::move(Header));
2150 void ModuleMapParser::parseUmbrellaDirDecl(
SourceLocation UmbrellaLoc) {
2164 Diags.
Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2172 if (llvm::sys::path::is_absolute(DirName))
2176 PathName = Directory->
getName();
2177 llvm::sys::path::append(PathName, DirName);
2182 Diags.
Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2187 if (UsesRequiresExcludedHack.count(ActiveModule)) {
2196 I !=
E && !EC; I.increment(EC)) {
2201 Headers.push_back(std::move(Header));
2208 for (
auto &Header : Headers)
2213 if (
Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2214 Diags.
Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2215 << OwningModule->getFullModuleName();
2233 void ModuleMapParser::parseExportDecl() {
2239 bool Wildcard =
false;
2243 ParsedModuleId.push_back(std::make_pair(Tok.
getString(),
2267 ExportLoc, ParsedModuleId, Wildcard
2276 void ModuleMapParser::parseUseDecl() {
2278 auto KWLoc = consumeToken();
2281 parseModuleId(ParsedModuleId);
2283 if (ActiveModule->
Parent)
2284 Diags.
Report(KWLoc, diag::err_mmap_use_decl_submodule);
2293 void ModuleMapParser::parseLinkDecl() {
2298 bool IsFramework =
false;
2312 std::string LibraryName = Tok.
getString();
2325 void ModuleMapParser::parseConfigMacros() {
2330 if (ActiveModule->
Parent) {
2331 Diags.
Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
2336 if (parseOptionalAttributes(Attrs))
2339 if (Attrs.IsExhaustive && !ActiveModule->
Parent) {
2349 if (!ActiveModule->
Parent) {
2368 if (!ActiveModule->
Parent) {
2379 llvm::raw_string_ostream OS(result);
2381 for (
unsigned I = 0, N = Id.size(); I != N; ++
I) {
2395 void ModuleMapParser::parseConflict() {
2401 if (parseModuleId(Conflict.
Id))
2434 void ModuleMapParser::parseInferredModuleDecl(
bool Framework,
bool Explicit) {
2437 bool Failed =
false;
2440 if (!ActiveModule && !Framework) {
2441 Diags.
Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2449 Diags.
Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2455 Diags.
Report(StarLoc, diag::err_mmap_inferred_redef);
2458 diag::note_mmap_prev_definition);
2464 Diags.
Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2467 }
else if (Explicit) {
2468 Diags.
Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2486 if (parseOptionalAttributes(Attrs))
2496 Map.InferredDirectories[Directory].InferModules =
true;
2497 Map.InferredDirectories[Directory].Attrs = Attrs;
2498 Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2522 << (ActiveModule !=
nullptr);
2534 Map.InferredDirectories[Directory].ExcludedModules
2541 if (!ActiveModule) {
2543 << (ActiveModule !=
nullptr);
2553 diag::err_mmap_expected_export_wildcard);
2564 << (ActiveModule !=
nullptr);
2574 Diags.
Report(LBraceLoc, diag::note_mmap_lbrace_match);
2591 bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
2592 bool HadError =
false;
2609 = llvm::StringSwitch<AttributeKind>(Tok.
getString())
2610 .Case(
"exhaustive", AT_exhaustive)
2611 .Case(
"extern_c", AT_extern_c)
2612 .Case(
"no_undeclared_includes", AT_no_undeclared_includes)
2613 .Case(
"system", AT_system)
2614 .Default(AT_unknown);
2615 switch (Attribute) {
2622 Attrs.IsSystem =
true;
2626 Attrs.IsExternC =
true;
2630 Attrs.IsExhaustive =
true;
2633 case AT_no_undeclared_includes:
2634 Attrs.NoUndeclaredIncludes =
true;
2642 Diags.
Report(LSquareLoc, diag::note_mmap_lsquare_match);
2705 assert(Target &&
"Missing target information");
2706 llvm::DenseMap<const FileEntry *, bool>::iterator Known
2707 = ParsedModuleMap.find(File);
2708 if (Known != ParsedModuleMap.end())
2709 return Known->second;
2713 auto FileCharacter =
2715 ID = SourceMgr.
createFileID(File, ExternModuleLoc, FileCharacter);
2718 assert(Target &&
"Missing target information");
2721 return ParsedModuleMap[File] =
true;
2723 "invalid buffer offset");
2727 Buffer->getBufferStart(),
2728 Buffer->getBufferStart() + (Offset ? *Offset : 0),
2729 Buffer->getBufferEnd());
2734 ParsedModuleMap[File] =
Result;
2738 assert(Loc.first == ID &&
"stopped in a different file?");
2739 *Offset = Loc.second;
2743 for (
const auto &Cb : Callbacks)
2744 Cb->moduleMapFileRead(Start, *File, IsSystem);
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
unsigned IsAvailable
Whether this module is available in the current translation unit.
bool is(TokenKind K) const
ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo)
Construct a new module map.
static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid=nullptr)
getSpelling - This method is used to get the spelling of a token into a preallocated buffer...
SmallVector< UnresolvedExportDecl, 2 > UnresolvedExports
The set of export declarations that have yet to be resolved.
std::string Name
The name of this module.
static Module * getTopLevelOrNull(Module *M)
Module * lookupModuleQualified(StringRef Name, Module *Context) const
Retrieve a module with the given name within the given context, using direct (qualified) name lookup...
This header is included but private.
static LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
module_iterator module_begin() const
SmallVector< UnresolvedHeaderDirective, 1 > MissingHeaders
Headers that are mentioned in the module map file but could not be found on the file system...
std::string Message
The message provided to the user when there is a conflict.
Implements support for file system lookup, file system caching, and directory search management...
void dump()
Dump the contents of the module map, for debugging purposes.
Defines the clang::FileManager interface and associated types.
An unresolved conflict with another module.
Module * findModule(StringRef Name) const
Retrieve a module with the given name.
This header is part of the module (for layering purposes) but should be textually included...
bool isHeaderInUnavailableModule(const FileEntry *Header) const
Determine whether the given header is part of a module marked 'unavailable'.
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
unsigned IsExternC
Whether this is an 'extern "C"' module (which implicitly puts all headers in it within an 'extern "...
std::vector< UnresolvedConflict > UnresolvedConflicts
The list of conflicts for which the module-id has not yet been resolved.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
void excludeHeader(Module *Mod, Module::Header Header)
Marks this header as being excluded from the given module.
unsigned IsFramework
Whether this is a framework module.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
ModuleMapParser(Lexer &L, SourceManager &SourceMgr, const TargetInfo *Target, DiagnosticsEngine &Diags, ModuleMap &Map, const FileEntry *ModuleMapFile, const DirectoryEntry *Directory, bool IsSystem)
std::unique_ptr< llvm::MemoryBuffer > Buffer
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Parser - This implements a parser for the C family of languages.
unsigned getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it...
bool resolveUses(Module *Mod, bool Complain)
Resolve all of the unresolved uses in the given module.
void addRequirement(StringRef Feature, bool RequiredState, const LangOptions &LangOpts, const TargetInfo &Target)
Add the given feature requirement to the list of features required by this module.
virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC)=0
Get a directory_iterator for Dir.
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...
bool isHeaderUnavailableInModule(const FileEntry *Header, const Module *RequestingModule) const
Determine whether the given header is unavailable as part of the specified module.
ModuleKind Kind
The kind of this module.
void markUnavailable(bool MissingRequirement=false)
Mark this module and all of its submodules as unavailable.
The virtual file system interface.
A library or framework to link against when an entity from this module is used.
bool resolveConflicts(Module *Mod, bool Complain)
Resolve all of the unresolved conflicts in the given module.
static SourceLocation getFromRawEncoding(unsigned Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
SourceLocation getLocation() const
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
bool fullModuleNameIs(ArrayRef< StringRef > nameParts) const
Whether the full name of this module is equal to joining nameParts with "."s.
Token - This structure provides full information about a lexed token.
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, Twine NameAsWritten)
Sets the umbrella directory of the given module to the given directory.
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Compiling a module from a module map.
Describes a module or submodule.
static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind)
Convert a header kind to a role. Requires Kind to not be HK_Excluded.
bool directlyUses(const Module *Requested) const
Determine whether this module has declared its intention to directly use another module.
static bool isBuiltinHeader(StringRef FileName)
Is this a compiler builtin header?
unsigned InferExportWildcard
Whether, when inferring submodules, the inferr submodules should export all modules they import (e...
bool isAvailable() const
Determine whether this module is available for use within the current translation unit...
std::string Message
The message provided to the user when there is a conflict.
ArrayRef< KnownHeader > findAllModulesForHeader(const FileEntry *File) const
Retrieve all the modules that contain the given header file.
IntrusiveRefCntPtr< vfs::FileSystem > getVirtualFileSystem() const
ModuleId Id
The (unresolved) module id.
Concrete class used by the front-end to report problems and issues.
Module * Parent
The parent of this module.
unsigned IsInferred
Whether this is an inferred submodule (module * { ... }).
module_iterator module_end() const
Defines the Diagnostic-related interfaces.
StringRef getName() const
const FileEntry * getContainingModuleMapFile(const Module *Module) const
Retrieve the module map file containing the definition of the given module.
tok::TokenKind getKind() const
detail::InMemoryDirectory::const_iterator I
void setTarget(const TargetInfo &Target)
Set the target information.
unsigned NoUndeclaredIncludes
Whether files in this module can only include non-modular headers and headers from used modules...
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers)...
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode), returns a reference to the text substring in the buffer if known.
static bool violatesPrivateInclude(Module *RequestingModule, const FileEntry *IncFileEnt, ModuleMap::KnownHeader Header)
Module * findSubmodule(StringRef Name) const
Find the submodule with the given name.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
void resolveHeaderDirectives(const FileEntry *File) const
Resolve all lazy header directives for the specified file.
std::string CurrentModule
The name of the current module, of which the main source file is a part.
const DirectoryEntry * getDirectory(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
bool parseModuleMapFile(const FileEntry *File, bool IsSystem, const DirectoryEntry *HomeDir, FileID ID=FileID(), unsigned *Offset=nullptr, SourceLocation ExternModuleLoc=SourceLocation())
Parse the given module map file, and record any modules we encounter.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
static LLVM_READONLY bool isValidIdentifier(StringRef S)
Return true if this is a valid ASCII identifier.
ModuleHeaderRole
Flags describing the role of a module header.
bool isPartOfFramework() const
Determine whether this module is a part of a framework, either because it is a framework module or be...
Exposes information about the current target.
void diagnoseHeaderInclusion(Module *RequestingModule, bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, const FileEntry *File)
Reports errors if a module must not include a specific file.
SmallVector< ModuleId, 2 > UnresolvedDirectUses
The set of use declarations that have yet to be resolved.
ModuleId Id
The name of the module.
Module * lookupModuleUnqualified(StringRef Name, Module *Context) const
Retrieve a module with the given name using lexical name lookup, starting at the given context...
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
FileManager & getFileManager() const
unsigned ConfigMacrosExhaustive
Whether the set of configuration macros is exhaustive.
bool hasUDSuffix() const
Return true if this token is a string or character literal which has a ud-suffix. ...
bool resolveExports(Module *Mod, bool Complain)
Resolve all of the unresolved exports in the given module.
llvm::SmallVector< LinkLibrary, 2 > LinkLibraries
The set of libraries or frameworks to link against when an entity from this module is used...
static int compareModuleHeaders(const Module::Header *A, const Module::Header *B)
SmallVector< std::pair< std::string, SourceLocation >, 2 > ModuleId
Describes the name of a module.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
bool isSubModuleOf(const Module *Other) const
Determine whether this module is a submodule of the given other module.
static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, const ModuleMap::KnownHeader &Old)
KnownHeader findModuleForHeader(const FileEntry *File, bool AllowTextual=false)
Retrieve the module that owns the given header file, if any.
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, Twine NameAsWritten)
Sets the umbrella header of the given module to the given header.
static std::string formatModuleId(const ModuleId &Id)
Format a module-id into a string.
DirectoryName getUmbrellaDir() const
Retrieve the directory for which this module serves as the umbrella.
The result type of a method or function.
void addAdditionalModuleMapFile(const Module *M, const FileEntry *ModuleMap)
enum clang::MMToken::TokenKind Kind
SmallVector< ExportDecl, 2 > Exports
The set of export declarations.
const DirectoryEntry * Directory
The build directory of this module.
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.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, FileManager &FileMgr)
For a framework module, infer the framework against which we should link.
SourceLocation getLocation()
static bool shouldAddRequirement(Module *M, StringRef Feature, bool &IsRequiresExcludedHack)
Whether to add the requirement Feature to the module M.
static StringRef sanitizeFilenameAsIdentifier(StringRef Name, SmallVectorImpl< char > &Buffer)
"Sanitize" a filename so that it can be used as an identifier.
void print(raw_ostream &OS, unsigned Indent=0) const
Print the module map for this module to the given stream.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Cached information about one file (either on disk or in the virtual file system). ...
SmallVector< Header, 2 > Headers[5]
The headers that are part of this module.
bool isSubFramework() const
Determine whether this module is a subframework of another framework.
Defines the clang::TargetOptions class.
bool Wildcard
Whether this export declaration ends in a wildcard, indicating that all of its submodules should be e...
static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role)
Convert a header role to a kind.
FileID getMainFileID() const
Returns the FileID of the main source file.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
This header is normally included in the module.
void addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role, bool Imported=false)
Adds this header to the given module.
bool parseModuleMapFile()
Parse a module map file.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
StringRef getCanonicalName(const DirectoryEntry *Dir)
Retrieve the canonical name for a given directory.
A conflict between two modules.
SmallVector< UnresolvedHeaderDirective, 1 > UnresolvedHeaders
Headers that are mentioned in the module map file but that we have not yet attempted to resolve to a ...
unsigned IsMissingRequirement
Whether this module is missing a feature from Requirements.
llvm::PointerUnion< const DirectoryEntry *, const FileEntry * > Umbrella
The umbrella header or directory.
SourceLocation InferredSubmoduleLoc
The location of the inferred submodule.
StringRef getName() const
detail::InMemoryDirectory::const_iterator E
void addTopHeader(const FileEntry *File)
Add a top-level header associated with this module.
Module * createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name)
Create a new module for a C++ Modules TS module interface unit.
bool terminatedByDirective()
SourceLocation DefinitionLoc
The location of the module definition.
time_t getModificationTime() const
const FileEntry * getModuleMapFileForUniquing(const Module *M) const
Get the module map file that (along with the module name) uniquely identifies this module...
A token in a module map file.
std::vector< Conflict > Conflicts
The list of conflicts.
SmallVector< Module *, 2 > DirectUses
The directly used modules.
Describes an exported module that has not yet been resolved (perhaps because the module it refers to ...
Cached information about one directory (either on disk or in the virtual file system).
static LLVM_READONLY bool isIdentifierBody(unsigned char c, bool AllowDollar=false)
Returns true if this is a body character of a C identifier, which is [a-zA-Z0-9_].
const LangOptions & getLangOpts() const
getLangOpts - Return the language features currently enabled.
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
unsigned InferSubmodules
Whether we should infer submodules for this module based on the headers.
llvm::PointerIntPair< Module *, 1, bool > ExportDecl
Describes an exported module.
StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
StringLiteral - This represents a string literal expression, e.g.
Defines the clang::TargetInfo interface.
StringRef getString() const
~ModuleMap()
Destroy the module map.
std::vector< std::string > ConfigMacros
The set of "configuration macros", which are macros that (intentionally) change how this module is bu...
bool isCompilingModule() const
Are we compiling a module interface (.cppm or module map)?
unsigned getLength() const
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
AttributeKind
Enumerates the known attributes.
uint64_t getInteger() const
std::string UmbrellaAsWritten
The name of the umbrella entry, as written in the module map.
Module * Other
The module that this module conflicts with.
A trivial tuple used to represent a source range.
const DirectoryEntry * getDir() const
Return the directory the file lives in.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap)
This class handles loading and caching of source files into memory.
unsigned InferExplicitSubmodules
Whether, when inferring submodules, the inferred submodules should be explicit.
This is a C++ Modules TS module interface unit.