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