2286 lines · cpp
1//===- ModuleMap.cpp - Describe the layout of modules ---------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the ModuleMap implementation, which describes the layout10// of a module as it relates to headers.11//12//===----------------------------------------------------------------------===//13 14#include "clang/Lex/ModuleMap.h"15#include "clang/Basic/CharInfo.h"16#include "clang/Basic/Diagnostic.h"17#include "clang/Basic/FileManager.h"18#include "clang/Basic/LLVM.h"19#include "clang/Basic/LangOptions.h"20#include "clang/Basic/Module.h"21#include "clang/Basic/SourceLocation.h"22#include "clang/Basic/SourceManager.h"23#include "clang/Basic/TargetInfo.h"24#include "clang/Lex/HeaderSearch.h"25#include "clang/Lex/HeaderSearchOptions.h"26#include "clang/Lex/LexDiagnostic.h"27#include "clang/Lex/ModuleMapFile.h"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"40#include <cassert>41#include <cstring>42#include <optional>43#include <string>44#include <system_error>45#include <utility>46 47using namespace clang;48 49void ModuleMapCallbacks::anchor() {}50 51void ModuleMap::resolveLinkAsDependencies(Module *Mod) {52 auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);53 if (PendingLinkAs != PendingLinkAsModule.end()) {54 for (auto &Name : PendingLinkAs->second) {55 auto *M = findModule(Name.getKey());56 if (M)57 M->UseExportAsModuleLinkName = true;58 }59 }60}61 62void ModuleMap::addLinkAsDependency(Module *Mod) {63 if (findModule(Mod->ExportAsModule))64 Mod->UseExportAsModuleLinkName = true;65 else66 PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);67}68 69Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {70 switch ((int)Role) {71 case NormalHeader:72 return Module::HK_Normal;73 case PrivateHeader:74 return Module::HK_Private;75 case TextualHeader:76 return Module::HK_Textual;77 case PrivateHeader | TextualHeader:78 return Module::HK_PrivateTextual;79 case ExcludedHeader:80 return Module::HK_Excluded;81 }82 llvm_unreachable("unknown header role");83}84 85ModuleMap::ModuleHeaderRole86ModuleMap::headerKindToRole(Module::HeaderKind Kind) {87 switch ((int)Kind) {88 case Module::HK_Normal:89 return NormalHeader;90 case Module::HK_Private:91 return PrivateHeader;92 case Module::HK_Textual:93 return TextualHeader;94 case Module::HK_PrivateTextual:95 return ModuleHeaderRole(PrivateHeader | TextualHeader);96 case Module::HK_Excluded:97 return ExcludedHeader;98 }99 llvm_unreachable("unknown header kind");100}101 102bool ModuleMap::isModular(ModuleHeaderRole Role) {103 return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));104}105 106Module::ExportDecl107ModuleMap::resolveExport(Module *Mod,108 const Module::UnresolvedExportDecl &Unresolved,109 bool Complain) const {110 // We may have just a wildcard.111 if (Unresolved.Id.empty()) {112 assert(Unresolved.Wildcard && "Invalid unresolved export");113 return Module::ExportDecl(nullptr, true);114 }115 116 // Resolve the module-id.117 Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);118 if (!Context)119 return {};120 121 return Module::ExportDecl(Context, Unresolved.Wildcard);122}123 124Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,125 bool Complain) const {126 // Find the starting module.127 Module *Context = lookupModuleUnqualified(Id[0].first, Mod);128 if (!Context) {129 if (Complain)130 Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)131 << Id[0].first << Mod->getFullModuleName();132 133 return nullptr;134 }135 136 // Dig into the module path.137 for (unsigned I = 1, N = Id.size(); I != N; ++I) {138 Module *Sub = lookupModuleQualified(Id[I].first, Context);139 if (!Sub) {140 if (Complain)141 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)142 << Id[I].first << Context->getFullModuleName()143 << SourceRange(Id[0].second, Id[I-1].second);144 145 return nullptr;146 }147 148 Context = Sub;149 }150 151 return Context;152}153 154/// Append to \p Paths the set of paths needed to get to the155/// subframework in which the given module lives.156static void appendSubframeworkPaths(Module *Mod,157 SmallVectorImpl<char> &Path) {158 // Collect the framework names from the given module to the top-level module.159 SmallVector<StringRef, 2> Paths;160 for (; Mod; Mod = Mod->Parent) {161 if (Mod->IsFramework)162 Paths.push_back(Mod->Name);163 }164 165 if (Paths.empty())166 return;167 168 // Add Frameworks/Name.framework for each subframework.169 for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))170 llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");171}172 173OptionalFileEntryRef ModuleMap::findHeader(174 Module *M, const Module::UnresolvedHeaderDirective &Header,175 SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {176 // Search for the header file within the module's home directory.177 auto Directory = M->Directory;178 SmallString<128> FullPathName(Directory->getName());179 180 auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {181 auto File =182 expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));183 if (!File || (Header.Size && File->getSize() != *Header.Size) ||184 (Header.ModTime && File->getModificationTime() != *Header.ModTime))185 return std::nullopt;186 return *File;187 };188 189 auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {190 unsigned FullPathLength = FullPathName.size();191 appendSubframeworkPaths(M, RelativePathName);192 unsigned RelativePathLength = RelativePathName.size();193 194 // Check whether this file is in the public headers.195 llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);196 llvm::sys::path::append(FullPathName, RelativePathName);197 if (auto File = GetFile(FullPathName))198 return File;199 200 // Check whether this file is in the private headers.201 // Ideally, private modules in the form 'FrameworkName.Private' should202 // be defined as 'module FrameworkName.Private', and not as203 // 'framework module FrameworkName.Private', since a 'Private.Framework'204 // does not usually exist. However, since both are currently widely used205 // for private modules, make sure we find the right path in both cases.206 if (M->IsFramework && M->Name == "Private")207 RelativePathName.clear();208 else209 RelativePathName.resize(RelativePathLength);210 FullPathName.resize(FullPathLength);211 llvm::sys::path::append(RelativePathName, "PrivateHeaders",212 Header.FileName);213 llvm::sys::path::append(FullPathName, RelativePathName);214 return GetFile(FullPathName);215 };216 217 if (llvm::sys::path::is_absolute(Header.FileName)) {218 RelativePathName.clear();219 RelativePathName.append(Header.FileName.begin(), Header.FileName.end());220 return GetFile(Header.FileName);221 }222 223 if (M->isPartOfFramework())224 return GetFrameworkFile();225 226 // Lookup for normal headers.227 llvm::sys::path::append(RelativePathName, Header.FileName);228 llvm::sys::path::append(FullPathName, RelativePathName);229 auto NormalHdrFile = GetFile(FullPathName);230 231 if (!NormalHdrFile && Directory->getName().ends_with(".framework")) {232 // The lack of 'framework' keyword in a module declaration it's a simple233 // mistake we can diagnose when the header exists within the proper234 // framework style path.235 FullPathName.assign(Directory->getName());236 RelativePathName.clear();237 if (GetFrameworkFile()) {238 Diags.Report(Header.FileNameLoc,239 diag::warn_mmap_incomplete_framework_module_declaration)240 << Header.FileName << M->getFullModuleName();241 NeedsFramework = true;242 }243 return std::nullopt;244 }245 246 return NormalHdrFile;247}248 249/// Determine whether the given file name is the name of a builtin250/// header, supplied by Clang to replace, override, or augment existing system251/// headers.252static bool isBuiltinHeaderName(StringRef FileName) {253 return llvm::StringSwitch<bool>(FileName)254 .Case("float.h", true)255 .Case("iso646.h", true)256 .Case("limits.h", true)257 .Case("stdalign.h", true)258 .Case("stdarg.h", true)259 .Case("stdatomic.h", true)260 .Case("stdbool.h", true)261 .Case("stdckdint.h", true)262 .Case("stdcountof.h", true)263 .Case("stddef.h", true)264 .Case("stdint.h", true)265 .Case("tgmath.h", true)266 .Case("unwind.h", true)267 .Default(false);268}269 270/// Determine whether the given module name is the name of a builtin271/// module that is cyclic with a system module on some platforms.272static bool isBuiltInModuleName(StringRef ModuleName) {273 return llvm::StringSwitch<bool>(ModuleName)274 .Case("_Builtin_float", true)275 .Case("_Builtin_inttypes", true)276 .Case("_Builtin_iso646", true)277 .Case("_Builtin_limits", true)278 .Case("_Builtin_stdalign", true)279 .Case("_Builtin_stdarg", true)280 .Case("_Builtin_stdatomic", true)281 .Case("_Builtin_stdbool", true)282 .Case("_Builtin_stddef", true)283 .Case("_Builtin_stdint", true)284 .Case("_Builtin_stdnoreturn", true)285 .Case("_Builtin_tgmath", true)286 .Case("_Builtin_unwind", true)287 .Default(false);288}289 290void ModuleMap::resolveHeader(Module *Mod,291 const Module::UnresolvedHeaderDirective &Header,292 bool &NeedsFramework) {293 SmallString<128> RelativePathName;294 if (OptionalFileEntryRef File =295 findHeader(Mod, Header, RelativePathName, NeedsFramework)) {296 if (Header.IsUmbrella) {297 const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();298 if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])299 Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)300 << UmbrellaMod->getFullModuleName();301 else302 // Record this umbrella header.303 setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,304 RelativePathName.str());305 } else {306 Module::Header H = {Header.FileName, std::string(RelativePathName),307 *File};308 addHeader(Mod, H, headerKindToRole(Header.Kind));309 }310 } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {311 // There's a builtin header but no corresponding on-disk header. Assume312 // this was supposed to modularize the builtin header alone.313 } else if (Header.Kind == Module::HK_Excluded) {314 // Ignore missing excluded header files. They're optional anyway.315 } else {316 // If we find a module that has a missing header, we mark this module as317 // unavailable and store the header directive for displaying diagnostics.318 Mod->MissingHeaders.push_back(Header);319 // A missing header with stat information doesn't make the module320 // unavailable; this keeps our behavior consistent as headers are lazily321 // resolved. (Such a module still can't be built though, except from322 // preprocessed source.)323 if (!Header.Size && !Header.ModTime)324 Mod->markUnavailable(/*Unimportable=*/false);325 }326}327 328bool ModuleMap::resolveAsBuiltinHeader(329 Module *Mod, const Module::UnresolvedHeaderDirective &Header) {330 if (Header.Kind == Module::HK_Excluded ||331 llvm::sys::path::is_absolute(Header.FileName) ||332 Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||333 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||334 !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))335 return false;336 337 // This is a system module with a top-level header. This header338 // may have a counterpart (or replacement) in the set of headers339 // supplied by Clang. Find that builtin header.340 SmallString<128> Path;341 llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);342 auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);343 if (!File)344 return false;345 346 Module::Header H = {Header.FileName, Header.FileName, *File};347 auto Role = headerKindToRole(Header.Kind);348 addHeader(Mod, H, Role);349 return true;350}351 352ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,353 const LangOptions &LangOpts, const TargetInfo *Target,354 HeaderSearch &HeaderInfo)355 : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),356 HeaderInfo(HeaderInfo) {357}358 359ModuleMap::~ModuleMap() = default;360 361void ModuleMap::setTarget(const TargetInfo &Target) {362 assert((!this->Target || this->Target == &Target) &&363 "Improper target override");364 this->Target = &Target;365}366 367/// "Sanitize" a filename so that it can be used as an identifier.368static StringRef sanitizeFilenameAsIdentifier(StringRef Name,369 SmallVectorImpl<char> &Buffer) {370 if (Name.empty())371 return Name;372 373 if (!isValidAsciiIdentifier(Name)) {374 // If we don't already have something with the form of an identifier,375 // create a buffer with the sanitized name.376 Buffer.clear();377 if (isDigit(Name[0]))378 Buffer.push_back('_');379 Buffer.reserve(Buffer.size() + Name.size());380 for (unsigned I = 0, N = Name.size(); I != N; ++I) {381 if (isAsciiIdentifierContinue(Name[I]))382 Buffer.push_back(Name[I]);383 else384 Buffer.push_back('_');385 }386 387 Name = StringRef(Buffer.data(), Buffer.size());388 }389 390 while (llvm::StringSwitch<bool>(Name)391#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)392#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)393#include "clang/Basic/TokenKinds.def"394 .Default(false)) {395 if (Name.data() != Buffer.data())396 Buffer.append(Name.begin(), Name.end());397 Buffer.push_back('_');398 Name = StringRef(Buffer.data(), Buffer.size());399 }400 401 return Name;402}403 404bool ModuleMap::isBuiltinHeader(FileEntryRef File) {405 return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&406 isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));407}408 409bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,410 Module *Module) const {411 return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&412 Module->IsSystem && !Module->isPartOfFramework() &&413 isBuiltinHeaderName(FileName);414}415 416ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(FileEntryRef File) {417 resolveHeaderDirectives(File);418 HeadersMap::iterator Known = Headers.find(File);419 if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&420 Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {421 HeaderInfo.loadTopLevelSystemModules();422 return Headers.find(File);423 }424 return Known;425}426 427ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(428 FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {429 if (UmbrellaDirs.empty())430 return {};431 432 OptionalDirectoryEntryRef Dir = File.getDir();433 434 // Note: as an egregious but useful hack we use the real path here, because435 // frameworks moving from top-level frameworks to embedded frameworks tend436 // to be symlinked from the top-level location to the embedded location,437 // and we need to resolve lookups as if we had found the embedded location.438 StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);439 440 // Keep walking up the directory hierarchy, looking for a directory with441 // an umbrella header.442 do {443 auto KnownDir = UmbrellaDirs.find(*Dir);444 if (KnownDir != UmbrellaDirs.end())445 return KnownHeader(KnownDir->second, NormalHeader);446 447 IntermediateDirs.push_back(*Dir);448 449 // Retrieve our parent path.450 DirName = llvm::sys::path::parent_path(DirName);451 if (DirName.empty())452 break;453 454 // Resolve the parent path to a directory entry.455 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);456 } while (Dir);457 return {};458}459 460static bool violatesPrivateInclude(Module *RequestingModule,461 const FileEntry *IncFileEnt,462 ModuleMap::KnownHeader Header) {463#ifndef NDEBUG464 if (Header.getRole() & ModuleMap::PrivateHeader) {465 // Check for consistency between the module header role466 // as obtained from the lookup and as obtained from the module.467 // This check is not cheap, so enable it only for debugging.468 bool IsPrivate = false;469 ArrayRef<Module::Header> HeaderList[] = {470 Header.getModule()->getHeaders(Module::HK_Private),471 Header.getModule()->getHeaders(Module::HK_PrivateTextual)};472 for (auto Hs : HeaderList)473 IsPrivate |= llvm::any_of(474 Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });475 assert(IsPrivate && "inconsistent headers and roles");476 }477#endif478 return !Header.isAccessibleFrom(RequestingModule);479}480 481static Module *getTopLevelOrNull(Module *M) {482 return M ? M->getTopLevelModule() : nullptr;483}484 485void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,486 bool RequestingModuleIsModuleInterface,487 SourceLocation FilenameLoc,488 StringRef Filename, FileEntryRef File) {489 // No errors for indirect modules. This may be a bit of a problem for modules490 // with no source files.491 if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))492 return;493 494 if (RequestingModule) {495 resolveUses(RequestingModule, /*Complain=*/false);496 resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);497 }498 499 bool Excluded = false;500 Module *Private = nullptr;501 Module *NotUsed = nullptr;502 503 HeadersMap::iterator Known = findKnownHeader(File);504 if (Known != Headers.end()) {505 for (const KnownHeader &Header : Known->second) {506 // Excluded headers don't really belong to a module.507 if (Header.getRole() == ModuleMap::ExcludedHeader) {508 Excluded = true;509 continue;510 }511 512 // Remember private headers for later printing of a diagnostic.513 if (violatesPrivateInclude(RequestingModule, File, Header)) {514 Private = Header.getModule();515 continue;516 }517 518 // If uses need to be specified explicitly, we are only allowed to return519 // modules that are explicitly used by the requesting module.520 if (RequestingModule && LangOpts.ModulesDeclUse &&521 !RequestingModule->directlyUses(Header.getModule())) {522 NotUsed = Header.getModule();523 continue;524 }525 526 // We have found a module that we can happily use.527 return;528 }529 530 Excluded = true;531 }532 533 // We have found a header, but it is private.534 if (Private) {535 Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)536 << Filename;537 return;538 }539 540 // We have found a module, but we don't use it.541 if (NotUsed) {542 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)543 << RequestingModule->getTopLevelModule()->Name << Filename544 << NotUsed->Name;545 return;546 }547 548 if (Excluded || isHeaderInUmbrellaDirs(File))549 return;550 551 // At this point, only non-modular includes remain.552 553 if (RequestingModule && LangOpts.ModulesStrictDeclUse) {554 Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)555 << RequestingModule->getTopLevelModule()->Name << Filename;556 } else if (RequestingModule && RequestingModuleIsModuleInterface &&557 LangOpts.isCompilingModule()) {558 // Do not diagnose when we are not compiling a module.559 diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?560 diag::warn_non_modular_include_in_framework_module :561 diag::warn_non_modular_include_in_module;562 Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()563 << File.getName();564 }565}566 567static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,568 const ModuleMap::KnownHeader &Old) {569 // Prefer available modules.570 // FIXME: Considering whether the module is available rather than merely571 // importable is non-hermetic and can result in surprising behavior for572 // prebuilt modules. Consider only checking for importability here.573 if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())574 return true;575 576 // Prefer a public header over a private header.577 if ((New.getRole() & ModuleMap::PrivateHeader) !=578 (Old.getRole() & ModuleMap::PrivateHeader))579 return !(New.getRole() & ModuleMap::PrivateHeader);580 581 // Prefer a non-textual header over a textual header.582 if ((New.getRole() & ModuleMap::TextualHeader) !=583 (Old.getRole() & ModuleMap::TextualHeader))584 return !(New.getRole() & ModuleMap::TextualHeader);585 586 // Prefer a non-excluded header over an excluded header.587 if ((New.getRole() == ModuleMap::ExcludedHeader) !=588 (Old.getRole() == ModuleMap::ExcludedHeader))589 return New.getRole() != ModuleMap::ExcludedHeader;590 591 // Don't have a reason to choose between these. Just keep the first one.592 return false;593}594 595ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File,596 bool AllowTextual,597 bool AllowExcluded) {598 auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {599 if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)600 return {};601 return R;602 };603 604 HeadersMap::iterator Known = findKnownHeader(File);605 if (Known != Headers.end()) {606 ModuleMap::KnownHeader Result;607 // Iterate over all modules that 'File' is part of to find the best fit.608 for (KnownHeader &H : Known->second) {609 // Cannot use a module if the header is excluded in it.610 if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)611 continue;612 // Prefer a header from the source module over all others.613 if (H.getModule()->getTopLevelModule() == SourceModule)614 return MakeResult(H);615 if (!Result || isBetterKnownHeader(H, Result))616 Result = H;617 }618 return MakeResult(Result);619 }620 621 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));622}623 624ModuleMap::KnownHeader625ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {626 assert(!Headers.count(File) && "already have a module for this header");627 628 SmallVector<DirectoryEntryRef, 2> SkippedDirs;629 KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);630 if (H) {631 Module *Result = H.getModule();632 633 // Search up the module stack until we find a module with an umbrella634 // directory.635 Module *UmbrellaModule = Result;636 while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)637 UmbrellaModule = UmbrellaModule->Parent;638 639 if (UmbrellaModule->InferSubmodules) {640 FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule);641 642 // Infer submodules for each of the directories we found between643 // the directory of the umbrella header and the directory where644 // the actual header is located.645 bool Explicit = UmbrellaModule->InferExplicitSubmodules;646 647 for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {648 // Find or create the module that corresponds to this directory name.649 SmallString<32> NameBuf;650 StringRef Name = sanitizeFilenameAsIdentifier(651 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);652 Result = findOrCreateModuleFirst(Name, Result, /*IsFramework=*/false,653 Explicit);654 setInferredModuleAllowedBy(Result, UmbrellaModuleMap);655 656 // Associate the module and the directory.657 UmbrellaDirs[SkippedDir] = Result;658 659 // If inferred submodules export everything they import, add a660 // wildcard to the set of exports.661 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())662 Result->Exports.push_back(Module::ExportDecl(nullptr, true));663 }664 665 // Infer a submodule with the same name as this header file.666 SmallString<32> NameBuf;667 StringRef Name = sanitizeFilenameAsIdentifier(668 llvm::sys::path::stem(File.getName()), NameBuf);669 Result = findOrCreateModuleFirst(Name, Result, /*IsFramework=*/false,670 Explicit);671 setInferredModuleAllowedBy(Result, UmbrellaModuleMap);672 Result->addTopHeader(File);673 674 // If inferred submodules export everything they import, add a675 // wildcard to the set of exports.676 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())677 Result->Exports.push_back(Module::ExportDecl(nullptr, true));678 } else {679 // Record each of the directories we stepped through as being part of680 // the module we found, since the umbrella header covers them all.681 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)682 UmbrellaDirs[SkippedDirs[I]] = Result;683 }684 685 KnownHeader Header(Result, NormalHeader);686 Headers[File].push_back(Header);687 return Header;688 }689 690 return {};691}692 693ArrayRef<ModuleMap::KnownHeader>694ModuleMap::findAllModulesForHeader(FileEntryRef File) {695 HeadersMap::iterator Known = findKnownHeader(File);696 if (Known != Headers.end())697 return Known->second;698 699 if (findOrCreateModuleForHeaderInUmbrellaDir(File))700 return Headers.find(File)->second;701 702 return {};703}704 705ArrayRef<ModuleMap::KnownHeader>706ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {707 // FIXME: Is this necessary?708 resolveHeaderDirectives(File);709 auto It = Headers.find(File);710 if (It == Headers.end())711 return {};712 return It->second;713}714 715bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {716 return isHeaderUnavailableInModule(Header, nullptr);717}718 719bool ModuleMap::isHeaderUnavailableInModule(720 FileEntryRef Header, const Module *RequestingModule) const {721 resolveHeaderDirectives(Header);722 HeadersMap::const_iterator Known = Headers.find(Header);723 if (Known != Headers.end()) {724 for (SmallVectorImpl<KnownHeader>::const_iterator725 I = Known->second.begin(),726 E = Known->second.end();727 I != E; ++I) {728 729 if (I->getRole() == ModuleMap::ExcludedHeader)730 continue;731 732 if (I->isAvailable() &&733 (!RequestingModule ||734 I->getModule()->isSubModuleOf(RequestingModule))) {735 // When no requesting module is available, the caller is looking if a736 // header is part a module by only looking into the module map. This is737 // done by warn_uncovered_module_header checks; don't consider textual738 // headers part of it in this mode, otherwise we get misleading warnings739 // that a umbrella header is not including a textual header.740 if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)741 continue;742 return false;743 }744 }745 return true;746 }747 748 OptionalDirectoryEntryRef Dir = Header.getDir();749 SmallVector<DirectoryEntryRef, 2> SkippedDirs;750 StringRef DirName = Dir->getName();751 752 auto IsUnavailable = [&](const Module *M) {753 return !M->isAvailable() && (!RequestingModule ||754 M->isSubModuleOf(RequestingModule));755 };756 757 // Keep walking up the directory hierarchy, looking for a directory with758 // an umbrella header.759 do {760 auto KnownDir = UmbrellaDirs.find(*Dir);761 if (KnownDir != UmbrellaDirs.end()) {762 Module *Found = KnownDir->second;763 if (IsUnavailable(Found))764 return true;765 766 // Search up the module stack until we find a module with an umbrella767 // directory.768 Module *UmbrellaModule = Found;769 while (!UmbrellaModule->getEffectiveUmbrellaDir() &&770 UmbrellaModule->Parent)771 UmbrellaModule = UmbrellaModule->Parent;772 773 if (UmbrellaModule->InferSubmodules) {774 for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {775 // Find or create the module that corresponds to this directory name.776 SmallString<32> NameBuf;777 StringRef Name = sanitizeFilenameAsIdentifier(778 llvm::sys::path::stem(SkippedDir.getName()), NameBuf);779 Found = lookupModuleQualified(Name, Found);780 if (!Found)781 return false;782 if (IsUnavailable(Found))783 return true;784 }785 786 // Infer a submodule with the same name as this header file.787 SmallString<32> NameBuf;788 StringRef Name = sanitizeFilenameAsIdentifier(789 llvm::sys::path::stem(Header.getName()),790 NameBuf);791 Found = lookupModuleQualified(Name, Found);792 if (!Found)793 return false;794 }795 796 return IsUnavailable(Found);797 }798 799 SkippedDirs.push_back(*Dir);800 801 // Retrieve our parent path.802 DirName = llvm::sys::path::parent_path(DirName);803 if (DirName.empty())804 break;805 806 // Resolve the parent path to a directory entry.807 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);808 } while (Dir);809 810 return false;811}812 813Module *ModuleMap::findModule(StringRef Name) const {814 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);815 if (Known != Modules.end())816 return Known->getValue();817 818 return nullptr;819}820 821Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {822 if (Module *SubM = Parent->findSubmodule(Name))823 return SubM;824 if (!Parent->InferSubmodules)825 return nullptr;826 Module *Result = new (ModulesAlloc.Allocate())827 Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,828 Parent->InferExplicitSubmodules, 0);829 Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;830 Result->InferSubmodules = Parent->InferSubmodules;831 Result->InferExportWildcard = Parent->InferExportWildcard;832 if (Result->InferExportWildcard)833 Result->Exports.push_back(Module::ExportDecl(nullptr, true));834 return Result;835}836 837Module *ModuleMap::lookupModuleUnqualified(StringRef Name,838 Module *Context) const {839 for(; Context; Context = Context->Parent) {840 if (Module *Sub = lookupModuleQualified(Name, Context))841 return Sub;842 }843 844 return findModule(Name);845}846 847Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{848 if (!Context)849 return findModule(Name);850 851 return Context->findSubmodule(Name);852}853 854std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,855 Module *Parent,856 bool IsFramework,857 bool IsExplicit) {858 // Try to find an existing module with this name.859 if (Module *Sub = lookupModuleQualified(Name, Parent))860 return std::make_pair(Sub, false);861 862 // Create a new module with this name.863 Module *M = createModule(Name, Parent, IsFramework, IsExplicit);864 return std::make_pair(M, true);865}866 867Module *ModuleMap::createModule(StringRef Name, Module *Parent,868 bool IsFramework, bool IsExplicit) {869 assert(lookupModuleQualified(Name, Parent) == nullptr &&870 "Creating duplicate submodule");871 872 Module *Result = new (ModulesAlloc.Allocate())873 Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,874 IsFramework, IsExplicit, NumCreatedModules++);875 if (!Parent) {876 if (LangOpts.CurrentModule == Name)877 SourceModule = Result;878 Modules[Name] = Result;879 ModuleScopeIDs[Result] = CurrentModuleScopeID;880 }881 return Result;882}883 884Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,885 Module *Parent) {886 auto *Result = new (ModulesAlloc.Allocate()) Module(887 ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,888 /*IsExplicit=*/true, NumCreatedModules++);889 Result->Kind = Module::ExplicitGlobalModuleFragment;890 // If the created module isn't owned by a parent, send it to PendingSubmodules891 // to wait for its parent.892 if (!Result->Parent)893 PendingSubmodules.emplace_back(Result);894 return Result;895}896 897Module *898ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,899 Module *Parent) {900 assert(Parent && "We should only create an implicit global module fragment "901 "in a module purview");902 // Note: Here the `IsExplicit` parameter refers to the semantics in clang903 // modules. All the non-explicit submodules in clang modules will be exported904 // too. Here we simplify the implementation by using the concept.905 auto *Result = new (ModulesAlloc.Allocate())906 Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,907 /*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);908 Result->Kind = Module::ImplicitGlobalModuleFragment;909 return Result;910}911 912Module *913ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,914 SourceLocation Loc) {915 auto *Result = new (ModulesAlloc.Allocate()) Module(916 ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,917 /*IsExplicit=*/true, NumCreatedModules++);918 Result->Kind = Module::PrivateModuleFragment;919 return Result;920}921 922Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,923 Module::ModuleKind Kind) {924 auto *Result = new (ModulesAlloc.Allocate())925 Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,926 /*IsExplicit=*/false, NumCreatedModules++);927 Result->Kind = Kind;928 929 // Reparent any current global module fragment as a submodule of this module.930 for (auto &Submodule : PendingSubmodules)931 Submodule->setParent(Result);932 PendingSubmodules.clear();933 return Result;934}935 936Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,937 StringRef Name) {938 assert(LangOpts.CurrentModule == Name && "module name mismatch");939 assert(!Modules[Name] && "redefining existing module");940 941 auto *Result =942 createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);943 Modules[Name] = SourceModule = Result;944 945 // Mark the main source file as being within the newly-created module so that946 // declarations and macros are properly visibility-restricted to it.947 auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());948 assert(MainFile && "no input file for module interface");949 Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));950 951 return Result;952}953 954Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,955 StringRef Name) {956 assert(LangOpts.CurrentModule == Name && "module name mismatch");957 // The interface for this implementation must exist and be loaded.958 assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&959 "creating implementation module without an interface");960 961 // Create an entry in the modules map to own the implementation unit module.962 // User module names must not start with a period (so that this cannot clash963 // with any legal user-defined module name).964 StringRef IName = ".ImplementationUnit";965 assert(!Modules[IName] && "multiple implementation units?");966 967 auto *Result =968 createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);969 Modules[IName] = SourceModule = Result;970 971 // Check that the main file is present.972 assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&973 "no input file for module implementation");974 975 return Result;976}977 978Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,979 Module::Header H) {980 assert(LangOpts.CurrentModule == Name && "module name mismatch");981 assert(!Modules[Name] && "redefining existing module");982 983 auto *Result = new (ModulesAlloc.Allocate())984 Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,985 /*IsExplicit=*/false, NumCreatedModules++);986 Result->Kind = Module::ModuleHeaderUnit;987 Modules[Name] = SourceModule = Result;988 addHeader(Result, H, NormalHeader);989 return Result;990}991 992/// For a framework module, infer the framework against which we993/// should link.994static void inferFrameworkLink(Module *Mod) {995 assert(Mod->IsFramework && "Can only infer linking for framework modules");996 assert(!Mod->isSubFramework() &&997 "Can only infer linking for top-level frameworks");998 999 StringRef FrameworkName(Mod->Name);1000 FrameworkName.consume_back("_Private");1001 Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),1002 /*IsFramework=*/true));1003}1004 1005Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,1006 bool IsSystem, Module *Parent) {1007 Attributes Attrs;1008 Attrs.IsSystem = IsSystem;1009 return inferFrameworkModule(FrameworkDir, Attrs, Parent);1010}1011 1012Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,1013 Attributes Attrs, Module *Parent) {1014 // Note: as an egregious but useful hack we use the real path here, because1015 // we might be looking at an embedded framework that symlinks out to a1016 // top-level framework, and we need to infer as if we were naming the1017 // top-level framework.1018 StringRef FrameworkDirName =1019 SourceMgr.getFileManager().getCanonicalName(FrameworkDir);1020 1021 // In case this is a case-insensitive filesystem, use the canonical1022 // directory name as the ModuleName, since modules are case-sensitive.1023 // FIXME: we should be able to give a fix-it hint for the correct spelling.1024 SmallString<32> ModuleNameStorage;1025 StringRef ModuleName = sanitizeFilenameAsIdentifier(1026 llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);1027 1028 // Check whether we've already found this module.1029 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))1030 return Mod;1031 1032 FileManager &FileMgr = SourceMgr.getFileManager();1033 1034 // If the framework has a parent path from which we're allowed to infer1035 // a framework module, do so.1036 FileID ModuleMapFID;1037 if (!Parent) {1038 // Determine whether we're allowed to infer a module map.1039 bool canInfer = false;1040 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {1041 // Figure out the parent path.1042 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);1043 if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {1044 // Check whether we have already looked into the parent directory1045 // for a module map.1046 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator1047 inferred = InferredDirectories.find(*ParentDir);1048 if (inferred == InferredDirectories.end()) {1049 // We haven't looked here before. Load a module map, if there is1050 // one.1051 bool IsFrameworkDir = Parent.ends_with(".framework");1052 if (OptionalFileEntryRef ModMapFile =1053 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {1054 // TODO: Parsing a module map should populate `InferredDirectories`1055 // so we don't need to do a full load here.1056 parseAndLoadModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir);1057 inferred = InferredDirectories.find(*ParentDir);1058 }1059 1060 if (inferred == InferredDirectories.end())1061 inferred = InferredDirectories.insert(1062 std::make_pair(*ParentDir, InferredDirectory())).first;1063 }1064 1065 if (inferred->second.InferModules) {1066 // We're allowed to infer for this directory, but make sure it's okay1067 // to infer this particular module.1068 StringRef Name = llvm::sys::path::stem(FrameworkDirName);1069 canInfer =1070 !llvm::is_contained(inferred->second.ExcludedModules, Name);1071 1072 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;1073 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;1074 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;1075 Attrs.NoUndeclaredIncludes |=1076 inferred->second.Attrs.NoUndeclaredIncludes;1077 ModuleMapFID = inferred->second.ModuleMapFID;1078 }1079 }1080 }1081 1082 // If we're not allowed to infer a framework module, don't.1083 if (!canInfer)1084 return nullptr;1085 } else {1086 ModuleMapFID = getModuleMapFileIDForUniquing(Parent);1087 }1088 1089 // Look for an umbrella header.1090 SmallString<128> UmbrellaName = FrameworkDir.getName();1091 llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");1092 auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);1093 1094 // FIXME: If there's no umbrella header, we could probably scan the1095 // framework to load *everything*. But, it's not clear that this is a good1096 // idea.1097 if (!UmbrellaHeader)1098 return nullptr;1099 1100 Module *Result = new (ModulesAlloc.Allocate())1101 Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,1102 /*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);1103 setInferredModuleAllowedBy(Result, ModuleMapFID);1104 if (!Parent) {1105 if (LangOpts.CurrentModule == ModuleName)1106 SourceModule = Result;1107 Modules[ModuleName] = Result;1108 ModuleScopeIDs[Result] = CurrentModuleScopeID;1109 }1110 1111 Result->IsSystem |= Attrs.IsSystem;1112 Result->IsExternC |= Attrs.IsExternC;1113 Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;1114 Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;1115 Result->Directory = FrameworkDir;1116 1117 // Chop off the first framework bit, as that is implied.1118 StringRef RelativePath = UmbrellaName.str().substr(1119 Result->getTopLevelModule()->Directory->getName().size());1120 RelativePath = llvm::sys::path::relative_path(RelativePath);1121 1122 // umbrella header "umbrella-header-name"1123 setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",1124 RelativePath);1125 1126 // export *1127 Result->Exports.push_back(Module::ExportDecl(nullptr, true));1128 1129 // module * { export * }1130 Result->InferSubmodules = true;1131 Result->InferExportWildcard = true;1132 1133 // Look for subframeworks.1134 std::error_code EC;1135 SmallString<128> SubframeworksDirName = FrameworkDir.getName();1136 llvm::sys::path::append(SubframeworksDirName, "Frameworks");1137 llvm::sys::path::native(SubframeworksDirName);1138 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();1139 for (llvm::vfs::directory_iterator1140 Dir = FS.dir_begin(SubframeworksDirName, EC),1141 DirEnd;1142 Dir != DirEnd && !EC; Dir.increment(EC)) {1143 if (!StringRef(Dir->path()).ends_with(".framework"))1144 continue;1145 1146 if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {1147 // Note: as an egregious but useful hack, we use the real path here and1148 // check whether it is actually a subdirectory of the parent directory.1149 // This will not be the case if the 'subframework' is actually a symlink1150 // out to a top-level framework.1151 StringRef SubframeworkDirName =1152 FileMgr.getCanonicalName(*SubframeworkDir);1153 bool FoundParent = false;1154 do {1155 // Get the parent directory name.1156 SubframeworkDirName1157 = llvm::sys::path::parent_path(SubframeworkDirName);1158 if (SubframeworkDirName.empty())1159 break;1160 1161 if (auto SubDir =1162 FileMgr.getOptionalDirectoryRef(SubframeworkDirName)) {1163 if (*SubDir == FrameworkDir) {1164 FoundParent = true;1165 break;1166 }1167 }1168 } while (true);1169 1170 if (!FoundParent)1171 continue;1172 1173 // FIXME: Do we want to warn about subframeworks without umbrella headers?1174 inferFrameworkModule(*SubframeworkDir, Attrs, Result);1175 }1176 }1177 1178 // If the module is a top-level framework, automatically link against the1179 // framework.1180 if (!Result->isSubFramework())1181 inferFrameworkLink(Result);1182 1183 return Result;1184}1185 1186Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,1187 Module *ShadowingModule) {1188 1189 // Create a new module with this name.1190 Module *Result = new (ModulesAlloc.Allocate())1191 Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,1192 IsFramework, /*IsExplicit=*/false, NumCreatedModules++);1193 Result->ShadowingModule = ShadowingModule;1194 Result->markUnavailable(/*Unimportable*/true);1195 ModuleScopeIDs[Result] = CurrentModuleScopeID;1196 ShadowModules.push_back(Result);1197 1198 return Result;1199}1200 1201void ModuleMap::setUmbrellaHeaderAsWritten(1202 Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,1203 const Twine &PathRelativeToRootModuleDirectory) {1204 Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));1205 Mod->Umbrella = UmbrellaHeader;1206 Mod->UmbrellaAsWritten = NameAsWritten.str();1207 Mod->UmbrellaRelativeToRootModuleDirectory =1208 PathRelativeToRootModuleDirectory.str();1209 UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;1210 1211 // Notify callbacks that we just added a new header.1212 for (const auto &Cb : Callbacks)1213 Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);1214}1215 1216void ModuleMap::setUmbrellaDirAsWritten(1217 Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,1218 const Twine &PathRelativeToRootModuleDirectory) {1219 Mod->Umbrella = UmbrellaDir;1220 Mod->UmbrellaAsWritten = NameAsWritten.str();1221 Mod->UmbrellaRelativeToRootModuleDirectory =1222 PathRelativeToRootModuleDirectory.str();1223 UmbrellaDirs[UmbrellaDir] = Mod;1224}1225 1226void ModuleMap::addUnresolvedHeader(Module *Mod,1227 Module::UnresolvedHeaderDirective Header,1228 bool &NeedsFramework) {1229 // If there is a builtin counterpart to this file, add it now so it can1230 // wrap the system header.1231 if (resolveAsBuiltinHeader(Mod, Header)) {1232 // If we have both a builtin and system version of the file, the1233 // builtin version may want to inject macros into the system header, so1234 // force the system header to be treated as a textual header in this1235 // case.1236 Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(1237 headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));1238 Header.HasBuiltinHeader = true;1239 }1240 1241 // If possible, don't stat the header until we need to. This requires the1242 // user to have provided us with some stat information about the file.1243 // FIXME: Add support for lazily stat'ing umbrella headers and excluded1244 // headers.1245 if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&1246 Header.Kind != Module::HK_Excluded) {1247 // We expect more variation in mtime than size, so if we're given both,1248 // use the mtime as the key.1249 if (Header.ModTime)1250 LazyHeadersByModTime[*Header.ModTime].push_back(Mod);1251 else1252 LazyHeadersBySize[*Header.Size].push_back(Mod);1253 Mod->UnresolvedHeaders.push_back(Header);1254 return;1255 }1256 1257 // We don't have stat information or can't defer looking this file up.1258 // Perform the lookup now.1259 resolveHeader(Mod, Header, NeedsFramework);1260}1261 1262void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {1263 auto BySize = LazyHeadersBySize.find(File->getSize());1264 if (BySize != LazyHeadersBySize.end()) {1265 for (auto *M : BySize->second)1266 resolveHeaderDirectives(M, File);1267 LazyHeadersBySize.erase(BySize);1268 }1269 1270 auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());1271 if (ByModTime != LazyHeadersByModTime.end()) {1272 for (auto *M : ByModTime->second)1273 resolveHeaderDirectives(M, File);1274 LazyHeadersByModTime.erase(ByModTime);1275 }1276}1277 1278void ModuleMap::resolveHeaderDirectives(1279 Module *Mod, std::optional<const FileEntry *> File) const {1280 bool NeedsFramework = false;1281 SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;1282 const auto Size = File ? (*File)->getSize() : 0;1283 const auto ModTime = File ? (*File)->getModificationTime() : 0;1284 1285 for (auto &Header : Mod->UnresolvedHeaders) {1286 if (File && ((Header.ModTime && Header.ModTime != ModTime) ||1287 (Header.Size && Header.Size != Size)))1288 NewHeaders.push_back(Header);1289 else1290 // This operation is logically const; we're just changing how we represent1291 // the header information for this file.1292 const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);1293 }1294 Mod->UnresolvedHeaders.swap(NewHeaders);1295}1296 1297void ModuleMap::addHeader(Module *Mod, Module::Header Header,1298 ModuleHeaderRole Role, bool Imported) {1299 KnownHeader KH(Mod, Role);1300 1301 FileEntryRef HeaderEntry = Header.Entry;1302 1303 // Only add each header to the headers list once.1304 // FIXME: Should we diagnose if a header is listed twice in the1305 // same module definition?1306 auto &HeaderList = Headers[HeaderEntry];1307 if (llvm::is_contained(HeaderList, KH))1308 return;1309 1310 HeaderList.push_back(KH);1311 Mod->addHeader(headerRoleToKind(Role), std::move(Header));1312 1313 bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);1314 if (!Imported || isCompilingModuleHeader) {1315 // When we import HeaderFileInfo, the external source is expected to1316 // set the isModuleHeader flag itself.1317 HeaderInfo.MarkFileModuleHeader(HeaderEntry, Role, isCompilingModuleHeader);1318 }1319 1320 // Notify callbacks that we just added a new header.1321 for (const auto &Cb : Callbacks)1322 Cb->moduleMapAddHeader(HeaderEntry.getName());1323}1324 1325bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,1326 DirectoryEntryRef Dir, FileID ID,1327 SourceLocation ExternModuleLoc) {1328 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator1329 Known = ParsedModuleMap.find(File);1330 if (Known != ParsedModuleMap.end())1331 return Known->second == nullptr;1332 1333 // If the module map file wasn't already entered, do so now.1334 if (ID.isInvalid()) {1335 ID = SourceMgr.translateFile(File);1336 if (ID.isInvalid() || SourceMgr.isLoadedFileID(ID)) {1337 auto FileCharacter =1338 IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;1339 ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);1340 }1341 }1342 1343 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);1344 if (!Buffer) {1345 ParsedModuleMap[File] = nullptr;1346 return true;1347 }1348 1349 Diags.Report(diag::remark_mmap_parse) << File.getName();1350 std::optional<modulemap::ModuleMapFile> MaybeMMF =1351 modulemap::parseModuleMap(ID, Dir, SourceMgr, Diags, IsSystem, nullptr);1352 1353 if (!MaybeMMF) {1354 ParsedModuleMap[File] = nullptr;1355 return true;1356 }1357 1358 ParsedModuleMaps.push_back(1359 std::make_unique<modulemap::ModuleMapFile>(std::move(*MaybeMMF)));1360 const modulemap::ModuleMapFile &MMF = *ParsedModuleMaps.back();1361 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;1362 for (const auto &Decl : MMF.Decls) {1363 std::visit(llvm::makeVisitor(1364 [&](const modulemap::ModuleDecl &MD) {1365 // Only use the first part of the name even for submodules.1366 // This will correctly load the submodule declarations when1367 // the module is loaded.1368 auto &ModuleDecls =1369 ParsedModules[StringRef(MD.Id.front().first)];1370 ModuleDecls.push_back(std::pair(&MMF, &MD));1371 },1372 [&](const modulemap::ExternModuleDecl &EMD) {1373 PendingExternalModuleMaps.push_back(&EMD);1374 }),1375 Decl);1376 }1377 1378 for (const modulemap::ExternModuleDecl *EMD : PendingExternalModuleMaps) {1379 StringRef FileNameRef = EMD->Path;1380 SmallString<128> ModuleMapFileName;1381 if (llvm::sys::path::is_relative(FileNameRef)) {1382 ModuleMapFileName += Dir.getName();1383 llvm::sys::path::append(ModuleMapFileName, EMD->Path);1384 FileNameRef = ModuleMapFileName;1385 }1386 1387 if (auto EFile =1388 SourceMgr.getFileManager().getOptionalFileRef(FileNameRef)) {1389 parseModuleMapFile(*EFile, IsSystem, EFile->getDir(), FileID(),1390 ExternModuleLoc);1391 }1392 }1393 1394 ParsedModuleMap[File] = &MMF;1395 1396 for (const auto &Cb : Callbacks)1397 Cb->moduleMapFileRead(SourceLocation(), File, IsSystem);1398 1399 return false;1400}1401 1402FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const {1403 if (Module->DefinitionLoc.isInvalid())1404 return {};1405 1406 return SourceMgr.getFileID(Module->DefinitionLoc);1407}1408 1409OptionalFileEntryRef1410ModuleMap::getContainingModuleMapFile(const Module *Module) const {1411 return SourceMgr.getFileEntryRefForID(getContainingModuleMapFileID(Module));1412}1413 1414FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {1415 if (M->IsInferred) {1416 assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");1417 return InferredModuleAllowedBy.find(M)->second;1418 }1419 return getContainingModuleMapFileID(M);1420}1421 1422OptionalFileEntryRef1423ModuleMap::getModuleMapFileForUniquing(const Module *M) const {1424 return SourceMgr.getFileEntryRefForID(getModuleMapFileIDForUniquing(M));1425}1426 1427void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {1428 M->IsInferred = true;1429 InferredModuleAllowedBy[M] = ModMapFID;1430}1431 1432std::error_code1433ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {1434 StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});1435 1436 // Do not canonicalize within the framework; the module map loader expects1437 // Modules/ not Versions/A/Modules.1438 if (llvm::sys::path::filename(Dir) == "Modules") {1439 StringRef Parent = llvm::sys::path::parent_path(Dir);1440 if (Parent.ends_with(".framework"))1441 Dir = Parent;1442 }1443 1444 FileManager &FM = SourceMgr.getFileManager();1445 auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);1446 if (!DirEntry)1447 return llvm::errorToErrorCode(DirEntry.takeError());1448 1449 // Canonicalize the directory.1450 StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);1451 if (CanonicalDir != Dir)1452 llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);1453 1454 // In theory, the filename component should also be canonicalized if it1455 // on a case-insensitive filesystem. However, the extra canonicalization is1456 // expensive and if clang looked up the filename it will always be lowercase.1457 1458 // Remove ., remove redundant separators, and switch to native separators.1459 // This is needed for separators between CanonicalDir and the filename.1460 llvm::sys::path::remove_dots(Path);1461 1462 return std::error_code();1463}1464 1465void ModuleMap::addAdditionalModuleMapFile(const Module *M,1466 FileEntryRef ModuleMap) {1467 AdditionalModMaps[M].insert(ModuleMap);1468}1469 1470LLVM_DUMP_METHOD void ModuleMap::dump() {1471 llvm::errs() << "Modules:";1472 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),1473 MEnd = Modules.end();1474 M != MEnd; ++M)1475 M->getValue()->print(llvm::errs(), 2);1476 1477 llvm::errs() << "Headers:";1478 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();1479 H != HEnd; ++H) {1480 llvm::errs() << " \"" << H->first.getName() << "\" -> ";1481 for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),1482 E = H->second.end();1483 I != E; ++I) {1484 if (I != H->second.begin())1485 llvm::errs() << ",";1486 llvm::errs() << I->getModule()->getFullModuleName();1487 }1488 llvm::errs() << "\n";1489 }1490}1491 1492bool ModuleMap::resolveExports(Module *Mod, bool Complain) {1493 auto Unresolved = std::move(Mod->UnresolvedExports);1494 Mod->UnresolvedExports.clear();1495 for (auto &UE : Unresolved) {1496 Module::ExportDecl Export = resolveExport(Mod, UE, Complain);1497 if (Export.getPointer() || Export.getInt())1498 Mod->Exports.push_back(Export);1499 else1500 Mod->UnresolvedExports.push_back(UE);1501 }1502 return !Mod->UnresolvedExports.empty();1503}1504 1505bool ModuleMap::resolveUses(Module *Mod, bool Complain) {1506 auto *Top = Mod->getTopLevelModule();1507 auto Unresolved = std::move(Top->UnresolvedDirectUses);1508 Top->UnresolvedDirectUses.clear();1509 for (auto &UDU : Unresolved) {1510 Module *DirectUse = resolveModuleId(UDU, Top, Complain);1511 if (DirectUse)1512 Top->DirectUses.push_back(DirectUse);1513 else1514 Top->UnresolvedDirectUses.push_back(UDU);1515 }1516 return !Top->UnresolvedDirectUses.empty();1517}1518 1519bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {1520 auto Unresolved = std::move(Mod->UnresolvedConflicts);1521 Mod->UnresolvedConflicts.clear();1522 for (auto &UC : Unresolved) {1523 if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {1524 Module::Conflict Conflict;1525 Conflict.Other = OtherMod;1526 Conflict.Message = UC.Message;1527 Mod->Conflicts.push_back(Conflict);1528 } else1529 Mod->UnresolvedConflicts.push_back(UC);1530 }1531 return !Mod->UnresolvedConflicts.empty();1532}1533 1534//----------------------------------------------------------------------------//1535// Module map file loader1536//----------------------------------------------------------------------------//1537 1538namespace clang {1539class ModuleMapLoader {1540 SourceManager &SourceMgr;1541 1542 DiagnosticsEngine &Diags;1543 ModuleMap ⤅1544 1545 /// The current module map file.1546 FileID ModuleMapFID;1547 1548 /// Source location of most recent loaded module declaration1549 SourceLocation CurrModuleDeclLoc;1550 1551 /// The directory that file names in this module map file should1552 /// be resolved relative to.1553 DirectoryEntryRef Directory;1554 1555 /// Whether this module map is in a system header directory.1556 bool IsSystem;1557 1558 /// Whether an error occurred.1559 bool HadError = false;1560 1561 /// The active module.1562 Module *ActiveModule = nullptr;1563 1564 /// Whether a module uses the 'requires excluded' hack to mark its1565 /// contents as 'textual'.1566 ///1567 /// On older Darwin SDK versions, 'requires excluded' is used to mark the1568 /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as1569 /// non-modular headers. For backwards compatibility, we continue to1570 /// support this idiom for just these modules, and map the headers to1571 /// 'textual' to match the original intent.1572 llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;1573 1574 void handleModuleDecl(const modulemap::ModuleDecl &MD);1575 void handleExternModuleDecl(const modulemap::ExternModuleDecl &EMD);1576 void handleRequiresDecl(const modulemap::RequiresDecl &RD);1577 void handleHeaderDecl(const modulemap::HeaderDecl &HD);1578 void handleUmbrellaDirDecl(const modulemap::UmbrellaDirDecl &UDD);1579 void handleExportDecl(const modulemap::ExportDecl &ED);1580 void handleExportAsDecl(const modulemap::ExportAsDecl &EAD);1581 void handleUseDecl(const modulemap::UseDecl &UD);1582 void handleLinkDecl(const modulemap::LinkDecl &LD);1583 void handleConfigMacros(const modulemap::ConfigMacrosDecl &CMD);1584 void handleConflict(const modulemap::ConflictDecl &CD);1585 void handleInferredModuleDecl(const modulemap::ModuleDecl &MD);1586 1587 /// Private modules are canonicalized as Foo_Private. Clang provides extra1588 /// module map search logic to find the appropriate private module when PCH1589 /// is used with implicit module maps. Warn when private modules are written1590 /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.1591 void diagnosePrivateModules(SourceLocation StartLoc);1592 1593 using Attributes = ModuleMap::Attributes;1594 1595public:1596 ModuleMapLoader(SourceManager &SourceMgr, DiagnosticsEngine &Diags,1597 ModuleMap &Map, FileID ModuleMapFID,1598 DirectoryEntryRef Directory, bool IsSystem)1599 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),1600 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) {}1601 1602 bool loadModuleDecl(const modulemap::ModuleDecl &MD);1603 bool loadExternModuleDecl(const modulemap::ExternModuleDecl &EMD);1604 bool parseAndLoadModuleMapFile(const modulemap::ModuleMapFile &MMF);1605};1606 1607} // namespace clang1608 1609/// Private modules are canonicalized as Foo_Private. Clang provides extra1610/// module map search logic to find the appropriate private module when PCH1611/// is used with implicit module maps. Warn when private modules are written1612/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.1613void ModuleMapLoader::diagnosePrivateModules(SourceLocation StartLoc) {1614 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,1615 const Module *M, SourceRange ReplLoc) {1616 auto D = Diags.Report(ActiveModule->DefinitionLoc,1617 diag::note_mmap_rename_top_level_private_module);1618 D << BadName << M->Name;1619 D << FixItHint::CreateReplacement(ReplLoc, Canonical);1620 };1621 1622 for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {1623 auto const *M = E->getValue();1624 if (M->Directory != ActiveModule->Directory)1625 continue;1626 1627 SmallString<128> FullName(ActiveModule->getFullModuleName());1628 if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))1629 continue;1630 SmallString<128> FixedPrivModDecl;1631 SmallString<128> Canonical(M->Name);1632 Canonical.append("_Private");1633 1634 // Foo.Private -> Foo_Private1635 if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&1636 M->Name == ActiveModule->Parent->Name) {1637 Diags.Report(ActiveModule->DefinitionLoc,1638 diag::warn_mmap_mismatched_private_submodule)1639 << FullName;1640 1641 SourceLocation FixItInitBegin = CurrModuleDeclLoc;1642 if (StartLoc.isValid())1643 FixItInitBegin = StartLoc;1644 1645 if (ActiveModule->Parent->IsFramework)1646 FixedPrivModDecl.append("framework ");1647 FixedPrivModDecl.append("module ");1648 FixedPrivModDecl.append(Canonical);1649 1650 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,1651 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));1652 continue;1653 }1654 1655 // FooPrivate and whatnots -> Foo_Private1656 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&1657 ActiveModule->Name != Canonical) {1658 Diags.Report(ActiveModule->DefinitionLoc,1659 diag::warn_mmap_mismatched_private_module_name)1660 << ActiveModule->Name;1661 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,1662 SourceRange(ActiveModule->DefinitionLoc));1663 }1664 }1665}1666 1667void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {1668 if (MD.Id.front().first == "*")1669 return handleInferredModuleDecl(MD);1670 1671 CurrModuleDeclLoc = MD.Location;1672 1673 Module *PreviousActiveModule = ActiveModule;1674 if (MD.Id.size() > 1) {1675 // This module map defines a submodule. Go find the module of which it1676 // is a submodule.1677 ActiveModule = nullptr;1678 const Module *TopLevelModule = nullptr;1679 for (unsigned I = 0, N = MD.Id.size() - 1; I != N; ++I) {1680 if (Module *Next =1681 Map.lookupModuleQualified(MD.Id[I].first, ActiveModule)) {1682 if (I == 0)1683 TopLevelModule = Next;1684 ActiveModule = Next;1685 continue;1686 }1687 1688 Diags.Report(MD.Id[I].second, diag::err_mmap_missing_parent_module)1689 << MD.Id[I].first << (ActiveModule != nullptr)1690 << (ActiveModule1691 ? ActiveModule->getTopLevelModule()->getFullModuleName()1692 : "");1693 HadError = true;1694 }1695 1696 if (TopLevelModule &&1697 ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {1698 assert(ModuleMapFID !=1699 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&1700 "submodule defined in same file as 'module *' that allowed its "1701 "top-level module");1702 Map.addAdditionalModuleMapFile(1703 TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));1704 }1705 }1706 1707 StringRef ModuleName = MD.Id.back().first;1708 SourceLocation ModuleNameLoc = MD.Id.back().second;1709 1710 // Determine whether this (sub)module has already been defined.1711 Module *ShadowingModule = nullptr;1712 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {1713 // We might see a (re)definition of a module that we already have a1714 // definition for in four cases:1715 // - If we loaded one definition from an AST file and we've just found a1716 // corresponding definition in a module map file, or1717 bool LoadedFromASTFile = Existing->IsFromModuleFile;1718 // - If we previously inferred this module from different module map file.1719 bool Inferred = Existing->IsInferred;1720 // - If we're building a framework that vends a module map, we might've1721 // previously seen the one in intermediate products and now the system1722 // one.1723 // FIXME: If we're parsing module map file that looks like this:1724 // framework module FW { ... }1725 // module FW.Sub { ... }1726 // We can't check the framework qualifier, since it's not attached to1727 // the definition of Sub. Checking that qualifier on \c Existing is1728 // not correct either, since we might've previously seen:1729 // module FW { ... }1730 // module FW.Sub { ... }1731 // We should enforce consistency of redefinitions so that we can rely1732 // that \c Existing is part of a framework iff the redefinition of FW1733 // we have just skipped had it too. Once we do that, stop checking1734 // the local framework qualifier and only rely on \c Existing.1735 bool PartOfFramework = MD.Framework || Existing->isPartOfFramework();1736 // - If we're building a (preprocessed) module and we've just loaded the1737 // module map file from which it was created.1738 bool ParsedAsMainInput =1739 Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&1740 Map.LangOpts.CurrentModule == ModuleName &&1741 SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=1742 SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;1743 // TODO: Remove this check when we can avoid loading module maps multiple1744 // times.1745 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;1746 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||1747 SameModuleDecl) {1748 ActiveModule = PreviousActiveModule;1749 // Skip the module definition.1750 return;1751 }1752 1753 if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {1754 ShadowingModule = Existing;1755 } else {1756 // This is not a shawdowed module decl, it is an illegal redefinition.1757 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)1758 << ModuleName;1759 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);1760 HadError = true;1761 return;1762 }1763 }1764 1765 // Start defining this module.1766 if (ShadowingModule) {1767 ActiveModule =1768 Map.createShadowedModule(ModuleName, MD.Framework, ShadowingModule);1769 } else {1770 ActiveModule = Map.findOrCreateModuleFirst(ModuleName, ActiveModule,1771 MD.Framework, MD.Explicit);1772 }1773 1774 ActiveModule->DefinitionLoc = ModuleNameLoc;1775 if (MD.Attrs.IsSystem || IsSystem)1776 ActiveModule->IsSystem = true;1777 if (MD.Attrs.IsExternC)1778 ActiveModule->IsExternC = true;1779 if (MD.Attrs.NoUndeclaredIncludes)1780 ActiveModule->NoUndeclaredIncludes = true;1781 ActiveModule->Directory = Directory;1782 1783 StringRef MapFileName(1784 SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());1785 if (MapFileName.ends_with("module.private.modulemap") ||1786 MapFileName.ends_with("module_private.map")) {1787 ActiveModule->ModuleMapIsPrivate = true;1788 }1789 1790 // Private modules named as FooPrivate, Foo.Private or similar are likely a1791 // user error; provide warnings, notes and fixits to direct users to use1792 // Foo_Private instead.1793 SourceLocation StartLoc =1794 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());1795 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&1796 !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,1797 StartLoc) &&1798 !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,1799 StartLoc) &&1800 ActiveModule->ModuleMapIsPrivate)1801 diagnosePrivateModules(MD.Location);1802 1803 for (const modulemap::Decl &Decl : MD.Decls) {1804 std::visit(1805 llvm::makeVisitor(1806 [&](const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },1807 [&](const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },1808 [&](const modulemap::UmbrellaDirDecl &UDD) {1809 handleUmbrellaDirDecl(UDD);1810 },1811 [&](const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },1812 [&](const modulemap::ExportDecl &ED) { handleExportDecl(ED); },1813 [&](const modulemap::ExportAsDecl &EAD) {1814 handleExportAsDecl(EAD);1815 },1816 [&](const modulemap::ExternModuleDecl &EMD) {1817 handleExternModuleDecl(EMD);1818 },1819 [&](const modulemap::UseDecl &UD) { handleUseDecl(UD); },1820 [&](const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },1821 [&](const modulemap::ConfigMacrosDecl &CMD) {1822 handleConfigMacros(CMD);1823 },1824 [&](const modulemap::ConflictDecl &CD) { handleConflict(CD); },1825 [&](const modulemap::ExcludeDecl &ED) {1826 Diags.Report(ED.Location, diag::err_mmap_expected_member);1827 }),1828 Decl);1829 }1830 1831 // If the active module is a top-level framework, and there are no link1832 // libraries, automatically link against the framework.1833 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&1834 ActiveModule->LinkLibraries.empty())1835 inferFrameworkLink(ActiveModule);1836 1837 // If the module meets all requirements but is still unavailable, mark the1838 // whole tree as unavailable to prevent it from building.1839 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&1840 ActiveModule->Parent) {1841 ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);1842 ActiveModule->getTopLevelModule()->MissingHeaders.append(1843 ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());1844 }1845 1846 // We're done parsing this module. Pop back to the previous module.1847 ActiveModule = PreviousActiveModule;1848}1849 1850void ModuleMapLoader::handleExternModuleDecl(1851 const modulemap::ExternModuleDecl &EMD) {1852 StringRef FileNameRef = EMD.Path;1853 SmallString<128> ModuleMapFileName;1854 if (llvm::sys::path::is_relative(FileNameRef)) {1855 ModuleMapFileName += Directory.getName();1856 llvm::sys::path::append(ModuleMapFileName, EMD.Path);1857 FileNameRef = ModuleMapFileName;1858 }1859 if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))1860 Map.parseAndLoadModuleMapFile(1861 *File, IsSystem,1862 Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd1863 ? Directory1864 : File->getDir(),1865 FileID(), nullptr, EMD.Location);1866}1867 1868/// Whether to add the requirement \p Feature to the module \p M.1869///1870/// This preserves backwards compatibility for two hacks in the Darwin system1871/// module map files:1872///1873/// 1. The use of 'requires excluded' to make headers non-modular, which1874/// should really be mapped to 'textual' now that we have this feature. We1875/// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to1876/// true. Later, this bit will be used to map all the headers inside this1877/// module to 'textual'.1878///1879/// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.1880///1881/// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement1882/// was never correct and causes issues now that we check it, so drop it.1883static bool shouldAddRequirement(Module *M, StringRef Feature,1884 bool &IsRequiresExcludedHack) {1885 if (Feature == "excluded" &&1886 (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||1887 M->fullModuleNameIs({"Tcl", "Private"}))) {1888 IsRequiresExcludedHack = true;1889 return false;1890 } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {1891 return false;1892 }1893 1894 return true;1895}1896 1897void ModuleMapLoader::handleRequiresDecl(const modulemap::RequiresDecl &RD) {1898 1899 for (const modulemap::RequiresFeature &RF : RD.Features) {1900 bool IsRequiresExcludedHack = false;1901 bool ShouldAddRequirement =1902 shouldAddRequirement(ActiveModule, RF.Feature, IsRequiresExcludedHack);1903 1904 if (IsRequiresExcludedHack)1905 UsesRequiresExcludedHack.insert(ActiveModule);1906 1907 if (ShouldAddRequirement) {1908 // Add this feature.1909 ActiveModule->addRequirement(RF.Feature, RF.RequiredState, Map.LangOpts,1910 *Map.Target);1911 }1912 }1913}1914 1915void ModuleMapLoader::handleHeaderDecl(const modulemap::HeaderDecl &HD) {1916 // We've already consumed the first token.1917 ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;1918 1919 if (HD.Private) {1920 Role = ModuleMap::PrivateHeader;1921 } else if (HD.Excluded) {1922 Role = ModuleMap::ExcludedHeader;1923 }1924 1925 if (HD.Textual)1926 Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);1927 1928 if (UsesRequiresExcludedHack.count(ActiveModule)) {1929 // Mark this header 'textual' (see doc comment for1930 // Module::UsesRequiresExcludedHack).1931 Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);1932 }1933 1934 Module::UnresolvedHeaderDirective Header;1935 Header.FileName = HD.Path;1936 Header.FileNameLoc = HD.PathLoc;1937 Header.IsUmbrella = HD.Umbrella;1938 Header.Kind = Map.headerRoleToKind(Role);1939 1940 // Check whether we already have an umbrella.1941 if (Header.IsUmbrella &&1942 !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {1943 Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)1944 << ActiveModule->getFullModuleName();1945 HadError = true;1946 return;1947 }1948 1949 if (HD.Size)1950 Header.Size = HD.Size;1951 if (HD.MTime)1952 Header.ModTime = HD.MTime;1953 1954 bool NeedsFramework = false;1955 // Don't add headers to the builtin modules if the builtin headers belong to1956 // the system modules, with the exception of __stddef_max_align_t.h which1957 // always had its own module.1958 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||1959 !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||1960 ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))1961 Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);1962 1963 if (NeedsFramework)1964 Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)1965 << ActiveModule->getFullModuleName()1966 << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");1967}1968 1969static bool compareModuleHeaders(const Module::Header &A,1970 const Module::Header &B) {1971 return A.NameAsWritten < B.NameAsWritten;1972}1973 1974void ModuleMapLoader::handleUmbrellaDirDecl(1975 const modulemap::UmbrellaDirDecl &UDD) {1976 std::string DirName = std::string(UDD.Path);1977 std::string DirNameAsWritten = DirName;1978 1979 // Check whether we already have an umbrella.1980 if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {1981 Diags.Report(UDD.Location, diag::err_mmap_umbrella_clash)1982 << ActiveModule->getFullModuleName();1983 HadError = true;1984 return;1985 }1986 1987 // Look for this file.1988 OptionalDirectoryEntryRef Dir;1989 if (llvm::sys::path::is_absolute(DirName)) {1990 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);1991 } else {1992 SmallString<128> PathName;1993 PathName = Directory.getName();1994 llvm::sys::path::append(PathName, DirName);1995 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);1996 }1997 1998 if (!Dir) {1999 Diags.Report(UDD.Location, diag::warn_mmap_umbrella_dir_not_found)2000 << DirName;2001 return;2002 }2003 2004 if (UsesRequiresExcludedHack.count(ActiveModule)) {2005 // Mark this header 'textual' (see doc comment for2006 // ModuleMapLoader::UsesRequiresExcludedHack). Although iterating over the2007 // directory is relatively expensive, in practice this only applies to the2008 // uncommonly used Tcl module on Darwin platforms.2009 std::error_code EC;2010 SmallVector<Module::Header, 6> Headers;2011 llvm::vfs::FileSystem &FS =2012 SourceMgr.getFileManager().getVirtualFileSystem();2013 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;2014 I != E && !EC; I.increment(EC)) {2015 if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {2016 Module::Header Header = {"", std::string(I->path()), *FE};2017 Headers.push_back(std::move(Header));2018 }2019 }2020 2021 // Sort header paths so that the pcm doesn't depend on iteration order.2022 llvm::stable_sort(Headers, compareModuleHeaders);2023 2024 for (auto &Header : Headers)2025 Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);2026 return;2027 }2028 2029 if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {2030 Diags.Report(UDD.Location, diag::err_mmap_umbrella_clash)2031 << OwningModule->getFullModuleName();2032 HadError = true;2033 return;2034 }2035 2036 // Record this umbrella directory.2037 Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);2038}2039 2040void ModuleMapLoader::handleExportDecl(const modulemap::ExportDecl &ED) {2041 Module::UnresolvedExportDecl Unresolved = {ED.Location, ED.Id, ED.Wildcard};2042 ActiveModule->UnresolvedExports.push_back(Unresolved);2043}2044 2045void ModuleMapLoader::handleExportAsDecl(const modulemap::ExportAsDecl &EAD) {2046 const auto &ModName = EAD.Id.front();2047 2048 if (!ActiveModule->ExportAsModule.empty()) {2049 if (ActiveModule->ExportAsModule == ModName.first) {2050 Diags.Report(ModName.second, diag::warn_mmap_redundant_export_as)2051 << ActiveModule->Name << ModName.first;2052 } else {2053 Diags.Report(ModName.second, diag::err_mmap_conflicting_export_as)2054 << ActiveModule->Name << ActiveModule->ExportAsModule2055 << ModName.first;2056 }2057 }2058 2059 ActiveModule->ExportAsModule = ModName.first;2060 Map.addLinkAsDependency(ActiveModule);2061}2062 2063void ModuleMapLoader::handleUseDecl(const modulemap::UseDecl &UD) {2064 if (ActiveModule->Parent)2065 Diags.Report(UD.Location, diag::err_mmap_use_decl_submodule);2066 else2067 ActiveModule->UnresolvedDirectUses.push_back(UD.Id);2068}2069 2070void ModuleMapLoader::handleLinkDecl(const modulemap::LinkDecl &LD) {2071 ActiveModule->LinkLibraries.push_back(2072 Module::LinkLibrary(std::string{LD.Library}, LD.Framework));2073}2074 2075void ModuleMapLoader::handleConfigMacros(2076 const modulemap::ConfigMacrosDecl &CMD) {2077 if (ActiveModule->Parent) {2078 Diags.Report(CMD.Location, diag::err_mmap_config_macro_submodule);2079 return;2080 }2081 2082 // TODO: Is this really the behavior we want for multiple config_macros2083 // declarations? If any of them are exhaustive then all of them are.2084 if (CMD.Exhaustive) {2085 ActiveModule->ConfigMacrosExhaustive = true;2086 }2087 ActiveModule->ConfigMacros.insert(ActiveModule->ConfigMacros.end(),2088 CMD.Macros.begin(), CMD.Macros.end());2089}2090 2091void ModuleMapLoader::handleConflict(const modulemap::ConflictDecl &CD) {2092 Module::UnresolvedConflict Conflict;2093 2094 Conflict.Id = CD.Id;2095 Conflict.Message = CD.Message;2096 2097 // FIXME: when we move to C++20 we should consider using emplace_back2098 ActiveModule->UnresolvedConflicts.push_back(std::move(Conflict));2099}2100 2101void ModuleMapLoader::handleInferredModuleDecl(2102 const modulemap::ModuleDecl &MD) {2103 SourceLocation StarLoc = MD.Id.front().second;2104 2105 // Inferred modules must be submodules.2106 if (!ActiveModule && !MD.Framework) {2107 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);2108 return;2109 }2110 2111 if (ActiveModule) {2112 // Inferred modules must have umbrella directories.2113 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {2114 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);2115 return;2116 }2117 2118 // Check for redefinition of an inferred module.2119 if (ActiveModule->InferSubmodules) {2120 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);2121 if (ActiveModule->InferredSubmoduleLoc.isValid())2122 Diags.Report(ActiveModule->InferredSubmoduleLoc,2123 diag::note_mmap_prev_definition);2124 return;2125 }2126 2127 // Check for the 'framework' keyword, which is not permitted here.2128 if (MD.Framework) {2129 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);2130 return;2131 }2132 } else if (MD.Explicit) {2133 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);2134 return;2135 }2136 2137 if (ActiveModule) {2138 // Note that we have an inferred submodule.2139 ActiveModule->InferSubmodules = true;2140 ActiveModule->InferredSubmoduleLoc = StarLoc;2141 ActiveModule->InferExplicitSubmodules = MD.Explicit;2142 } else {2143 // We'll be inferring framework modules for this directory.2144 auto &InfDir = Map.InferredDirectories[Directory];2145 InfDir.InferModules = true;2146 InfDir.Attrs = MD.Attrs;2147 InfDir.ModuleMapFID = ModuleMapFID;2148 // FIXME: Handle the 'framework' keyword.2149 }2150 2151 for (const modulemap::Decl &Decl : MD.Decls) {2152 std::visit(2153 llvm::makeVisitor(2154 [&](const auto &Other) {2155 Diags.Report(Other.Location,2156 diag::err_mmap_expected_inferred_member)2157 << (ActiveModule != nullptr);2158 },2159 [&](const modulemap::ExcludeDecl &ED) {2160 // Only inferred frameworks can have exclude decls2161 if (ActiveModule) {2162 Diags.Report(ED.Location,2163 diag::err_mmap_expected_inferred_member)2164 << (ActiveModule != nullptr);2165 HadError = true;2166 return;2167 }2168 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(2169 ED.Module);2170 },2171 [&](const modulemap::ExportDecl &ED) {2172 // Only inferred submodules can have export decls2173 if (!ActiveModule) {2174 Diags.Report(ED.Location,2175 diag::err_mmap_expected_inferred_member)2176 << (ActiveModule != nullptr);2177 HadError = true;2178 return;2179 }2180 2181 if (ED.Wildcard && ED.Id.size() == 0)2182 ActiveModule->InferExportWildcard = true;2183 else2184 Diags.Report(ED.Id.front().second,2185 diag::err_mmap_expected_export_wildcard);2186 }),2187 Decl);2188 }2189}2190 2191bool ModuleMapLoader::loadModuleDecl(const modulemap::ModuleDecl &MD) {2192 handleModuleDecl(MD);2193 return HadError;2194}2195 2196bool ModuleMapLoader::loadExternModuleDecl(2197 const modulemap::ExternModuleDecl &EMD) {2198 handleExternModuleDecl(EMD);2199 return HadError;2200}2201 2202bool ModuleMapLoader::parseAndLoadModuleMapFile(2203 const modulemap::ModuleMapFile &MMF) {2204 for (const auto &Decl : MMF.Decls) {2205 std::visit(2206 llvm::makeVisitor(2207 [&](const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },2208 [&](const modulemap::ExternModuleDecl &EMD) {2209 handleExternModuleDecl(EMD);2210 }),2211 Decl);2212 }2213 return HadError;2214}2215 2216Module *ModuleMap::findOrLoadModule(StringRef Name) {2217 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);2218 if (Known != Modules.end())2219 return Known->getValue();2220 2221 auto ParsedMod = ParsedModules.find(Name);2222 if (ParsedMod == ParsedModules.end())2223 return nullptr;2224 2225 Diags.Report(diag::remark_mmap_load_module) << Name;2226 2227 for (const auto &ModuleDecl : ParsedMod->second) {2228 const modulemap::ModuleMapFile &MMF = *ModuleDecl.first;2229 ModuleMapLoader Loader(SourceMgr, Diags, const_cast<ModuleMap &>(*this),2230 MMF.ID, *MMF.Dir, MMF.IsSystem);2231 if (Loader.loadModuleDecl(*ModuleDecl.second))2232 return nullptr;2233 }2234 2235 return findModule(Name);2236}2237 2238bool ModuleMap::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,2239 DirectoryEntryRef Dir, FileID ID,2240 unsigned *Offset,2241 SourceLocation ExternModuleLoc) {2242 assert(Target && "Missing target information");2243 llvm::DenseMap<const FileEntry *, bool>::iterator Known =2244 LoadedModuleMap.find(File);2245 if (Known != LoadedModuleMap.end())2246 return Known->second;2247 2248 // If the module map file wasn't already entered, do so now.2249 if (ID.isInvalid()) {2250 ID = SourceMgr.translateFile(File);2251 // TODO: The way we compute affecting module maps requires this to be a2252 // local FileID. This should be changed to reuse loaded FileIDs when2253 // available, and change the way that affecting module maps are2254 // computed to not require this.2255 if (ID.isInvalid() || SourceMgr.isLoadedFileID(ID)) {2256 auto FileCharacter =2257 IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;2258 ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);2259 }2260 }2261 2262 assert(Target && "Missing target information");2263 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);2264 if (!Buffer)2265 return LoadedModuleMap[File] = true;2266 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&2267 "invalid buffer offset");2268 2269 std::optional<modulemap::ModuleMapFile> MMF =2270 modulemap::parseModuleMap(ID, Dir, SourceMgr, Diags, IsSystem, Offset);2271 bool Result = false;2272 if (MMF) {2273 Diags.Report(diag::remark_mmap_load) << File.getName();2274 ModuleMapLoader Loader(SourceMgr, Diags, *this, ID, Dir, IsSystem);2275 Result = Loader.parseAndLoadModuleMapFile(*MMF);2276 }2277 LoadedModuleMap[File] = Result;2278 2279 // Notify callbacks that we observed it.2280 // FIXME: We should only report module maps that were actually used.2281 for (const auto &Cb : Callbacks)2282 Cb->moduleMapFileRead(MMF ? MMF->Start : SourceLocation(), File, IsSystem);2283 2284 return Result;2285}2286