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