brintos

brintos / llvm-project-archived public Read only

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