10b57cec5SDimitry Andric //===- ModuleLoader.h - Module Loader Interface -----------------*- C++ -*-===//
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 ModuleLoader interface, which is responsible for
100b57cec5SDimitry Andric //  loading named modules.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LEX_MODULELOADER_H
150b57cec5SDimitry Andric #define LLVM_CLANG_LEX_MODULELOADER_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
180b57cec5SDimitry Andric #include "clang/Basic/Module.h"
190b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
200b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
210b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace clang {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric class GlobalModuleIndex;
280b57cec5SDimitry Andric class IdentifierInfo;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric /// A sequence of identifier/location pairs used to describe a particular
310b57cec5SDimitry Andric /// module or submodule, e.g., std.vector.
320b57cec5SDimitry Andric using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric /// Describes the result of attempting to load a module.
350b57cec5SDimitry Andric class ModuleLoadResult {
360b57cec5SDimitry Andric public:
370b57cec5SDimitry Andric   enum LoadResultKind {
380b57cec5SDimitry Andric     // We either succeeded or failed to load the named module.
390b57cec5SDimitry Andric     Normal,
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric     // The module exists, but does not actually contain the named submodule.
420b57cec5SDimitry Andric     // This should only happen if the named submodule was inferred from an
430b57cec5SDimitry Andric     // umbrella directory, but not actually part of the umbrella header.
440b57cec5SDimitry Andric     MissingExpected,
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric     // The module exists but cannot be imported due to a configuration mismatch.
47480093f4SDimitry Andric     ConfigMismatch,
480b57cec5SDimitry Andric   };
490b57cec5SDimitry Andric   llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   ModuleLoadResult() = default;
ModuleLoadResult(Module * M)520b57cec5SDimitry Andric   ModuleLoadResult(Module *M) : Storage(M, Normal) {}
ModuleLoadResult(LoadResultKind Kind)530b57cec5SDimitry Andric   ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
ModuleLoadResult(Module * M,LoadResultKind Kind)54bdd1243dSDimitry Andric   ModuleLoadResult(Module *M, LoadResultKind Kind) : Storage(M, Kind) {}
55bdd1243dSDimitry Andric 
56bdd1243dSDimitry Andric   operator bool() const {
57bdd1243dSDimitry Andric     return Storage.getInt() == Normal && Storage.getPointer();
58bdd1243dSDimitry Andric   }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   operator Module *() const { return Storage.getPointer(); }
610b57cec5SDimitry Andric 
62480093f4SDimitry Andric   /// Determines whether this is a normal return, whether or not loading the
63480093f4SDimitry Andric   /// module was successful.
isNormal()64480093f4SDimitry Andric   bool isNormal() const { return Storage.getInt() == Normal; }
65480093f4SDimitry Andric 
660b57cec5SDimitry Andric   /// Determines whether the module, which failed to load, was
670b57cec5SDimitry Andric   /// actually a submodule that we expected to see (based on implying the
680b57cec5SDimitry Andric   /// submodule from header structure), but didn't materialize in the actual
690b57cec5SDimitry Andric   /// module.
isMissingExpected()700b57cec5SDimitry Andric   bool isMissingExpected() const { return Storage.getInt() == MissingExpected; }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   /// Determines whether the module failed to load due to a configuration
730b57cec5SDimitry Andric   /// mismatch with an explicitly-named .pcm file from the command line.
isConfigMismatch()740b57cec5SDimitry Andric   bool isConfigMismatch() const { return Storage.getInt() == ConfigMismatch; }
750b57cec5SDimitry Andric };
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric /// Abstract interface for a module loader.
780b57cec5SDimitry Andric ///
790b57cec5SDimitry Andric /// This abstract interface describes a module loader, which is responsible
800b57cec5SDimitry Andric /// for resolving a module name (e.g., "std") to an actual module file, and
810b57cec5SDimitry Andric /// then loading that module.
820b57cec5SDimitry Andric class ModuleLoader {
830b57cec5SDimitry Andric   // Building a module if true.
840b57cec5SDimitry Andric   bool BuildingModule;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric public:
870b57cec5SDimitry Andric   explicit ModuleLoader(bool BuildingModule = false)
BuildingModule(BuildingModule)880b57cec5SDimitry Andric       : BuildingModule(BuildingModule) {}
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   virtual ~ModuleLoader();
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   /// Returns true if this instance is building a module.
buildingModule()930b57cec5SDimitry Andric   bool buildingModule() const {
940b57cec5SDimitry Andric     return BuildingModule;
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   /// Flag indicating whether this instance is building a module.
setBuildingModule(bool BuildingModuleFlag)980b57cec5SDimitry Andric   void setBuildingModule(bool BuildingModuleFlag) {
990b57cec5SDimitry Andric     BuildingModule = BuildingModuleFlag;
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   /// Attempt to load the given module.
1030b57cec5SDimitry Andric   ///
1040b57cec5SDimitry Andric   /// This routine attempts to load the module described by the given
105480093f4SDimitry Andric   /// parameters.  If there is a module cache, this may implicitly compile the
106480093f4SDimitry Andric   /// module before loading it.
1070b57cec5SDimitry Andric   ///
1080b57cec5SDimitry Andric   /// \param ImportLoc The location of the 'import' keyword.
1090b57cec5SDimitry Andric   ///
1100b57cec5SDimitry Andric   /// \param Path The identifiers (and their locations) of the module
1110b57cec5SDimitry Andric   /// "path", e.g., "std.vector" would be split into "std" and "vector".
1120b57cec5SDimitry Andric   ///
1130b57cec5SDimitry Andric   /// \param Visibility The visibility provided for the names in the loaded
1140b57cec5SDimitry Andric   /// module.
1150b57cec5SDimitry Andric   ///
1160b57cec5SDimitry Andric   /// \param IsInclusionDirective Indicates that this module is being loaded
1170b57cec5SDimitry Andric   /// implicitly, due to the presence of an inclusion directive. Otherwise,
1180b57cec5SDimitry Andric   /// it is being loaded due to an import declaration.
1190b57cec5SDimitry Andric   ///
1200b57cec5SDimitry Andric   /// \returns If successful, returns the loaded module. Otherwise, returns
1210b57cec5SDimitry Andric   /// NULL to indicate that the module could not be loaded.
1220b57cec5SDimitry Andric   virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
1230b57cec5SDimitry Andric                                       ModuleIdPath Path,
1240b57cec5SDimitry Andric                                       Module::NameVisibilityKind Visibility,
1250b57cec5SDimitry Andric                                       bool IsInclusionDirective) = 0;
1260b57cec5SDimitry Andric 
127480093f4SDimitry Andric   /// Attempt to create the given module from the specified source buffer.
128480093f4SDimitry Andric   /// Does not load the module or make any submodule visible; for that, use
129480093f4SDimitry Andric   /// loadModule and makeModuleVisible.
1300b57cec5SDimitry Andric   ///
131480093f4SDimitry Andric   /// \param Loc The location at which to create the module.
132480093f4SDimitry Andric   /// \param ModuleName The name of the module to create.
1330b57cec5SDimitry Andric   /// \param Source The source of the module: a (preprocessed) module map.
134480093f4SDimitry Andric   virtual void createModuleFromSource(SourceLocation Loc, StringRef ModuleName,
1350b57cec5SDimitry Andric                                       StringRef Source) = 0;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   /// Make the given module visible.
1380b57cec5SDimitry Andric   virtual void makeModuleVisible(Module *Mod,
1390b57cec5SDimitry Andric                                  Module::NameVisibilityKind Visibility,
1400b57cec5SDimitry Andric                                  SourceLocation ImportLoc) = 0;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   /// Load, create, or return global module.
1430b57cec5SDimitry Andric   /// This function returns an existing global module index, if one
1440b57cec5SDimitry Andric   /// had already been loaded or created, or loads one if it
1450b57cec5SDimitry Andric   /// exists, or creates one if it doesn't exist.
1460b57cec5SDimitry Andric   /// Also, importantly, if the index doesn't cover all the modules
1470b57cec5SDimitry Andric   /// in the module map, it will be update to do so here, because
1480b57cec5SDimitry Andric   /// of its use in searching for needed module imports and
1490b57cec5SDimitry Andric   /// associated fixit messages.
1500b57cec5SDimitry Andric   /// \param TriggerLoc The location for what triggered the load.
1510b57cec5SDimitry Andric   /// \returns Returns null if load failed.
1520b57cec5SDimitry Andric   virtual GlobalModuleIndex *loadGlobalModuleIndex(
1530b57cec5SDimitry Andric                                                 SourceLocation TriggerLoc) = 0;
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   /// Check global module index for missing imports.
1560b57cec5SDimitry Andric   /// \param Name The symbol name to look for.
1570b57cec5SDimitry Andric   /// \param TriggerLoc The location for what triggered the load.
1580b57cec5SDimitry Andric   /// \returns Returns true if any modules with that symbol found.
1590b57cec5SDimitry Andric   virtual bool lookupMissingImports(StringRef Name,
1600b57cec5SDimitry Andric                                     SourceLocation TriggerLoc) = 0;
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   bool HadFatalFailure = false;
1630b57cec5SDimitry Andric };
1640b57cec5SDimitry Andric 
165480093f4SDimitry Andric /// A module loader that doesn't know how to create or load modules.
1660b57cec5SDimitry Andric class TrivialModuleLoader : public ModuleLoader {
1670b57cec5SDimitry Andric public:
loadModule(SourceLocation ImportLoc,ModuleIdPath Path,Module::NameVisibilityKind Visibility,bool IsInclusionDirective)1680b57cec5SDimitry Andric   ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
1690b57cec5SDimitry Andric                               Module::NameVisibilityKind Visibility,
1700b57cec5SDimitry Andric                               bool IsInclusionDirective) override {
1710b57cec5SDimitry Andric     return {};
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric 
createModuleFromSource(SourceLocation ImportLoc,StringRef ModuleName,StringRef Source)174480093f4SDimitry Andric   void createModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
1750b57cec5SDimitry Andric                               StringRef Source) override {}
1760b57cec5SDimitry Andric 
makeModuleVisible(Module * Mod,Module::NameVisibilityKind Visibility,SourceLocation ImportLoc)1770b57cec5SDimitry Andric   void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
1780b57cec5SDimitry Andric                          SourceLocation ImportLoc) override {}
1790b57cec5SDimitry Andric 
loadGlobalModuleIndex(SourceLocation TriggerLoc)1800b57cec5SDimitry Andric   GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override {
1810b57cec5SDimitry Andric     return nullptr;
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
lookupMissingImports(StringRef Name,SourceLocation TriggerLoc)1840b57cec5SDimitry Andric   bool lookupMissingImports(StringRef Name,
1850b57cec5SDimitry Andric                             SourceLocation TriggerLoc) override {
1860b57cec5SDimitry Andric     return false;
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric };
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric } // namespace clang
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric #endif // LLVM_CLANG_LEX_MODULELOADER_H
193