10b57cec5SDimitry Andric //===- Module.cpp - Describe a module -------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the Module class, which describes a module in the source
100b57cec5SDimitry Andric // code.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "clang/Basic/Module.h"
150b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
160b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
170b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
180b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
190b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
250b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
270b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
280b57cec5SDimitry Andric #include <algorithm>
290b57cec5SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <functional>
310b57cec5SDimitry Andric #include <string>
320b57cec5SDimitry Andric #include <utility>
330b57cec5SDimitry Andric #include <vector>
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric using namespace clang;
360b57cec5SDimitry Andric
Module(StringRef Name,SourceLocation DefinitionLoc,Module * Parent,bool IsFramework,bool IsExplicit,unsigned VisibilityID)370b57cec5SDimitry Andric Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
380b57cec5SDimitry Andric bool IsFramework, bool IsExplicit, unsigned VisibilityID)
390b57cec5SDimitry Andric : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
405ffd83dbSDimitry Andric VisibilityID(VisibilityID), IsUnimportable(false),
410b57cec5SDimitry Andric HasIncompatibleModuleFile(false), IsAvailable(true),
420b57cec5SDimitry Andric IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),
430b57cec5SDimitry Andric IsSystem(false), IsExternC(false), IsInferred(false),
440b57cec5SDimitry Andric InferSubmodules(false), InferExplicitSubmodules(false),
450b57cec5SDimitry Andric InferExportWildcard(false), ConfigMacrosExhaustive(false),
460b57cec5SDimitry Andric NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
475f757f3fSDimitry Andric NamedModuleHasInit(true), NameVisibility(Hidden) {
480b57cec5SDimitry Andric if (Parent) {
495ffd83dbSDimitry Andric IsAvailable = Parent->isAvailable();
505ffd83dbSDimitry Andric IsUnimportable = Parent->isUnimportable();
515ffd83dbSDimitry Andric IsSystem = Parent->IsSystem;
525ffd83dbSDimitry Andric IsExternC = Parent->IsExternC;
535ffd83dbSDimitry Andric NoUndeclaredIncludes = Parent->NoUndeclaredIncludes;
545ffd83dbSDimitry Andric ModuleMapIsPrivate = Parent->ModuleMapIsPrivate;
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric Parent->SubModuleIndex[Name] = Parent->SubModules.size();
570b57cec5SDimitry Andric Parent->SubModules.push_back(this);
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
~Module()610b57cec5SDimitry Andric Module::~Module() {
6206c3fb27SDimitry Andric for (auto *Submodule : SubModules) {
6306c3fb27SDimitry Andric delete Submodule;
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
isPlatformEnvironment(const TargetInfo & Target,StringRef Feature)670b57cec5SDimitry Andric static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
680b57cec5SDimitry Andric StringRef Platform = Target.getPlatformName();
690b57cec5SDimitry Andric StringRef Env = Target.getTriple().getEnvironmentName();
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric // Attempt to match platform and environment.
720b57cec5SDimitry Andric if (Platform == Feature || Target.getTriple().getOSName() == Feature ||
730b57cec5SDimitry Andric Env == Feature)
740b57cec5SDimitry Andric return true;
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {
77e8d8bef9SDimitry Andric auto Pos = LHS.find('-');
780b57cec5SDimitry Andric if (Pos == StringRef::npos)
790b57cec5SDimitry Andric return false;
800b57cec5SDimitry Andric SmallString<128> NewLHS = LHS.slice(0, Pos);
810b57cec5SDimitry Andric NewLHS += LHS.slice(Pos+1, LHS.size());
820b57cec5SDimitry Andric return NewLHS == RHS;
830b57cec5SDimitry Andric };
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName();
860b57cec5SDimitry Andric // Darwin has different but equivalent variants for simulators, example:
870b57cec5SDimitry Andric // 1. x86_64-apple-ios-simulator
880b57cec5SDimitry Andric // 2. x86_64-apple-iossimulator
890b57cec5SDimitry Andric // where both are valid examples of the same platform+environment but in the
900b57cec5SDimitry Andric // variant (2) the simulator is hardcoded as part of the platform name. Both
910b57cec5SDimitry Andric // forms above should match for "iossimulator" requirement.
925f757f3fSDimitry Andric if (Target.getTriple().isOSDarwin() && PlatformEnv.ends_with("simulator"))
930b57cec5SDimitry Andric return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric return PlatformEnv == Feature;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric /// Determine whether a translation unit built using the current
990b57cec5SDimitry Andric /// language options has the given feature.
hasFeature(StringRef Feature,const LangOptions & LangOpts,const TargetInfo & Target)1000b57cec5SDimitry Andric static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
1010b57cec5SDimitry Andric const TargetInfo &Target) {
1020b57cec5SDimitry Andric bool HasFeature = llvm::StringSwitch<bool>(Feature)
1030b57cec5SDimitry Andric .Case("altivec", LangOpts.AltiVec)
1040b57cec5SDimitry Andric .Case("blocks", LangOpts.Blocks)
1050b57cec5SDimitry Andric .Case("coroutines", LangOpts.Coroutines)
1060b57cec5SDimitry Andric .Case("cplusplus", LangOpts.CPlusPlus)
1070b57cec5SDimitry Andric .Case("cplusplus11", LangOpts.CPlusPlus11)
1080b57cec5SDimitry Andric .Case("cplusplus14", LangOpts.CPlusPlus14)
1090b57cec5SDimitry Andric .Case("cplusplus17", LangOpts.CPlusPlus17)
11006c3fb27SDimitry Andric .Case("cplusplus20", LangOpts.CPlusPlus20)
11106c3fb27SDimitry Andric .Case("cplusplus23", LangOpts.CPlusPlus23)
11206c3fb27SDimitry Andric .Case("cplusplus26", LangOpts.CPlusPlus26)
1130b57cec5SDimitry Andric .Case("c99", LangOpts.C99)
1140b57cec5SDimitry Andric .Case("c11", LangOpts.C11)
1150b57cec5SDimitry Andric .Case("c17", LangOpts.C17)
1165f757f3fSDimitry Andric .Case("c23", LangOpts.C23)
1170b57cec5SDimitry Andric .Case("freestanding", LangOpts.Freestanding)
1180b57cec5SDimitry Andric .Case("gnuinlineasm", LangOpts.GNUAsm)
1190b57cec5SDimitry Andric .Case("objc", LangOpts.ObjC)
1200b57cec5SDimitry Andric .Case("objc_arc", LangOpts.ObjCAutoRefCount)
1210b57cec5SDimitry Andric .Case("opencl", LangOpts.OpenCL)
1220b57cec5SDimitry Andric .Case("tls", Target.isTLSSupported())
1230b57cec5SDimitry Andric .Case("zvector", LangOpts.ZVector)
1240b57cec5SDimitry Andric .Default(Target.hasFeature(Feature) ||
1250b57cec5SDimitry Andric isPlatformEnvironment(Target, Feature));
1260b57cec5SDimitry Andric if (!HasFeature)
127349cc55cSDimitry Andric HasFeature = llvm::is_contained(LangOpts.ModuleFeatures, Feature);
1280b57cec5SDimitry Andric return HasFeature;
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
isUnimportable(const LangOptions & LangOpts,const TargetInfo & Target,Requirement & Req,Module * & ShadowingModule) const1315ffd83dbSDimitry Andric bool Module::isUnimportable(const LangOptions &LangOpts,
1325ffd83dbSDimitry Andric const TargetInfo &Target, Requirement &Req,
1335ffd83dbSDimitry Andric Module *&ShadowingModule) const {
1345ffd83dbSDimitry Andric if (!IsUnimportable)
1355ffd83dbSDimitry Andric return false;
1365ffd83dbSDimitry Andric
1375ffd83dbSDimitry Andric for (const Module *Current = this; Current; Current = Current->Parent) {
1385ffd83dbSDimitry Andric if (Current->ShadowingModule) {
1395ffd83dbSDimitry Andric ShadowingModule = Current->ShadowingModule;
1405ffd83dbSDimitry Andric return true;
1415ffd83dbSDimitry Andric }
1425ffd83dbSDimitry Andric for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
143*0fca6ea1SDimitry Andric if (hasFeature(Current->Requirements[I].FeatureName, LangOpts, Target) !=
144*0fca6ea1SDimitry Andric Current->Requirements[I].RequiredState) {
1455ffd83dbSDimitry Andric Req = Current->Requirements[I];
1465ffd83dbSDimitry Andric return true;
1475ffd83dbSDimitry Andric }
1485ffd83dbSDimitry Andric }
1495ffd83dbSDimitry Andric }
1505ffd83dbSDimitry Andric
1515ffd83dbSDimitry Andric llvm_unreachable("could not find a reason why module is unimportable");
1525ffd83dbSDimitry Andric }
1535ffd83dbSDimitry Andric
154bdd1243dSDimitry Andric // The -fmodule-name option tells the compiler to textually include headers in
155bdd1243dSDimitry Andric // the specified module, meaning Clang won't build the specified module. This
156bdd1243dSDimitry Andric // is useful in a number of situations, for instance, when building a library
157bdd1243dSDimitry Andric // that vends a module map, one might want to avoid hitting intermediate build
158bdd1243dSDimitry Andric // products containing the module map or avoid finding the system installed
159bdd1243dSDimitry Andric // modulemap for that library.
isForBuilding(const LangOptions & LangOpts) const160bdd1243dSDimitry Andric bool Module::isForBuilding(const LangOptions &LangOpts) const {
161bdd1243dSDimitry Andric StringRef TopLevelName = getTopLevelModuleName();
162bdd1243dSDimitry Andric StringRef CurrentModule = LangOpts.CurrentModule;
163bdd1243dSDimitry Andric
1645f757f3fSDimitry Andric // When building the implementation of framework Foo, we want to make sure
1655f757f3fSDimitry Andric // that Foo *and* Foo_Private are textually included and no modules are built
1665f757f3fSDimitry Andric // for either.
1675f757f3fSDimitry Andric if (!LangOpts.isCompilingModule() && getTopLevelModule()->IsFramework &&
168bdd1243dSDimitry Andric CurrentModule == LangOpts.ModuleName &&
1695f757f3fSDimitry Andric !CurrentModule.ends_with("_Private") &&
1705f757f3fSDimitry Andric TopLevelName.ends_with("_Private"))
171bdd1243dSDimitry Andric TopLevelName = TopLevelName.drop_back(8);
172bdd1243dSDimitry Andric
173bdd1243dSDimitry Andric return TopLevelName == CurrentModule;
174bdd1243dSDimitry Andric }
175bdd1243dSDimitry Andric
isAvailable(const LangOptions & LangOpts,const TargetInfo & Target,Requirement & Req,UnresolvedHeaderDirective & MissingHeader,Module * & ShadowingModule) const1760b57cec5SDimitry Andric bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
1770b57cec5SDimitry Andric Requirement &Req,
1780b57cec5SDimitry Andric UnresolvedHeaderDirective &MissingHeader,
1790b57cec5SDimitry Andric Module *&ShadowingModule) const {
1800b57cec5SDimitry Andric if (IsAvailable)
1810b57cec5SDimitry Andric return true;
1820b57cec5SDimitry Andric
1835ffd83dbSDimitry Andric if (isUnimportable(LangOpts, Target, Req, ShadowingModule))
1845ffd83dbSDimitry Andric return false;
1855ffd83dbSDimitry Andric
1865ffd83dbSDimitry Andric // FIXME: All missing headers are listed on the top-level module. Should we
1875ffd83dbSDimitry Andric // just look there?
1880b57cec5SDimitry Andric for (const Module *Current = this; Current; Current = Current->Parent) {
1890b57cec5SDimitry Andric if (!Current->MissingHeaders.empty()) {
1900b57cec5SDimitry Andric MissingHeader = Current->MissingHeaders.front();
1910b57cec5SDimitry Andric return false;
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric llvm_unreachable("could not find a reason why module is unavailable");
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
isSubModuleOf(const Module * Other) const1980b57cec5SDimitry Andric bool Module::isSubModuleOf(const Module *Other) const {
199e8d8bef9SDimitry Andric for (auto *Parent = this; Parent; Parent = Parent->Parent) {
200e8d8bef9SDimitry Andric if (Parent == Other)
2010b57cec5SDimitry Andric return true;
202e8d8bef9SDimitry Andric }
2030b57cec5SDimitry Andric return false;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric
getTopLevelModule() const2060b57cec5SDimitry Andric const Module *Module::getTopLevelModule() const {
2070b57cec5SDimitry Andric const Module *Result = this;
2080b57cec5SDimitry Andric while (Result->Parent)
2090b57cec5SDimitry Andric Result = Result->Parent;
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric return Result;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
getModuleNameFromComponent(const std::pair<std::string,SourceLocation> & IdComponent)2140b57cec5SDimitry Andric static StringRef getModuleNameFromComponent(
2150b57cec5SDimitry Andric const std::pair<std::string, SourceLocation> &IdComponent) {
2160b57cec5SDimitry Andric return IdComponent.first;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
getModuleNameFromComponent(StringRef R)2190b57cec5SDimitry Andric static StringRef getModuleNameFromComponent(StringRef R) { return R; }
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric template<typename InputIter>
printModuleId(raw_ostream & OS,InputIter Begin,InputIter End,bool AllowStringLiterals=true)2220b57cec5SDimitry Andric static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,
2230b57cec5SDimitry Andric bool AllowStringLiterals = true) {
2240b57cec5SDimitry Andric for (InputIter It = Begin; It != End; ++It) {
2250b57cec5SDimitry Andric if (It != Begin)
2260b57cec5SDimitry Andric OS << ".";
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric StringRef Name = getModuleNameFromComponent(*It);
229349cc55cSDimitry Andric if (!AllowStringLiterals || isValidAsciiIdentifier(Name))
2300b57cec5SDimitry Andric OS << Name;
2310b57cec5SDimitry Andric else {
2320b57cec5SDimitry Andric OS << '"';
2330b57cec5SDimitry Andric OS.write_escaped(Name);
2340b57cec5SDimitry Andric OS << '"';
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric
2390b57cec5SDimitry Andric template<typename Container>
printModuleId(raw_ostream & OS,const Container & C)2400b57cec5SDimitry Andric static void printModuleId(raw_ostream &OS, const Container &C) {
2410b57cec5SDimitry Andric return printModuleId(OS, C.begin(), C.end());
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric
getFullModuleName(bool AllowStringLiterals) const2440b57cec5SDimitry Andric std::string Module::getFullModuleName(bool AllowStringLiterals) const {
2450b57cec5SDimitry Andric SmallVector<StringRef, 2> Names;
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric // Build up the set of module names (from innermost to outermost).
2480b57cec5SDimitry Andric for (const Module *M = this; M; M = M->Parent)
2490b57cec5SDimitry Andric Names.push_back(M->Name);
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric std::string Result;
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric llvm::raw_string_ostream Out(Result);
2540b57cec5SDimitry Andric printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);
2550b57cec5SDimitry Andric Out.flush();
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric return Result;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric
fullModuleNameIs(ArrayRef<StringRef> nameParts) const2600b57cec5SDimitry Andric bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
2610b57cec5SDimitry Andric for (const Module *M = this; M; M = M->Parent) {
2620b57cec5SDimitry Andric if (nameParts.empty() || M->Name != nameParts.back())
2630b57cec5SDimitry Andric return false;
2640b57cec5SDimitry Andric nameParts = nameParts.drop_back();
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric return nameParts.empty();
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric
getEffectiveUmbrellaDir() const26906c3fb27SDimitry Andric OptionalDirectoryEntryRef Module::getEffectiveUmbrellaDir() const {
2705f757f3fSDimitry Andric if (const auto *Hdr = std::get_if<FileEntryRef>(&Umbrella))
2715f757f3fSDimitry Andric return Hdr->getDir();
2725f757f3fSDimitry Andric if (const auto *Dir = std::get_if<DirectoryEntryRef>(&Umbrella))
2735f757f3fSDimitry Andric return *Dir;
27406c3fb27SDimitry Andric return std::nullopt;
2755ffd83dbSDimitry Andric }
2765ffd83dbSDimitry Andric
addTopHeader(FileEntryRef File)27706c3fb27SDimitry Andric void Module::addTopHeader(FileEntryRef File) {
2785ffd83dbSDimitry Andric assert(File);
2795ffd83dbSDimitry Andric TopHeaders.insert(File);
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric
getTopHeaders(FileManager & FileMgr)28206c3fb27SDimitry Andric ArrayRef<FileEntryRef> Module::getTopHeaders(FileManager &FileMgr) {
2830b57cec5SDimitry Andric if (!TopHeaderNames.empty()) {
28406c3fb27SDimitry Andric for (StringRef TopHeaderName : TopHeaderNames)
28506c3fb27SDimitry Andric if (auto FE = FileMgr.getOptionalFileRef(TopHeaderName))
286a7dea167SDimitry Andric TopHeaders.insert(*FE);
2870b57cec5SDimitry Andric TopHeaderNames.clear();
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric
290bdd1243dSDimitry Andric return llvm::ArrayRef(TopHeaders.begin(), TopHeaders.end());
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
directlyUses(const Module * Requested)29381ad6265SDimitry Andric bool Module::directlyUses(const Module *Requested) {
2940b57cec5SDimitry Andric auto *Top = getTopLevelModule();
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric // A top-level module implicitly uses itself.
2970b57cec5SDimitry Andric if (Requested->isSubModuleOf(Top))
2980b57cec5SDimitry Andric return true;
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric for (auto *Use : Top->DirectUses)
3010b57cec5SDimitry Andric if (Requested->isSubModuleOf(Use))
3020b57cec5SDimitry Andric return true;
3030b57cec5SDimitry Andric
304439352acSDimitry Andric // Anyone is allowed to use our builtin stddef.h and its accompanying modules.
305439352acSDimitry Andric if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) ||
306439352acSDimitry Andric Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"}))
3070b57cec5SDimitry Andric return true;
308*0fca6ea1SDimitry Andric // Darwin is allowed is to use our builtin 'ptrauth.h' and its accompanying
309*0fca6ea1SDimitry Andric // module.
310*0fca6ea1SDimitry Andric if (!Requested->Parent && Requested->Name == "ptrauth")
311*0fca6ea1SDimitry Andric return true;
3120b57cec5SDimitry Andric
31381ad6265SDimitry Andric if (NoUndeclaredIncludes)
31481ad6265SDimitry Andric UndeclaredUses.insert(Requested);
31581ad6265SDimitry Andric
3160b57cec5SDimitry Andric return false;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric
addRequirement(StringRef Feature,bool RequiredState,const LangOptions & LangOpts,const TargetInfo & Target)3190b57cec5SDimitry Andric void Module::addRequirement(StringRef Feature, bool RequiredState,
3200b57cec5SDimitry Andric const LangOptions &LangOpts,
3210b57cec5SDimitry Andric const TargetInfo &Target) {
322*0fca6ea1SDimitry Andric Requirements.push_back(Requirement{std::string(Feature), RequiredState});
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric // If this feature is currently available, we're done.
3250b57cec5SDimitry Andric if (hasFeature(Feature, LangOpts, Target) == RequiredState)
3260b57cec5SDimitry Andric return;
3270b57cec5SDimitry Andric
3285ffd83dbSDimitry Andric markUnavailable(/*Unimportable*/true);
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric
markUnavailable(bool Unimportable)3315ffd83dbSDimitry Andric void Module::markUnavailable(bool Unimportable) {
3325ffd83dbSDimitry Andric auto needUpdate = [Unimportable](Module *M) {
3335ffd83dbSDimitry Andric return M->IsAvailable || (!M->IsUnimportable && Unimportable);
3340b57cec5SDimitry Andric };
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric if (!needUpdate(this))
3370b57cec5SDimitry Andric return;
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric SmallVector<Module *, 2> Stack;
3400b57cec5SDimitry Andric Stack.push_back(this);
3410b57cec5SDimitry Andric while (!Stack.empty()) {
3420b57cec5SDimitry Andric Module *Current = Stack.back();
3430b57cec5SDimitry Andric Stack.pop_back();
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric if (!needUpdate(Current))
3460b57cec5SDimitry Andric continue;
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric Current->IsAvailable = false;
3495ffd83dbSDimitry Andric Current->IsUnimportable |= Unimportable;
35006c3fb27SDimitry Andric for (auto *Submodule : Current->submodules()) {
35106c3fb27SDimitry Andric if (needUpdate(Submodule))
35206c3fb27SDimitry Andric Stack.push_back(Submodule);
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
findSubmodule(StringRef Name) const3570b57cec5SDimitry Andric Module *Module::findSubmodule(StringRef Name) const {
3580b57cec5SDimitry Andric llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
3590b57cec5SDimitry Andric if (Pos == SubModuleIndex.end())
3600b57cec5SDimitry Andric return nullptr;
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric return SubModules[Pos->getValue()];
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
findOrInferSubmodule(StringRef Name)3650b57cec5SDimitry Andric Module *Module::findOrInferSubmodule(StringRef Name) {
3660b57cec5SDimitry Andric llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
3670b57cec5SDimitry Andric if (Pos != SubModuleIndex.end())
3680b57cec5SDimitry Andric return SubModules[Pos->getValue()];
3690b57cec5SDimitry Andric if (!InferSubmodules)
3700b57cec5SDimitry Andric return nullptr;
3710b57cec5SDimitry Andric Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
3720b57cec5SDimitry Andric Result->InferExplicitSubmodules = InferExplicitSubmodules;
3730b57cec5SDimitry Andric Result->InferSubmodules = InferSubmodules;
3740b57cec5SDimitry Andric Result->InferExportWildcard = InferExportWildcard;
3750b57cec5SDimitry Andric if (Result->InferExportWildcard)
3760b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
3770b57cec5SDimitry Andric return Result;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric
getGlobalModuleFragment() const3805f757f3fSDimitry Andric Module *Module::getGlobalModuleFragment() const {
3815f757f3fSDimitry Andric assert(isNamedModuleUnit() && "We should only query the global module "
3825f757f3fSDimitry Andric "fragment from the C++20 Named modules");
3835f757f3fSDimitry Andric
3845f757f3fSDimitry Andric for (auto *SubModule : SubModules)
3855f757f3fSDimitry Andric if (SubModule->isExplicitGlobalModule())
3865f757f3fSDimitry Andric return SubModule;
3875f757f3fSDimitry Andric
3885f757f3fSDimitry Andric return nullptr;
3895f757f3fSDimitry Andric }
3905f757f3fSDimitry Andric
getPrivateModuleFragment() const3915f757f3fSDimitry Andric Module *Module::getPrivateModuleFragment() const {
3925f757f3fSDimitry Andric assert(isNamedModuleUnit() && "We should only query the private module "
3935f757f3fSDimitry Andric "fragment from the C++20 Named modules");
3945f757f3fSDimitry Andric
3955f757f3fSDimitry Andric for (auto *SubModule : SubModules)
3965f757f3fSDimitry Andric if (SubModule->isPrivateModule())
3975f757f3fSDimitry Andric return SubModule;
3985f757f3fSDimitry Andric
3995f757f3fSDimitry Andric return nullptr;
4005f757f3fSDimitry Andric }
4015f757f3fSDimitry Andric
getExportedModules(SmallVectorImpl<Module * > & Exported) const4020b57cec5SDimitry Andric void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
4030b57cec5SDimitry Andric // All non-explicit submodules are exported.
4040b57cec5SDimitry Andric for (std::vector<Module *>::const_iterator I = SubModules.begin(),
4050b57cec5SDimitry Andric E = SubModules.end();
4060b57cec5SDimitry Andric I != E; ++I) {
4070b57cec5SDimitry Andric Module *Mod = *I;
4080b57cec5SDimitry Andric if (!Mod->IsExplicit)
4090b57cec5SDimitry Andric Exported.push_back(Mod);
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric // Find re-exported modules by filtering the list of imported modules.
4130b57cec5SDimitry Andric bool AnyWildcard = false;
4140b57cec5SDimitry Andric bool UnrestrictedWildcard = false;
4150b57cec5SDimitry Andric SmallVector<Module *, 4> WildcardRestrictions;
4160b57cec5SDimitry Andric for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
4170b57cec5SDimitry Andric Module *Mod = Exports[I].getPointer();
4180b57cec5SDimitry Andric if (!Exports[I].getInt()) {
4190b57cec5SDimitry Andric // Export a named module directly; no wildcards involved.
4200b57cec5SDimitry Andric Exported.push_back(Mod);
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andric continue;
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric // Wildcard export: export all of the imported modules that match
4260b57cec5SDimitry Andric // the given pattern.
4270b57cec5SDimitry Andric AnyWildcard = true;
4280b57cec5SDimitry Andric if (UnrestrictedWildcard)
4290b57cec5SDimitry Andric continue;
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric if (Module *Restriction = Exports[I].getPointer())
4320b57cec5SDimitry Andric WildcardRestrictions.push_back(Restriction);
4330b57cec5SDimitry Andric else {
4340b57cec5SDimitry Andric WildcardRestrictions.clear();
4350b57cec5SDimitry Andric UnrestrictedWildcard = true;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric
4390b57cec5SDimitry Andric // If there were any wildcards, push any imported modules that were
4400b57cec5SDimitry Andric // re-exported by the wildcard restriction.
4410b57cec5SDimitry Andric if (!AnyWildcard)
4420b57cec5SDimitry Andric return;
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric for (unsigned I = 0, N = Imports.size(); I != N; ++I) {
4450b57cec5SDimitry Andric Module *Mod = Imports[I];
4460b57cec5SDimitry Andric bool Acceptable = UnrestrictedWildcard;
4470b57cec5SDimitry Andric if (!Acceptable) {
4480b57cec5SDimitry Andric // Check whether this module meets one of the restrictions.
4490b57cec5SDimitry Andric for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {
4500b57cec5SDimitry Andric Module *Restriction = WildcardRestrictions[R];
4510b57cec5SDimitry Andric if (Mod == Restriction || Mod->isSubModuleOf(Restriction)) {
4520b57cec5SDimitry Andric Acceptable = true;
4530b57cec5SDimitry Andric break;
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric
4580b57cec5SDimitry Andric if (!Acceptable)
4590b57cec5SDimitry Andric continue;
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric Exported.push_back(Mod);
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric
buildVisibleModulesCache() const4650b57cec5SDimitry Andric void Module::buildVisibleModulesCache() const {
4660b57cec5SDimitry Andric assert(VisibleModulesCache.empty() && "cache does not need building");
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric // This module is visible to itself.
4690b57cec5SDimitry Andric VisibleModulesCache.insert(this);
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric // Every imported module is visible.
4720b57cec5SDimitry Andric SmallVector<Module *, 16> Stack(Imports.begin(), Imports.end());
4730b57cec5SDimitry Andric while (!Stack.empty()) {
4740b57cec5SDimitry Andric Module *CurrModule = Stack.pop_back_val();
4750b57cec5SDimitry Andric
4760b57cec5SDimitry Andric // Every module transitively exported by an imported module is visible.
4770b57cec5SDimitry Andric if (VisibleModulesCache.insert(CurrModule).second)
4780b57cec5SDimitry Andric CurrModule->getExportedModules(Stack);
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric
print(raw_ostream & OS,unsigned Indent,bool Dump) const482fe6060f1SDimitry Andric void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
4830b57cec5SDimitry Andric OS.indent(Indent);
4840b57cec5SDimitry Andric if (IsFramework)
4850b57cec5SDimitry Andric OS << "framework ";
4860b57cec5SDimitry Andric if (IsExplicit)
4870b57cec5SDimitry Andric OS << "explicit ";
4880b57cec5SDimitry Andric OS << "module ";
4890b57cec5SDimitry Andric printModuleId(OS, &Name, &Name + 1);
4900b57cec5SDimitry Andric
4910b57cec5SDimitry Andric if (IsSystem || IsExternC) {
4920b57cec5SDimitry Andric OS.indent(Indent + 2);
4930b57cec5SDimitry Andric if (IsSystem)
4940b57cec5SDimitry Andric OS << " [system]";
4950b57cec5SDimitry Andric if (IsExternC)
4960b57cec5SDimitry Andric OS << " [extern_c]";
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric OS << " {\n";
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric if (!Requirements.empty()) {
5020b57cec5SDimitry Andric OS.indent(Indent + 2);
5030b57cec5SDimitry Andric OS << "requires ";
5040b57cec5SDimitry Andric for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {
5050b57cec5SDimitry Andric if (I)
5060b57cec5SDimitry Andric OS << ", ";
507*0fca6ea1SDimitry Andric if (!Requirements[I].RequiredState)
5080b57cec5SDimitry Andric OS << "!";
509*0fca6ea1SDimitry Andric OS << Requirements[I].FeatureName;
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric OS << "\n";
5120b57cec5SDimitry Andric }
5130b57cec5SDimitry Andric
51406c3fb27SDimitry Andric if (std::optional<Header> H = getUmbrellaHeaderAsWritten()) {
5150b57cec5SDimitry Andric OS.indent(Indent + 2);
5160b57cec5SDimitry Andric OS << "umbrella header \"";
51706c3fb27SDimitry Andric OS.write_escaped(H->NameAsWritten);
5180b57cec5SDimitry Andric OS << "\"\n";
51906c3fb27SDimitry Andric } else if (std::optional<DirectoryName> D = getUmbrellaDirAsWritten()) {
5200b57cec5SDimitry Andric OS.indent(Indent + 2);
5210b57cec5SDimitry Andric OS << "umbrella \"";
52206c3fb27SDimitry Andric OS.write_escaped(D->NameAsWritten);
5230b57cec5SDimitry Andric OS << "\"\n";
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric
5260b57cec5SDimitry Andric if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {
5270b57cec5SDimitry Andric OS.indent(Indent + 2);
5280b57cec5SDimitry Andric OS << "config_macros ";
5290b57cec5SDimitry Andric if (ConfigMacrosExhaustive)
5300b57cec5SDimitry Andric OS << "[exhaustive]";
5310b57cec5SDimitry Andric for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {
5320b57cec5SDimitry Andric if (I)
5330b57cec5SDimitry Andric OS << ", ";
5340b57cec5SDimitry Andric OS << ConfigMacros[I];
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric OS << "\n";
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric struct {
5400b57cec5SDimitry Andric StringRef Prefix;
5410b57cec5SDimitry Andric HeaderKind Kind;
5420b57cec5SDimitry Andric } Kinds[] = {{"", HK_Normal},
5430b57cec5SDimitry Andric {"textual ", HK_Textual},
5440b57cec5SDimitry Andric {"private ", HK_Private},
5450b57cec5SDimitry Andric {"private textual ", HK_PrivateTextual},
5460b57cec5SDimitry Andric {"exclude ", HK_Excluded}};
5470b57cec5SDimitry Andric
5480b57cec5SDimitry Andric for (auto &K : Kinds) {
5490b57cec5SDimitry Andric assert(&K == &Kinds[K.Kind] && "kinds in wrong order");
5500b57cec5SDimitry Andric for (auto &H : Headers[K.Kind]) {
5510b57cec5SDimitry Andric OS.indent(Indent + 2);
5520b57cec5SDimitry Andric OS << K.Prefix << "header \"";
5530b57cec5SDimitry Andric OS.write_escaped(H.NameAsWritten);
55406c3fb27SDimitry Andric OS << "\" { size " << H.Entry.getSize()
55506c3fb27SDimitry Andric << " mtime " << H.Entry.getModificationTime() << " }\n";
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric }
5580b57cec5SDimitry Andric for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) {
5590b57cec5SDimitry Andric for (auto &U : *Unresolved) {
5600b57cec5SDimitry Andric OS.indent(Indent + 2);
5610b57cec5SDimitry Andric OS << Kinds[U.Kind].Prefix << "header \"";
5620b57cec5SDimitry Andric OS.write_escaped(U.FileName);
5630b57cec5SDimitry Andric OS << "\"";
5640b57cec5SDimitry Andric if (U.Size || U.ModTime) {
5650b57cec5SDimitry Andric OS << " {";
5660b57cec5SDimitry Andric if (U.Size)
5670b57cec5SDimitry Andric OS << " size " << *U.Size;
5680b57cec5SDimitry Andric if (U.ModTime)
5690b57cec5SDimitry Andric OS << " mtime " << *U.ModTime;
5700b57cec5SDimitry Andric OS << " }";
5710b57cec5SDimitry Andric }
5720b57cec5SDimitry Andric OS << "\n";
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric if (!ExportAsModule.empty()) {
5770b57cec5SDimitry Andric OS.indent(Indent + 2);
5780b57cec5SDimitry Andric OS << "export_as" << ExportAsModule << "\n";
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric
58106c3fb27SDimitry Andric for (auto *Submodule : submodules())
5820b57cec5SDimitry Andric // Print inferred subframework modules so that we don't need to re-infer
5830b57cec5SDimitry Andric // them (requires expensive directory iteration + stat calls) when we build
5840b57cec5SDimitry Andric // the module. Regular inferred submodules are OK, as we need to look at all
5850b57cec5SDimitry Andric // those header files anyway.
58606c3fb27SDimitry Andric if (!Submodule->IsInferred || Submodule->IsFramework)
58706c3fb27SDimitry Andric Submodule->print(OS, Indent + 2, Dump);
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
5900b57cec5SDimitry Andric OS.indent(Indent + 2);
5910b57cec5SDimitry Andric OS << "export ";
5920b57cec5SDimitry Andric if (Module *Restriction = Exports[I].getPointer()) {
5930b57cec5SDimitry Andric OS << Restriction->getFullModuleName(true);
5940b57cec5SDimitry Andric if (Exports[I].getInt())
5950b57cec5SDimitry Andric OS << ".*";
5960b57cec5SDimitry Andric } else {
5970b57cec5SDimitry Andric OS << "*";
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric OS << "\n";
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
6030b57cec5SDimitry Andric OS.indent(Indent + 2);
6040b57cec5SDimitry Andric OS << "export ";
6050b57cec5SDimitry Andric printModuleId(OS, UnresolvedExports[I].Id);
6060b57cec5SDimitry Andric if (UnresolvedExports[I].Wildcard)
6070b57cec5SDimitry Andric OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");
6080b57cec5SDimitry Andric OS << "\n";
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric
611fe6060f1SDimitry Andric if (Dump) {
612fe6060f1SDimitry Andric for (Module *M : Imports) {
613fe6060f1SDimitry Andric OS.indent(Indent + 2);
614fe6060f1SDimitry Andric llvm::errs() << "import " << M->getFullModuleName() << "\n";
615fe6060f1SDimitry Andric }
616fe6060f1SDimitry Andric }
617fe6060f1SDimitry Andric
6180b57cec5SDimitry Andric for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
6190b57cec5SDimitry Andric OS.indent(Indent + 2);
6200b57cec5SDimitry Andric OS << "use ";
6210b57cec5SDimitry Andric OS << DirectUses[I]->getFullModuleName(true);
6220b57cec5SDimitry Andric OS << "\n";
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andric for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) {
6260b57cec5SDimitry Andric OS.indent(Indent + 2);
6270b57cec5SDimitry Andric OS << "use ";
6280b57cec5SDimitry Andric printModuleId(OS, UnresolvedDirectUses[I]);
6290b57cec5SDimitry Andric OS << "\n";
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) {
6330b57cec5SDimitry Andric OS.indent(Indent + 2);
6340b57cec5SDimitry Andric OS << "link ";
6350b57cec5SDimitry Andric if (LinkLibraries[I].IsFramework)
6360b57cec5SDimitry Andric OS << "framework ";
6370b57cec5SDimitry Andric OS << "\"";
6380b57cec5SDimitry Andric OS.write_escaped(LinkLibraries[I].Library);
6390b57cec5SDimitry Andric OS << "\"";
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric
6420b57cec5SDimitry Andric for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) {
6430b57cec5SDimitry Andric OS.indent(Indent + 2);
6440b57cec5SDimitry Andric OS << "conflict ";
6450b57cec5SDimitry Andric printModuleId(OS, UnresolvedConflicts[I].Id);
6460b57cec5SDimitry Andric OS << ", \"";
6470b57cec5SDimitry Andric OS.write_escaped(UnresolvedConflicts[I].Message);
6480b57cec5SDimitry Andric OS << "\"\n";
6490b57cec5SDimitry Andric }
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {
6520b57cec5SDimitry Andric OS.indent(Indent + 2);
6530b57cec5SDimitry Andric OS << "conflict ";
6540b57cec5SDimitry Andric OS << Conflicts[I].Other->getFullModuleName(true);
6550b57cec5SDimitry Andric OS << ", \"";
6560b57cec5SDimitry Andric OS.write_escaped(Conflicts[I].Message);
6570b57cec5SDimitry Andric OS << "\"\n";
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric
6600b57cec5SDimitry Andric if (InferSubmodules) {
6610b57cec5SDimitry Andric OS.indent(Indent + 2);
6620b57cec5SDimitry Andric if (InferExplicitSubmodules)
6630b57cec5SDimitry Andric OS << "explicit ";
6640b57cec5SDimitry Andric OS << "module * {\n";
6650b57cec5SDimitry Andric if (InferExportWildcard) {
6660b57cec5SDimitry Andric OS.indent(Indent + 4);
6670b57cec5SDimitry Andric OS << "export *\n";
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric OS.indent(Indent + 2);
6700b57cec5SDimitry Andric OS << "}\n";
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric
6730b57cec5SDimitry Andric OS.indent(Indent);
6740b57cec5SDimitry Andric OS << "}\n";
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric
dump() const6770b57cec5SDimitry Andric LLVM_DUMP_METHOD void Module::dump() const {
678fe6060f1SDimitry Andric print(llvm::errs(), 0, true);
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric
setVisible(Module * M,SourceLocation Loc,VisibleCallback Vis,ConflictCallback Cb)6810b57cec5SDimitry Andric void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
6820b57cec5SDimitry Andric VisibleCallback Vis, ConflictCallback Cb) {
683bdd1243dSDimitry Andric // We can't import a global module fragment so the location can be invalid.
684bdd1243dSDimitry Andric assert((M->isGlobalModule() || Loc.isValid()) &&
685bdd1243dSDimitry Andric "setVisible expects a valid import location");
6860b57cec5SDimitry Andric if (isVisible(M))
6870b57cec5SDimitry Andric return;
6880b57cec5SDimitry Andric
6890b57cec5SDimitry Andric ++Generation;
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric struct Visiting {
6920b57cec5SDimitry Andric Module *M;
6930b57cec5SDimitry Andric Visiting *ExportedBy;
6940b57cec5SDimitry Andric };
6950b57cec5SDimitry Andric
6960b57cec5SDimitry Andric std::function<void(Visiting)> VisitModule = [&](Visiting V) {
6970b57cec5SDimitry Andric // Nothing to do for a module that's already visible.
6980b57cec5SDimitry Andric unsigned ID = V.M->getVisibilityID();
6990b57cec5SDimitry Andric if (ImportLocs.size() <= ID)
7000b57cec5SDimitry Andric ImportLocs.resize(ID + 1);
7010b57cec5SDimitry Andric else if (ImportLocs[ID].isValid())
7020b57cec5SDimitry Andric return;
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andric ImportLocs[ID] = Loc;
705bdd1243dSDimitry Andric Vis(V.M);
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric // Make any exported modules visible.
7080b57cec5SDimitry Andric SmallVector<Module *, 16> Exports;
7090b57cec5SDimitry Andric V.M->getExportedModules(Exports);
7100b57cec5SDimitry Andric for (Module *E : Exports) {
7115ffd83dbSDimitry Andric // Don't import non-importable modules.
7125ffd83dbSDimitry Andric if (!E->isUnimportable())
7130b57cec5SDimitry Andric VisitModule({E, &V});
7140b57cec5SDimitry Andric }
7150b57cec5SDimitry Andric
7160b57cec5SDimitry Andric for (auto &C : V.M->Conflicts) {
7170b57cec5SDimitry Andric if (isVisible(C.Other)) {
7180b57cec5SDimitry Andric llvm::SmallVector<Module*, 8> Path;
7190b57cec5SDimitry Andric for (Visiting *I = &V; I; I = I->ExportedBy)
7200b57cec5SDimitry Andric Path.push_back(I->M);
7210b57cec5SDimitry Andric Cb(Path, C.Other, C.Message);
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric };
7250b57cec5SDimitry Andric VisitModule({M, nullptr});
7260b57cec5SDimitry Andric }
727