Path: blob/main/contrib/llvm-project/clang/lib/Basic/Module.cpp
35232 views
//===- Module.cpp - Describe a module -------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the Module class, which describes a module in the source9// code.10//11//===----------------------------------------------------------------------===//1213#include "clang/Basic/Module.h"14#include "clang/Basic/CharInfo.h"15#include "clang/Basic/FileManager.h"16#include "clang/Basic/LangOptions.h"17#include "clang/Basic/SourceLocation.h"18#include "clang/Basic/TargetInfo.h"19#include "llvm/ADT/ArrayRef.h"20#include "llvm/ADT/SmallVector.h"21#include "llvm/ADT/StringMap.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/ADT/StringSwitch.h"24#include "llvm/Support/Compiler.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/Support/raw_ostream.h"27#include <algorithm>28#include <cassert>29#include <functional>30#include <string>31#include <utility>32#include <vector>3334using namespace clang;3536Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,37bool IsFramework, bool IsExplicit, unsigned VisibilityID)38: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),39VisibilityID(VisibilityID), IsUnimportable(false),40HasIncompatibleModuleFile(false), IsAvailable(true),41IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit),42IsSystem(false), IsExternC(false), IsInferred(false),43InferSubmodules(false), InferExplicitSubmodules(false),44InferExportWildcard(false), ConfigMacrosExhaustive(false),45NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),46NamedModuleHasInit(true), NameVisibility(Hidden) {47if (Parent) {48IsAvailable = Parent->isAvailable();49IsUnimportable = Parent->isUnimportable();50IsSystem = Parent->IsSystem;51IsExternC = Parent->IsExternC;52NoUndeclaredIncludes = Parent->NoUndeclaredIncludes;53ModuleMapIsPrivate = Parent->ModuleMapIsPrivate;5455Parent->SubModuleIndex[Name] = Parent->SubModules.size();56Parent->SubModules.push_back(this);57}58}5960Module::~Module() {61for (auto *Submodule : SubModules) {62delete Submodule;63}64}6566static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {67StringRef Platform = Target.getPlatformName();68StringRef Env = Target.getTriple().getEnvironmentName();6970// Attempt to match platform and environment.71if (Platform == Feature || Target.getTriple().getOSName() == Feature ||72Env == Feature)73return true;7475auto CmpPlatformEnv = [](StringRef LHS, StringRef RHS) {76auto Pos = LHS.find('-');77if (Pos == StringRef::npos)78return false;79SmallString<128> NewLHS = LHS.slice(0, Pos);80NewLHS += LHS.slice(Pos+1, LHS.size());81return NewLHS == RHS;82};8384SmallString<128> PlatformEnv = Target.getTriple().getOSAndEnvironmentName();85// Darwin has different but equivalent variants for simulators, example:86// 1. x86_64-apple-ios-simulator87// 2. x86_64-apple-iossimulator88// where both are valid examples of the same platform+environment but in the89// variant (2) the simulator is hardcoded as part of the platform name. Both90// forms above should match for "iossimulator" requirement.91if (Target.getTriple().isOSDarwin() && PlatformEnv.ends_with("simulator"))92return PlatformEnv == Feature || CmpPlatformEnv(PlatformEnv, Feature);9394return PlatformEnv == Feature;95}9697/// Determine whether a translation unit built using the current98/// language options has the given feature.99static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,100const TargetInfo &Target) {101bool HasFeature = llvm::StringSwitch<bool>(Feature)102.Case("altivec", LangOpts.AltiVec)103.Case("blocks", LangOpts.Blocks)104.Case("coroutines", LangOpts.Coroutines)105.Case("cplusplus", LangOpts.CPlusPlus)106.Case("cplusplus11", LangOpts.CPlusPlus11)107.Case("cplusplus14", LangOpts.CPlusPlus14)108.Case("cplusplus17", LangOpts.CPlusPlus17)109.Case("cplusplus20", LangOpts.CPlusPlus20)110.Case("cplusplus23", LangOpts.CPlusPlus23)111.Case("cplusplus26", LangOpts.CPlusPlus26)112.Case("c99", LangOpts.C99)113.Case("c11", LangOpts.C11)114.Case("c17", LangOpts.C17)115.Case("c23", LangOpts.C23)116.Case("freestanding", LangOpts.Freestanding)117.Case("gnuinlineasm", LangOpts.GNUAsm)118.Case("objc", LangOpts.ObjC)119.Case("objc_arc", LangOpts.ObjCAutoRefCount)120.Case("opencl", LangOpts.OpenCL)121.Case("tls", Target.isTLSSupported())122.Case("zvector", LangOpts.ZVector)123.Default(Target.hasFeature(Feature) ||124isPlatformEnvironment(Target, Feature));125if (!HasFeature)126HasFeature = llvm::is_contained(LangOpts.ModuleFeatures, Feature);127return HasFeature;128}129130bool Module::isUnimportable(const LangOptions &LangOpts,131const TargetInfo &Target, Requirement &Req,132Module *&ShadowingModule) const {133if (!IsUnimportable)134return false;135136for (const Module *Current = this; Current; Current = Current->Parent) {137if (Current->ShadowingModule) {138ShadowingModule = Current->ShadowingModule;139return true;140}141for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {142if (hasFeature(Current->Requirements[I].FeatureName, LangOpts, Target) !=143Current->Requirements[I].RequiredState) {144Req = Current->Requirements[I];145return true;146}147}148}149150llvm_unreachable("could not find a reason why module is unimportable");151}152153// The -fmodule-name option tells the compiler to textually include headers in154// the specified module, meaning Clang won't build the specified module. This155// is useful in a number of situations, for instance, when building a library156// that vends a module map, one might want to avoid hitting intermediate build157// products containing the module map or avoid finding the system installed158// modulemap for that library.159bool Module::isForBuilding(const LangOptions &LangOpts) const {160StringRef TopLevelName = getTopLevelModuleName();161StringRef CurrentModule = LangOpts.CurrentModule;162163// When building the implementation of framework Foo, we want to make sure164// that Foo *and* Foo_Private are textually included and no modules are built165// for either.166if (!LangOpts.isCompilingModule() && getTopLevelModule()->IsFramework &&167CurrentModule == LangOpts.ModuleName &&168!CurrentModule.ends_with("_Private") &&169TopLevelName.ends_with("_Private"))170TopLevelName = TopLevelName.drop_back(8);171172return TopLevelName == CurrentModule;173}174175bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,176Requirement &Req,177UnresolvedHeaderDirective &MissingHeader,178Module *&ShadowingModule) const {179if (IsAvailable)180return true;181182if (isUnimportable(LangOpts, Target, Req, ShadowingModule))183return false;184185// FIXME: All missing headers are listed on the top-level module. Should we186// just look there?187for (const Module *Current = this; Current; Current = Current->Parent) {188if (!Current->MissingHeaders.empty()) {189MissingHeader = Current->MissingHeaders.front();190return false;191}192}193194llvm_unreachable("could not find a reason why module is unavailable");195}196197bool Module::isSubModuleOf(const Module *Other) const {198for (auto *Parent = this; Parent; Parent = Parent->Parent) {199if (Parent == Other)200return true;201}202return false;203}204205const Module *Module::getTopLevelModule() const {206const Module *Result = this;207while (Result->Parent)208Result = Result->Parent;209210return Result;211}212213static StringRef getModuleNameFromComponent(214const std::pair<std::string, SourceLocation> &IdComponent) {215return IdComponent.first;216}217218static StringRef getModuleNameFromComponent(StringRef R) { return R; }219220template<typename InputIter>221static void printModuleId(raw_ostream &OS, InputIter Begin, InputIter End,222bool AllowStringLiterals = true) {223for (InputIter It = Begin; It != End; ++It) {224if (It != Begin)225OS << ".";226227StringRef Name = getModuleNameFromComponent(*It);228if (!AllowStringLiterals || isValidAsciiIdentifier(Name))229OS << Name;230else {231OS << '"';232OS.write_escaped(Name);233OS << '"';234}235}236}237238template<typename Container>239static void printModuleId(raw_ostream &OS, const Container &C) {240return printModuleId(OS, C.begin(), C.end());241}242243std::string Module::getFullModuleName(bool AllowStringLiterals) const {244SmallVector<StringRef, 2> Names;245246// Build up the set of module names (from innermost to outermost).247for (const Module *M = this; M; M = M->Parent)248Names.push_back(M->Name);249250std::string Result;251252llvm::raw_string_ostream Out(Result);253printModuleId(Out, Names.rbegin(), Names.rend(), AllowStringLiterals);254Out.flush();255256return Result;257}258259bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {260for (const Module *M = this; M; M = M->Parent) {261if (nameParts.empty() || M->Name != nameParts.back())262return false;263nameParts = nameParts.drop_back();264}265return nameParts.empty();266}267268OptionalDirectoryEntryRef Module::getEffectiveUmbrellaDir() const {269if (const auto *Hdr = std::get_if<FileEntryRef>(&Umbrella))270return Hdr->getDir();271if (const auto *Dir = std::get_if<DirectoryEntryRef>(&Umbrella))272return *Dir;273return std::nullopt;274}275276void Module::addTopHeader(FileEntryRef File) {277assert(File);278TopHeaders.insert(File);279}280281ArrayRef<FileEntryRef> Module::getTopHeaders(FileManager &FileMgr) {282if (!TopHeaderNames.empty()) {283for (StringRef TopHeaderName : TopHeaderNames)284if (auto FE = FileMgr.getOptionalFileRef(TopHeaderName))285TopHeaders.insert(*FE);286TopHeaderNames.clear();287}288289return llvm::ArrayRef(TopHeaders.begin(), TopHeaders.end());290}291292bool Module::directlyUses(const Module *Requested) {293auto *Top = getTopLevelModule();294295// A top-level module implicitly uses itself.296if (Requested->isSubModuleOf(Top))297return true;298299for (auto *Use : Top->DirectUses)300if (Requested->isSubModuleOf(Use))301return true;302303// Anyone is allowed to use our builtin stddef.h and its accompanying modules.304if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) ||305Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"}))306return true;307// Darwin is allowed is to use our builtin 'ptrauth.h' and its accompanying308// module.309if (!Requested->Parent && Requested->Name == "ptrauth")310return true;311312if (NoUndeclaredIncludes)313UndeclaredUses.insert(Requested);314315return false;316}317318void Module::addRequirement(StringRef Feature, bool RequiredState,319const LangOptions &LangOpts,320const TargetInfo &Target) {321Requirements.push_back(Requirement{std::string(Feature), RequiredState});322323// If this feature is currently available, we're done.324if (hasFeature(Feature, LangOpts, Target) == RequiredState)325return;326327markUnavailable(/*Unimportable*/true);328}329330void Module::markUnavailable(bool Unimportable) {331auto needUpdate = [Unimportable](Module *M) {332return M->IsAvailable || (!M->IsUnimportable && Unimportable);333};334335if (!needUpdate(this))336return;337338SmallVector<Module *, 2> Stack;339Stack.push_back(this);340while (!Stack.empty()) {341Module *Current = Stack.back();342Stack.pop_back();343344if (!needUpdate(Current))345continue;346347Current->IsAvailable = false;348Current->IsUnimportable |= Unimportable;349for (auto *Submodule : Current->submodules()) {350if (needUpdate(Submodule))351Stack.push_back(Submodule);352}353}354}355356Module *Module::findSubmodule(StringRef Name) const {357llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);358if (Pos == SubModuleIndex.end())359return nullptr;360361return SubModules[Pos->getValue()];362}363364Module *Module::findOrInferSubmodule(StringRef Name) {365llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);366if (Pos != SubModuleIndex.end())367return SubModules[Pos->getValue()];368if (!InferSubmodules)369return nullptr;370Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);371Result->InferExplicitSubmodules = InferExplicitSubmodules;372Result->InferSubmodules = InferSubmodules;373Result->InferExportWildcard = InferExportWildcard;374if (Result->InferExportWildcard)375Result->Exports.push_back(Module::ExportDecl(nullptr, true));376return Result;377}378379Module *Module::getGlobalModuleFragment() const {380assert(isNamedModuleUnit() && "We should only query the global module "381"fragment from the C++20 Named modules");382383for (auto *SubModule : SubModules)384if (SubModule->isExplicitGlobalModule())385return SubModule;386387return nullptr;388}389390Module *Module::getPrivateModuleFragment() const {391assert(isNamedModuleUnit() && "We should only query the private module "392"fragment from the C++20 Named modules");393394for (auto *SubModule : SubModules)395if (SubModule->isPrivateModule())396return SubModule;397398return nullptr;399}400401void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {402// All non-explicit submodules are exported.403for (std::vector<Module *>::const_iterator I = SubModules.begin(),404E = SubModules.end();405I != E; ++I) {406Module *Mod = *I;407if (!Mod->IsExplicit)408Exported.push_back(Mod);409}410411// Find re-exported modules by filtering the list of imported modules.412bool AnyWildcard = false;413bool UnrestrictedWildcard = false;414SmallVector<Module *, 4> WildcardRestrictions;415for (unsigned I = 0, N = Exports.size(); I != N; ++I) {416Module *Mod = Exports[I].getPointer();417if (!Exports[I].getInt()) {418// Export a named module directly; no wildcards involved.419Exported.push_back(Mod);420421continue;422}423424// Wildcard export: export all of the imported modules that match425// the given pattern.426AnyWildcard = true;427if (UnrestrictedWildcard)428continue;429430if (Module *Restriction = Exports[I].getPointer())431WildcardRestrictions.push_back(Restriction);432else {433WildcardRestrictions.clear();434UnrestrictedWildcard = true;435}436}437438// If there were any wildcards, push any imported modules that were439// re-exported by the wildcard restriction.440if (!AnyWildcard)441return;442443for (unsigned I = 0, N = Imports.size(); I != N; ++I) {444Module *Mod = Imports[I];445bool Acceptable = UnrestrictedWildcard;446if (!Acceptable) {447// Check whether this module meets one of the restrictions.448for (unsigned R = 0, NR = WildcardRestrictions.size(); R != NR; ++R) {449Module *Restriction = WildcardRestrictions[R];450if (Mod == Restriction || Mod->isSubModuleOf(Restriction)) {451Acceptable = true;452break;453}454}455}456457if (!Acceptable)458continue;459460Exported.push_back(Mod);461}462}463464void Module::buildVisibleModulesCache() const {465assert(VisibleModulesCache.empty() && "cache does not need building");466467// This module is visible to itself.468VisibleModulesCache.insert(this);469470// Every imported module is visible.471SmallVector<Module *, 16> Stack(Imports.begin(), Imports.end());472while (!Stack.empty()) {473Module *CurrModule = Stack.pop_back_val();474475// Every module transitively exported by an imported module is visible.476if (VisibleModulesCache.insert(CurrModule).second)477CurrModule->getExportedModules(Stack);478}479}480481void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {482OS.indent(Indent);483if (IsFramework)484OS << "framework ";485if (IsExplicit)486OS << "explicit ";487OS << "module ";488printModuleId(OS, &Name, &Name + 1);489490if (IsSystem || IsExternC) {491OS.indent(Indent + 2);492if (IsSystem)493OS << " [system]";494if (IsExternC)495OS << " [extern_c]";496}497498OS << " {\n";499500if (!Requirements.empty()) {501OS.indent(Indent + 2);502OS << "requires ";503for (unsigned I = 0, N = Requirements.size(); I != N; ++I) {504if (I)505OS << ", ";506if (!Requirements[I].RequiredState)507OS << "!";508OS << Requirements[I].FeatureName;509}510OS << "\n";511}512513if (std::optional<Header> H = getUmbrellaHeaderAsWritten()) {514OS.indent(Indent + 2);515OS << "umbrella header \"";516OS.write_escaped(H->NameAsWritten);517OS << "\"\n";518} else if (std::optional<DirectoryName> D = getUmbrellaDirAsWritten()) {519OS.indent(Indent + 2);520OS << "umbrella \"";521OS.write_escaped(D->NameAsWritten);522OS << "\"\n";523}524525if (!ConfigMacros.empty() || ConfigMacrosExhaustive) {526OS.indent(Indent + 2);527OS << "config_macros ";528if (ConfigMacrosExhaustive)529OS << "[exhaustive]";530for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) {531if (I)532OS << ", ";533OS << ConfigMacros[I];534}535OS << "\n";536}537538struct {539StringRef Prefix;540HeaderKind Kind;541} Kinds[] = {{"", HK_Normal},542{"textual ", HK_Textual},543{"private ", HK_Private},544{"private textual ", HK_PrivateTextual},545{"exclude ", HK_Excluded}};546547for (auto &K : Kinds) {548assert(&K == &Kinds[K.Kind] && "kinds in wrong order");549for (auto &H : Headers[K.Kind]) {550OS.indent(Indent + 2);551OS << K.Prefix << "header \"";552OS.write_escaped(H.NameAsWritten);553OS << "\" { size " << H.Entry.getSize()554<< " mtime " << H.Entry.getModificationTime() << " }\n";555}556}557for (auto *Unresolved : {&UnresolvedHeaders, &MissingHeaders}) {558for (auto &U : *Unresolved) {559OS.indent(Indent + 2);560OS << Kinds[U.Kind].Prefix << "header \"";561OS.write_escaped(U.FileName);562OS << "\"";563if (U.Size || U.ModTime) {564OS << " {";565if (U.Size)566OS << " size " << *U.Size;567if (U.ModTime)568OS << " mtime " << *U.ModTime;569OS << " }";570}571OS << "\n";572}573}574575if (!ExportAsModule.empty()) {576OS.indent(Indent + 2);577OS << "export_as" << ExportAsModule << "\n";578}579580for (auto *Submodule : submodules())581// Print inferred subframework modules so that we don't need to re-infer582// them (requires expensive directory iteration + stat calls) when we build583// the module. Regular inferred submodules are OK, as we need to look at all584// those header files anyway.585if (!Submodule->IsInferred || Submodule->IsFramework)586Submodule->print(OS, Indent + 2, Dump);587588for (unsigned I = 0, N = Exports.size(); I != N; ++I) {589OS.indent(Indent + 2);590OS << "export ";591if (Module *Restriction = Exports[I].getPointer()) {592OS << Restriction->getFullModuleName(true);593if (Exports[I].getInt())594OS << ".*";595} else {596OS << "*";597}598OS << "\n";599}600601for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {602OS.indent(Indent + 2);603OS << "export ";604printModuleId(OS, UnresolvedExports[I].Id);605if (UnresolvedExports[I].Wildcard)606OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*");607OS << "\n";608}609610if (Dump) {611for (Module *M : Imports) {612OS.indent(Indent + 2);613llvm::errs() << "import " << M->getFullModuleName() << "\n";614}615}616617for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {618OS.indent(Indent + 2);619OS << "use ";620OS << DirectUses[I]->getFullModuleName(true);621OS << "\n";622}623624for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) {625OS.indent(Indent + 2);626OS << "use ";627printModuleId(OS, UnresolvedDirectUses[I]);628OS << "\n";629}630631for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) {632OS.indent(Indent + 2);633OS << "link ";634if (LinkLibraries[I].IsFramework)635OS << "framework ";636OS << "\"";637OS.write_escaped(LinkLibraries[I].Library);638OS << "\"";639}640641for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) {642OS.indent(Indent + 2);643OS << "conflict ";644printModuleId(OS, UnresolvedConflicts[I].Id);645OS << ", \"";646OS.write_escaped(UnresolvedConflicts[I].Message);647OS << "\"\n";648}649650for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) {651OS.indent(Indent + 2);652OS << "conflict ";653OS << Conflicts[I].Other->getFullModuleName(true);654OS << ", \"";655OS.write_escaped(Conflicts[I].Message);656OS << "\"\n";657}658659if (InferSubmodules) {660OS.indent(Indent + 2);661if (InferExplicitSubmodules)662OS << "explicit ";663OS << "module * {\n";664if (InferExportWildcard) {665OS.indent(Indent + 4);666OS << "export *\n";667}668OS.indent(Indent + 2);669OS << "}\n";670}671672OS.indent(Indent);673OS << "}\n";674}675676LLVM_DUMP_METHOD void Module::dump() const {677print(llvm::errs(), 0, true);678}679680void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,681VisibleCallback Vis, ConflictCallback Cb) {682// We can't import a global module fragment so the location can be invalid.683assert((M->isGlobalModule() || Loc.isValid()) &&684"setVisible expects a valid import location");685if (isVisible(M))686return;687688++Generation;689690struct Visiting {691Module *M;692Visiting *ExportedBy;693};694695std::function<void(Visiting)> VisitModule = [&](Visiting V) {696// Nothing to do for a module that's already visible.697unsigned ID = V.M->getVisibilityID();698if (ImportLocs.size() <= ID)699ImportLocs.resize(ID + 1);700else if (ImportLocs[ID].isValid())701return;702703ImportLocs[ID] = Loc;704Vis(V.M);705706// Make any exported modules visible.707SmallVector<Module *, 16> Exports;708V.M->getExportedModules(Exports);709for (Module *E : Exports) {710// Don't import non-importable modules.711if (!E->isUnimportable())712VisitModule({E, &V});713}714715for (auto &C : V.M->Conflicts) {716if (isVisible(C.Other)) {717llvm::SmallVector<Module*, 8> Path;718for (Visiting *I = &V; I; I = I->ExportedBy)719Path.push_back(I->M);720Cb(Path, C.Other, C.Message);721}722}723};724VisitModule({M, nullptr});725}726727728