1327952Sdim//===- ModuleLoader.h - Module Loader Interface -----------------*- C++ -*-===//
2226586Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6226586Sdim//
7226586Sdim//===----------------------------------------------------------------------===//
8226586Sdim//
9341825Sdim//  This file defines the ModuleLoader interface, which is responsible for
10226586Sdim//  loading named modules.
11226586Sdim//
12226586Sdim//===----------------------------------------------------------------------===//
13327952Sdim
14280031Sdim#ifndef LLVM_CLANG_LEX_MODULELOADER_H
15280031Sdim#define LLVM_CLANG_LEX_MODULELOADER_H
16226586Sdim
17327952Sdim#include "clang/Basic/LLVM.h"
18234353Sdim#include "clang/Basic/Module.h"
19226586Sdim#include "clang/Basic/SourceLocation.h"
20234353Sdim#include "llvm/ADT/ArrayRef.h"
21249423Sdim#include "llvm/ADT/PointerIntPair.h"
22327952Sdim#include "llvm/ADT/StringRef.h"
23327952Sdim#include <utility>
24226586Sdim
25226586Sdimnamespace clang {
26226586Sdim
27276479Sdimclass GlobalModuleIndex;
28226586Sdimclass IdentifierInfo;
29249423Sdim
30341825Sdim/// A sequence of identifier/location pairs used to describe a particular
31234353Sdim/// module or submodule, e.g., std.vector.
32327952Sdimusing ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>;
33249423Sdim
34341825Sdim/// Describes the result of attempting to load a module.
35249423Sdimclass ModuleLoadResult {
36314564Sdimpublic:
37314564Sdim  enum LoadResultKind {
38314564Sdim    // We either succeeded or failed to load the named module.
39314564Sdim    Normal,
40327952Sdim
41314564Sdim    // The module exists, but does not actually contain the named submodule.
42314564Sdim    // This should only happen if the named submodule was inferred from an
43314564Sdim    // umbrella directory, but not actually part of the umbrella header.
44314564Sdim    MissingExpected,
45327952Sdim
46314564Sdim    // The module exists but cannot be imported due to a configuration mismatch.
47360784Sdim    ConfigMismatch,
48360784Sdim
49360784Sdim    // We failed to load the module, but we shouldn't cache the failure.
50360784Sdim    OtherUncachedFailure,
51314564Sdim  };
52314564Sdim  llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage;
53249423Sdim
54327952Sdim  ModuleLoadResult() = default;
55314564Sdim  ModuleLoadResult(Module *M) : Storage(M, Normal) {}
56314564Sdim  ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
57249423Sdim
58249423Sdim  operator Module *() const { return Storage.getPointer(); }
59249423Sdim
60360784Sdim  /// Determines whether this is a normal return, whether or not loading the
61360784Sdim  /// module was successful.
62360784Sdim  bool isNormal() const { return Storage.getInt() == Normal; }
63360784Sdim
64341825Sdim  /// Determines whether the module, which failed to load, was
65249423Sdim  /// actually a submodule that we expected to see (based on implying the
66249423Sdim  /// submodule from header structure), but didn't materialize in the actual
67249423Sdim  /// module.
68314564Sdim  bool isMissingExpected() const { return Storage.getInt() == MissingExpected; }
69314564Sdim
70341825Sdim  /// Determines whether the module failed to load due to a configuration
71314564Sdim  /// mismatch with an explicitly-named .pcm file from the command line.
72314564Sdim  bool isConfigMismatch() const { return Storage.getInt() == ConfigMismatch; }
73249423Sdim};
74249423Sdim
75341825Sdim/// Abstract interface for a module loader.
76226586Sdim///
77226586Sdim/// This abstract interface describes a module loader, which is responsible
78226586Sdim/// for resolving a module name (e.g., "std") to an actual module file, and
79226586Sdim/// then loading that module.
80226586Sdimclass ModuleLoader {
81276479Sdim  // Building a module if true.
82276479Sdim  bool BuildingModule;
83327952Sdim
84226586Sdimpublic:
85327952Sdim  explicit ModuleLoader(bool BuildingModule = false)
86327952Sdim      : BuildingModule(BuildingModule) {}
87261991Sdim
88226586Sdim  virtual ~ModuleLoader();
89341825Sdim
90341825Sdim  /// Returns true if this instance is building a module.
91276479Sdim  bool buildingModule() const {
92276479Sdim    return BuildingModule;
93276479Sdim  }
94327952Sdim
95341825Sdim  /// Flag indicating whether this instance is building a module.
96276479Sdim  void setBuildingModule(bool BuildingModuleFlag) {
97276479Sdim    BuildingModule = BuildingModuleFlag;
98276479Sdim  }
99341825Sdim
100341825Sdim  /// Attempt to load the given module.
101226586Sdim  ///
102341825Sdim  /// This routine attempts to load the module described by the given
103360784Sdim  /// parameters.  If there is a module cache, this may implicitly compile the
104360784Sdim  /// module before loading it.
105226586Sdim  ///
106226586Sdim  /// \param ImportLoc The location of the 'import' keyword.
107226586Sdim  ///
108234353Sdim  /// \param Path The identifiers (and their locations) of the module
109234353Sdim  /// "path", e.g., "std.vector" would be split into "std" and "vector".
110341825Sdim  ///
111234353Sdim  /// \param Visibility The visibility provided for the names in the loaded
112234353Sdim  /// module.
113234353Sdim  ///
114234353Sdim  /// \param IsInclusionDirective Indicates that this module is being loaded
115234353Sdim  /// implicitly, due to the presence of an inclusion directive. Otherwise,
116234353Sdim  /// it is being loaded due to an import declaration.
117234353Sdim  ///
118341825Sdim  /// \returns If successful, returns the loaded module. Otherwise, returns
119234353Sdim  /// NULL to indicate that the module could not be loaded.
120249423Sdim  virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
121249423Sdim                                      ModuleIdPath Path,
122249423Sdim                                      Module::NameVisibilityKind Visibility,
123249423Sdim                                      bool IsInclusionDirective) = 0;
124249423Sdim
125360784Sdim  /// Attempt to create the given module from the specified source buffer.
126360784Sdim  /// Does not load the module or make any submodule visible; for that, use
127360784Sdim  /// loadModule and makeModuleVisible.
128321369Sdim  ///
129360784Sdim  /// \param Loc The location at which to create the module.
130360784Sdim  /// \param ModuleName The name of the module to create.
131321369Sdim  /// \param Source The source of the module: a (preprocessed) module map.
132360784Sdim  virtual void createModuleFromSource(SourceLocation Loc, StringRef ModuleName,
133360784Sdim                                      StringRef Source) = 0;
134321369Sdim
135341825Sdim  /// Make the given module visible.
136249423Sdim  virtual void makeModuleVisible(Module *Mod,
137249423Sdim                                 Module::NameVisibilityKind Visibility,
138288943Sdim                                 SourceLocation ImportLoc) = 0;
139261991Sdim
140341825Sdim  /// Load, create, or return global module.
141276479Sdim  /// This function returns an existing global module index, if one
142276479Sdim  /// had already been loaded or created, or loads one if it
143276479Sdim  /// exists, or creates one if it doesn't exist.
144276479Sdim  /// Also, importantly, if the index doesn't cover all the modules
145276479Sdim  /// in the module map, it will be update to do so here, because
146276479Sdim  /// of its use in searching for needed module imports and
147276479Sdim  /// associated fixit messages.
148276479Sdim  /// \param TriggerLoc The location for what triggered the load.
149276479Sdim  /// \returns Returns null if load failed.
150276479Sdim  virtual GlobalModuleIndex *loadGlobalModuleIndex(
151276479Sdim                                                SourceLocation TriggerLoc) = 0;
152276479Sdim
153276479Sdim  /// Check global module index for missing imports.
154276479Sdim  /// \param Name The symbol name to look for.
155276479Sdim  /// \param TriggerLoc The location for what triggered the load.
156276479Sdim  /// \returns Returns true if any modules with that symbol found.
157276479Sdim  virtual bool lookupMissingImports(StringRef Name,
158276479Sdim                                    SourceLocation TriggerLoc) = 0;
159276479Sdim
160327952Sdim  bool HadFatalFailure = false;
161226586Sdim};
162321369Sdim
163360784Sdim/// A module loader that doesn't know how to create or load modules.
164321369Sdimclass TrivialModuleLoader : public ModuleLoader {
165321369Sdimpublic:
166321369Sdim  ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
167321369Sdim                              Module::NameVisibilityKind Visibility,
168321369Sdim                              bool IsInclusionDirective) override {
169327952Sdim    return {};
170321369Sdim  }
171321369Sdim
172360784Sdim  void createModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
173360784Sdim                              StringRef Source) override {}
174321369Sdim
175321369Sdim  void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
176321369Sdim                         SourceLocation ImportLoc) override {}
177321369Sdim
178321369Sdim  GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override {
179321369Sdim    return nullptr;
180321369Sdim  }
181327952Sdim
182321369Sdim  bool lookupMissingImports(StringRef Name,
183321369Sdim                            SourceLocation TriggerLoc) override {
184327952Sdim    return false;
185321369Sdim  }
186321369Sdim};
187341825Sdim
188327952Sdim} // namespace clang
189226586Sdim
190327952Sdim#endif // LLVM_CLANG_LEX_MODULELOADER_H
191