1//===- Module.cpp - Describe a module -------------------------------------===//
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 Module class, which describes a module in the source
10// code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/Module.h"
15#include "clang/Basic/CharInfo.h"
16#include "clang/Basic/FileManager.h"
17#include "clang/Basic/LangOptions.h"
18#include "clang/Basic/SourceLocation.h"
19#include "clang/Basic/TargetInfo.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/Support/Compiler.h"
26#include "llvm/Support/ErrorHandling.h"
27#include "llvm/Support/raw_ostream.h"
28#include <cassert>
29#include <functional>
30#include <string>
31#include <utility>
32#include <vector>
33
34using namespace clang;
35
36std::optional<ModuleFileKey>
37ModuleFileName::makeKey(FileManager &FileMgr) const {
38 if (ImplicitModuleSuffixLength) {
39 StringRef ModuleCachePath =
40 StringRef(Path).drop_back(N: ImplicitModuleSuffixLength);
41 StringRef ImplicitModuleSuffix =
42 StringRef(Path).take_back(N: ImplicitModuleSuffixLength);
43 if (auto ModuleCache = FileMgr.getOptionalDirectoryRef(
44 DirName: ModuleCachePath, /*CacheFailure=*/false))
45 return ModuleFileKey(*ModuleCache, ImplicitModuleSuffix);
46 } else {
47 if (auto ModuleFile = FileMgr.getOptionalFileRef(Filename: Path, /*OpenFile=*/true,
48 /*CacheFailure=*/false))
49 return ModuleFileKey(*ModuleFile);
50 }
51
52 return std::nullopt;
53}
54
55Module::Module(ModuleConstructorTag, StringRef Name,
56 SourceLocation DefinitionLoc, Module *Parent, bool IsFramework,
57 bool IsExplicit, unsigned VisibilityID)
58 : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
59 VisibilityID(VisibilityID), IsUnimportable(false),
60 HasIncompatibleModuleFile(false), IsAvailable(true),
61 IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),
62 IsSystem(false), IsExternC(false), IsInferred(false),
63 InferSubmodules(false), InferExplicitSubmodules(false),
64 InferExportWildcard(false), ConfigMacrosExhaustive(false),
65 NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
66 NamedModuleHasInit(true), NameVisibility(Hidden) {
67 if (Parent) {
68 IsAvailable = Parent->isAvailable();
69 IsUnimportable = Parent->isUnimportable();
70 IsSystem = Parent->IsSystem;
71 IsExternC = Parent->IsExternC;
72 NoUndeclaredIncludes = Parent->NoUndeclaredIncludes;
73 ModuleMapIsPrivate = Parent->ModuleMapIsPrivate;
74
75 Parent->SubModules.push_back(x: this);
76 }
77}
78
79Module::~Module() = default;
80
81static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
82 StringRef Platform = Target.getPlatformName();
83 StringRef Env = Target.getTriple().getEnvironmentName();
84
85 // Attempt to match platform and environment.
86 if (Platform == Feature || Target.getTriple().getOSName() == Feature ||
87 Env == Feature)
88 return true;
89
90 auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {
91 auto Pos = LHS.find(C: '-');
92 if (Pos == StringRef::npos)
93 return false;
94 SmallString<128> NewLHS = LHS.slice(Start: 0, End: Pos);
95 NewLHS += LHS.slice(Start: Pos+1, End: LHS.size());
96 return NewLHS == RHS;
97 };
98
99 SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName();
100 // Darwin has different but equivalent variants for simulators, example:
101 // 1. x86_64-apple-ios-simulator
102 // 2. x86_64-apple-iossimulator
103 // where both are valid examples of the same platform+environment but in the
104 // variant (2) the simulator is hardcoded as part of the platform name. Both
105 // forms above should match for "iossimulator" requirement.
106 if (Target.getTriple().isOSDarwin() && PlatformEnv.ends_with(Suffix: "simulator"))
107 return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);
108
109 return PlatformEnv == Feature;
110}
111
112/// Determine whether a translation unit built using the current
113/// language options has the given feature.
114static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
115 const TargetInfo &Target) {
116 bool HasFeature = llvm::StringSwitch<bool>(Feature)
117 .Case(S: "altivec", Value: LangOpts.AltiVec)
118 .Case(S: "blocks", Value: LangOpts.Blocks)
119 .Case(S: "coroutines", Value: LangOpts.Coroutines)
120 .Case(S: "cplusplus", Value: LangOpts.CPlusPlus)
121 .Case(S: "cplusplus11", Value: LangOpts.CPlusPlus11)
122 .Case(S: "cplusplus14", Value: LangOpts.CPlusPlus14)
123 .Case(S: "cplusplus17", Value: LangOpts.CPlusPlus17)
124 .Case(S: "cplusplus20", Value: LangOpts.CPlusPlus20)
125 .Case(S: "cplusplus23", Value: LangOpts.CPlusPlus23)
126 .Case(S: "cplusplus26", Value: LangOpts.CPlusPlus26)
127 .Case(S: "c99", Value: LangOpts.C99)
128 .Case(S: "c11", Value: LangOpts.C11)
129 .Case(S: "c17", Value: LangOpts.C17)
130 .Case(S: "c23", Value: LangOpts.C23)
131 .Case(S: "freestanding", Value: LangOpts.Freestanding)
132 .Case(S: "gnuinlineasm", Value: LangOpts.GNUAsm)
133 .Case(S: "objc", Value: LangOpts.ObjC)
134 .Case(S: "objc_arc", Value: LangOpts.ObjCAutoRefCount)
135 .Case(S: "opencl", Value: LangOpts.OpenCL)
136 .Case(S: "tls", Value: Target.isTLSSupported())
137 .Case(S: "zvector", Value: LangOpts.ZVector)
138 .Default(Value: Target.hasFeature(Feature) ||
139 isPlatformEnvironment(Target, Feature));
140 if (!HasFeature)
141 HasFeature = llvm::is_contained(Range: LangOpts.ModuleFeatures, Element: Feature);
142 return HasFeature;
143}
144
145bool Module::isUnimportable(const LangOptions &LangOpts,
146 const TargetInfo &Target, Requirement &Req,
147 Module *&ShadowingModule) const {
148 if (!IsUnimportable)
149 return false;
150
151 for (const Module *Current = this; Current; Current = Current->Parent) {
152 if (Current->ShadowingModule) {
153 ShadowingModule = Current->ShadowingModule;
154 return true;
155 }
156 for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
157 if (hasFeature(Feature: Current->Requirements[I].FeatureName, LangOpts, Target) !=
158 Current->Requirements[I].RequiredState) {
159 Req = Current->Requirements[I];
160 return true;
161 }
162 }
163 }
164
165 llvm_unreachable("could not find a reason why module is unimportable");
166}
167
168// The -fmodule-name option tells the compiler to textually include headers in
169// the specified module, meaning Clang won't build the specified module. This
170// is useful in a number of situations, for instance, when building a library
171// that vends a module map, one might want to avoid hitting intermediate build
172// products containing the module map or avoid finding the system installed
173// modulemap for that library.
174bool Module::isForBuilding(const LangOptions &LangOpts) const {
175 StringRef TopLevelName = getTopLevelModuleName();
176 StringRef CurrentModule = LangOpts.CurrentModule;
177
178 // When building the implementation of framework Foo, we want to make sure
179 // that Foo *and* Foo_Private are textually included and no modules are built
180 // for either.
181 if (!LangOpts.isCompilingModule() && getTopLevelModule()->IsFramework &&
182 CurrentModule == LangOpts.ModuleName &&
183 !CurrentModule.ends_with(Suffix: "_Private") &&
184 TopLevelName.ends_with(Suffix: "_Private"))
185 TopLevelName = TopLevelName.drop_back(N: 8);
186
187 return TopLevelName == CurrentModule;
188}
189
190bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
191 Requirement &Req,
192 UnresolvedHeaderDirective &MissingHeader,
193 Module *&ShadowingModule) const {
194 if (IsAvailable)
195 return true;
196
197 if (isUnimportable(LangOpts, Target, Req, ShadowingModule))
198 return false;
199
200 // FIXME: All missing headers are listed on the top-level module. Should we
201 // just look there?
202 for (const Module *Current = this; Current; Current = Current->Parent) {
203 if (!Current->MissingHeaders.empty()) {
204 MissingHeader = Current->MissingHeaders.front();
205 return false;
206 }
207 }
208
209 llvm_unreachable("could not find a reason why module is unavailable");
210}
211
212bool Module::isSubModuleOf(const Module *Other) const {
213 for (auto *Parent = this; Parent; Parent = Parent->Parent) {
214 if (Parent == Other)
215 return true;
216 }
217 return false;
218}
219
220const Module *Module::getTopLevelModule() const {
221 const Module *Result = this;
222 while (Result->Parent)
223 Result = Result->Parent;
224
225 return Result;
226}
227
228static StringRef getModuleNameFromComponent(
229 const std::pair<std::string, SourceLocation> &IdComponent) {
230 return IdComponent.first;
231}
232
233static StringRef getModuleNameFromComponent(StringRef R) { return R; }
234
235template<typename InputIter>
236static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,
237 bool AllowStringLiterals = true) {
238 for (InputIter It = Begin; It != End; ++It) {
239 if (It != Begin)
240 OS << ".";
241
242 StringRef Name = getModuleNameFromComponent(*It);
243 if (!AllowStringLiterals || isValidAsciiIdentifier(S: Name))
244 OS << Name;
245 else {
246 OS << '"';
247 OS.write_escaped(Str: Name);
248 OS << '"';
249 }
250 }
251}
252
253template<typename Container>
254static void printModuleId(raw_ostream &OS, const Container &C) {
255 return printModuleId(OS, C.begin(), C.end());
256}
257
258std::string Module::getFullModuleName(bool AllowStringLiterals) const {
259 SmallVector<StringRef, 2> Names;
260
261 // Build up the set of module names (from innermost to outermost).
262 for (const Module *M = this; M; M = M->Parent)
263 Names.push_back(Elt: M->Name);
264
265 std::string Result;
266
267 llvm::raw_string_ostream Out(Result);
268 printModuleId(OS&: Out, Begin: Names.rbegin(), End: Names.rend(), AllowStringLiterals);
269
270 return Result;
271}
272
273bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
274 for (const Module *M = this; M; M = M->Parent) {
275 if (nameParts.empty() || M->Name != nameParts.back())
276 return false;
277 nameParts = nameParts.drop_back();
278 }
279 return nameParts.empty();
280}
281
282OptionalDirectoryEntryRef Module::getEffectiveUmbrellaDir() const {
283 if (const auto *Hdr = std::get_if<FileEntryRef>(ptr: &Umbrella))
284 return Hdr->getDir();
285 if (const auto *Dir = std::get_if<DirectoryEntryRef>(ptr: &Umbrella))
286 return *Dir;
287 return std::nullopt;
288}
289
290void Module::addTopHeader(FileEntryRef File) {
291 assert(File);
292 TopHeaders.insert(X: File);
293}
294
295ArrayRef<FileEntryRef> Module::getTopHeaders(FileManager &FileMgr) {
296 if (!TopHeaderNames.empty()) {
297 for (StringRef TopHeaderName : TopHeaderNames)
298 if (auto FE = FileMgr.getOptionalFileRef(Filename: TopHeaderName))
299 TopHeaders.insert(X: *FE);
300 TopHeaderNames.clear();
301 }
302
303 return llvm::ArrayRef(TopHeaders.begin(), TopHeaders.end());
304}
305
306bool Module::directlyUses(const Module *Requested) {
307 auto *Top = getTopLevelModule();
308
309 // A top-level module implicitly uses itself.
310 if (Requested->isSubModuleOf(Other: Top))
311 return true;
312
313 for (auto *Use : Top->DirectUses)
314 if (Requested->isSubModuleOf(Other: Use))
315 return true;
316
317 // Anyone is allowed to use our builtin stddef.h and its accompanying modules.
318 if (Requested->fullModuleNameIs(nameParts: {"_Builtin_stddef", "max_align_t"}) ||
319 Requested->fullModuleNameIs(nameParts: {"_Builtin_stddef_wint_t"}))
320 return true;
321 // Darwin is allowed is to use our builtin 'ptrauth.h' and its accompanying
322 // module.
323 if (!Requested->Parent && Requested->Name == "ptrauth")
324 return true;
325
326 if (NoUndeclaredIncludes)
327 UndeclaredUses.insert(X: Requested);
328
329 return false;
330}
331
332void Module::addRequirement(StringRef Feature, bool RequiredState,
333 const LangOptions &LangOpts,
334 const TargetInfo &Target) {
335 Requirements.push_back(Elt: Requirement{.FeatureName: std::string(Feature), .RequiredState: RequiredState});
336
337 // If this feature is currently available, we're done.
338 if (hasFeature(Feature, LangOpts, Target) == RequiredState)
339 return;
340
341 markUnavailable(/*Unimportable*/true);
342}
343
344void Module::markUnavailable(bool Unimportable) {
345 auto needUpdate = [Unimportable](Module *M) {
346 return M->IsAvailable || (!M->IsUnimportable && Unimportable);
347 };
348
349 if (!needUpdate(this))
350 return;
351
352 SmallVector<Module *, 2> Stack;
353 Stack.push_back(Elt: this);
354 while (!Stack.empty()) {
355 Module *Current = Stack.pop_back_val();
356
357 if (!needUpdate(Current))
358 continue;
359
360 Current->IsAvailable = false;
361 Current->IsUnimportable |= Unimportable;
362 for (auto *Submodule : Current->submodules()) {
363 if (needUpdate(Submodule))
364 Stack.push_back(Elt: Submodule);
365 }
366 }
367}
368
369Module *Module::findSubmodule(StringRef Name) const {
370 // Add new submodules into the index.
371 for (unsigned I = SubModuleIndex.size(), E = SubModules.size(); I != E; ++I)
372 SubModuleIndex[SubModules[I]->Name] = I;
373
374 if (auto It = SubModuleIndex.find(Key: Name); It != SubModuleIndex.end())
375 return SubModules[It->second];
376
377 return nullptr;
378}
379
380Module *Module::getGlobalModuleFragment() const {
381 assert(isNamedModuleUnit() && "We should only query the global module "
382 "fragment from the C++20 Named modules");
383
384 for (auto *SubModule : SubModules)
385 if (SubModule->isExplicitGlobalModule())
386 return SubModule;
387
388 return nullptr;
389}
390
391Module *Module::getPrivateModuleFragment() const {
392 assert(isNamedModuleUnit() && "We should only query the private module "
393 "fragment from the C++20 Named modules");
394
395 for (auto *SubModule : SubModules)
396 if (SubModule->isPrivateModule())
397 return SubModule;
398
399 return nullptr;
400}
401
402void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
403 // All non-explicit submodules are exported.
404 for (std::vector<Module *>::const_iterator I = SubModules.begin(),
405 E = SubModules.end();
406 I != E; ++I) {
407 Module *Mod = *I;
408 if (!Mod->IsExplicit)
409 Exported.push_back(Elt: Mod);
410 }
411
412 // Find re-exported modules by filtering the list of imported modules.
413 bool AnyWildcard = false;
414 bool UnrestrictedWildcard = false;
415 SmallVector<Module *, 4> WildcardRestrictions;
416 for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
417 Module *Mod = Exports[I].getPointer();
418 if (!Exports[I].getInt()) {
419 // Export a named module directly; no wildcards involved.
420 Exported.push_back(Elt: Mod);
421
422 continue;
423 }
424
425 // Wildcard export: export all of the imported modules that match
426 // the given pattern.
427 AnyWildcard = true;
428 if (UnrestrictedWildcard)
429 continue;
430
431 if (Module *Restriction = Exports[I].getPointer())
432 WildcardRestrictions.push_back(Elt: Restriction);
433 else {
434 WildcardRestrictions.clear();
435 UnrestrictedWildcard = true;
436 }
437 }
438
439 // If there were any wildcards, push any imported modules that were
440 // re-exported by the wildcard restriction.
441 if (!AnyWildcard)
442 return;
443
444 for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
445 Module *Mod = Imports[I];
446 bool Acceptable = UnrestrictedWildcard;
447 if (!Acceptable) {
448 // Check whether this module meets one of the restrictions.
449 for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
450 Module *Restriction = WildcardRestrictions[R];
451 if (Mod == Restriction || Mod->isSubModuleOf(Other: Restriction)) {
452 Acceptable = true;
453 break;
454 }
455 }
456 }
457
458 if (!Acceptable)
459 continue;
460
461 Exported.push_back(Elt: Mod);
462 }
463}
464
465void Module::buildVisibleModulesCache() const {
466 assert(VisibleModulesCache.empty() && "cache does not need building");
467
468 // This module is visible to itself.
469 VisibleModulesCache.insert(V: this);
470
471 // Every imported module is visible.
472 SmallVector<Module *, 16> Stack(Imports.begin(), Imports.end());
473 while (!Stack.empty()) {
474 Module *CurrModule = Stack.pop_back_val();
475
476 // Every module transitively exported by an imported module is visible.
477 if (VisibleModulesCache.insert(V: CurrModule).second)
478 CurrModule->getExportedModules(Exported&: Stack);
479 }
480}
481
482void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
483 OS.indent(NumSpaces: Indent);
484 if (IsFramework)
485 OS << "framework ";
486 if (IsExplicit)
487 OS << "explicit ";
488 OS << "module ";
489 printModuleId(OS, Begin: &Name, End: &Name + 1);
490
491 if (IsSystem || IsExternC) {
492 OS.indent(NumSpaces: Indent + 2);
493 if (IsSystem)
494 OS << " [system]";
495 if (IsExternC)
496 OS << " [extern_c]";
497 }
498
499 OS << " {\n";
500
501 if (!Requirements.empty()) {
502 OS.indent(NumSpaces: Indent + 2);
503 OS << "requires ";
504 for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {
505 if (I)
506 OS << ", ";
507 if (!Requirements[I].RequiredState)
508 OS << "!";
509 OS << Requirements[I].FeatureName;
510 }
511 OS << "\n";
512 }
513
514 if (std::optional<Header> H = getUmbrellaHeaderAsWritten()) {
515 OS.indent(NumSpaces: Indent + 2);
516 OS << "umbrella header \"";
517 OS.write_escaped(Str: H->NameAsWritten);
518 OS << "\"\n";
519 } else if (std::optional<DirectoryName> D = getUmbrellaDirAsWritten()) {
520 OS.indent(NumSpaces: Indent + 2);
521 OS << "umbrella \"";
522 OS.write_escaped(Str: D->NameAsWritten);
523 OS << "\"\n";
524 }
525
526 if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
527 OS.indent(NumSpaces: Indent + 2);
528 OS << "config_macros ";
529 if (ConfigMacrosExhaustive)
530 OS << "[exhaustive]";
531 for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {
532 if (I)
533 OS << ", ";
534 OS << ConfigMacros[I];
535 }
536 OS << "\n";
537 }
538
539 struct {
540 StringRef Prefix;
541 HeaderKind Kind;
542 } Kinds[] = {{.Prefix: "", .Kind: HK_Normal},
543 {.Prefix: "textual ", .Kind: HK_Textual},
544 {.Prefix: "private ", .Kind: HK_Private},
545 {.Prefix: "private textual ", .Kind: HK_PrivateTextual},
546 {.Prefix: "exclude ", .Kind: HK_Excluded}};
547
548 for (auto &K : Kinds) {
549 assert(&K == &Kinds[K.Kind] && "kinds in wrong order");
550 for (auto &H : getHeaders(HK: K.Kind)) {
551 OS.indent(NumSpaces: Indent + 2);
552 OS << K.Prefix << "header \"";
553 OS.write_escaped(Str: H.NameAsWritten);
554 OS << "\" { size " << H.Entry.getSize()
555 << " mtime " << H.Entry.getModificationTime() << " }\n";
556 }
557 }
558 for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) {
559 for (auto &U : *Unresolved) {
560 OS.indent(NumSpaces: Indent + 2);
561 OS << Kinds[U.Kind].Prefix << "header \"";
562 OS.write_escaped(Str: U.FileName);
563 OS << "\"";
564 if (U.Size || U.ModTime) {
565 OS << " {";
566 if (U.Size)
567 OS << " size " << *U.Size;
568 if (U.ModTime)
569 OS << " mtime " << *U.ModTime;
570 OS << " }";
571 }
572 OS << "\n";
573 }
574 }
575
576 if (!ExportAsModule.empty()) {
577 OS.indent(NumSpaces: Indent + 2);
578 OS << "export_as" << ExportAsModule << "\n";
579 }
580
581 for (auto *Submodule : submodules())
582 // Print inferred subframework modules so that we don't need to re-infer
583 // them (requires expensive directory iteration + stat calls) when we build
584 // the module. Regular inferred submodules are OK, as we need to look at all
585 // those header files anyway.
586 if (!Submodule->IsInferred || Submodule->IsFramework)
587 Submodule->print(OS, Indent: Indent + 2, Dump);
588
589 for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
590 OS.indent(NumSpaces: Indent + 2);
591 OS << "export ";
592 if (Module *Restriction = Exports[I].getPointer()) {
593 OS << Restriction->getFullModuleName(AllowStringLiterals: true);
594 if (Exports[I].getInt())
595 OS << ".*";
596 } else {
597 OS << "*";
598 }
599 OS << "\n";
600 }
601
602 for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
603 OS.indent(NumSpaces: Indent + 2);
604 OS << "export ";
605 printModuleId(OS, C: UnresolvedExports[I].Id);
606 if (UnresolvedExports[I].Wildcard)
607 OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");
608 OS << "\n";
609 }
610
611 if (Dump) {
612 for (Module *M : Imports) {
613 OS.indent(NumSpaces: Indent + 2);
614 llvm::errs() << "import " << M->getFullModuleName() << "\n";
615 }
616 }
617
618 for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
619 OS.indent(NumSpaces: Indent + 2);
620 OS << "use ";
621 OS << DirectUses[I]->getFullModuleName(AllowStringLiterals: true);
622 OS << "\n";
623 }
624
625 for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) {
626 OS.indent(NumSpaces: Indent + 2);
627 OS << "use ";
628 printModuleId(OS, C: UnresolvedDirectUses[I]);
629 OS << "\n";
630 }
631
632 for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) {
633 OS.indent(NumSpaces: Indent + 2);
634 OS << "link ";
635 if (LinkLibraries[I].IsFramework)
636 OS << "framework ";
637 OS << "\"";
638 OS.write_escaped(Str: LinkLibraries[I].Library);
639 OS << "\"";
640 }
641
642 for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) {
643 OS.indent(NumSpaces: Indent + 2);
644 OS << "conflict ";
645 printModuleId(OS, C: UnresolvedConflicts[I].Id);
646 OS << ", \"";
647 OS.write_escaped(Str: UnresolvedConflicts[I].Message);
648 OS << "\"\n";
649 }
650
651 for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
652 OS.indent(NumSpaces: Indent + 2);
653 OS << "conflict ";
654 OS << Conflicts[I].Other->getFullModuleName(AllowStringLiterals: true);
655 OS << ", \"";
656 OS.write_escaped(Str: Conflicts[I].Message);
657 OS << "\"\n";
658 }
659
660 if (InferSubmodules) {
661 OS.indent(NumSpaces: Indent + 2);
662 if (InferExplicitSubmodules)
663 OS << "explicit ";
664 OS << "module * {\n";
665 if (InferExportWildcard) {
666 OS.indent(NumSpaces: Indent + 4);
667 OS << "export *\n";
668 }
669 OS.indent(NumSpaces: Indent + 2);
670 OS << "}\n";
671 }
672
673 OS.indent(NumSpaces: Indent);
674 OS << "}\n";
675}
676
677LLVM_DUMP_METHOD void Module::dump() const {
678 print(OS&: llvm::errs(), Indent: 0, Dump: true);
679}
680
681void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
682 bool IncludeExports, VisibleCallback Vis,
683 ConflictCallback Cb) {
684 // We can't import a global module fragment so the location can be invalid.
685 assert((M->isGlobalModule() || Loc.isValid()) &&
686 "setVisible expects a valid import location");
687 if (isVisible(M))
688 return;
689
690 ++Generation;
691
692 struct Visiting {
693 Module *M;
694 Visiting *ExportedBy;
695 };
696
697 std::function<void(Visiting)> VisitModule = [&](Visiting V) {
698 // Nothing to do for a module that's already visible.
699 unsigned ID = V.M->getVisibilityID();
700 if (ImportLocs.size() <= ID)
701 ImportLocs.resize(new_size: ID + 1);
702 else if (ImportLocs[ID].isValid())
703 return;
704
705 ImportLocs[ID] = Loc;
706 Vis(V.M);
707
708 // Make any exported modules visible.
709 if (IncludeExports) {
710 SmallVector<Module *, 16> Exports;
711 V.M->getExportedModules(Exported&: Exports);
712 for (Module *E : Exports) {
713 // Don't import non-importable modules.
714 if (!E->isUnimportable())
715 VisitModule({.M: E, .ExportedBy: &V});
716 }
717 }
718
719 for (auto &C : V.M->Conflicts) {
720 if (isVisible(M: C.Other)) {
721 llvm::SmallVector<Module*, 8> Path;
722 for (Visiting *I = &V; I; I = I->ExportedBy)
723 Path.push_back(Elt: I->M);
724 Cb(Path, C.Other, C.Message);
725 }
726 }
727 };
728 VisitModule({.M: M, .ExportedBy: nullptr});
729}
730