Home | History | Annotate | Line # | Download | only in Lex
      1 //===- ModuleLoader.h - Module Loader Interface -----------------*- C++ -*-===//
      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 ModuleLoader interface, which is responsible for
     10 //  loading named modules.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_LEX_MODULELOADER_H
     15 #define LLVM_CLANG_LEX_MODULELOADER_H
     16 
     17 #include "clang/Basic/LLVM.h"
     18 #include "clang/Basic/Module.h"
     19 #include "clang/Basic/SourceLocation.h"
     20 #include "llvm/ADT/ArrayRef.h"
     21 #include "llvm/ADT/PointerIntPair.h"
     22 #include "llvm/ADT/StringRef.h"
     23 #include <utility>
     24 
     25 namespace clang {
     26 
     27 class GlobalModuleIndex;
     28 class IdentifierInfo;
     29 
     30 /// A sequence of identifier/location pairs used to describe a particular
     31 /// module or submodule, e.g., std.vector.
     32 using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>;
     33 
     34 /// Describes the result of attempting to load a module.
     35 class ModuleLoadResult {
     36 public:
     37   enum LoadResultKind {
     38     // We either succeeded or failed to load the named module.
     39     Normal,
     40 
     41     // The module exists, but does not actually contain the named submodule.
     42     // This should only happen if the named submodule was inferred from an
     43     // umbrella directory, but not actually part of the umbrella header.
     44     MissingExpected,
     45 
     46     // The module exists but cannot be imported due to a configuration mismatch.
     47     ConfigMismatch,
     48   };
     49   llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage;
     50 
     51   ModuleLoadResult() = default;
     52   ModuleLoadResult(Module *M) : Storage(M, Normal) {}
     53   ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
     54 
     55   operator Module *() const { return Storage.getPointer(); }
     56 
     57   /// Determines whether this is a normal return, whether or not loading the
     58   /// module was successful.
     59   bool isNormal() const { return Storage.getInt() == Normal; }
     60 
     61   /// Determines whether the module, which failed to load, was
     62   /// actually a submodule that we expected to see (based on implying the
     63   /// submodule from header structure), but didn't materialize in the actual
     64   /// module.
     65   bool isMissingExpected() const { return Storage.getInt() == MissingExpected; }
     66 
     67   /// Determines whether the module failed to load due to a configuration
     68   /// mismatch with an explicitly-named .pcm file from the command line.
     69   bool isConfigMismatch() const { return Storage.getInt() == ConfigMismatch; }
     70 };
     71 
     72 /// Abstract interface for a module loader.
     73 ///
     74 /// This abstract interface describes a module loader, which is responsible
     75 /// for resolving a module name (e.g., "std") to an actual module file, and
     76 /// then loading that module.
     77 class ModuleLoader {
     78   // Building a module if true.
     79   bool BuildingModule;
     80 
     81 public:
     82   explicit ModuleLoader(bool BuildingModule = false)
     83       : BuildingModule(BuildingModule) {}
     84 
     85   virtual ~ModuleLoader();
     86 
     87   /// Returns true if this instance is building a module.
     88   bool buildingModule() const {
     89     return BuildingModule;
     90   }
     91 
     92   /// Flag indicating whether this instance is building a module.
     93   void setBuildingModule(bool BuildingModuleFlag) {
     94     BuildingModule = BuildingModuleFlag;
     95   }
     96 
     97   /// Attempt to load the given module.
     98   ///
     99   /// This routine attempts to load the module described by the given
    100   /// parameters.  If there is a module cache, this may implicitly compile the
    101   /// module before loading it.
    102   ///
    103   /// \param ImportLoc The location of the 'import' keyword.
    104   ///
    105   /// \param Path The identifiers (and their locations) of the module
    106   /// "path", e.g., "std.vector" would be split into "std" and "vector".
    107   ///
    108   /// \param Visibility The visibility provided for the names in the loaded
    109   /// module.
    110   ///
    111   /// \param IsInclusionDirective Indicates that this module is being loaded
    112   /// implicitly, due to the presence of an inclusion directive. Otherwise,
    113   /// it is being loaded due to an import declaration.
    114   ///
    115   /// \returns If successful, returns the loaded module. Otherwise, returns
    116   /// NULL to indicate that the module could not be loaded.
    117   virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
    118                                       ModuleIdPath Path,
    119                                       Module::NameVisibilityKind Visibility,
    120                                       bool IsInclusionDirective) = 0;
    121 
    122   /// Attempt to create the given module from the specified source buffer.
    123   /// Does not load the module or make any submodule visible; for that, use
    124   /// loadModule and makeModuleVisible.
    125   ///
    126   /// \param Loc The location at which to create the module.
    127   /// \param ModuleName The name of the module to create.
    128   /// \param Source The source of the module: a (preprocessed) module map.
    129   virtual void createModuleFromSource(SourceLocation Loc, StringRef ModuleName,
    130                                       StringRef Source) = 0;
    131 
    132   /// Make the given module visible.
    133   virtual void makeModuleVisible(Module *Mod,
    134                                  Module::NameVisibilityKind Visibility,
    135                                  SourceLocation ImportLoc) = 0;
    136 
    137   /// Load, create, or return global module.
    138   /// This function returns an existing global module index, if one
    139   /// had already been loaded or created, or loads one if it
    140   /// exists, or creates one if it doesn't exist.
    141   /// Also, importantly, if the index doesn't cover all the modules
    142   /// in the module map, it will be update to do so here, because
    143   /// of its use in searching for needed module imports and
    144   /// associated fixit messages.
    145   /// \param TriggerLoc The location for what triggered the load.
    146   /// \returns Returns null if load failed.
    147   virtual GlobalModuleIndex *loadGlobalModuleIndex(
    148                                                 SourceLocation TriggerLoc) = 0;
    149 
    150   /// Check global module index for missing imports.
    151   /// \param Name The symbol name to look for.
    152   /// \param TriggerLoc The location for what triggered the load.
    153   /// \returns Returns true if any modules with that symbol found.
    154   virtual bool lookupMissingImports(StringRef Name,
    155                                     SourceLocation TriggerLoc) = 0;
    156 
    157   bool HadFatalFailure = false;
    158 };
    159 
    160 /// A module loader that doesn't know how to create or load modules.
    161 class TrivialModuleLoader : public ModuleLoader {
    162 public:
    163   ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
    164                               Module::NameVisibilityKind Visibility,
    165                               bool IsInclusionDirective) override {
    166     return {};
    167   }
    168 
    169   void createModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
    170                               StringRef Source) override {}
    171 
    172   void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
    173                          SourceLocation ImportLoc) override {}
    174 
    175   GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override {
    176     return nullptr;
    177   }
    178 
    179   bool lookupMissingImports(StringRef Name,
    180                             SourceLocation TriggerLoc) override {
    181     return false;
    182   }
    183 };
    184 
    185 } // namespace clang
    186 
    187 #endif // LLVM_CLANG_LEX_MODULELOADER_H
    188