-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
Copy pathASTAnnotations.h
362 lines (298 loc) · 12.2 KB
/
ASTAnnotations.h
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
/**
* @author Christian <[email protected]>
* @date 2015
* Object containing the type and other annotations for the AST nodes.
*/
#pragma once
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/ast/ASTEnums.h>
#include <libsolidity/ast/ExperimentalFeatures.h>
#include <libsolutil/Numeric.h>
#include <libsolutil/SetOnce.h>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <vector>
namespace solidity::yul
{
struct AsmAnalysisInfo;
struct Identifier;
class Dialect;
}
namespace solidity::frontend
{
class Type;
class ArrayType;
struct CallGraph;
struct ASTAnnotation
{
ASTAnnotation() = default;
ASTAnnotation(ASTAnnotation const&) = delete;
ASTAnnotation(ASTAnnotation&&) = delete;
ASTAnnotation& operator=(ASTAnnotation const&) = delete;
ASTAnnotation& operator=(ASTAnnotation&&) = delete;
virtual ~ASTAnnotation() = default;
};
struct DocTag
{
std::string content; ///< The text content of the tag.
std::string paramName; ///< Only used for @param, stores the parameter name.
};
struct StructurallyDocumentedAnnotation
{
StructurallyDocumentedAnnotation() = default;
StructurallyDocumentedAnnotation(StructurallyDocumentedAnnotation const&) = delete;
StructurallyDocumentedAnnotation(StructurallyDocumentedAnnotation&&) = delete;
StructurallyDocumentedAnnotation& operator=(StructurallyDocumentedAnnotation const&) = delete;
StructurallyDocumentedAnnotation& operator=(StructurallyDocumentedAnnotation&&) = delete;
virtual ~StructurallyDocumentedAnnotation() = default;
/// Mapping docstring tag name -> content.
std::multimap<std::string, DocTag> docTags;
/// contract that @inheritdoc references if it exists
ContractDefinition const* inheritdocReference = nullptr;
};
struct SourceUnitAnnotation: ASTAnnotation
{
/// The "absolute" (in the compiler sense) path of this source unit.
util::SetOnce<std::string> path;
/// The exported symbols (all global symbols).
util::SetOnce<std::map<ASTString, std::vector<Declaration const*>>> exportedSymbols;
/// Experimental features.
std::set<ExperimentalFeature> experimentalFeatures;
/// Using the new ABI coder. Set to `false` if using ABI coder v1.
util::SetOnce<bool> useABICoderV2;
};
struct ScopableAnnotation
{
ScopableAnnotation() = default;
ScopableAnnotation(ScopableAnnotation const&) = delete;
ScopableAnnotation(ScopableAnnotation&&) = delete;
ScopableAnnotation& operator=(ScopableAnnotation const&) = delete;
ScopableAnnotation& operator=(ScopableAnnotation&&) = delete;
virtual ~ScopableAnnotation() = default;
/// The scope this declaration resides in. Can be nullptr if it is the global scope.
/// Filled by the Scoper.
ASTNode const* scope = nullptr;
/// Pointer to the contract this declaration resides in. Can be nullptr if the current scope
/// is not part of a contract. Filled by the Scoper.
ContractDefinition const* contract = nullptr;
};
struct DeclarationAnnotation: ASTAnnotation, ScopableAnnotation
{
};
struct ImportAnnotation: DeclarationAnnotation
{
/// The absolute path of the source unit to import.
util::SetOnce<std::string> absolutePath;
/// The actual source unit.
SourceUnit const* sourceUnit = nullptr;
};
struct TypeDeclarationAnnotation: DeclarationAnnotation
{
/// The name of this type, prefixed by proper namespaces if globally accessible.
util::SetOnce<std::string> canonicalName;
};
struct StructDeclarationAnnotation: TypeDeclarationAnnotation
{
/// Whether the struct is recursive, i.e. if the struct (recursively) contains a member that involves a struct of the same
/// type, either in a dynamic array, as member of another struct or inside a mapping.
/// Only cases in which the recursive occurrence is within a dynamic array or a mapping are valid, while direct
/// recursion immediately raises an error.
/// Will be filled in by the DeclarationTypeChecker.
std::optional<bool> recursive;
/// Whether the struct contains a mapping type, either directly or, indirectly inside another
/// struct or an array.
std::optional<bool> containsNestedMapping;
};
struct ContractDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation
{
/// List of functions and modifiers without a body. Can also contain functions from base classes.
std::optional<std::vector<Declaration const*>> unimplementedDeclarations;
/// List of all (direct and indirect) base contracts in order from derived to
/// base, including the contract itself.
std::vector<ContractDefinition const*> linearizedBaseContracts;
/// Mapping containing the nodes that define the arguments for base constructors.
/// These can either be inheritance specifiers or modifier invocations.
std::map<FunctionDefinition const*, ASTNode const*> baseConstructorArguments;
/// A graph with edges representing calls between functions that may happen during contract construction.
util::SetOnce<std::shared_ptr<CallGraph const>> creationCallGraph;
/// A graph with edges representing calls between functions that may happen in a deployed contract.
util::SetOnce<std::shared_ptr<CallGraph const>> deployedCallGraph;
/// List of contracts whose bytecode is referenced by this contract, e.g. through "new".
/// The Value represents the ast node that referenced the contract.
std::map<ContractDefinition const*, ASTNode const*, ASTCompareByID<ContractDefinition>> contractDependencies;
// Per-contract map from function AST IDs to internal dispatch function IDs.
std::map<FunctionDefinition const*, uint64_t> internalFunctionIDs;
};
struct StorageLayoutSpecifierAnnotation: ASTAnnotation
{
// The evaluated value of the expression specifying the contract storage layout base
util::SetOnce<u256> baseSlot;
};
struct CallableDeclarationAnnotation: DeclarationAnnotation
{
/// The set of functions/modifiers/events this callable overrides.
std::set<CallableDeclaration const*> baseFunctions;
};
struct FunctionDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
{
};
struct EventDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
{
};
struct ErrorDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
{
};
struct ModifierDefinitionAnnotation: CallableDeclarationAnnotation, StructurallyDocumentedAnnotation
{
};
struct VariableDeclarationAnnotation: DeclarationAnnotation, StructurallyDocumentedAnnotation
{
/// Type of variable (type of identifier referencing this variable).
Type const* type = nullptr;
/// The set of functions this (public state) variable overrides.
std::set<CallableDeclaration const*> baseFunctions;
};
struct StatementAnnotation: ASTAnnotation
{
};
struct InlineAssemblyAnnotation: StatementAnnotation
{
struct ExternalIdentifierInfo
{
Declaration const* declaration = nullptr;
/// Suffix used, one of "slot", "offset", "length", "address", "selector" or empty.
std::string suffix;
size_t valueSize = size_t(-1);
};
/// Mapping containing resolved references to external identifiers and their value size
std::map<yul::Identifier const*, ExternalIdentifierInfo> externalReferences;
/// Information generated during analysis phase.
std::shared_ptr<yul::AsmAnalysisInfo> analysisInfo;
/// True, if the assembly block was annotated to be memory-safe.
bool markedMemorySafe = false;
/// True, if the assembly block involves any memory opcode or assigns to variables in memory.
util::SetOnce<bool> hasMemoryEffects;
};
struct BlockAnnotation: StatementAnnotation, ScopableAnnotation
{
};
struct TryCatchClauseAnnotation: ASTAnnotation, ScopableAnnotation
{
};
struct ForStatementAnnotation: StatementAnnotation, ScopableAnnotation
{
util::SetOnce<bool> isSimpleCounterLoop;
};
struct ReturnAnnotation: StatementAnnotation
{
/// Reference to the return parameters of the function.
ParameterList const* functionReturnParameters = nullptr;
/// Reference to the function containing the return statement.
FunctionDefinition const* function = nullptr;
};
struct TypeNameAnnotation: ASTAnnotation
{
/// Type declared by this type name, i.e. type of a variable where this type name is used.
/// Set during reference resolution stage.
Type const* type = nullptr;
};
struct IdentifierPathAnnotation: ASTAnnotation
{
/// Referenced declaration, set during reference resolution stage.
Declaration const* referencedDeclaration = nullptr;
/// What kind of lookup needs to be done (static, virtual, super) find the declaration.
util::SetOnce<VirtualLookup> requiredLookup;
/// Declaration of each path element.
std::vector<Declaration const*> pathDeclarations;
};
struct ExpressionAnnotation: ASTAnnotation
{
/// Inferred type of the expression.
Type const* type = nullptr;
/// Whether the expression is a constant variable
util::SetOnce<bool> isConstant;
/// Whether the expression is pure, i.e. compile-time constant.
util::SetOnce<bool> isPure;
/// Whether it is an LValue (i.e. something that can be assigned to).
util::SetOnce<bool> isLValue;
/// Whether the expression is used in a context where the LValue is actually required.
bool willBeWrittenTo = false;
/// Types and - if given - names of arguments if the expr. is a function
/// that is called, used for overload resolution
std::optional<FuncCallArguments> arguments;
/// True if the expression consists solely of the name of the function and the function is called immediately
/// instead of being stored or processed. The name may be qualified with the name of a contract, library
/// module, etc., that clarifies the scope. For example: `m.L.f()`, where `m` is a module, `L` is a library
/// and `f` is a function is a direct call. This means that the function to be called is known at compilation
/// time and it's not necessary to rely on any runtime dispatch mechanism to resolve it.
/// Note that even the simplest expressions, like `(f)()`, result in an indirect call even if they consist of
/// values known at compilation time.
bool calledDirectly = false;
};
struct IdentifierAnnotation: ExpressionAnnotation
{
/// Referenced declaration, set at latest during overload resolution stage.
Declaration const* referencedDeclaration = nullptr;
/// What kind of lookup needs to be done (static, virtual, super) find the declaration.
util::SetOnce<VirtualLookup> requiredLookup;
/// List of possible declarations it could refer to (can contain duplicates).
std::vector<Declaration const*> candidateDeclarations;
/// List of possible declarations it could refer to.
std::vector<Declaration const*> overloadedDeclarations;
};
struct MemberAccessAnnotation: ExpressionAnnotation
{
/// Referenced declaration, set at latest during overload resolution stage.
Declaration const* referencedDeclaration = nullptr;
/// What kind of lookup needs to be done (static, virtual, super) find the declaration.
util::SetOnce<VirtualLookup> requiredLookup;
};
struct OperationAnnotation: ExpressionAnnotation
{
util::SetOnce<FunctionDefinition const*> userDefinedFunction;
};
struct BinaryOperationAnnotation: OperationAnnotation
{
/// The common type that is used for the operation, not necessarily the result type (which
/// e.g. for comparisons is bool).
Type const* commonType = nullptr;
};
enum class FunctionCallKind
{
FunctionCall,
TypeConversion,
StructConstructorCall
};
struct FunctionCallAnnotation: ExpressionAnnotation
{
util::SetOnce<FunctionCallKind> kind;
/// If true, this is the external call of a try statement.
bool tryCall = false;
};
/// Experimental Solidity annotations.
/// Used to integrate with name and type resolution.
/// @{
struct TypeClassDefinitionAnnotation: TypeDeclarationAnnotation, StructurallyDocumentedAnnotation
{
};
struct ForAllQuantifierAnnotation: StatementAnnotation, ScopableAnnotation
{
};
/// @}
}