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