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