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