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