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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the ModuleMap implementation, which describes the layout
10// 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(Key: Mod->Name);
53 if (PendingLinkAs != PendingLinkAsModule.end()) {
54 for (auto &Name : PendingLinkAs->second) {
55 auto *M = findModule(Name: Name.getKey());
56 if (M)
57 M->UseExportAsModuleLinkName = true;
58 }
59 }
60}
61
62void ModuleMap::addLinkAsDependency(Module *Mod) {
63 if (findModule(Name: Mod->ExportAsModule))
64 Mod->UseExportAsModuleLinkName = true;
65 else
66 PendingLinkAsModule[Mod->ExportAsModule].insert(key: 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::ModuleHeaderRole
86ModuleMap::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::ExportDecl
107ModuleMap::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(Id: 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(Name: Id[0].first, Context: Mod);
128 if (!Context) {
129 if (Complain)
130 Diags.Report(Loc: Id[0].second, DiagID: 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(Name: Id[I].first, Context);
139 if (!Sub) {
140 if (Complain)
141 Diags.Report(Loc: Id[I].second, DiagID: 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 the
155/// 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(Elt: 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(RangeOrContainer: llvm::reverse(C&: Paths)))
170 llvm::sys::path::append(path&: Path, a: "Frameworks", b: 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(E: 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(Mod: M, Path&: RelativePathName);
192 unsigned RelativePathLength = RelativePathName.size();
193
194 // Check whether this file is in the public headers.
195 llvm::sys::path::append(path&: RelativePathName, a: "Headers", b: Header.FileName);
196 llvm::sys::path::append(path&: FullPathName, a: 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' should
202 // be defined as 'module FrameworkName.Private', and not as
203 // 'framework module FrameworkName.Private', since a 'Private.Framework'
204 // does not usually exist. However, since both are currently widely used
205 // for private modules, make sure we find the right path in both cases.
206 if (M->IsFramework && M->Name == "Private")
207 RelativePathName.clear();
208 else
209 RelativePathName.resize(N: RelativePathLength);
210 FullPathName.resize(N: FullPathLength);
211 llvm::sys::path::append(path&: RelativePathName, a: "PrivateHeaders",
212 b: Header.FileName);
213 llvm::sys::path::append(path&: FullPathName, a: RelativePathName);
214 return GetFile(FullPathName);
215 };
216
217 if (llvm::sys::path::is_absolute(path: Header.FileName)) {
218 RelativePathName.clear();
219 RelativePathName.append(in_start: Header.FileName.begin(), in_end: 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(path&: RelativePathName, a: Header.FileName);
228 llvm::sys::path::append(path&: FullPathName, a: RelativePathName);
229 auto NormalHdrFile = GetFile(FullPathName);
230
231 if (!NormalHdrFile && Directory->getName().ends_with(Suffix: ".framework")) {
232 // The lack of 'framework' keyword in a module declaration it's a simple
233 // mistake we can diagnose when the header exists within the proper
234 // framework style path.
235 FullPathName.assign(RHS: Directory->getName());
236 RelativePathName.clear();
237 if (GetFrameworkFile()) {
238 Diags.Report(Loc: Header.FileNameLoc,
239 DiagID: 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 builtin
250/// header, supplied by Clang to replace, override, or augment existing system
251/// headers.
252static bool isBuiltinHeaderName(StringRef FileName) {
253 return llvm::StringSwitch<bool>(FileName)
254 .Case(S: "float.h", Value: true)
255 .Case(S: "iso646.h", Value: true)
256 .Case(S: "limits.h", Value: true)
257 .Case(S: "stdalign.h", Value: true)
258 .Case(S: "stdarg.h", Value: true)
259 .Case(S: "stdatomic.h", Value: true)
260 .Case(S: "stdbool.h", Value: true)
261 .Case(S: "stdckdint.h", Value: true)
262 .Case(S: "stdcountof.h", Value: true)
263 .Case(S: "stddef.h", Value: true)
264 .Case(S: "stdint.h", Value: true)
265 .Case(S: "tgmath.h", Value: true)
266 .Case(S: "unwind.h", Value: true)
267 .Default(Value: false);
268}
269
270/// Determine whether the given module name is the name of a builtin
271/// module that is cyclic with a system module on some platforms.
272static bool isBuiltInModuleName(StringRef ModuleName) {
273 return llvm::StringSwitch<bool>(ModuleName)
274 .Case(S: "_Builtin_float", Value: true)
275 .Case(S: "_Builtin_inttypes", Value: true)
276 .Case(S: "_Builtin_iso646", Value: true)
277 .Case(S: "_Builtin_limits", Value: true)
278 .Case(S: "_Builtin_stdalign", Value: true)
279 .Case(S: "_Builtin_stdarg", Value: true)
280 .Case(S: "_Builtin_stdatomic", Value: true)
281 .Case(S: "_Builtin_stdbool", Value: true)
282 .Case(S: "_Builtin_stddef", Value: true)
283 .Case(S: "_Builtin_stdint", Value: true)
284 .Case(S: "_Builtin_stdnoreturn", Value: true)
285 .Case(S: "_Builtin_tgmath", Value: true)
286 .Case(S: "_Builtin_unwind", Value: true)
287 .Default(Value: 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(M: Mod, Header, RelativePathName, NeedsFramework)) {
296 if (Header.IsUmbrella) {
297 const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
298 if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
299 Diags.Report(Loc: Header.FileNameLoc, DiagID: diag::err_mmap_umbrella_clash)
300 << UmbrellaMod->getFullModuleName();
301 else
302 // Record this umbrella header.
303 setUmbrellaHeaderAsWritten(Mod, UmbrellaHeader: *File, NameAsWritten: Header.FileName,
304 PathRelativeToRootModuleDirectory: RelativePathName.str());
305 } else {
306 Module::Header H = {.NameAsWritten: Header.FileName, .PathRelativeToRootModuleDirectory: std::string(RelativePathName),
307 .Entry: *File};
308 addHeader(Mod, Header: H, Role: headerKindToRole(Kind: Header.Kind));
309 }
310 } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
311 // There's a builtin header but no corresponding on-disk header. Assume
312 // 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 as
317 // unavailable and store the header directive for displaying diagnostics.
318 Mod->MissingHeaders.push_back(Elt: Header);
319 // A missing header with stat information doesn't make the module
320 // unavailable; this keeps our behavior consistent as headers are lazily
321 // resolved. (Such a module still can't be built though, except from
322 // 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(path: Header.FileName) ||
332 Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
333 !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
334 !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(FileName: Header.FileName))
335 return false;
336
337 // This is a system module with a top-level header. This header
338 // may have a counterpart (or replacement) in the set of headers
339 // supplied by Clang. Find that builtin header.
340 SmallString<128> Path;
341 llvm::sys::path::append(path&: Path, a: BuiltinIncludeDir->getName(), b: Header.FileName);
342 auto File = SourceMgr.getFileManager().getOptionalFileRef(Filename: Path);
343 if (!File)
344 return false;
345
346 Module::Header H = {.NameAsWritten: Header.FileName, .PathRelativeToRootModuleDirectory: Header.FileName, .Entry: *File};
347 auto Role = headerKindToRole(Kind: Header.Kind);
348 addHeader(Mod, Header: 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(S: 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(c: Name[0]))
378 Buffer.push_back(Elt: '_');
379 Buffer.reserve(N: Buffer.size() + Name.size());
380 for (unsigned I = 0, N = Name.size(); I != N; ++I) {
381 if (isAsciiIdentifierContinue(c: Name[I]))
382 Buffer.push_back(Elt: Name[I]);
383 else
384 Buffer.push_back(Elt: '_');
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(Value: false)) {
395 if (Name.data() != Buffer.data())
396 Buffer.append(in_start: Name.begin(), in_end: Name.end());
397 Buffer.push_back(Elt: '_');
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(FileName: llvm::sys::path::filename(path: 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(Val: File);
419 if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
420 Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
421 HeaderInfo.loadTopLevelSystemModules();
422 return Headers.find(Val: 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, because
435 // frameworks moving from top-level frameworks to embedded frameworks tend
436 // 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: *Dir);
439
440 // Keep walking up the directory hierarchy, looking for a directory with
441 // an umbrella header.
442 do {
443 auto KnownDir = UmbrellaDirs.find(Val: *Dir);
444 if (KnownDir != UmbrellaDirs.end())
445 return KnownHeader(KnownDir->second, NormalHeader);
446
447 IntermediateDirs.push_back(Elt: *Dir);
448
449 // Retrieve our parent path.
450 DirName = llvm::sys::path::parent_path(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 NDEBUG
464 if (Header.getRole() & ModuleMap::PrivateHeader) {
465 // Check for consistency between the module header role
466 // 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#endif
478 return !Header.isAccessibleFrom(M: 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 modules
490 // with no source files.
491 if (getTopLevelOrNull(M: RequestingModule) != getTopLevelOrNull(M: SourceModule))
492 return;
493
494 if (RequestingModule) {
495 resolveUses(Mod: RequestingModule, /*Complain=*/false);
496 resolveHeaderDirectives(Mod: 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, IncFileEnt: File, Header)) {
514 Private = Header.getModule();
515 continue;
516 }
517
518 // If uses need to be specified explicitly, we are only allowed to return
519 // modules that are explicitly used by the requesting module.
520 if (RequestingModule && LangOpts.ModulesDeclUse &&
521 !RequestingModule->directlyUses(Requested: 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(Loc: FilenameLoc, DiagID: 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(Loc: FilenameLoc, DiagID: diag::err_undeclared_use_of_module_indirect)
543 << RequestingModule->getTopLevelModule()->Name << Filename
544 << 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(Loc: FilenameLoc, DiagID: 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(Loc: 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 merely
571 // importable is non-hermetic and can result in surprising behavior for
572 // 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(New: H, Old: Result))
616 Result = H;
617 }
618 return MakeResult(Result);
619 }
620
621 return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
622}
623
624OptionalFileEntryRef ModuleMap::findUmbrellaHeaderForModule(
625 Module *M, std::string NameAsWritten,
626 SmallVectorImpl<char> &RelativePathName) {
627 Module::UnresolvedHeaderDirective Header;
628 Header.FileName = std::move(NameAsWritten);
629 Header.IsUmbrella = true;
630 bool NeedsFramework;
631 return findHeader(M, Header, RelativePathName, NeedsFramework);
632}
633
634ModuleMap::KnownHeader
635ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
636 assert(!Headers.count(File) && "already have a module for this header");
637
638 SmallVector<DirectoryEntryRef, 2> SkippedDirs;
639 KnownHeader H = findHeaderInUmbrellaDirs(File, IntermediateDirs&: SkippedDirs);
640 if (H) {
641 Module *Result = H.getModule();
642
643 // Search up the module stack until we find a module with an umbrella
644 // directory.
645 Module *UmbrellaModule = Result;
646 while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
647 UmbrellaModule = UmbrellaModule->Parent;
648
649 if (UmbrellaModule->InferSubmodules) {
650 FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(M: UmbrellaModule);
651
652 // Infer submodules for each of the directories we found between
653 // the directory of the umbrella header and the directory where
654 // the actual header is located.
655 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
656
657 for (DirectoryEntryRef SkippedDir : llvm::reverse(C&: SkippedDirs)) {
658 // Find or create the module that corresponds to this directory name.
659 SmallString<32> NameBuf;
660 StringRef Name = sanitizeFilenameAsIdentifier(
661 Name: llvm::sys::path::stem(path: SkippedDir.getName()), Buffer&: NameBuf);
662 Result = findOrCreateModuleFirst(Name, Parent: Result, /*IsFramework=*/false,
663 IsExplicit: Explicit);
664 setInferredModuleAllowedBy(M: Result, ModMapFID: UmbrellaModuleMap);
665
666 // Associate the module and the directory.
667 UmbrellaDirs[SkippedDir] = Result;
668
669 // If inferred submodules export everything they import, add a
670 // wildcard to the set of exports.
671 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
672 Result->Exports.push_back(Elt: Module::ExportDecl(nullptr, true));
673 }
674
675 // Infer a submodule with the same name as this header file.
676 SmallString<32> NameBuf;
677 StringRef Name = sanitizeFilenameAsIdentifier(
678 Name: llvm::sys::path::stem(path: File.getName()), Buffer&: NameBuf);
679 Result = findOrCreateModuleFirst(Name, Parent: Result, /*IsFramework=*/false,
680 IsExplicit: Explicit);
681 setInferredModuleAllowedBy(M: Result, ModMapFID: UmbrellaModuleMap);
682 Result->addTopHeader(File);
683
684 // If inferred submodules export everything they import, add a
685 // wildcard to the set of exports.
686 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
687 Result->Exports.push_back(Elt: Module::ExportDecl(nullptr, true));
688 } else {
689 // Record each of the directories we stepped through as being part of
690 // the module we found, since the umbrella header covers them all.
691 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
692 UmbrellaDirs[SkippedDirs[I]] = Result;
693 }
694
695 KnownHeader Header(Result, NormalHeader);
696 Headers[File].push_back(Elt: Header);
697 return Header;
698 }
699
700 return {};
701}
702
703ArrayRef<ModuleMap::KnownHeader>
704ModuleMap::findAllModulesForHeader(FileEntryRef File) {
705 HeadersMap::iterator Known = findKnownHeader(File);
706 if (Known != Headers.end())
707 return Known->second;
708
709 if (findOrCreateModuleForHeaderInUmbrellaDir(File))
710 return Headers.find(Val: File)->second;
711
712 return {};
713}
714
715ArrayRef<ModuleMap::KnownHeader>
716ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
717 // FIXME: Is this necessary?
718 resolveHeaderDirectives(File);
719 auto It = Headers.find(Val: File);
720 if (It == Headers.end())
721 return {};
722 return It->second;
723}
724
725bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
726 return isHeaderUnavailableInModule(Header, RequestingModule: nullptr);
727}
728
729bool ModuleMap::isHeaderUnavailableInModule(
730 FileEntryRef Header, const Module *RequestingModule) const {
731 resolveHeaderDirectives(File: Header);
732 HeadersMap::const_iterator Known = Headers.find(Val: Header);
733 if (Known != Headers.end()) {
734 for (SmallVectorImpl<KnownHeader>::const_iterator
735 I = Known->second.begin(),
736 E = Known->second.end();
737 I != E; ++I) {
738
739 if (I->getRole() == ModuleMap::ExcludedHeader)
740 continue;
741
742 if (I->isAvailable() &&
743 (!RequestingModule ||
744 I->getModule()->isSubModuleOf(Other: RequestingModule))) {
745 // When no requesting module is available, the caller is looking if a
746 // header is part a module by only looking into the module map. This is
747 // done by warn_uncovered_module_header checks; don't consider textual
748 // headers part of it in this mode, otherwise we get misleading warnings
749 // that a umbrella header is not including a textual header.
750 if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
751 continue;
752 return false;
753 }
754 }
755 return true;
756 }
757
758 OptionalDirectoryEntryRef Dir = Header.getDir();
759 SmallVector<DirectoryEntryRef, 2> SkippedDirs;
760 StringRef DirName = Dir->getName();
761
762 auto IsUnavailable = [&](const Module *M) {
763 return !M->isAvailable() && (!RequestingModule ||
764 M->isSubModuleOf(Other: RequestingModule));
765 };
766
767 // Keep walking up the directory hierarchy, looking for a directory with
768 // an umbrella header.
769 do {
770 auto KnownDir = UmbrellaDirs.find(Val: *Dir);
771 if (KnownDir != UmbrellaDirs.end()) {
772 Module *Found = KnownDir->second;
773 if (IsUnavailable(Found))
774 return true;
775
776 // Search up the module stack until we find a module with an umbrella
777 // directory.
778 Module *UmbrellaModule = Found;
779 while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
780 UmbrellaModule->Parent)
781 UmbrellaModule = UmbrellaModule->Parent;
782
783 if (UmbrellaModule->InferSubmodules) {
784 for (DirectoryEntryRef SkippedDir : llvm::reverse(C&: SkippedDirs)) {
785 // Find or create the module that corresponds to this directory name.
786 SmallString<32> NameBuf;
787 StringRef Name = sanitizeFilenameAsIdentifier(
788 Name: llvm::sys::path::stem(path: SkippedDir.getName()), Buffer&: NameBuf);
789 Found = lookupModuleQualified(Name, Context: Found);
790 if (!Found)
791 return false;
792 if (IsUnavailable(Found))
793 return true;
794 }
795
796 // Infer a submodule with the same name as this header file.
797 SmallString<32> NameBuf;
798 StringRef Name = sanitizeFilenameAsIdentifier(
799 Name: llvm::sys::path::stem(path: Header.getName()),
800 Buffer&: NameBuf);
801 Found = lookupModuleQualified(Name, Context: Found);
802 if (!Found)
803 return false;
804 }
805
806 return IsUnavailable(Found);
807 }
808
809 SkippedDirs.push_back(Elt: *Dir);
810
811 // Retrieve our parent path.
812 DirName = llvm::sys::path::parent_path(path: DirName);
813 if (DirName.empty())
814 break;
815
816 // Resolve the parent path to a directory entry.
817 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
818 } while (Dir);
819
820 return false;
821}
822
823Module *ModuleMap::findModule(StringRef Name) const {
824 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Key: Name);
825 if (Known != Modules.end())
826 return Known->getValue();
827
828 return nullptr;
829}
830
831Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
832 if (Module *SubM = Parent->findSubmodule(Name))
833 return SubM;
834 if (!Parent->InferSubmodules)
835 return nullptr;
836 Module *Result = new (ModulesAlloc.Allocate())
837 Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
838 Parent->InferExplicitSubmodules, 0);
839 Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
840 Result->InferSubmodules = Parent->InferSubmodules;
841 Result->InferExportWildcard = Parent->InferExportWildcard;
842 if (Result->InferExportWildcard)
843 Result->Exports.push_back(Elt: Module::ExportDecl(nullptr, true));
844 return Result;
845}
846
847Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
848 Module *Context) const {
849 for(; Context; Context = Context->Parent) {
850 if (Module *Sub = lookupModuleQualified(Name, Context))
851 return Sub;
852 }
853
854 return findModule(Name);
855}
856
857Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
858 if (!Context)
859 return findModule(Name);
860
861 return Context->findSubmodule(Name);
862}
863
864std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
865 Module *Parent,
866 bool IsFramework,
867 bool IsExplicit) {
868 // Try to find an existing module with this name.
869 if (Module *Sub = lookupModuleQualified(Name, Context: Parent))
870 return std::make_pair(x&: Sub, y: false);
871
872 // Create a new module with this name.
873 Module *M = createModule(Name, Parent, IsFramework, IsExplicit);
874 return std::make_pair(x&: M, y: true);
875}
876
877Module *ModuleMap::createModule(StringRef Name, Module *Parent,
878 bool IsFramework, bool IsExplicit) {
879 assert(lookupModuleQualified(Name, Parent) == nullptr &&
880 "Creating duplicate submodule");
881
882 Module *Result = new (ModulesAlloc.Allocate())
883 Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,
884 IsFramework, IsExplicit, NumCreatedModules++);
885 if (!Parent) {
886 if (LangOpts.CurrentModule == Name)
887 SourceModule = Result;
888 Modules[Name] = Result;
889 ModuleScopeIDs[Result] = CurrentModuleScopeID;
890 }
891 return Result;
892}
893
894Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
895 Module *Parent) {
896 auto *Result = new (ModulesAlloc.Allocate()) Module(
897 ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,
898 /*IsExplicit=*/true, NumCreatedModules++);
899 Result->Kind = Module::ExplicitGlobalModuleFragment;
900 // If the created module isn't owned by a parent, send it to PendingSubmodules
901 // to wait for its parent.
902 if (!Result->Parent)
903 PendingSubmodules.emplace_back(Args&: Result);
904 return Result;
905}
906
907Module *
908ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
909 Module *Parent) {
910 assert(Parent && "We should only create an implicit global module fragment "
911 "in a module purview");
912 // Note: Here the `IsExplicit` parameter refers to the semantics in clang
913 // modules. All the non-explicit submodules in clang modules will be exported
914 // too. Here we simplify the implementation by using the concept.
915 auto *Result = new (ModulesAlloc.Allocate())
916 Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,
917 /*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);
918 Result->Kind = Module::ImplicitGlobalModuleFragment;
919 return Result;
920}
921
922Module *
923ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
924 SourceLocation Loc) {
925 auto *Result = new (ModulesAlloc.Allocate()) Module(
926 ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,
927 /*IsExplicit=*/true, NumCreatedModules++);
928 Result->Kind = Module::PrivateModuleFragment;
929 return Result;
930}
931
932Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
933 Module::ModuleKind Kind) {
934 auto *Result = new (ModulesAlloc.Allocate())
935 Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
936 /*IsExplicit=*/false, NumCreatedModules++);
937 Result->Kind = Kind;
938
939 // Reparent any current global module fragment as a submodule of this module.
940 for (auto &Submodule : PendingSubmodules)
941 Submodule->setParent(Result);
942 PendingSubmodules.clear();
943 return Result;
944}
945
946Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
947 StringRef Name) {
948 assert(LangOpts.CurrentModule == Name && "module name mismatch");
949 assert(!Modules[Name] && "redefining existing module");
950
951 auto *Result =
952 createModuleUnitWithKind(Loc, Name, Kind: Module::ModuleInterfaceUnit);
953 Modules[Name] = SourceModule = Result;
954
955 // Mark the main source file as being within the newly-created module so that
956 // declarations and macros are properly visibility-restricted to it.
957 auto MainFile = SourceMgr.getFileEntryRefForID(FID: SourceMgr.getMainFileID());
958 assert(MainFile && "no input file for module interface");
959 Headers[*MainFile].push_back(Elt: KnownHeader(Result, PrivateHeader));
960
961 return Result;
962}
963
964Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
965 StringRef Name) {
966 assert(LangOpts.CurrentModule == Name && "module name mismatch");
967 // The interface for this implementation must exist and be loaded.
968 assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
969 "creating implementation module without an interface");
970
971 // Create an entry in the modules map to own the implementation unit module.
972 // User module names must not start with a period (so that this cannot clash
973 // with any legal user-defined module name).
974 StringRef IName = ".ImplementationUnit";
975 assert(!Modules[IName] && "multiple implementation units?");
976
977 auto *Result =
978 createModuleUnitWithKind(Loc, Name, Kind: Module::ModuleImplementationUnit);
979 Modules[IName] = SourceModule = Result;
980
981 // Check that the main file is present.
982 assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
983 "no input file for module implementation");
984
985 return Result;
986}
987
988Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
989 Module::Header H) {
990 assert(LangOpts.CurrentModule == Name && "module name mismatch");
991 assert(!Modules[Name] && "redefining existing module");
992
993 auto *Result = new (ModulesAlloc.Allocate())
994 Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
995 /*IsExplicit=*/false, NumCreatedModules++);
996 Result->Kind = Module::ModuleHeaderUnit;
997 Modules[Name] = SourceModule = Result;
998 addHeader(Mod: Result, Header: H, Role: NormalHeader);
999 return Result;
1000}
1001
1002/// For a framework module, infer the framework against which we
1003/// should link.
1004static void inferFrameworkLink(Module *Mod) {
1005 assert(Mod->IsFramework && "Can only infer linking for framework modules");
1006 assert(!Mod->isSubFramework() &&
1007 "Can only infer linking for top-level frameworks");
1008
1009 StringRef FrameworkName(Mod->Name);
1010 FrameworkName.consume_back(Suffix: "_Private");
1011 Mod->LinkLibraries.push_back(Elt: Module::LinkLibrary(FrameworkName.str(),
1012 /*IsFramework=*/true));
1013}
1014
1015Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
1016 bool IsSystem, Module *Parent) {
1017 Attributes Attrs;
1018 Attrs.IsSystem = IsSystem;
1019 return inferFrameworkModule(FrameworkDir, Attrs, Parent);
1020}
1021
1022Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
1023 Attributes Attrs, Module *Parent) {
1024 // Note: as an egregious but useful hack we use the real path here, because
1025 // we might be looking at an embedded framework that symlinks out to a
1026 // top-level framework, and we need to infer as if we were naming the
1027 // top-level framework.
1028 StringRef FrameworkDirName =
1029 SourceMgr.getFileManager().getCanonicalName(Dir: FrameworkDir);
1030
1031 // In case this is a case-insensitive filesystem, use the canonical
1032 // directory name as the ModuleName, since modules are case-sensitive.
1033 // FIXME: we should be able to give a fix-it hint for the correct spelling.
1034 SmallString<32> ModuleNameStorage;
1035 StringRef ModuleName = sanitizeFilenameAsIdentifier(
1036 Name: llvm::sys::path::stem(path: FrameworkDirName), Buffer&: ModuleNameStorage);
1037
1038 // Check whether we've already found this module.
1039 if (Module *Mod = lookupModuleQualified(Name: ModuleName, Context: Parent))
1040 return Mod;
1041
1042 FileManager &FileMgr = SourceMgr.getFileManager();
1043
1044 // If the framework has a parent path from which we're allowed to infer
1045 // a framework module, do so.
1046 FileID ModuleMapFID;
1047 if (!Parent) {
1048 // Determine whether we're allowed to infer a module map.
1049 bool canInfer = false;
1050 if (llvm::sys::path::has_parent_path(path: FrameworkDirName)) {
1051 // Figure out the parent path.
1052 StringRef Parent = llvm::sys::path::parent_path(path: FrameworkDirName);
1053 if (auto ParentDir = FileMgr.getOptionalDirectoryRef(DirName: Parent)) {
1054 // Check whether we have already looked into the parent directory
1055 // for a module map.
1056 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1057 inferred = InferredDirectories.find(Val: *ParentDir);
1058 if (inferred == InferredDirectories.end()) {
1059 // We haven't looked here before. Load a module map, if there is
1060 // one.
1061 bool IsFrameworkDir = Parent.ends_with(Suffix: ".framework");
1062 if (OptionalFileEntryRef ModMapFile =
1063 HeaderInfo.lookupModuleMapFile(Dir: *ParentDir, IsFramework: IsFrameworkDir)) {
1064 // TODO: Parsing a module map should populate `InferredDirectories`
1065 // so we don't need to do a full load here.
1066 parseAndLoadModuleMapFile(File: *ModMapFile, IsSystem: Attrs.IsSystem,
1067 /*ImplicitlyDiscovered=*/true,
1068 HomeDir: *ParentDir);
1069 inferred = InferredDirectories.find(Val: *ParentDir);
1070 }
1071
1072 if (inferred == InferredDirectories.end())
1073 inferred = InferredDirectories.insert(
1074 KV: std::make_pair(x&: *ParentDir, y: InferredDirectory())).first;
1075 }
1076
1077 if (inferred->second.InferModules) {
1078 // We're allowed to infer for this directory, but make sure it's okay
1079 // to infer this particular module.
1080 StringRef Name = llvm::sys::path::stem(path: FrameworkDirName);
1081 canInfer =
1082 !llvm::is_contained(Range: inferred->second.ExcludedModules, Element: Name);
1083
1084 Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1085 Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1086 Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1087 Attrs.NoUndeclaredIncludes |=
1088 inferred->second.Attrs.NoUndeclaredIncludes;
1089 ModuleMapFID = inferred->second.ModuleMapFID;
1090 }
1091 }
1092 }
1093
1094 // If we're not allowed to infer a framework module, don't.
1095 if (!canInfer)
1096 return nullptr;
1097 } else {
1098 ModuleMapFID = getModuleMapFileIDForUniquing(M: Parent);
1099 }
1100
1101 // Look for an umbrella header.
1102 SmallString<128> UmbrellaName = FrameworkDir.getName();
1103 llvm::sys::path::append(path&: UmbrellaName, a: "Headers", b: ModuleName + ".h");
1104 auto UmbrellaHeader = FileMgr.getOptionalFileRef(Filename: UmbrellaName);
1105
1106 // FIXME: If there's no umbrella header, we could probably scan the
1107 // framework to load *everything*. But, it's not clear that this is a good
1108 // idea.
1109 if (!UmbrellaHeader)
1110 return nullptr;
1111
1112 Module *Result = new (ModulesAlloc.Allocate())
1113 Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
1114 /*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);
1115 setInferredModuleAllowedBy(M: Result, ModMapFID: ModuleMapFID);
1116 if (!Parent) {
1117 if (LangOpts.CurrentModule == ModuleName)
1118 SourceModule = Result;
1119 Modules[ModuleName] = Result;
1120 ModuleScopeIDs[Result] = CurrentModuleScopeID;
1121 }
1122
1123 Result->IsSystem |= Attrs.IsSystem;
1124 Result->IsExternC |= Attrs.IsExternC;
1125 Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1126 Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1127 Result->Directory = FrameworkDir;
1128
1129 // Chop off the first framework bit, as that is implied.
1130 StringRef RelativePath = UmbrellaName.str().substr(
1131 Start: Result->getTopLevelModule()->Directory->getName().size());
1132 RelativePath = llvm::sys::path::relative_path(path: RelativePath);
1133
1134 // umbrella header "umbrella-header-name"
1135 setUmbrellaHeaderAsWritten(Mod: Result, UmbrellaHeader: *UmbrellaHeader, NameAsWritten: ModuleName + ".h",
1136 PathRelativeToRootModuleDirectory: RelativePath);
1137
1138 // export *
1139 Result->Exports.push_back(Elt: Module::ExportDecl(nullptr, true));
1140
1141 // module * { export * }
1142 Result->InferSubmodules = true;
1143 Result->InferExportWildcard = true;
1144
1145 // Look for subframeworks.
1146 std::error_code EC;
1147 SmallString<128> SubframeworksDirName = FrameworkDir.getName();
1148 llvm::sys::path::append(path&: SubframeworksDirName, a: "Frameworks");
1149 llvm::sys::path::native(path&: SubframeworksDirName);
1150 llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1151 for (llvm::vfs::directory_iterator
1152 Dir = FS.dir_begin(Dir: SubframeworksDirName, EC),
1153 DirEnd;
1154 Dir != DirEnd && !EC; Dir.increment(EC)) {
1155 if (!StringRef(Dir->path()).ends_with(Suffix: ".framework"))
1156 continue;
1157
1158 if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(DirName: Dir->path())) {
1159 // Note: as an egregious but useful hack, we use the real path here and
1160 // check whether it is actually a subdirectory of the parent directory.
1161 // This will not be the case if the 'subframework' is actually a symlink
1162 // out to a top-level framework.
1163 StringRef SubframeworkDirName =
1164 FileMgr.getCanonicalName(Dir: *SubframeworkDir);
1165 bool FoundParent = false;
1166 do {
1167 // Get the parent directory name.
1168 SubframeworkDirName
1169 = llvm::sys::path::parent_path(path: SubframeworkDirName);
1170 if (SubframeworkDirName.empty())
1171 break;
1172
1173 if (auto SubDir =
1174 FileMgr.getOptionalDirectoryRef(DirName: SubframeworkDirName)) {
1175 if (*SubDir == FrameworkDir) {
1176 FoundParent = true;
1177 break;
1178 }
1179 }
1180 } while (true);
1181
1182 if (!FoundParent)
1183 continue;
1184
1185 // FIXME: Do we want to warn about subframeworks without umbrella headers?
1186 inferFrameworkModule(FrameworkDir: *SubframeworkDir, Attrs, Parent: Result);
1187 }
1188 }
1189
1190 // If the module is a top-level framework, automatically link against the
1191 // framework.
1192 if (!Result->isSubFramework())
1193 inferFrameworkLink(Mod: Result);
1194
1195 return Result;
1196}
1197
1198Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
1199 Module *ShadowingModule) {
1200
1201 // Create a new module with this name.
1202 Module *Result = new (ModulesAlloc.Allocate())
1203 Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,
1204 IsFramework, /*IsExplicit=*/false, NumCreatedModules++);
1205 Result->ShadowingModule = ShadowingModule;
1206 Result->markUnavailable(/*Unimportable*/true);
1207 ModuleScopeIDs[Result] = CurrentModuleScopeID;
1208 ShadowModules.push_back(Elt: Result);
1209
1210 return Result;
1211}
1212
1213void ModuleMap::setUmbrellaHeaderAsWritten(
1214 Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1215 const Twine &PathRelativeToRootModuleDirectory) {
1216 Headers[UmbrellaHeader].push_back(Elt: KnownHeader(Mod, NormalHeader));
1217 Mod->Umbrella = UmbrellaHeader;
1218 Mod->UmbrellaAsWritten = NameAsWritten.str();
1219 Mod->UmbrellaRelativeToRootModuleDirectory =
1220 PathRelativeToRootModuleDirectory.str();
1221 UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
1222
1223 // Notify callbacks that we just added a new header.
1224 for (const auto &Cb : Callbacks)
1225 Cb->moduleMapAddUmbrellaHeader(Header: UmbrellaHeader);
1226}
1227
1228void ModuleMap::setUmbrellaDirAsWritten(
1229 Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
1230 const Twine &PathRelativeToRootModuleDirectory) {
1231 Mod->Umbrella = UmbrellaDir;
1232 Mod->UmbrellaAsWritten = NameAsWritten.str();
1233 Mod->UmbrellaRelativeToRootModuleDirectory =
1234 PathRelativeToRootModuleDirectory.str();
1235 UmbrellaDirs[UmbrellaDir] = Mod;
1236}
1237
1238void ModuleMap::addUnresolvedHeader(Module *Mod,
1239 Module::UnresolvedHeaderDirective Header,
1240 bool &NeedsFramework) {
1241 // If there is a builtin counterpart to this file, add it now so it can
1242 // wrap the system header.
1243 if (resolveAsBuiltinHeader(Mod, Header)) {
1244 // If we have both a builtin and system version of the file, the
1245 // builtin version may want to inject macros into the system header, so
1246 // force the system header to be treated as a textual header in this
1247 // case.
1248 Header.Kind = headerRoleToKind(Role: ModuleMap::ModuleHeaderRole(
1249 headerKindToRole(Kind: Header.Kind) | ModuleMap::TextualHeader));
1250 Header.HasBuiltinHeader = true;
1251 }
1252
1253 // If possible, don't stat the header until we need to. This requires the
1254 // user to have provided us with some stat information about the file.
1255 // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1256 // headers.
1257 if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1258 Header.Kind != Module::HK_Excluded) {
1259 // We expect more variation in mtime than size, so if we're given both,
1260 // use the mtime as the key.
1261 if (Header.ModTime)
1262 LazyHeadersByModTime[*Header.ModTime].push_back(NewVal: Mod);
1263 else
1264 LazyHeadersBySize[*Header.Size].push_back(NewVal: Mod);
1265 Mod->UnresolvedHeaders.push_back(Elt: Header);
1266 return;
1267 }
1268
1269 // We don't have stat information or can't defer looking this file up.
1270 // Perform the lookup now.
1271 resolveHeader(Mod, Header, NeedsFramework);
1272}
1273
1274void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1275 auto BySize = LazyHeadersBySize.find(Val: File->getSize());
1276 if (BySize != LazyHeadersBySize.end()) {
1277 for (auto *M : BySize->second)
1278 resolveHeaderDirectives(Mod: M, File);
1279 LazyHeadersBySize.erase(I: BySize);
1280 }
1281
1282 auto ByModTime = LazyHeadersByModTime.find(Val: File->getModificationTime());
1283 if (ByModTime != LazyHeadersByModTime.end()) {
1284 for (auto *M : ByModTime->second)
1285 resolveHeaderDirectives(Mod: M, File);
1286 LazyHeadersByModTime.erase(I: ByModTime);
1287 }
1288}
1289
1290void ModuleMap::resolveHeaderDirectives(
1291 Module *Mod, std::optional<const FileEntry *> File) const {
1292 bool NeedsFramework = false;
1293 SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1294 const auto Size = File ? (*File)->getSize() : 0;
1295 const auto ModTime = File ? (*File)->getModificationTime() : 0;
1296
1297 for (auto &Header : Mod->UnresolvedHeaders) {
1298 if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
1299 (Header.Size && Header.Size != Size)))
1300 NewHeaders.push_back(Elt: Header);
1301 else
1302 // This operation is logically const; we're just changing how we represent
1303 // the header information for this file.
1304 const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
1305 }
1306 Mod->UnresolvedHeaders.swap(RHS&: NewHeaders);
1307}
1308
1309void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1310 ModuleHeaderRole Role, bool Imported) {
1311 KnownHeader KH(Mod, Role);
1312
1313 FileEntryRef HeaderEntry = Header.Entry;
1314
1315 // Only add each header to the headers list once.
1316 // FIXME: Should we diagnose if a header is listed twice in the
1317 // same module definition?
1318 auto &HeaderList = Headers[HeaderEntry];
1319 if (llvm::is_contained(Range&: HeaderList, Element: KH))
1320 return;
1321
1322 HeaderList.push_back(Elt: KH);
1323 Mod->addHeader(HK: headerRoleToKind(Role), H: std::move(Header));
1324
1325 bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
1326 if (!Imported || isCompilingModuleHeader) {
1327 // When we import HeaderFileInfo, the external source is expected to
1328 // set the isModuleHeader flag itself.
1329 HeaderInfo.MarkFileModuleHeader(FE: HeaderEntry, Role, isCompilingModuleHeader);
1330 }
1331
1332 // Notify callbacks that we just added a new header.
1333 for (const auto &Cb : Callbacks)
1334 Cb->moduleMapAddHeader(Filename: HeaderEntry.getName());
1335}
1336
1337bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
1338 bool ImplicitlyDiscovered,
1339 DirectoryEntryRef Dir, FileID ID,
1340 SourceLocation ExternModuleLoc) {
1341 llvm::DenseMap<const FileEntry *, const modulemap::ModuleMapFile *>::iterator
1342 Known = ParsedModuleMap.find(Val: File);
1343 if (Known != ParsedModuleMap.end())
1344 return Known->second == nullptr;
1345
1346 // If the module map file wasn't already entered, do so now.
1347 if (ID.isInvalid()) {
1348 FileID &LocalFID = ModuleMapLocalFileID[File];
1349 if (LocalFID.isInvalid()) {
1350 auto FileCharacter =
1351 IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
1352 LocalFID = SourceMgr.createFileID(SourceFile: File, IncludePos: ExternModuleLoc, FileCharacter);
1353 }
1354 ID = LocalFID;
1355 }
1356
1357 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(FID: ID);
1358 if (!Buffer) {
1359 ParsedModuleMap[File] = nullptr;
1360 return true;
1361 }
1362
1363 Diags.Report(DiagID: diag::remark_mmap_parse) << File.getName();
1364 std::optional<modulemap::ModuleMapFile> MaybeMMF = modulemap::parseModuleMap(
1365 ID, Dir, SM&: SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset: nullptr);
1366
1367 if (!MaybeMMF) {
1368 ParsedModuleMap[File] = nullptr;
1369 return true;
1370 }
1371
1372 ParsedModuleMaps.push_back(
1373 x: std::make_unique<modulemap::ModuleMapFile>(args: std::move(*MaybeMMF)));
1374 const modulemap::ModuleMapFile &MMF = *ParsedModuleMaps.back();
1375 std::vector<const modulemap::ExternModuleDecl *> PendingExternalModuleMaps;
1376 std::function<void(const modulemap::ModuleDecl &)> CollectExternDecls =
1377 [&](const modulemap::ModuleDecl &MD) {
1378 for (const auto &Decl : MD.Decls) {
1379 std::visit(visitor: llvm::makeVisitor(
1380 Callables: [&](const modulemap::ModuleDecl &SubMD) {
1381 // Skip inferred submodules (module *)
1382 if (SubMD.Id.front().first == "*")
1383 return;
1384 CollectExternDecls(SubMD);
1385 },
1386 Callables: [&](const modulemap::ExternModuleDecl &EMD) {
1387 PendingExternalModuleMaps.push_back(x: &EMD);
1388 },
1389 Callables: [&](const auto &) {
1390 // Ignore other decls
1391 }),
1392 variants: Decl);
1393 }
1394 };
1395
1396 for (const auto &Decl : MMF.Decls) {
1397 std::visit(visitor: llvm::makeVisitor(
1398 Callables: [&](const modulemap::ModuleDecl &MD) {
1399 // Only use the first part of the name even for submodules.
1400 // This will correctly load the submodule declarations when
1401 // the module is loaded.
1402 auto &ModuleDecls =
1403 ParsedModules[StringRef(MD.Id.front().first)];
1404 ModuleDecls.push_back(Elt: std::pair(&MMF, &MD));
1405 CollectExternDecls(MD);
1406 },
1407 Callables: [&](const modulemap::ExternModuleDecl &EMD) {
1408 PendingExternalModuleMaps.push_back(x: &EMD);
1409 }),
1410 variants: Decl);
1411 }
1412
1413 for (const modulemap::ExternModuleDecl *EMD : PendingExternalModuleMaps) {
1414 StringRef FileNameRef = EMD->Path;
1415 SmallString<128> ModuleMapFileName;
1416 if (llvm::sys::path::is_relative(path: FileNameRef)) {
1417 ModuleMapFileName += Dir.getName();
1418 llvm::sys::path::append(path&: ModuleMapFileName, a: EMD->Path);
1419 FileNameRef = ModuleMapFileName;
1420 }
1421
1422 if (auto EFile =
1423 SourceMgr.getFileManager().getOptionalFileRef(Filename: FileNameRef)) {
1424 parseModuleMapFile(File: *EFile, IsSystem, ImplicitlyDiscovered,
1425 Dir: EFile->getDir(), ID: FileID(), ExternModuleLoc);
1426 }
1427 }
1428
1429 ParsedModuleMap[File] = &MMF;
1430
1431 for (const auto &Cb : Callbacks)
1432 Cb->moduleMapFileRead(FileStart: SourceLocation(), File, IsSystem);
1433
1434 return false;
1435}
1436
1437void ModuleMap::loadAllParsedModules() {
1438 for (const auto &Entry : ParsedModules)
1439 findOrLoadModule(Name: Entry.first());
1440}
1441
1442FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const {
1443 if (Module->DefinitionLoc.isInvalid())
1444 return {};
1445
1446 return SourceMgr.getFileID(SpellingLoc: Module->DefinitionLoc);
1447}
1448
1449OptionalFileEntryRef
1450ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1451 return SourceMgr.getFileEntryRefForID(FID: getContainingModuleMapFileID(Module));
1452}
1453
1454FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {
1455 if (M->IsInferred) {
1456 assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1457 return InferredModuleAllowedBy.find(Val: M)->second;
1458 }
1459 return getContainingModuleMapFileID(Module: M);
1460}
1461
1462OptionalFileEntryRef
1463ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
1464 return SourceMgr.getFileEntryRefForID(FID: getModuleMapFileIDForUniquing(M));
1465}
1466
1467void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {
1468 M->IsInferred = true;
1469 InferredModuleAllowedBy[M] = ModMapFID;
1470}
1471
1472std::error_code
1473ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1474 StringRef Dir = llvm::sys::path::parent_path(path: {Path.data(), Path.size()});
1475
1476 // Do not canonicalize within the framework; the module map loader expects
1477 // Modules/ not Versions/A/Modules.
1478 if (llvm::sys::path::filename(path: Dir) == "Modules") {
1479 StringRef Parent = llvm::sys::path::parent_path(path: Dir);
1480 if (Parent.ends_with(Suffix: ".framework"))
1481 Dir = Parent;
1482 }
1483
1484 FileManager &FM = SourceMgr.getFileManager();
1485 auto DirEntry = FM.getDirectoryRef(DirName: Dir.empty() ? "." : Dir);
1486 if (!DirEntry)
1487 return llvm::errorToErrorCode(Err: DirEntry.takeError());
1488
1489 // Canonicalize the directory.
1490 StringRef CanonicalDir = FM.getCanonicalName(Dir: *DirEntry);
1491 if (CanonicalDir != Dir)
1492 llvm::sys::path::replace_path_prefix(Path, OldPrefix: Dir, NewPrefix: CanonicalDir);
1493
1494 // In theory, the filename component should also be canonicalized if it
1495 // on a case-insensitive filesystem. However, the extra canonicalization is
1496 // expensive and if clang looked up the filename it will always be lowercase.
1497
1498 // Remove ., remove redundant separators, and switch to native separators.
1499 // This is needed for separators between CanonicalDir and the filename.
1500 llvm::sys::path::remove_dots(path&: Path);
1501
1502 return std::error_code();
1503}
1504
1505void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1506 FileEntryRef ModuleMap) {
1507 AdditionalModMaps[M].insert(V: ModuleMap);
1508}
1509
1510LLVM_DUMP_METHOD void ModuleMap::dump() {
1511 llvm::errs() << "Modules:";
1512 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1513 MEnd = Modules.end();
1514 M != MEnd; ++M)
1515 M->getValue()->print(OS&: llvm::errs(), Indent: 2);
1516
1517 llvm::errs() << "Headers:";
1518 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1519 H != HEnd; ++H) {
1520 llvm::errs() << " \"" << H->first.getName() << "\" -> ";
1521 for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
1522 E = H->second.end();
1523 I != E; ++I) {
1524 if (I != H->second.begin())
1525 llvm::errs() << ",";
1526 llvm::errs() << I->getModule()->getFullModuleName();
1527 }
1528 llvm::errs() << "\n";
1529 }
1530}
1531
1532bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
1533 auto Unresolved = std::move(Mod->UnresolvedExports);
1534 Mod->UnresolvedExports.clear();
1535 for (auto &UE : Unresolved) {
1536 Module::ExportDecl Export = resolveExport(Mod, Unresolved: UE, Complain);
1537 if (Export.getPointer() || Export.getInt())
1538 Mod->Exports.push_back(Elt: Export);
1539 else
1540 Mod->UnresolvedExports.push_back(Elt: UE);
1541 }
1542 return !Mod->UnresolvedExports.empty();
1543}
1544
1545bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1546 auto *Top = Mod->getTopLevelModule();
1547 auto Unresolved = std::move(Top->UnresolvedDirectUses);
1548 Top->UnresolvedDirectUses.clear();
1549 for (auto &UDU : Unresolved) {
1550 Module *DirectUse = resolveModuleId(Id: UDU, Mod: Top, Complain);
1551 if (DirectUse)
1552 Top->DirectUses.push_back(Elt: DirectUse);
1553 else
1554 Top->UnresolvedDirectUses.push_back(Elt: UDU);
1555 }
1556 return !Top->UnresolvedDirectUses.empty();
1557}
1558
1559bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
1560 auto Unresolved = std::move(Mod->UnresolvedConflicts);
1561 Mod->UnresolvedConflicts.clear();
1562 for (auto &UC : Unresolved) {
1563 if (Module *OtherMod = resolveModuleId(Id: UC.Id, Mod, Complain)) {
1564 Module::Conflict Conflict;
1565 Conflict.Other = OtherMod;
1566 Conflict.Message = UC.Message;
1567 Mod->Conflicts.push_back(x: Conflict);
1568 } else
1569 Mod->UnresolvedConflicts.push_back(x: UC);
1570 }
1571 return !Mod->UnresolvedConflicts.empty();
1572}
1573
1574//----------------------------------------------------------------------------//
1575// Module map file loader
1576//----------------------------------------------------------------------------//
1577
1578namespace clang {
1579class ModuleMapLoader {
1580 SourceManager &SourceMgr;
1581
1582 DiagnosticsEngine &Diags;
1583 ModuleMap &Map;
1584
1585 /// The current module map file.
1586 FileID ModuleMapFID;
1587
1588 /// Source location of most recent loaded module declaration
1589 SourceLocation CurrModuleDeclLoc;
1590
1591 /// The directory that file names in this module map file should
1592 /// be resolved relative to.
1593 DirectoryEntryRef Directory;
1594
1595 /// Whether this module map is in a system header directory.
1596 bool IsSystem;
1597
1598 bool ImplicitlyDiscovered;
1599
1600 /// Whether an error occurred.
1601 bool HadError = false;
1602
1603 /// The active module.
1604 Module *ActiveModule = nullptr;
1605
1606 /// Whether a module uses the 'requires excluded' hack to mark its
1607 /// contents as 'textual'.
1608 ///
1609 /// On older Darwin SDK versions, 'requires excluded' is used to mark the
1610 /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
1611 /// non-modular headers. For backwards compatibility, we continue to
1612 /// support this idiom for just these modules, and map the headers to
1613 /// 'textual' to match the original intent.
1614 llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
1615
1616 void handleModuleDecl(const modulemap::ModuleDecl &MD);
1617 void handleExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
1618 void handleRequiresDecl(const modulemap::RequiresDecl &RD);
1619 void handleHeaderDecl(const modulemap::HeaderDecl &HD);
1620 void handleUmbrellaDirDecl(const modulemap::UmbrellaDirDecl &UDD);
1621 void handleExportDecl(const modulemap::ExportDecl &ED);
1622 void handleExportAsDecl(const modulemap::ExportAsDecl &EAD);
1623 void handleUseDecl(const modulemap::UseDecl &UD);
1624 void handleLinkDecl(const modulemap::LinkDecl &LD);
1625 void handleConfigMacros(const modulemap::ConfigMacrosDecl &CMD);
1626 void handleConflict(const modulemap::ConflictDecl &CD);
1627 void handleInferredModuleDecl(const modulemap::ModuleDecl &MD);
1628
1629 /// Private modules are canonicalized as Foo_Private. Clang provides extra
1630 /// module map search logic to find the appropriate private module when PCH
1631 /// is used with implicit module maps. Warn when private modules are written
1632 /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
1633 void diagnosePrivateModules(SourceLocation StartLoc);
1634
1635 using Attributes = ModuleMap::Attributes;
1636
1637public:
1638 ModuleMapLoader(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
1639 ModuleMap &Map, FileID ModuleMapFID,
1640 DirectoryEntryRef Directory, bool IsSystem,
1641 bool ImplicitlyDiscovered)
1642 : SourceMgr(SourceMgr), Diags(Diags), Map(Map),
1643 ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem),
1644 ImplicitlyDiscovered(ImplicitlyDiscovered) {}
1645
1646 bool loadModuleDecl(const modulemap::ModuleDecl &MD);
1647 bool loadExternModuleDecl(const modulemap::ExternModuleDecl &EMD);
1648 bool parseAndLoadModuleMapFile(const modulemap::ModuleMapFile &MMF);
1649};
1650
1651} // namespace clang
1652
1653/// Private modules are canonicalized as Foo_Private. Clang provides extra
1654/// module map search logic to find the appropriate private module when PCH
1655/// is used with implicit module maps. Warn when private modules are written
1656/// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
1657void ModuleMapLoader::diagnosePrivateModules(SourceLocation StartLoc) {
1658 auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1659 const Module *M, SourceRange ReplLoc) {
1660 auto D = Diags.Report(Loc: ActiveModule->DefinitionLoc,
1661 DiagID: diag::note_mmap_rename_top_level_private_module);
1662 D << BadName << M->Name;
1663 D << FixItHint::CreateReplacement(RemoveRange: ReplLoc, Code: Canonical);
1664 };
1665
1666 for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1667 auto const *M = E->getValue();
1668 if (M->Directory != ActiveModule->Directory)
1669 continue;
1670
1671 SmallString<128> FullName(ActiveModule->getFullModuleName());
1672 if (!FullName.starts_with(Prefix: M->Name) && !FullName.ends_with(Suffix: "Private"))
1673 continue;
1674 SmallString<128> FixedPrivModDecl;
1675 SmallString<128> Canonical(M->Name);
1676 Canonical.append(RHS: "_Private");
1677
1678 // Foo.Private -> Foo_Private
1679 if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
1680 M->Name == ActiveModule->Parent->Name) {
1681 Diags.Report(Loc: ActiveModule->DefinitionLoc,
1682 DiagID: diag::warn_mmap_mismatched_private_submodule)
1683 << FullName;
1684
1685 SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1686 if (StartLoc.isValid())
1687 FixItInitBegin = StartLoc;
1688
1689 if (ActiveModule->Parent->IsFramework)
1690 FixedPrivModDecl.append(RHS: "framework ");
1691 FixedPrivModDecl.append(RHS: "module ");
1692 FixedPrivModDecl.append(RHS: Canonical);
1693
1694 GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1695 SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1696 continue;
1697 }
1698
1699 // FooPrivate and whatnots -> Foo_Private
1700 if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1701 ActiveModule->Name != Canonical) {
1702 Diags.Report(Loc: ActiveModule->DefinitionLoc,
1703 DiagID: diag::warn_mmap_mismatched_private_module_name)
1704 << ActiveModule->Name;
1705 GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1706 SourceRange(ActiveModule->DefinitionLoc));
1707 }
1708 }
1709}
1710
1711void ModuleMapLoader::handleModuleDecl(const modulemap::ModuleDecl &MD) {
1712 if (MD.Id.front().first == "*")
1713 return handleInferredModuleDecl(MD);
1714
1715 CurrModuleDeclLoc = MD.Location;
1716
1717 Module *PreviousActiveModule = ActiveModule;
1718 if (MD.Id.size() > 1) {
1719 // This module map defines a submodule. Go find the module of which it
1720 // is a submodule.
1721 ActiveModule = nullptr;
1722 const Module *TopLevelModule = nullptr;
1723 for (unsigned I = 0, N = MD.Id.size() - 1; I != N; ++I) {
1724 if (Module *Next =
1725 Map.lookupModuleQualified(Name: MD.Id[I].first, Context: ActiveModule)) {
1726 if (I == 0)
1727 TopLevelModule = Next;
1728 ActiveModule = Next;
1729 continue;
1730 }
1731
1732 Diags.Report(Loc: MD.Id[I].second, DiagID: diag::err_mmap_missing_parent_module)
1733 << MD.Id[I].first << (ActiveModule != nullptr)
1734 << (ActiveModule
1735 ? ActiveModule->getTopLevelModule()->getFullModuleName()
1736 : "");
1737 HadError = true;
1738 }
1739
1740 if (TopLevelModule &&
1741 ModuleMapFID != Map.getContainingModuleMapFileID(Module: TopLevelModule)) {
1742 assert(ModuleMapFID !=
1743 Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
1744 "submodule defined in same file as 'module *' that allowed its "
1745 "top-level module");
1746 Map.addAdditionalModuleMapFile(
1747 M: TopLevelModule, ModuleMap: *SourceMgr.getFileEntryRefForID(FID: ModuleMapFID));
1748 }
1749 }
1750
1751 StringRef ModuleName = MD.Id.back().first;
1752 SourceLocation ModuleNameLoc = MD.Id.back().second;
1753
1754 // Determine whether this (sub)module has already been defined.
1755 Module *ShadowingModule = nullptr;
1756 if (Module *Existing = Map.lookupModuleQualified(Name: ModuleName, Context: ActiveModule)) {
1757 // We might see a (re)definition of a module that we already have a
1758 // definition for in four cases:
1759 // - If we loaded one definition from an AST file and we've just found a
1760 // corresponding definition in a module map file, or
1761 bool LoadedFromASTFile = Existing->IsFromModuleFile;
1762 // - If we previously inferred this module from different module map file.
1763 bool Inferred = Existing->IsInferred;
1764 // - If we're building a framework that vends a module map, we might've
1765 // previously seen the one in intermediate products and now the system
1766 // one.
1767 // FIXME: If we're parsing module map file that looks like this:
1768 // framework module FW { ... }
1769 // module FW.Sub { ... }
1770 // We can't check the framework qualifier, since it's not attached to
1771 // the definition of Sub. Checking that qualifier on \c Existing is
1772 // not correct either, since we might've previously seen:
1773 // module FW { ... }
1774 // module FW.Sub { ... }
1775 // We should enforce consistency of redefinitions so that we can rely
1776 // that \c Existing is part of a framework iff the redefinition of FW
1777 // we have just skipped had it too. Once we do that, stop checking
1778 // the local framework qualifier and only rely on \c Existing.
1779 bool PartOfFramework = MD.Framework || Existing->isPartOfFramework();
1780 // - If we're building a (preprocessed) module and we've just loaded the
1781 // module map file from which it was created.
1782 bool ParsedAsMainInput =
1783 Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
1784 Map.LangOpts.CurrentModule == ModuleName &&
1785 SourceMgr.getDecomposedLoc(Loc: ModuleNameLoc).first !=
1786 SourceMgr.getDecomposedLoc(Loc: Existing->DefinitionLoc).first;
1787 // TODO: Remove this check when we can avoid loading module maps multiple
1788 // times.
1789 bool SameModuleDecl = ModuleNameLoc == Existing->DefinitionLoc;
1790 if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput ||
1791 SameModuleDecl) {
1792 ActiveModule = PreviousActiveModule;
1793 // Skip the module definition.
1794 return;
1795 }
1796
1797 if (!Existing->Parent && Map.mayShadowNewModule(ExistingModule: Existing)) {
1798 ShadowingModule = Existing;
1799 } else {
1800 // This is not a shawdowed module decl, it is an illegal redefinition.
1801 Diags.Report(Loc: ModuleNameLoc, DiagID: diag::err_mmap_module_redefinition)
1802 << ModuleName;
1803 Diags.Report(Loc: Existing->DefinitionLoc, DiagID: diag::note_mmap_prev_definition);
1804 HadError = true;
1805 return;
1806 }
1807 }
1808
1809 // Start defining this module.
1810 if (ShadowingModule) {
1811 ActiveModule =
1812 Map.createShadowedModule(Name: ModuleName, IsFramework: MD.Framework, ShadowingModule);
1813 } else {
1814 ActiveModule = Map.findOrCreateModuleFirst(Name: ModuleName, Parent: ActiveModule,
1815 IsFramework: MD.Framework, IsExplicit: MD.Explicit);
1816 }
1817
1818 ActiveModule->DefinitionLoc = ModuleNameLoc;
1819 if (MD.Attrs.IsSystem || IsSystem)
1820 ActiveModule->IsSystem = true;
1821 if (MD.Attrs.IsExternC)
1822 ActiveModule->IsExternC = true;
1823 if (MD.Attrs.NoUndeclaredIncludes)
1824 ActiveModule->NoUndeclaredIncludes = true;
1825 ActiveModule->Directory = Directory;
1826
1827 StringRef MapFileName(
1828 SourceMgr.getFileEntryRefForID(FID: ModuleMapFID)->getName());
1829 if (MapFileName.ends_with(Suffix: "module.private.modulemap") ||
1830 MapFileName.ends_with(Suffix: "module_private.map")) {
1831 ActiveModule->ModuleMapIsPrivate = true;
1832 }
1833
1834 // Private modules named as FooPrivate, Foo.Private or similar are likely a
1835 // user error; provide warnings, notes and fixits to direct users to use
1836 // Foo_Private instead.
1837 SourceLocation StartLoc =
1838 SourceMgr.getLocForStartOfFile(FID: SourceMgr.getMainFileID());
1839 if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
1840 !Diags.isIgnored(DiagID: diag::warn_mmap_mismatched_private_submodule,
1841 Loc: StartLoc) &&
1842 !Diags.isIgnored(DiagID: diag::warn_mmap_mismatched_private_module_name,
1843 Loc: StartLoc) &&
1844 ActiveModule->ModuleMapIsPrivate)
1845 diagnosePrivateModules(StartLoc: MD.Location);
1846
1847 for (const modulemap::Decl &Decl : MD.Decls) {
1848 std::visit(
1849 visitor: llvm::makeVisitor(
1850 Callables: [&](const modulemap::RequiresDecl &RD) { handleRequiresDecl(RD); },
1851 Callables: [&](const modulemap::HeaderDecl &HD) { handleHeaderDecl(HD); },
1852 Callables: [&](const modulemap::UmbrellaDirDecl &UDD) {
1853 handleUmbrellaDirDecl(UDD);
1854 },
1855 Callables: [&](const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
1856 Callables: [&](const modulemap::ExportDecl &ED) { handleExportDecl(ED); },
1857 Callables: [&](const modulemap::ExportAsDecl &EAD) {
1858 handleExportAsDecl(EAD);
1859 },
1860 Callables: [&](const modulemap::ExternModuleDecl &EMD) {
1861 handleExternModuleDecl(EMD);
1862 },
1863 Callables: [&](const modulemap::UseDecl &UD) { handleUseDecl(UD); },
1864 Callables: [&](const modulemap::LinkDecl &LD) { handleLinkDecl(LD); },
1865 Callables: [&](const modulemap::ConfigMacrosDecl &CMD) {
1866 handleConfigMacros(CMD);
1867 },
1868 Callables: [&](const modulemap::ConflictDecl &CD) { handleConflict(CD); },
1869 Callables: [&](const modulemap::ExcludeDecl &ED) {
1870 Diags.Report(Loc: ED.Location, DiagID: diag::err_mmap_expected_member);
1871 }),
1872 variants: Decl);
1873 }
1874
1875 // If the active module is a top-level framework, and there are no link
1876 // libraries, automatically link against the framework.
1877 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
1878 ActiveModule->LinkLibraries.empty())
1879 inferFrameworkLink(Mod: ActiveModule);
1880
1881 // If the module meets all requirements but is still unavailable, mark the
1882 // whole tree as unavailable to prevent it from building.
1883 if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
1884 ActiveModule->Parent) {
1885 ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
1886 ActiveModule->getTopLevelModule()->MissingHeaders.append(
1887 in_start: ActiveModule->MissingHeaders.begin(), in_end: ActiveModule->MissingHeaders.end());
1888 }
1889
1890 // We're done parsing this module. Pop back to the previous module.
1891 ActiveModule = PreviousActiveModule;
1892}
1893
1894void ModuleMapLoader::handleExternModuleDecl(
1895 const modulemap::ExternModuleDecl &EMD) {
1896 StringRef FileNameRef = EMD.Path;
1897 SmallString<128> ModuleMapFileName;
1898 if (llvm::sys::path::is_relative(path: FileNameRef)) {
1899 ModuleMapFileName += Directory.getName();
1900 llvm::sys::path::append(path&: ModuleMapFileName, a: EMD.Path);
1901 FileNameRef = ModuleMapFileName;
1902 }
1903 if (auto File = SourceMgr.getFileManager().getOptionalFileRef(Filename: FileNameRef))
1904 Map.parseAndLoadModuleMapFile(
1905 File: *File, IsSystem, ImplicitlyDiscovered,
1906 HomeDir: Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
1907 ? Directory
1908 : File->getDir(),
1909 ID: FileID(), Offset: nullptr, ExternModuleLoc: EMD.Location);
1910}
1911
1912/// Whether to add the requirement \p Feature to the module \p M.
1913///
1914/// This preserves backwards compatibility for two hacks in the Darwin system
1915/// module map files:
1916///
1917/// 1. The use of 'requires excluded' to make headers non-modular, which
1918/// should really be mapped to 'textual' now that we have this feature. We
1919/// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
1920/// true. Later, this bit will be used to map all the headers inside this
1921/// module to 'textual'.
1922///
1923/// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
1924///
1925/// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
1926/// was never correct and causes issues now that we check it, so drop it.
1927static bool shouldAddRequirement(Module *M, StringRef Feature,
1928 bool &IsRequiresExcludedHack) {
1929 if (Feature == "excluded" &&
1930 (M->fullModuleNameIs(nameParts: {"Darwin", "C", "excluded"}) ||
1931 M->fullModuleNameIs(nameParts: {"Tcl", "Private"}))) {
1932 IsRequiresExcludedHack = true;
1933 return false;
1934 } else if (Feature == "cplusplus" && M->fullModuleNameIs(nameParts: {"IOKit", "avc"})) {
1935 return false;
1936 }
1937
1938 return true;
1939}
1940
1941void ModuleMapLoader::handleRequiresDecl(const modulemap::RequiresDecl &RD) {
1942
1943 for (const modulemap::RequiresFeature &RF : RD.Features) {
1944 bool IsRequiresExcludedHack = false;
1945 bool ShouldAddRequirement =
1946 shouldAddRequirement(M: ActiveModule, Feature: RF.Feature, IsRequiresExcludedHack);
1947
1948 if (IsRequiresExcludedHack)
1949 UsesRequiresExcludedHack.insert(Ptr: ActiveModule);
1950
1951 if (ShouldAddRequirement) {
1952 // Add this feature.
1953 ActiveModule->addRequirement(Feature: RF.Feature, RequiredState: RF.RequiredState, LangOpts: Map.LangOpts,
1954 Target: *Map.Target);
1955 }
1956 }
1957}
1958
1959void ModuleMapLoader::handleHeaderDecl(const modulemap::HeaderDecl &HD) {
1960 // We've already consumed the first token.
1961 ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
1962
1963 if (HD.Private) {
1964 Role = ModuleMap::PrivateHeader;
1965 } else if (HD.Excluded) {
1966 Role = ModuleMap::ExcludedHeader;
1967 }
1968
1969 if (HD.Textual)
1970 Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
1971
1972 if (UsesRequiresExcludedHack.count(Ptr: ActiveModule)) {
1973 // Mark this header 'textual' (see doc comment for
1974 // Module::UsesRequiresExcludedHack).
1975 Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
1976 }
1977
1978 Module::UnresolvedHeaderDirective Header;
1979 Header.FileName = HD.Path;
1980 Header.FileNameLoc = HD.PathLoc;
1981 Header.IsUmbrella = HD.Umbrella;
1982 Header.Kind = Map.headerRoleToKind(Role);
1983
1984 // Check whether we already have an umbrella.
1985 if (Header.IsUmbrella &&
1986 !std::holds_alternative<std::monostate>(v: ActiveModule->Umbrella)) {
1987 Diags.Report(Loc: Header.FileNameLoc, DiagID: diag::err_mmap_umbrella_clash)
1988 << ActiveModule->getFullModuleName();
1989 HadError = true;
1990 return;
1991 }
1992
1993 if (ImplicitlyDiscovered) {
1994 SmallString<128> NormalizedPath(HD.Path);
1995 llvm::sys::path::remove_dots(path&: NormalizedPath, /*remove_dot_dot=*/true);
1996 if (NormalizedPath.starts_with(Prefix: ".."))
1997 Diags.Report(Loc: HD.PathLoc, DiagID: diag::warn_mmap_path_outside_directory);
1998 }
1999
2000 if (HD.Size)
2001 Header.Size = HD.Size;
2002 if (HD.MTime)
2003 Header.ModTime = HD.MTime;
2004
2005 bool NeedsFramework = false;
2006 // Don't add headers to the builtin modules if the builtin headers belong to
2007 // the system modules, with the exception of __stddef_max_align_t.h which
2008 // always had its own module.
2009 if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2010 !isBuiltInModuleName(ModuleName: ActiveModule->getTopLevelModuleName()) ||
2011 ActiveModule->fullModuleNameIs(nameParts: {"_Builtin_stddef", "max_align_t"}))
2012 Map.addUnresolvedHeader(Mod: ActiveModule, Header: std::move(Header), NeedsFramework);
2013
2014 if (NeedsFramework)
2015 Diags.Report(Loc: CurrModuleDeclLoc, DiagID: diag::note_mmap_add_framework_keyword)
2016 << ActiveModule->getFullModuleName()
2017 << FixItHint::CreateReplacement(RemoveRange: CurrModuleDeclLoc, Code: "framework module");
2018}
2019
2020static bool compareModuleHeaders(const Module::Header &A,
2021 const Module::Header &B) {
2022 return A.NameAsWritten < B.NameAsWritten;
2023}
2024
2025void ModuleMapLoader::handleUmbrellaDirDecl(
2026 const modulemap::UmbrellaDirDecl &UDD) {
2027 std::string DirName = std::string(UDD.Path);
2028 std::string DirNameAsWritten = DirName;
2029
2030 // Check whether we already have an umbrella.
2031 if (!std::holds_alternative<std::monostate>(v: ActiveModule->Umbrella)) {
2032 Diags.Report(Loc: UDD.Location, DiagID: diag::err_mmap_umbrella_clash)
2033 << ActiveModule->getFullModuleName();
2034 HadError = true;
2035 return;
2036 }
2037
2038 if (ImplicitlyDiscovered) {
2039 SmallString<128> NormalizedPath(UDD.Path);
2040 llvm::sys::path::remove_dots(path&: NormalizedPath, /*remove_dot_dot=*/true);
2041 if (NormalizedPath.starts_with(Prefix: ".."))
2042 Diags.Report(Loc: UDD.Location, DiagID: diag::warn_mmap_path_outside_directory);
2043 }
2044
2045 // Look for this file.
2046 OptionalDirectoryEntryRef Dir;
2047 if (llvm::sys::path::is_absolute(path: DirName)) {
2048 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2049 } else {
2050 SmallString<128> PathName;
2051 PathName = Directory.getName();
2052 llvm::sys::path::append(path&: PathName, a: DirName);
2053 Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName: PathName);
2054 }
2055
2056 if (!Dir) {
2057 Diags.Report(Loc: UDD.Location, DiagID: diag::warn_mmap_umbrella_dir_not_found)
2058 << DirName;
2059 return;
2060 }
2061
2062 if (UsesRequiresExcludedHack.count(Ptr: ActiveModule)) {
2063 // Mark this header 'textual' (see doc comment for
2064 // ModuleMapLoader::UsesRequiresExcludedHack). Although iterating over the
2065 // directory is relatively expensive, in practice this only applies to the
2066 // uncommonly used Tcl module on Darwin platforms.
2067 std::error_code EC;
2068 SmallVector<Module::Header, 6> Headers;
2069 llvm::vfs::FileSystem &FS =
2070 SourceMgr.getFileManager().getVirtualFileSystem();
2071 for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
2072 I != E && !EC; I.increment(EC)) {
2073 if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(Filename: I->path())) {
2074 Module::Header Header = {.NameAsWritten: "", .PathRelativeToRootModuleDirectory: std::string(I->path()), .Entry: *FE};
2075 Headers.push_back(Elt: std::move(Header));
2076 }
2077 }
2078
2079 // Sort header paths so that the pcm doesn't depend on iteration order.
2080 llvm::stable_sort(Range&: Headers, C: compareModuleHeaders);
2081
2082 for (auto &Header : Headers)
2083 Map.addHeader(Mod: ActiveModule, Header: std::move(Header), Role: ModuleMap::TextualHeader);
2084 return;
2085 }
2086
2087 if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2088 Diags.Report(Loc: UDD.Location, DiagID: diag::err_mmap_umbrella_clash)
2089 << OwningModule->getFullModuleName();
2090 HadError = true;
2091 return;
2092 }
2093
2094 // Record this umbrella directory.
2095 Map.setUmbrellaDirAsWritten(Mod: ActiveModule, UmbrellaDir: *Dir, NameAsWritten: DirNameAsWritten, PathRelativeToRootModuleDirectory: DirName);
2096}
2097
2098void ModuleMapLoader::handleExportDecl(const modulemap::ExportDecl &ED) {
2099 Module::UnresolvedExportDecl Unresolved = {.ExportLoc: ED.Location, .Id: ED.Id, .Wildcard: ED.Wildcard};
2100 ActiveModule->UnresolvedExports.push_back(Elt: Unresolved);
2101}
2102
2103void ModuleMapLoader::handleExportAsDecl(const modulemap::ExportAsDecl &EAD) {
2104 const auto &ModName = EAD.Id.front();
2105
2106 if (!ActiveModule->ExportAsModule.empty()) {
2107 if (ActiveModule->ExportAsModule == ModName.first) {
2108 Diags.Report(Loc: ModName.second, DiagID: diag::warn_mmap_redundant_export_as)
2109 << ActiveModule->Name << ModName.first;
2110 } else {
2111 Diags.Report(Loc: ModName.second, DiagID: diag::err_mmap_conflicting_export_as)
2112 << ActiveModule->Name << ActiveModule->ExportAsModule
2113 << ModName.first;
2114 }
2115 }
2116
2117 ActiveModule->ExportAsModule = ModName.first;
2118 Map.addLinkAsDependency(Mod: ActiveModule);
2119}
2120
2121void ModuleMapLoader::handleUseDecl(const modulemap::UseDecl &UD) {
2122 if (ActiveModule->Parent)
2123 Diags.Report(Loc: UD.Location, DiagID: diag::err_mmap_use_decl_submodule);
2124 else
2125 ActiveModule->UnresolvedDirectUses.push_back(Elt: UD.Id);
2126}
2127
2128void ModuleMapLoader::handleLinkDecl(const modulemap::LinkDecl &LD) {
2129 ActiveModule->LinkLibraries.push_back(
2130 Elt: Module::LinkLibrary(std::string{LD.Library}, LD.Framework));
2131}
2132
2133void ModuleMapLoader::handleConfigMacros(
2134 const modulemap::ConfigMacrosDecl &CMD) {
2135 if (ActiveModule->Parent) {
2136 Diags.Report(Loc: CMD.Location, DiagID: diag::err_mmap_config_macro_submodule);
2137 return;
2138 }
2139
2140 // TODO: Is this really the behavior we want for multiple config_macros
2141 // declarations? If any of them are exhaustive then all of them are.
2142 if (CMD.Exhaustive) {
2143 ActiveModule->ConfigMacrosExhaustive = true;
2144 }
2145 ActiveModule->ConfigMacros.insert(position: ActiveModule->ConfigMacros.end(),
2146 first: CMD.Macros.begin(), last: CMD.Macros.end());
2147}
2148
2149void ModuleMapLoader::handleConflict(const modulemap::ConflictDecl &CD) {
2150 Module::UnresolvedConflict Conflict;
2151
2152 Conflict.Id = CD.Id;
2153 Conflict.Message = CD.Message;
2154
2155 // FIXME: when we move to C++20 we should consider using emplace_back
2156 ActiveModule->UnresolvedConflicts.push_back(x: std::move(Conflict));
2157}
2158
2159void ModuleMapLoader::handleInferredModuleDecl(
2160 const modulemap::ModuleDecl &MD) {
2161 SourceLocation StarLoc = MD.Id.front().second;
2162
2163 // Inferred modules must be submodules.
2164 if (!ActiveModule && !MD.Framework) {
2165 Diags.Report(Loc: StarLoc, DiagID: diag::err_mmap_top_level_inferred_submodule);
2166 return;
2167 }
2168
2169 if (ActiveModule) {
2170 // Inferred modules must have umbrella directories.
2171 if (ActiveModule->IsAvailable && !ActiveModule->getEffectiveUmbrellaDir()) {
2172 Diags.Report(Loc: StarLoc, DiagID: diag::err_mmap_inferred_no_umbrella);
2173 return;
2174 }
2175
2176 // Check for redefinition of an inferred module.
2177 if (ActiveModule->InferSubmodules) {
2178 Diags.Report(Loc: StarLoc, DiagID: diag::err_mmap_inferred_redef);
2179 if (ActiveModule->InferredSubmoduleLoc.isValid())
2180 Diags.Report(Loc: ActiveModule->InferredSubmoduleLoc,
2181 DiagID: diag::note_mmap_prev_definition);
2182 return;
2183 }
2184
2185 // Check for the 'framework' keyword, which is not permitted here.
2186 if (MD.Framework) {
2187 Diags.Report(Loc: StarLoc, DiagID: diag::err_mmap_inferred_framework_submodule);
2188 return;
2189 }
2190 } else if (MD.Explicit) {
2191 Diags.Report(Loc: StarLoc, DiagID: diag::err_mmap_explicit_inferred_framework);
2192 return;
2193 }
2194
2195 if (ActiveModule) {
2196 // Note that we have an inferred submodule.
2197 ActiveModule->InferSubmodules = true;
2198 ActiveModule->InferredSubmoduleLoc = StarLoc;
2199 ActiveModule->InferExplicitSubmodules = MD.Explicit;
2200 } else {
2201 // We'll be inferring framework modules for this directory.
2202 auto &InfDir = Map.InferredDirectories[Directory];
2203 InfDir.InferModules = true;
2204 InfDir.Attrs = MD.Attrs;
2205 InfDir.ModuleMapFID = ModuleMapFID;
2206 // FIXME: Handle the 'framework' keyword.
2207 }
2208
2209 for (const modulemap::Decl &Decl : MD.Decls) {
2210 std::visit(
2211 visitor: llvm::makeVisitor(
2212 Callables: [&](const auto &Other) {
2213 Diags.Report(Other.Location,
2214 diag::err_mmap_expected_inferred_member)
2215 << (ActiveModule != nullptr);
2216 },
2217 Callables: [&](const modulemap::ExcludeDecl &ED) {
2218 // Only inferred frameworks can have exclude decls
2219 if (ActiveModule) {
2220 Diags.Report(Loc: ED.Location,
2221 DiagID: diag::err_mmap_expected_inferred_member)
2222 << (ActiveModule != nullptr);
2223 HadError = true;
2224 return;
2225 }
2226 Map.InferredDirectories[Directory].ExcludedModules.emplace_back(
2227 Args: ED.Module);
2228 },
2229 Callables: [&](const modulemap::ExportDecl &ED) {
2230 // Only inferred submodules can have export decls
2231 if (!ActiveModule) {
2232 Diags.Report(Loc: ED.Location,
2233 DiagID: diag::err_mmap_expected_inferred_member)
2234 << (ActiveModule != nullptr);
2235 HadError = true;
2236 return;
2237 }
2238
2239 if (ED.Wildcard && ED.Id.size() == 0)
2240 ActiveModule->InferExportWildcard = true;
2241 else
2242 Diags.Report(Loc: ED.Id.front().second,
2243 DiagID: diag::err_mmap_expected_export_wildcard);
2244 }),
2245 variants: Decl);
2246 }
2247}
2248
2249bool ModuleMapLoader::loadModuleDecl(const modulemap::ModuleDecl &MD) {
2250 handleModuleDecl(MD);
2251 return HadError;
2252}
2253
2254bool ModuleMapLoader::loadExternModuleDecl(
2255 const modulemap::ExternModuleDecl &EMD) {
2256 handleExternModuleDecl(EMD);
2257 return HadError;
2258}
2259
2260bool ModuleMapLoader::parseAndLoadModuleMapFile(
2261 const modulemap::ModuleMapFile &MMF) {
2262 for (const auto &Decl : MMF.Decls) {
2263 std::visit(
2264 visitor: llvm::makeVisitor(
2265 Callables: [&](const modulemap::ModuleDecl &MD) { handleModuleDecl(MD); },
2266 Callables: [&](const modulemap::ExternModuleDecl &EMD) {
2267 handleExternModuleDecl(EMD);
2268 }),
2269 variants: Decl);
2270 }
2271 return HadError;
2272}
2273
2274Module *ModuleMap::findOrLoadModule(StringRef Name) {
2275 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Key: Name);
2276 if (Known != Modules.end())
2277 return Known->getValue();
2278
2279 auto ParsedMod = ParsedModules.find(Key: Name);
2280 if (ParsedMod == ParsedModules.end())
2281 return nullptr;
2282
2283 Diags.Report(DiagID: diag::remark_mmap_load_module) << Name;
2284
2285 for (const auto &ModuleDecl : ParsedMod->second) {
2286 const modulemap::ModuleMapFile &MMF = *ModuleDecl.first;
2287 ModuleMapLoader Loader(SourceMgr, Diags, const_cast<ModuleMap &>(*this),
2288 MMF.ID, *MMF.Dir, MMF.IsSystem,
2289 MMF.ImplicitlyDiscovered);
2290 if (Loader.loadModuleDecl(MD: *ModuleDecl.second))
2291 return nullptr;
2292 }
2293
2294 return findModule(Name);
2295}
2296
2297bool ModuleMap::parseAndLoadModuleMapFile(FileEntryRef File, bool IsSystem,
2298 bool ImplicitlyDiscovered,
2299 DirectoryEntryRef Dir, FileID ID,
2300 unsigned *Offset,
2301 SourceLocation ExternModuleLoc) {
2302 assert(Target && "Missing target information");
2303 llvm::DenseMap<const FileEntry *, bool>::iterator Known =
2304 LoadedModuleMap.find(Val: File);
2305 if (Known != LoadedModuleMap.end())
2306 return Known->second;
2307
2308 // If the module map file wasn't already entered, do so now.
2309 if (ID.isInvalid()) {
2310 // TODO: The way we compute affecting module maps requires this to be a
2311 // local FileID. This should be changed to reuse loaded FileIDs when
2312 // available, and change the way that affecting module maps are
2313 // computed to not require this.
2314 FileID &LocalFID = ModuleMapLocalFileID[File];
2315 if (LocalFID.isInvalid()) {
2316 auto FileCharacter =
2317 IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
2318 LocalFID = SourceMgr.createFileID(SourceFile: File, IncludePos: ExternModuleLoc, FileCharacter);
2319 }
2320 ID = LocalFID;
2321 }
2322
2323 assert(Target && "Missing target information");
2324 std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(FID: ID);
2325 if (!Buffer)
2326 return LoadedModuleMap[File] = true;
2327 assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
2328 "invalid buffer offset");
2329
2330 std::optional<modulemap::ModuleMapFile> MMF = modulemap::parseModuleMap(
2331 ID, Dir, SM&: SourceMgr, Diags, IsSystem, ImplicitlyDiscovered, Offset);
2332 bool Result = false;
2333 if (MMF) {
2334 Diags.Report(DiagID: diag::remark_mmap_load) << File.getName();
2335 ModuleMapLoader Loader(SourceMgr, Diags, *this, ID, Dir, IsSystem,
2336 ImplicitlyDiscovered);
2337 Result = Loader.parseAndLoadModuleMapFile(MMF: *MMF);
2338 }
2339 LoadedModuleMap[File] = Result;
2340
2341 // Notify callbacks that we observed it.
2342 // FIXME: We should only report module maps that were actually used.
2343 for (const auto &Cb : Callbacks)
2344 Cb->moduleMapFileRead(FileStart: MMF ? MMF->Start : SourceLocation(), File, IsSystem);
2345
2346 return Result;
2347}
2348