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