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