xref: /src/contrib/llvm-project/clang/lib/Basic/Module.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1461a67faSDimitry Andric //===- Module.cpp - Describe a module -------------------------------------===//
2dbe13110SDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dbe13110SDimitry Andric //
7dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
8dbe13110SDimitry Andric //
9dbe13110SDimitry Andric // This file defines the Module class, which describes a module in the source
10dbe13110SDimitry Andric // code.
11dbe13110SDimitry Andric //
12dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
13bfef3995SDimitry Andric 
14dbe13110SDimitry Andric #include "clang/Basic/Module.h"
15ef915aabSDimitry Andric #include "clang/Basic/CharInfo.h"
16dbe13110SDimitry Andric #include "clang/Basic/FileManager.h"
17dbe13110SDimitry Andric #include "clang/Basic/LangOptions.h"
18461a67faSDimitry Andric #include "clang/Basic/SourceLocation.h"
19dbe13110SDimitry Andric #include "clang/Basic/TargetInfo.h"
20809500fcSDimitry Andric #include "llvm/ADT/ArrayRef.h"
21dbe13110SDimitry Andric #include "llvm/ADT/SmallVector.h"
22461a67faSDimitry Andric #include "llvm/ADT/StringMap.h"
23461a67faSDimitry Andric #include "llvm/ADT/StringRef.h"
24dbe13110SDimitry Andric #include "llvm/ADT/StringSwitch.h"
25461a67faSDimitry Andric #include "llvm/Support/Compiler.h"
26809500fcSDimitry Andric #include "llvm/Support/ErrorHandling.h"
27809500fcSDimitry Andric #include "llvm/Support/raw_ostream.h"
28461a67faSDimitry Andric #include <algorithm>
29461a67faSDimitry Andric #include <cassert>
30461a67faSDimitry Andric #include <functional>
31461a67faSDimitry Andric #include <string>
32461a67faSDimitry Andric #include <utility>
33461a67faSDimitry Andric #include <vector>
34bfef3995SDimitry Andric 
35dbe13110SDimitry Andric using namespace clang;
36dbe13110SDimitry Andric 
Module(StringRef Name,SourceLocation DefinitionLoc,Module * Parent,bool IsFramework,bool IsExplicit,unsigned VisibilityID)37dbe13110SDimitry Andric Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
385e20cdd8SDimitry Andric                bool IsFramework, bool IsExplicit, unsigned VisibilityID)
39461a67faSDimitry Andric     : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
40cfca06d7SDimitry Andric       VisibilityID(VisibilityID), IsUnimportable(false),
41461a67faSDimitry Andric       HasIncompatibleModuleFile(false), IsAvailable(true),
42461a67faSDimitry Andric       IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),
43461a67faSDimitry Andric       IsSystem(false), IsExternC(false), IsInferred(false),
44461a67faSDimitry Andric       InferSubmodules(false), InferExplicitSubmodules(false),
4545b53394SDimitry Andric       InferExportWildcard(false), ConfigMacrosExhaustive(false),
4648675466SDimitry Andric       NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
47b1c73532SDimitry Andric       NamedModuleHasInit(true), NameVisibility(Hidden) {
48dbe13110SDimitry Andric   if (Parent) {
49cfca06d7SDimitry Andric     IsAvailable = Parent->isAvailable();
50cfca06d7SDimitry Andric     IsUnimportable = Parent->isUnimportable();
51cfca06d7SDimitry Andric     IsSystem = Parent->IsSystem;
52cfca06d7SDimitry Andric     IsExternC = Parent->IsExternC;
53cfca06d7SDimitry Andric     NoUndeclaredIncludes = Parent->NoUndeclaredIncludes;
54cfca06d7SDimitry Andric     ModuleMapIsPrivate = Parent->ModuleMapIsPrivate;
55dbe13110SDimitry Andric 
56dbe13110SDimitry Andric     Parent->SubModuleIndex[Name] = Parent->SubModules.size();
57dbe13110SDimitry Andric     Parent->SubModules.push_back(this);
58dbe13110SDimitry Andric   }
59dbe13110SDimitry Andric }
60dbe13110SDimitry Andric 
~Module()61dbe13110SDimitry Andric Module::~Module() {
627fa27ce4SDimitry Andric   for (auto *Submodule : SubModules) {
637fa27ce4SDimitry Andric     delete Submodule;
64dbe13110SDimitry Andric   }
65dbe13110SDimitry Andric }
66dbe13110SDimitry Andric 
isPlatformEnvironment(const TargetInfo & Target,StringRef Feature)67676fbe81SDimitry Andric static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
68676fbe81SDimitry Andric   StringRef Platform = Target.getPlatformName();
69676fbe81SDimitry Andric   StringRef Env = Target.getTriple().getEnvironmentName();
70676fbe81SDimitry Andric 
71676fbe81SDimitry Andric   // Attempt to match platform and environment.
72676fbe81SDimitry Andric   if (Platform == Feature || Target.getTriple().getOSName() == Feature ||
73676fbe81SDimitry Andric       Env == Feature)
74676fbe81SDimitry Andric     return true;
75676fbe81SDimitry Andric 
76676fbe81SDimitry Andric   auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {
77b60736ecSDimitry Andric     auto Pos = LHS.find('-');
78676fbe81SDimitry Andric     if (Pos == StringRef::npos)
79676fbe81SDimitry Andric       return false;
80676fbe81SDimitry Andric     SmallString<128> NewLHS = LHS.slice(0, Pos);
81676fbe81SDimitry Andric     NewLHS += LHS.slice(Pos+1, LHS.size());
82676fbe81SDimitry Andric     return NewLHS == RHS;
83676fbe81SDimitry Andric   };
84676fbe81SDimitry Andric 
85676fbe81SDimitry Andric   SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName();
86676fbe81SDimitry Andric   // Darwin has different but equivalent variants for simulators, example:
87676fbe81SDimitry Andric   //   1. x86_64-apple-ios-simulator
88676fbe81SDimitry Andric   //   2. x86_64-apple-iossimulator
89676fbe81SDimitry Andric   // where both are valid examples of the same platform+environment but in the
90676fbe81SDimitry Andric   // variant (2) the simulator is hardcoded as part of the platform name. Both
91676fbe81SDimitry Andric   // forms above should match for "iossimulator" requirement.
92312c0ed1SDimitry Andric   if (Target.getTriple().isOSDarwin() && PlatformEnv.ends_with("simulator"))
93676fbe81SDimitry Andric     return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);
94676fbe81SDimitry Andric 
95676fbe81SDimitry Andric   return PlatformEnv == Feature;
96676fbe81SDimitry Andric }
97676fbe81SDimitry Andric 
9848675466SDimitry Andric /// Determine whether a translation unit built using the current
99dbe13110SDimitry Andric /// language options has the given feature.
hasFeature(StringRef Feature,const LangOptions & LangOpts,const TargetInfo & Target)100dbe13110SDimitry Andric static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
101dbe13110SDimitry Andric                        const TargetInfo &Target) {
1025e20cdd8SDimitry Andric   bool HasFeature = llvm::StringSwitch<bool>(Feature)
103dbe13110SDimitry Andric                         .Case("altivec", LangOpts.AltiVec)
104dbe13110SDimitry Andric                         .Case("blocks", LangOpts.Blocks)
10522989816SDimitry Andric                         .Case("coroutines", LangOpts.Coroutines)
106dbe13110SDimitry Andric                         .Case("cplusplus", LangOpts.CPlusPlus)
107809500fcSDimitry Andric                         .Case("cplusplus11", LangOpts.CPlusPlus11)
10848675466SDimitry Andric                         .Case("cplusplus14", LangOpts.CPlusPlus14)
10948675466SDimitry Andric                         .Case("cplusplus17", LangOpts.CPlusPlus17)
1107fa27ce4SDimitry Andric                         .Case("cplusplus20", LangOpts.CPlusPlus20)
1117fa27ce4SDimitry Andric                         .Case("cplusplus23", LangOpts.CPlusPlus23)
1127fa27ce4SDimitry Andric                         .Case("cplusplus26", LangOpts.CPlusPlus26)
11348675466SDimitry Andric                         .Case("c99", LangOpts.C99)
11448675466SDimitry Andric                         .Case("c11", LangOpts.C11)
11548675466SDimitry Andric                         .Case("c17", LangOpts.C17)
116b1c73532SDimitry Andric                         .Case("c23", LangOpts.C23)
117bab175ecSDimitry Andric                         .Case("freestanding", LangOpts.Freestanding)
118bab175ecSDimitry Andric                         .Case("gnuinlineasm", LangOpts.GNUAsm)
119676fbe81SDimitry Andric                         .Case("objc", LangOpts.ObjC)
120dbe13110SDimitry Andric                         .Case("objc_arc", LangOpts.ObjCAutoRefCount)
121dbe13110SDimitry Andric                         .Case("opencl", LangOpts.OpenCL)
122dbe13110SDimitry Andric                         .Case("tls", Target.isTLSSupported())
12336c5ade2SDimitry Andric                         .Case("zvector", LangOpts.ZVector)
124676fbe81SDimitry Andric                         .Default(Target.hasFeature(Feature) ||
125676fbe81SDimitry Andric                                  isPlatformEnvironment(Target, Feature));
1265e20cdd8SDimitry Andric   if (!HasFeature)
127c0981da4SDimitry Andric     HasFeature = llvm::is_contained(LangOpts.ModuleFeatures, Feature);
1285e20cdd8SDimitry Andric   return HasFeature;
129dbe13110SDimitry Andric }
130dbe13110SDimitry Andric 
isUnimportable(const LangOptions & LangOpts,const TargetInfo & Target,Requirement & Req,Module * & ShadowingModule) const131cfca06d7SDimitry Andric bool Module::isUnimportable(const LangOptions &LangOpts,
132cfca06d7SDimitry Andric                             const TargetInfo &Target, Requirement &Req,
133cfca06d7SDimitry Andric                             Module *&ShadowingModule) const {
134cfca06d7SDimitry Andric   if (!IsUnimportable)
135cfca06d7SDimitry Andric     return false;
136cfca06d7SDimitry Andric 
137cfca06d7SDimitry Andric   for (const Module *Current = this; Current; Current = Current->Parent) {
138cfca06d7SDimitry Andric     if (Current->ShadowingModule) {
139cfca06d7SDimitry Andric       ShadowingModule = Current->ShadowingModule;
140cfca06d7SDimitry Andric       return true;
141cfca06d7SDimitry Andric     }
142cfca06d7SDimitry Andric     for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
143ac9a064cSDimitry Andric       if (hasFeature(Current->Requirements[I].FeatureName, LangOpts, Target) !=
144ac9a064cSDimitry Andric           Current->Requirements[I].RequiredState) {
145cfca06d7SDimitry Andric         Req = Current->Requirements[I];
146cfca06d7SDimitry Andric         return true;
147cfca06d7SDimitry Andric       }
148cfca06d7SDimitry Andric     }
149cfca06d7SDimitry Andric   }
150cfca06d7SDimitry Andric 
151cfca06d7SDimitry Andric   llvm_unreachable("could not find a reason why module is unimportable");
152cfca06d7SDimitry Andric }
153cfca06d7SDimitry Andric 
154e3b55780SDimitry Andric // The -fmodule-name option tells the compiler to textually include headers in
155e3b55780SDimitry Andric // the specified module, meaning Clang won't build the specified module. This
156e3b55780SDimitry Andric // is useful in a number of situations, for instance, when building a library
157e3b55780SDimitry Andric // that vends a module map, one might want to avoid hitting intermediate build
158e3b55780SDimitry Andric // products containing the module map or avoid finding the system installed
159e3b55780SDimitry Andric // modulemap for that library.
isForBuilding(const LangOptions & LangOpts) const160e3b55780SDimitry Andric bool Module::isForBuilding(const LangOptions &LangOpts) const {
161e3b55780SDimitry Andric   StringRef TopLevelName = getTopLevelModuleName();
162e3b55780SDimitry Andric   StringRef CurrentModule = LangOpts.CurrentModule;
163e3b55780SDimitry Andric 
164b1c73532SDimitry Andric   // When building the implementation of framework Foo, we want to make sure
165b1c73532SDimitry Andric   // that Foo *and* Foo_Private are textually included and no modules are built
166b1c73532SDimitry Andric   // for either.
167b1c73532SDimitry Andric   if (!LangOpts.isCompilingModule() && getTopLevelModule()->IsFramework &&
168e3b55780SDimitry Andric       CurrentModule == LangOpts.ModuleName &&
169312c0ed1SDimitry Andric       !CurrentModule.ends_with("_Private") &&
170312c0ed1SDimitry Andric       TopLevelName.ends_with("_Private"))
171e3b55780SDimitry Andric     TopLevelName = TopLevelName.drop_back(8);
172e3b55780SDimitry Andric 
173e3b55780SDimitry Andric   return TopLevelName == CurrentModule;
174e3b55780SDimitry Andric }
175e3b55780SDimitry Andric 
isAvailable(const LangOptions & LangOpts,const TargetInfo & Target,Requirement & Req,UnresolvedHeaderDirective & MissingHeader,Module * & ShadowingModule) const17606d4ba38SDimitry Andric bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
17706d4ba38SDimitry Andric                          Requirement &Req,
17848675466SDimitry Andric                          UnresolvedHeaderDirective &MissingHeader,
17948675466SDimitry Andric                          Module *&ShadowingModule) const {
180dbe13110SDimitry Andric   if (IsAvailable)
181dbe13110SDimitry Andric     return true;
182dbe13110SDimitry Andric 
183cfca06d7SDimitry Andric   if (isUnimportable(LangOpts, Target, Req, ShadowingModule))
184cfca06d7SDimitry Andric     return false;
185cfca06d7SDimitry Andric 
186cfca06d7SDimitry Andric   // FIXME: All missing headers are listed on the top-level module. Should we
187cfca06d7SDimitry Andric   // just look there?
188dbe13110SDimitry Andric   for (const Module *Current = this; Current; Current = Current->Parent) {
18951ece4aaSDimitry Andric     if (!Current->MissingHeaders.empty()) {
19051ece4aaSDimitry Andric       MissingHeader = Current->MissingHeaders.front();
19151ece4aaSDimitry Andric       return false;
19251ece4aaSDimitry Andric     }
193dbe13110SDimitry Andric   }
194dbe13110SDimitry Andric 
195dbe13110SDimitry Andric   llvm_unreachable("could not find a reason why module is unavailable");
196dbe13110SDimitry Andric }
197dbe13110SDimitry Andric 
isSubModuleOf(const Module * Other) const1989f4dbff6SDimitry Andric bool Module::isSubModuleOf(const Module *Other) const {
199b60736ecSDimitry Andric   for (auto *Parent = this; Parent; Parent = Parent->Parent) {
200b60736ecSDimitry Andric     if (Parent == Other)
201dbe13110SDimitry Andric       return true;
202b60736ecSDimitry Andric   }
203dbe13110SDimitry Andric   return false;
204dbe13110SDimitry Andric }
205dbe13110SDimitry Andric 
getTopLevelModule() const206dbe13110SDimitry Andric const Module *Module::getTopLevelModule() const {
207dbe13110SDimitry Andric   const Module *Result = this;
208dbe13110SDimitry Andric   while (Result->Parent)
209dbe13110SDimitry Andric     Result = Result->Parent;
210dbe13110SDimitry Andric 
211dbe13110SDimitry Andric   return Result;
212dbe13110SDimitry Andric }
213dbe13110SDimitry Andric 
getModuleNameFromComponent(const std::pair<std::string,SourceLocation> & IdComponent)214ef915aabSDimitry Andric static StringRef getModuleNameFromComponent(
215ef915aabSDimitry Andric     const std::pair<std::string, SourceLocation> &IdComponent) {
216ef915aabSDimitry Andric   return IdComponent.first;
217ef915aabSDimitry Andric }
218461a67faSDimitry Andric 
getModuleNameFromComponent(StringRef R)219ef915aabSDimitry Andric static StringRef getModuleNameFromComponent(StringRef R) { return R; }
220ef915aabSDimitry Andric 
221ef915aabSDimitry Andric template<typename InputIter>
printModuleId(raw_ostream & OS,InputIter Begin,InputIter End,bool AllowStringLiterals=true)222ef915aabSDimitry Andric static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,
223ef915aabSDimitry Andric                           bool AllowStringLiterals = true) {
224ef915aabSDimitry Andric   for (InputIter It = Begin; It != End; ++It) {
225ef915aabSDimitry Andric     if (It != Begin)
226ef915aabSDimitry Andric       OS << ".";
227ef915aabSDimitry Andric 
228ef915aabSDimitry Andric     StringRef Name = getModuleNameFromComponent(*It);
229c0981da4SDimitry Andric     if (!AllowStringLiterals || isValidAsciiIdentifier(Name))
230ef915aabSDimitry Andric       OS << Name;
231ef915aabSDimitry Andric     else {
232ef915aabSDimitry Andric       OS << '"';
233ef915aabSDimitry Andric       OS.write_escaped(Name);
234ef915aabSDimitry Andric       OS << '"';
235ef915aabSDimitry Andric     }
236ef915aabSDimitry Andric   }
237ef915aabSDimitry Andric }
238ef915aabSDimitry Andric 
239ef915aabSDimitry Andric template<typename Container>
printModuleId(raw_ostream & OS,const Container & C)240ef915aabSDimitry Andric static void printModuleId(raw_ostream &OS, const Container &C) {
241ef915aabSDimitry Andric   return printModuleId(OS, C.begin(), C.end());
242ef915aabSDimitry Andric }
243ef915aabSDimitry Andric 
getFullModuleName(bool AllowStringLiterals) const244ef915aabSDimitry Andric std::string Module::getFullModuleName(bool AllowStringLiterals) const {
245809500fcSDimitry Andric   SmallVector<StringRef, 2> Names;
246dbe13110SDimitry Andric 
247dbe13110SDimitry Andric   // Build up the set of module names (from innermost to outermost).
248dbe13110SDimitry Andric   for (const Module *M = this; M; M = M->Parent)
249dbe13110SDimitry Andric     Names.push_back(M->Name);
250dbe13110SDimitry Andric 
251dbe13110SDimitry Andric   std::string Result;
252dbe13110SDimitry Andric 
253ef915aabSDimitry Andric   llvm::raw_string_ostream Out(Result);
254ef915aabSDimitry Andric   printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
255ef915aabSDimitry Andric   Out.flush();
256dbe13110SDimitry Andric 
257dbe13110SDimitry Andric   return Result;
258dbe13110SDimitry Andric }
259dbe13110SDimitry Andric 
fullModuleNameIs(ArrayRef<StringRef> nameParts) const26045b53394SDimitry Andric bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
26145b53394SDimitry Andric   for (const Module *M = this; M; M = M->Parent) {
26245b53394SDimitry Andric     if (nameParts.empty() || M->Name != nameParts.back())
26345b53394SDimitry Andric       return false;
26445b53394SDimitry Andric     nameParts = nameParts.drop_back();
26545b53394SDimitry Andric   }
26645b53394SDimitry Andric   return nameParts.empty();
26745b53394SDimitry Andric }
26845b53394SDimitry Andric 
getEffectiveUmbrellaDir() const2697fa27ce4SDimitry Andric OptionalDirectoryEntryRef Module::getEffectiveUmbrellaDir() const {
270b1c73532SDimitry Andric   if (const auto *Hdr = std::get_if<FileEntryRef>(&Umbrella))
271b1c73532SDimitry Andric     return Hdr->getDir();
272b1c73532SDimitry Andric   if (const auto *Dir = std::get_if<DirectoryEntryRef>(&Umbrella))
273b1c73532SDimitry Andric     return *Dir;
2747fa27ce4SDimitry Andric   return std::nullopt;
275cfca06d7SDimitry Andric }
276cfca06d7SDimitry Andric 
addTopHeader(FileEntryRef File)2777fa27ce4SDimitry Andric void Module::addTopHeader(FileEntryRef File) {
278cfca06d7SDimitry Andric   assert(File);
279cfca06d7SDimitry Andric   TopHeaders.insert(File);
280dbe13110SDimitry Andric }
281dbe13110SDimitry Andric 
getTopHeaders(FileManager & FileMgr)2827fa27ce4SDimitry Andric ArrayRef<FileEntryRef> Module::getTopHeaders(FileManager &FileMgr) {
283809500fcSDimitry Andric   if (!TopHeaderNames.empty()) {
2847fa27ce4SDimitry Andric     for (StringRef TopHeaderName : TopHeaderNames)
2857fa27ce4SDimitry Andric       if (auto FE = FileMgr.getOptionalFileRef(TopHeaderName))
286519fc96cSDimitry Andric         TopHeaders.insert(*FE);
287809500fcSDimitry Andric     TopHeaderNames.clear();
288809500fcSDimitry Andric   }
289809500fcSDimitry Andric 
290e3b55780SDimitry Andric   return llvm::ArrayRef(TopHeaders.begin(), TopHeaders.end());
291809500fcSDimitry Andric }
292809500fcSDimitry Andric 
directlyUses(const Module * Requested)293145449b1SDimitry Andric bool Module::directlyUses(const Module *Requested) {
2945e20cdd8SDimitry Andric   auto *Top = getTopLevelModule();
2955e20cdd8SDimitry Andric 
2965e20cdd8SDimitry Andric   // A top-level module implicitly uses itself.
2975e20cdd8SDimitry Andric   if (Requested->isSubModuleOf(Top))
2985e20cdd8SDimitry Andric     return true;
2995e20cdd8SDimitry Andric 
3005e20cdd8SDimitry Andric   for (auto *Use : Top->DirectUses)
3015e20cdd8SDimitry Andric     if (Requested->isSubModuleOf(Use))
3025e20cdd8SDimitry Andric       return true;
303bab175ecSDimitry Andric 
304ac9a064cSDimitry Andric   // Anyone is allowed to use our builtin stddef.h and its accompanying modules.
305ac9a064cSDimitry Andric   if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) ||
306ac9a064cSDimitry Andric       Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"}))
307ac9a064cSDimitry Andric     return true;
308ac9a064cSDimitry Andric   // Darwin is allowed is to use our builtin 'ptrauth.h' and its accompanying
309ac9a064cSDimitry Andric   // module.
310ac9a064cSDimitry Andric   if (!Requested->Parent && Requested->Name == "ptrauth")
311bab175ecSDimitry Andric     return true;
312bab175ecSDimitry Andric 
313145449b1SDimitry Andric   if (NoUndeclaredIncludes)
314145449b1SDimitry Andric     UndeclaredUses.insert(Requested);
315145449b1SDimitry Andric 
3165e20cdd8SDimitry Andric   return false;
3175e20cdd8SDimitry Andric }
3185e20cdd8SDimitry Andric 
addRequirement(StringRef Feature,bool RequiredState,const LangOptions & LangOpts,const TargetInfo & Target)319bfef3995SDimitry Andric void Module::addRequirement(StringRef Feature, bool RequiredState,
320bfef3995SDimitry Andric                             const LangOptions &LangOpts,
321dbe13110SDimitry Andric                             const TargetInfo &Target) {
322ac9a064cSDimitry Andric   Requirements.push_back(Requirement{std::string(Feature), RequiredState});
323dbe13110SDimitry Andric 
324dbe13110SDimitry Andric   // If this feature is currently available, we're done.
325bfef3995SDimitry Andric   if (hasFeature(Feature, LangOpts, Target) == RequiredState)
326dbe13110SDimitry Andric     return;
327dbe13110SDimitry Andric 
328cfca06d7SDimitry Andric   markUnavailable(/*Unimportable*/true);
3299f4dbff6SDimitry Andric }
3309f4dbff6SDimitry Andric 
markUnavailable(bool Unimportable)331cfca06d7SDimitry Andric void Module::markUnavailable(bool Unimportable) {
332cfca06d7SDimitry Andric   auto needUpdate = [Unimportable](Module *M) {
333cfca06d7SDimitry Andric     return M->IsAvailable || (!M->IsUnimportable && Unimportable);
33451ece4aaSDimitry Andric   };
33551ece4aaSDimitry Andric 
33651ece4aaSDimitry Andric   if (!needUpdate(this))
337dbe13110SDimitry Andric     return;
338dbe13110SDimitry Andric 
339809500fcSDimitry Andric   SmallVector<Module *, 2> Stack;
340dbe13110SDimitry Andric   Stack.push_back(this);
341dbe13110SDimitry Andric   while (!Stack.empty()) {
342dbe13110SDimitry Andric     Module *Current = Stack.back();
343dbe13110SDimitry Andric     Stack.pop_back();
344dbe13110SDimitry Andric 
34551ece4aaSDimitry Andric     if (!needUpdate(Current))
346dbe13110SDimitry Andric       continue;
347dbe13110SDimitry Andric 
348dbe13110SDimitry Andric     Current->IsAvailable = false;
349cfca06d7SDimitry Andric     Current->IsUnimportable |= Unimportable;
3507fa27ce4SDimitry Andric     for (auto *Submodule : Current->submodules()) {
3517fa27ce4SDimitry Andric       if (needUpdate(Submodule))
3527fa27ce4SDimitry Andric         Stack.push_back(Submodule);
353dbe13110SDimitry Andric     }
354dbe13110SDimitry Andric   }
355dbe13110SDimitry Andric }
356dbe13110SDimitry Andric 
findSubmodule(StringRef Name) const357dbe13110SDimitry Andric Module *Module::findSubmodule(StringRef Name) const {
358dbe13110SDimitry Andric   llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
359dbe13110SDimitry Andric   if (Pos == SubModuleIndex.end())
3609f4dbff6SDimitry Andric     return nullptr;
361dbe13110SDimitry Andric 
362dbe13110SDimitry Andric   return SubModules[Pos->getValue()];
363dbe13110SDimitry Andric }
364dbe13110SDimitry Andric 
findOrInferSubmodule(StringRef Name)36522989816SDimitry Andric Module *Module::findOrInferSubmodule(StringRef Name) {
36622989816SDimitry Andric   llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
36722989816SDimitry Andric   if (Pos != SubModuleIndex.end())
36822989816SDimitry Andric     return SubModules[Pos->getValue()];
36922989816SDimitry Andric   if (!InferSubmodules)
37022989816SDimitry Andric     return nullptr;
37122989816SDimitry Andric   Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
37222989816SDimitry Andric   Result->InferExplicitSubmodules = InferExplicitSubmodules;
37322989816SDimitry Andric   Result->InferSubmodules = InferSubmodules;
37422989816SDimitry Andric   Result->InferExportWildcard = InferExportWildcard;
37522989816SDimitry Andric   if (Result->InferExportWildcard)
37622989816SDimitry Andric     Result->Exports.push_back(Module::ExportDecl(nullptr, true));
37722989816SDimitry Andric   return Result;
37822989816SDimitry Andric }
37922989816SDimitry Andric 
getGlobalModuleFragment() const380b1c73532SDimitry Andric Module *Module::getGlobalModuleFragment() const {
381b1c73532SDimitry Andric   assert(isNamedModuleUnit() && "We should only query the global module "
382b1c73532SDimitry Andric                                 "fragment from the C++20 Named modules");
383b1c73532SDimitry Andric 
384b1c73532SDimitry Andric   for (auto *SubModule : SubModules)
385b1c73532SDimitry Andric     if (SubModule->isExplicitGlobalModule())
386b1c73532SDimitry Andric       return SubModule;
387b1c73532SDimitry Andric 
388b1c73532SDimitry Andric   return nullptr;
389b1c73532SDimitry Andric }
390b1c73532SDimitry Andric 
getPrivateModuleFragment() const391b1c73532SDimitry Andric Module *Module::getPrivateModuleFragment() const {
392b1c73532SDimitry Andric   assert(isNamedModuleUnit() && "We should only query the private module "
393b1c73532SDimitry Andric                                 "fragment from the C++20 Named modules");
394b1c73532SDimitry Andric 
395b1c73532SDimitry Andric   for (auto *SubModule : SubModules)
396b1c73532SDimitry Andric     if (SubModule->isPrivateModule())
397b1c73532SDimitry Andric       return SubModule;
398b1c73532SDimitry Andric 
399b1c73532SDimitry Andric   return nullptr;
400b1c73532SDimitry Andric }
401b1c73532SDimitry Andric 
getExportedModules(SmallVectorImpl<Module * > & Exported) const402809500fcSDimitry Andric void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
403bfef3995SDimitry Andric   // All non-explicit submodules are exported.
404bfef3995SDimitry Andric   for (std::vector<Module *>::const_iterator I = SubModules.begin(),
405bfef3995SDimitry Andric                                              E = SubModules.end();
406bfef3995SDimitry Andric        I != E; ++I) {
407bfef3995SDimitry Andric     Module *Mod = *I;
408bfef3995SDimitry Andric     if (!Mod->IsExplicit)
409bfef3995SDimitry Andric       Exported.push_back(Mod);
410bfef3995SDimitry Andric   }
411bfef3995SDimitry Andric 
412bfef3995SDimitry Andric   // Find re-exported modules by filtering the list of imported modules.
413809500fcSDimitry Andric   bool AnyWildcard = false;
414809500fcSDimitry Andric   bool UnrestrictedWildcard = false;
415809500fcSDimitry Andric   SmallVector<Module *, 4> WildcardRestrictions;
416809500fcSDimitry Andric   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
417809500fcSDimitry Andric     Module *Mod = Exports[I].getPointer();
418809500fcSDimitry Andric     if (!Exports[I].getInt()) {
419809500fcSDimitry Andric       // Export a named module directly; no wildcards involved.
420809500fcSDimitry Andric       Exported.push_back(Mod);
421809500fcSDimitry Andric 
422809500fcSDimitry Andric       continue;
423809500fcSDimitry Andric     }
424809500fcSDimitry Andric 
425809500fcSDimitry Andric     // Wildcard export: export all of the imported modules that match
426809500fcSDimitry Andric     // the given pattern.
427809500fcSDimitry Andric     AnyWildcard = true;
428809500fcSDimitry Andric     if (UnrestrictedWildcard)
429809500fcSDimitry Andric       continue;
430809500fcSDimitry Andric 
431809500fcSDimitry Andric     if (Module *Restriction = Exports[I].getPointer())
432809500fcSDimitry Andric       WildcardRestrictions.push_back(Restriction);
433809500fcSDimitry Andric     else {
434809500fcSDimitry Andric       WildcardRestrictions.clear();
435809500fcSDimitry Andric       UnrestrictedWildcard = true;
436809500fcSDimitry Andric     }
437809500fcSDimitry Andric   }
438809500fcSDimitry Andric 
439809500fcSDimitry Andric   // If there were any wildcards, push any imported modules that were
440809500fcSDimitry Andric   // re-exported by the wildcard restriction.
441809500fcSDimitry Andric   if (!AnyWildcard)
442809500fcSDimitry Andric     return;
443809500fcSDimitry Andric 
444809500fcSDimitry Andric   for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
445809500fcSDimitry Andric     Module *Mod = Imports[I];
446809500fcSDimitry Andric     bool Acceptable = UnrestrictedWildcard;
447809500fcSDimitry Andric     if (!Acceptable) {
448809500fcSDimitry Andric       // Check whether this module meets one of the restrictions.
449809500fcSDimitry Andric       for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
450809500fcSDimitry Andric         Module *Restriction = WildcardRestrictions[R];
451809500fcSDimitry Andric         if (Mod == Restriction || Mod->isSubModuleOf(Restriction)) {
452809500fcSDimitry Andric           Acceptable = true;
453809500fcSDimitry Andric           break;
454809500fcSDimitry Andric         }
455809500fcSDimitry Andric       }
456809500fcSDimitry Andric     }
457809500fcSDimitry Andric 
458809500fcSDimitry Andric     if (!Acceptable)
459809500fcSDimitry Andric       continue;
460809500fcSDimitry Andric 
461809500fcSDimitry Andric     Exported.push_back(Mod);
462809500fcSDimitry Andric   }
463809500fcSDimitry Andric }
464809500fcSDimitry Andric 
buildVisibleModulesCache() const465bfef3995SDimitry Andric void Module::buildVisibleModulesCache() const {
466bfef3995SDimitry Andric   assert(VisibleModulesCache.empty() && "cache does not need building");
467bfef3995SDimitry Andric 
468bfef3995SDimitry Andric   // This module is visible to itself.
469bfef3995SDimitry Andric   VisibleModulesCache.insert(this);
470bfef3995SDimitry Andric 
471bfef3995SDimitry Andric   // Every imported module is visible.
472bfef3995SDimitry Andric   SmallVector<Module *, 16> Stack(Imports.begin(), Imports.end());
473bfef3995SDimitry Andric   while (!Stack.empty()) {
474bfef3995SDimitry Andric     Module *CurrModule = Stack.pop_back_val();
475bfef3995SDimitry Andric 
476bfef3995SDimitry Andric     // Every module transitively exported by an imported module is visible.
477bfef3995SDimitry Andric     if (VisibleModulesCache.insert(CurrModule).second)
478bfef3995SDimitry Andric       CurrModule->getExportedModules(Stack);
479bfef3995SDimitry Andric   }
480bfef3995SDimitry Andric }
481bfef3995SDimitry Andric 
print(raw_ostream & OS,unsigned Indent,bool Dump) const482344a3780SDimitry Andric void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
483dbe13110SDimitry Andric   OS.indent(Indent);
484dbe13110SDimitry Andric   if (IsFramework)
485dbe13110SDimitry Andric     OS << "framework ";
486dbe13110SDimitry Andric   if (IsExplicit)
487dbe13110SDimitry Andric     OS << "explicit ";
488ef915aabSDimitry Andric   OS << "module ";
489ef915aabSDimitry Andric   printModuleId(OS, &Name, &Name + 1);
490dbe13110SDimitry Andric 
49106d4ba38SDimitry Andric   if (IsSystem || IsExternC) {
492dbe13110SDimitry Andric     OS.indent(Indent + 2);
49306d4ba38SDimitry Andric     if (IsSystem)
494dbe13110SDimitry Andric       OS << " [system]";
49506d4ba38SDimitry Andric     if (IsExternC)
49606d4ba38SDimitry Andric       OS << " [extern_c]";
497dbe13110SDimitry Andric   }
498dbe13110SDimitry Andric 
499dbe13110SDimitry Andric   OS << " {\n";
500dbe13110SDimitry Andric 
501bfef3995SDimitry Andric   if (!Requirements.empty()) {
502dbe13110SDimitry Andric     OS.indent(Indent + 2);
503dbe13110SDimitry Andric     OS << "requires ";
504bfef3995SDimitry Andric     for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {
505dbe13110SDimitry Andric       if (I)
506dbe13110SDimitry Andric         OS << ", ";
507ac9a064cSDimitry Andric       if (!Requirements[I].RequiredState)
508bfef3995SDimitry Andric         OS << "!";
509ac9a064cSDimitry Andric       OS << Requirements[I].FeatureName;
510dbe13110SDimitry Andric     }
511dbe13110SDimitry Andric     OS << "\n";
512dbe13110SDimitry Andric   }
513dbe13110SDimitry Andric 
5147fa27ce4SDimitry Andric   if (std::optional<Header> H = getUmbrellaHeaderAsWritten()) {
515dbe13110SDimitry Andric     OS.indent(Indent + 2);
516dbe13110SDimitry Andric     OS << "umbrella header \"";
5177fa27ce4SDimitry Andric     OS.write_escaped(H->NameAsWritten);
518dbe13110SDimitry Andric     OS << "\"\n";
5197fa27ce4SDimitry Andric   } else if (std::optional<DirectoryName> D = getUmbrellaDirAsWritten()) {
520dbe13110SDimitry Andric     OS.indent(Indent + 2);
521dbe13110SDimitry Andric     OS << "umbrella \"";
5227fa27ce4SDimitry Andric     OS.write_escaped(D->NameAsWritten);
523dbe13110SDimitry Andric     OS << "\"\n";
524dbe13110SDimitry Andric   }
525dbe13110SDimitry Andric 
526809500fcSDimitry Andric   if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
527809500fcSDimitry Andric     OS.indent(Indent + 2);
528809500fcSDimitry Andric     OS << "config_macros ";
529809500fcSDimitry Andric     if (ConfigMacrosExhaustive)
530809500fcSDimitry Andric       OS << "[exhaustive]";
531809500fcSDimitry Andric     for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {
532809500fcSDimitry Andric       if (I)
533809500fcSDimitry Andric         OS << ", ";
534809500fcSDimitry Andric       OS << ConfigMacros[I];
535809500fcSDimitry Andric     }
536809500fcSDimitry Andric     OS << "\n";
537809500fcSDimitry Andric   }
538809500fcSDimitry Andric 
53906d4ba38SDimitry Andric   struct {
54006d4ba38SDimitry Andric     StringRef Prefix;
54106d4ba38SDimitry Andric     HeaderKind Kind;
54206d4ba38SDimitry Andric   } Kinds[] = {{"", HK_Normal},
54306d4ba38SDimitry Andric                {"textual ", HK_Textual},
54406d4ba38SDimitry Andric                {"private ", HK_Private},
54506d4ba38SDimitry Andric                {"private textual ", HK_PrivateTextual},
54606d4ba38SDimitry Andric                {"exclude ", HK_Excluded}};
54706d4ba38SDimitry Andric 
54806d4ba38SDimitry Andric   for (auto &K : Kinds) {
549551c6985SDimitry Andric     assert(&K == &Kinds[K.Kind] && "kinds in wrong order");
55006d4ba38SDimitry Andric     for (auto &H : Headers[K.Kind]) {
551dbe13110SDimitry Andric       OS.indent(Indent + 2);
55206d4ba38SDimitry Andric       OS << K.Prefix << "header \"";
55306d4ba38SDimitry Andric       OS.write_escaped(H.NameAsWritten);
5547fa27ce4SDimitry Andric       OS << "\" { size " << H.Entry.getSize()
5557fa27ce4SDimitry Andric          << " mtime " << H.Entry.getModificationTime() << " }\n";
556551c6985SDimitry Andric     }
557551c6985SDimitry Andric   }
558551c6985SDimitry Andric   for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) {
559551c6985SDimitry Andric     for (auto &U : *Unresolved) {
560551c6985SDimitry Andric       OS.indent(Indent + 2);
561551c6985SDimitry Andric       OS << Kinds[U.Kind].Prefix << "header \"";
562551c6985SDimitry Andric       OS.write_escaped(U.FileName);
563551c6985SDimitry Andric       OS << "\"";
564551c6985SDimitry Andric       if (U.Size || U.ModTime) {
565551c6985SDimitry Andric         OS << " {";
566551c6985SDimitry Andric         if (U.Size)
567551c6985SDimitry Andric           OS << " size " << *U.Size;
568551c6985SDimitry Andric         if (U.ModTime)
569551c6985SDimitry Andric           OS << " mtime " << *U.ModTime;
570551c6985SDimitry Andric         OS << " }";
571551c6985SDimitry Andric       }
572551c6985SDimitry Andric       OS << "\n";
573dbe13110SDimitry Andric     }
574bfef3995SDimitry Andric   }
575bfef3995SDimitry Andric 
576461a67faSDimitry Andric   if (!ExportAsModule.empty()) {
577461a67faSDimitry Andric     OS.indent(Indent + 2);
578461a67faSDimitry Andric     OS << "export_as" << ExportAsModule << "\n";
579461a67faSDimitry Andric   }
580461a67faSDimitry Andric 
5817fa27ce4SDimitry Andric   for (auto *Submodule : submodules())
58206d4ba38SDimitry Andric     // Print inferred subframework modules so that we don't need to re-infer
58306d4ba38SDimitry Andric     // them (requires expensive directory iteration + stat calls) when we build
58406d4ba38SDimitry Andric     // the module. Regular inferred submodules are OK, as we need to look at all
58506d4ba38SDimitry Andric     // those header files anyway.
5867fa27ce4SDimitry Andric     if (!Submodule->IsInferred || Submodule->IsFramework)
5877fa27ce4SDimitry Andric       Submodule->print(OS, Indent + 2, Dump);
588dbe13110SDimitry Andric 
589dbe13110SDimitry Andric   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
590dbe13110SDimitry Andric     OS.indent(Indent + 2);
591dbe13110SDimitry Andric     OS << "export ";
592dbe13110SDimitry Andric     if (Module *Restriction = Exports[I].getPointer()) {
593ef915aabSDimitry Andric       OS << Restriction->getFullModuleName(true);
594dbe13110SDimitry Andric       if (Exports[I].getInt())
595dbe13110SDimitry Andric         OS << ".*";
596dbe13110SDimitry Andric     } else {
597dbe13110SDimitry Andric       OS << "*";
598dbe13110SDimitry Andric     }
599dbe13110SDimitry Andric     OS << "\n";
600dbe13110SDimitry Andric   }
601dbe13110SDimitry Andric 
602dbe13110SDimitry Andric   for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
603dbe13110SDimitry Andric     OS.indent(Indent + 2);
604dbe13110SDimitry Andric     OS << "export ";
605dbe13110SDimitry Andric     printModuleId(OS, UnresolvedExports[I].Id);
6062b6b257fSDimitry Andric     if (UnresolvedExports[I].Wildcard)
6072b6b257fSDimitry Andric       OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");
608dbe13110SDimitry Andric     OS << "\n";
609dbe13110SDimitry Andric   }
610dbe13110SDimitry Andric 
611344a3780SDimitry Andric   if (Dump) {
612344a3780SDimitry Andric     for (Module *M : Imports) {
613344a3780SDimitry Andric       OS.indent(Indent + 2);
614344a3780SDimitry Andric       llvm::errs() << "import " << M->getFullModuleName() << "\n";
615344a3780SDimitry Andric     }
616344a3780SDimitry Andric   }
617344a3780SDimitry Andric 
618bfef3995SDimitry Andric   for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
619bfef3995SDimitry Andric     OS.indent(Indent + 2);
620bfef3995SDimitry Andric     OS << "use ";
621ef915aabSDimitry Andric     OS << DirectUses[I]->getFullModuleName(true);
622bfef3995SDimitry Andric     OS << "\n";
623bfef3995SDimitry Andric   }
624bfef3995SDimitry Andric 
625bfef3995SDimitry Andric   for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) {
626bfef3995SDimitry Andric     OS.indent(Indent + 2);
627bfef3995SDimitry Andric     OS << "use ";
628bfef3995SDimitry Andric     printModuleId(OS, UnresolvedDirectUses[I]);
629bfef3995SDimitry Andric     OS << "\n";
630bfef3995SDimitry Andric   }
631bfef3995SDimitry Andric 
632809500fcSDimitry Andric   for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) {
633809500fcSDimitry Andric     OS.indent(Indent + 2);
634809500fcSDimitry Andric     OS << "link ";
635809500fcSDimitry Andric     if (LinkLibraries[I].IsFramework)
636809500fcSDimitry Andric       OS << "framework ";
637809500fcSDimitry Andric     OS << "\"";
638809500fcSDimitry Andric     OS.write_escaped(LinkLibraries[I].Library);
639809500fcSDimitry Andric     OS << "\"";
640809500fcSDimitry Andric   }
641809500fcSDimitry Andric 
642809500fcSDimitry Andric   for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) {
643809500fcSDimitry Andric     OS.indent(Indent + 2);
644809500fcSDimitry Andric     OS << "conflict ";
645809500fcSDimitry Andric     printModuleId(OS, UnresolvedConflicts[I].Id);
646809500fcSDimitry Andric     OS << ", \"";
647809500fcSDimitry Andric     OS.write_escaped(UnresolvedConflicts[I].Message);
648809500fcSDimitry Andric     OS << "\"\n";
649809500fcSDimitry Andric   }
650809500fcSDimitry Andric 
651809500fcSDimitry Andric   for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
652809500fcSDimitry Andric     OS.indent(Indent + 2);
653809500fcSDimitry Andric     OS << "conflict ";
654ef915aabSDimitry Andric     OS << Conflicts[I].Other->getFullModuleName(true);
655809500fcSDimitry Andric     OS << ", \"";
656809500fcSDimitry Andric     OS.write_escaped(Conflicts[I].Message);
657809500fcSDimitry Andric     OS << "\"\n";
658809500fcSDimitry Andric   }
659809500fcSDimitry Andric 
660dbe13110SDimitry Andric   if (InferSubmodules) {
661dbe13110SDimitry Andric     OS.indent(Indent + 2);
662dbe13110SDimitry Andric     if (InferExplicitSubmodules)
663dbe13110SDimitry Andric       OS << "explicit ";
664dbe13110SDimitry Andric     OS << "module * {\n";
665dbe13110SDimitry Andric     if (InferExportWildcard) {
666dbe13110SDimitry Andric       OS.indent(Indent + 4);
667dbe13110SDimitry Andric       OS << "export *\n";
668dbe13110SDimitry Andric     }
669dbe13110SDimitry Andric     OS.indent(Indent + 2);
670dbe13110SDimitry Andric     OS << "}\n";
671dbe13110SDimitry Andric   }
672dbe13110SDimitry Andric 
673dbe13110SDimitry Andric   OS.indent(Indent);
674dbe13110SDimitry Andric   OS << "}\n";
675dbe13110SDimitry Andric }
676dbe13110SDimitry Andric 
dump() const6772b6b257fSDimitry Andric LLVM_DUMP_METHOD void Module::dump() const {
678344a3780SDimitry Andric   print(llvm::errs(), 0, true);
679dbe13110SDimitry Andric }
680dbe13110SDimitry Andric 
setVisible(Module * M,SourceLocation Loc,VisibleCallback Vis,ConflictCallback Cb)6815e20cdd8SDimitry Andric void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
6825e20cdd8SDimitry Andric                                   VisibleCallback Vis, ConflictCallback Cb) {
683e3b55780SDimitry Andric   // We can't import a global module fragment so the location can be invalid.
684e3b55780SDimitry Andric   assert((M->isGlobalModule() || Loc.isValid()) &&
685e3b55780SDimitry Andric          "setVisible expects a valid import location");
6865e20cdd8SDimitry Andric   if (isVisible(M))
6875e20cdd8SDimitry Andric     return;
688dbe13110SDimitry Andric 
6895e20cdd8SDimitry Andric   ++Generation;
6905e20cdd8SDimitry Andric 
6915e20cdd8SDimitry Andric   struct Visiting {
6925e20cdd8SDimitry Andric     Module *M;
6935e20cdd8SDimitry Andric     Visiting *ExportedBy;
6945e20cdd8SDimitry Andric   };
6955e20cdd8SDimitry Andric 
6965e20cdd8SDimitry Andric   std::function<void(Visiting)> VisitModule = [&](Visiting V) {
6975e20cdd8SDimitry Andric     // Nothing to do for a module that's already visible.
6985e20cdd8SDimitry Andric     unsigned ID = V.M->getVisibilityID();
6995e20cdd8SDimitry Andric     if (ImportLocs.size() <= ID)
7005e20cdd8SDimitry Andric       ImportLocs.resize(ID + 1);
7015e20cdd8SDimitry Andric     else if (ImportLocs[ID].isValid())
7025e20cdd8SDimitry Andric       return;
7035e20cdd8SDimitry Andric 
7045e20cdd8SDimitry Andric     ImportLocs[ID] = Loc;
705e3b55780SDimitry Andric     Vis(V.M);
7065e20cdd8SDimitry Andric 
7075e20cdd8SDimitry Andric     // Make any exported modules visible.
7085e20cdd8SDimitry Andric     SmallVector<Module *, 16> Exports;
7095e20cdd8SDimitry Andric     V.M->getExportedModules(Exports);
710676fbe81SDimitry Andric     for (Module *E : Exports) {
711cfca06d7SDimitry Andric       // Don't import non-importable modules.
712cfca06d7SDimitry Andric       if (!E->isUnimportable())
7135e20cdd8SDimitry Andric         VisitModule({E, &V});
714676fbe81SDimitry Andric     }
7155e20cdd8SDimitry Andric 
7165e20cdd8SDimitry Andric     for (auto &C : V.M->Conflicts) {
7175e20cdd8SDimitry Andric       if (isVisible(C.Other)) {
7185e20cdd8SDimitry Andric         llvm::SmallVector<Module*, 8> Path;
7195e20cdd8SDimitry Andric         for (Visiting *I = &V; I; I = I->ExportedBy)
7205e20cdd8SDimitry Andric           Path.push_back(I->M);
7215e20cdd8SDimitry Andric         Cb(Path, C.Other, C.Message);
7225e20cdd8SDimitry Andric       }
7235e20cdd8SDimitry Andric     }
7245e20cdd8SDimitry Andric   };
7255e20cdd8SDimitry Andric   VisitModule({M, nullptr});
7265e20cdd8SDimitry Andric }
727