/src/solidity/libsolidity/formal/SMTEncoder.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** |
19 | | * Encodes Solidity into SMT expressions without creating |
20 | | * any verification targets. |
21 | | * Also implements the SSA scheme for branches. |
22 | | */ |
23 | | |
24 | | #pragma once |
25 | | |
26 | | |
27 | | #include <libsolidity/formal/EncodingContext.h> |
28 | | #include <libsolidity/formal/ModelCheckerSettings.h> |
29 | | #include <libsolidity/formal/SymbolicVariables.h> |
30 | | #include <libsolidity/formal/VariableUsage.h> |
31 | | |
32 | | #include <libsolidity/ast/AST.h> |
33 | | #include <libsolidity/ast/ASTVisitor.h> |
34 | | #include <libsolidity/interface/ReadFile.h> |
35 | | #include <liblangutil/UniqueErrorReporter.h> |
36 | | |
37 | | #include <string> |
38 | | #include <unordered_map> |
39 | | #include <vector> |
40 | | #include <utility> |
41 | | |
42 | | namespace solidity::langutil |
43 | | { |
44 | | class ErrorReporter; |
45 | | struct SourceLocation; |
46 | | class CharStreamProvider; |
47 | | } |
48 | | |
49 | | namespace solidity::frontend |
50 | | { |
51 | | |
52 | | class SMTEncoder: public ASTConstVisitor |
53 | | { |
54 | | public: |
55 | | SMTEncoder( |
56 | | smt::EncodingContext& _context, |
57 | | ModelCheckerSettings const& _settings, |
58 | | langutil::UniqueErrorReporter& _errorReporter, |
59 | | langutil::CharStreamProvider const& _charStreamProvider |
60 | | ); |
61 | | |
62 | | /// @returns the leftmost identifier in a multi-d IndexAccess. |
63 | | static Expression const* leftmostBase(IndexAccess const& _indexAccess); |
64 | | |
65 | | /// @returns the key type in _type. |
66 | | /// _type must allow IndexAccess, that is, |
67 | | /// it must be either ArrayType or MappingType |
68 | | static Type const* keyType(Type const* _type); |
69 | | |
70 | | /// @returns the innermost element in a chain of 1-tuples if applicable, |
71 | | /// otherwise _expr. |
72 | | static Expression const* innermostTuple(Expression const& _expr); |
73 | | |
74 | | /// @returns the underlying type if _type is UserDefinedValueType, |
75 | | /// and _type otherwise. |
76 | | static Type const* underlyingType(Type const* _type); |
77 | | |
78 | | static TypePointers replaceUserTypes(TypePointers const& _types); |
79 | | |
80 | | /// @returns {_funCall.expression(), nullptr} if function call option values are not given, and |
81 | | /// {_funCall.expression().expression(), _funCall.expression()} if they are. |
82 | | static std::pair<Expression const*, FunctionCallOptions const*> functionCallExpression(FunctionCall const& _funCall); |
83 | | |
84 | | /// @returns the expression after stripping redundant syntactic sugar. |
85 | | /// Currently supports stripping: |
86 | | /// 1. 1-tuple; i.e. ((x)) -> x |
87 | | /// 2. Explicit cast from string to bytes; i.e. bytes(s) -> s; for s of type string |
88 | | static Expression const* cleanExpression(Expression const& _expr); |
89 | | |
90 | | /// @returns the FunctionDefinition of a FunctionCall |
91 | | /// if possible or nullptr. |
92 | | /// @param _scopeContract is the contract that contains the function currently being |
93 | | /// analyzed, if applicable. |
94 | | /// @param _contextContract is the most derived contract currently being analyzed. |
95 | | /// The difference between the two parameters appears in the case of inheritance. |
96 | | /// Let A and B be two contracts so that B derives from A, and A defines a function `f` |
97 | | /// that `B` does not override. Function `f` is visited twice: |
98 | | /// - Once when A is the most derived contract, where both _scopeContract and _contextContract are A. |
99 | | /// - Once when B is the most derived contract, where _scopeContract is A and _contextContract is B. |
100 | | static FunctionDefinition const* functionCallToDefinition( |
101 | | FunctionCall const& _funCall, |
102 | | ContractDefinition const* _scopeContract, |
103 | | ContractDefinition const* _contextContract |
104 | | ); |
105 | | |
106 | | static std::vector<VariableDeclaration const*> stateVariablesIncludingInheritedAndPrivate(ContractDefinition const& _contract); |
107 | | static std::vector<VariableDeclaration const*> stateVariablesIncludingInheritedAndPrivate(FunctionDefinition const& _function); |
108 | | |
109 | | static std::vector<VariableDeclaration const*> localVariablesIncludingModifiers(FunctionDefinition const& _function, ContractDefinition const* _contract); |
110 | | static std::vector<VariableDeclaration const*> modifiersVariables(FunctionDefinition const& _function, ContractDefinition const* _contract); |
111 | | static std::vector<VariableDeclaration const*> tryCatchVariables(FunctionDefinition const& _function); |
112 | | |
113 | | /// @returns the ModifierDefinition of a ModifierInvocation if possible, or nullptr. |
114 | | static ModifierDefinition const* resolveModifierInvocation(ModifierInvocation const& _invocation, ContractDefinition const* _contract); |
115 | | |
116 | | /// @returns the SourceUnit that contains _scopable. |
117 | | static SourceUnit const* sourceUnitContaining(Scopable const& _scopable); |
118 | | |
119 | | /// @returns the arguments for each base constructor call in the hierarchy of @a _contract. |
120 | | std::map<ContractDefinition const*, std::vector<ASTPointer<frontend::Expression>>> baseArguments(ContractDefinition const& _contract); |
121 | | |
122 | | /// @returns a valid RationalNumberType pointer if _expr has type |
123 | | /// RationalNumberType or can be const evaluated, and nullptr otherwise. |
124 | | static RationalNumberType const* isConstant(Expression const& _expr); |
125 | | |
126 | | static std::set<FunctionCall const*> collectABICalls(ASTNode const* _node); |
127 | | |
128 | | /// @returns all the sources that @param _source depends on, |
129 | | /// including itself. |
130 | | static std::set<SourceUnit const*, ASTNode::CompareByID> sourceDependencies(SourceUnit const& _source); |
131 | | |
132 | | protected: |
133 | | void resetSourceAnalysis(); |
134 | | |
135 | | // TODO: Check that we do not have concurrent reads and writes to a variable, |
136 | | // because the order of expression evaluation is undefined |
137 | | // TODO: or just force a certain order, but people might have a different idea about that. |
138 | | |
139 | | bool visit(ImportDirective const& _node) override; |
140 | | bool visit(ContractDefinition const& _node) override; |
141 | | void endVisit(ContractDefinition const& _node) override; |
142 | | void endVisit(VariableDeclaration const& _node) override; |
143 | | bool visit(ModifierDefinition const& _node) override; |
144 | | bool visit(FunctionDefinition const& _node) override; |
145 | | void endVisit(FunctionDefinition const& _node) override; |
146 | | bool visit(Block const& _node) override; |
147 | | void endVisit(Block const& _node) override; |
148 | | bool visit(PlaceholderStatement const& _node) override; |
149 | 0 | bool visit(IfStatement const&) override { return false; } |
150 | 0 | bool visit(WhileStatement const&) override { return false; } |
151 | 0 | bool visit(ForStatement const&) override { return false; } |
152 | 454 | void endVisit(ForStatement const&) override {} |
153 | | void endVisit(VariableDeclarationStatement const& _node) override; |
154 | | bool visit(Assignment const& _node) override; |
155 | | void endVisit(Assignment const& _node) override; |
156 | | void endVisit(TupleExpression const& _node) override; |
157 | | bool visit(UnaryOperation const& _node) override; |
158 | | void endVisit(UnaryOperation const& _node) override; |
159 | | bool visit(BinaryOperation const& _node) override; |
160 | | void endVisit(BinaryOperation const& _node) override; |
161 | | bool visit(Conditional const& _node) override; |
162 | | bool visit(FunctionCall const& _node) override; |
163 | | void endVisit(FunctionCall const& _node) override; |
164 | | bool visit(ModifierInvocation const& _node) override; |
165 | | void endVisit(Identifier const& _node) override; |
166 | | void endVisit(ElementaryTypeNameExpression const& _node) override; |
167 | | void endVisit(Literal const& _node) override; |
168 | | void endVisit(Return const& _node) override; |
169 | | bool visit(MemberAccess const& _node) override; |
170 | | void endVisit(IndexAccess const& _node) override; |
171 | | void endVisit(IndexRangeAccess const& _node) override; |
172 | | bool visit(InlineAssembly const& _node) override; |
173 | 66 | void endVisit(Break const&) override {} |
174 | 49 | void endVisit(Continue const&) override {} |
175 | 622 | bool visit(TryCatchClause const&) override { return true; } |
176 | 307 | void endVisit(TryCatchClause const&) override {} |
177 | 0 | bool visit(TryStatement const&) override { return false; } |
178 | | |
179 | | virtual void pushInlineFrame(CallableDeclaration const&); |
180 | | virtual void popInlineFrame(CallableDeclaration const&); |
181 | | |
182 | | /// Do not visit subtree if node is a RationalNumber. |
183 | | /// Symbolic _expr is the rational literal. |
184 | | bool shortcutRationalNumber(Expression const& _expr); |
185 | | void arithmeticOperation(BinaryOperation const& _op); |
186 | | /// @returns _op(_left, _right) with and without modular arithmetic. |
187 | | /// Used by the function above, compound assignments and |
188 | | /// unary increment/decrement. |
189 | | virtual std::pair<smtutil::Expression, smtutil::Expression> arithmeticOperation( |
190 | | Token _op, |
191 | | smtutil::Expression const& _left, |
192 | | smtutil::Expression const& _right, |
193 | | Type const* _commonType, |
194 | | Expression const& _expression |
195 | | ); |
196 | | |
197 | | smtutil::Expression bitwiseOperation( |
198 | | Token _op, |
199 | | smtutil::Expression const& _left, |
200 | | smtutil::Expression const& _right, |
201 | | Type const* _commonType |
202 | | ); |
203 | | |
204 | | void compareOperation(BinaryOperation const& _op); |
205 | | void booleanOperation(BinaryOperation const& _op); |
206 | | void bitwiseOperation(BinaryOperation const& _op); |
207 | | void bitwiseNotOperation(UnaryOperation const& _op); |
208 | | |
209 | | void initContract(ContractDefinition const& _contract); |
210 | | void initFunction(FunctionDefinition const& _function); |
211 | | void visitAssert(FunctionCall const& _funCall); |
212 | | void visitRequire(FunctionCall const& _funCall); |
213 | | void visitABIFunction(FunctionCall const& _funCall); |
214 | | void visitCryptoFunction(FunctionCall const& _funCall); |
215 | | void visitGasLeft(FunctionCall const& _funCall); |
216 | | virtual void visitAddMulMod(FunctionCall const& _funCall); |
217 | | void visitWrapUnwrap(FunctionCall const& _funCall); |
218 | | void visitObjectCreation(FunctionCall const& _funCall); |
219 | | void visitTypeConversion(FunctionCall const& _funCall); |
220 | | void visitStructConstructorCall(FunctionCall const& _funCall); |
221 | | void visitFunctionIdentifier(Identifier const& _identifier); |
222 | | void visitPublicGetter(FunctionCall const& _funCall); |
223 | | |
224 | | /// @returns true if @param _contract is set for analysis in the settings |
225 | | /// and it is not abstract. |
226 | | bool shouldAnalyze(ContractDefinition const& _contract) const; |
227 | | /// @returns true if @param _source is set for analysis in the settings. |
228 | | bool shouldAnalyze(SourceUnit const& _source) const; |
229 | | |
230 | | bool isPublicGetter(Expression const& _expr); |
231 | | |
232 | | /// Encodes a modifier or function body according to the modifier |
233 | | /// visit depth. |
234 | | void visitFunctionOrModifier(); |
235 | | |
236 | | /// Inlines a modifier or base constructor call. |
237 | | void inlineModifierInvocation(ModifierInvocation const* _invocation, CallableDeclaration const* _definition); |
238 | | |
239 | | /// Inlines the constructor hierarchy into a single constructor. |
240 | | void inlineConstructorHierarchy(ContractDefinition const& _contract); |
241 | | |
242 | | /// Defines a new global variable or function. |
243 | | void defineGlobalVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex = false); |
244 | | |
245 | | /// Handles the side effects of assignment |
246 | | /// to variable of some SMT array type |
247 | | /// while aliasing is not supported. |
248 | | void arrayAssignment(); |
249 | | /// Handles assignments to index or member access. |
250 | | void indexOrMemberAssignment(Expression const& _expr, smtutil::Expression const& _rightHandSide); |
251 | | |
252 | | void arrayPush(FunctionCall const& _funCall); |
253 | | void arrayPop(FunctionCall const& _funCall); |
254 | | /// Allows BMC and CHC to create verification targets for popping |
255 | | /// an empty array. |
256 | 247 | virtual void makeArrayPopVerificationTarget(FunctionCall const&) {} |
257 | | /// Allows BMC and CHC to create verification targets for out of bounds access. |
258 | 14.1k | virtual void makeOutOfBoundsVerificationTarget(IndexAccess const&) {} |
259 | | |
260 | | void addArrayLiteralAssertions( |
261 | | smt::SymbolicArrayVariable& _symArray, |
262 | | std::vector<smtutil::Expression> const& _elementValues |
263 | | ); |
264 | | |
265 | | void bytesToFixedBytesAssertions( |
266 | | smt::SymbolicArrayVariable& _symArray, |
267 | | Expression const& _fixedBytes |
268 | | ); |
269 | | |
270 | | /// @returns a pair of expressions representing _left / _right and _left mod _right, respectively. |
271 | | /// Uses slack variables and additional constraints to express the results using only operations |
272 | | /// more friendly to the SMT solver (multiplication, addition, subtraction and comparison). |
273 | | std::pair<smtutil::Expression, smtutil::Expression> divModWithSlacks( |
274 | | smtutil::Expression _left, |
275 | | smtutil::Expression _right, |
276 | | IntegerType const& _type |
277 | | ); |
278 | | |
279 | | /// Handles the actual assertion of the new value to the encoding context. |
280 | | /// Other assignment methods should use this one in the end. |
281 | | virtual void assignment(smt::SymbolicVariable& _symVar, smtutil::Expression const& _value); |
282 | | |
283 | | void assignment(VariableDeclaration const& _variable, Expression const& _value); |
284 | | /// Handles assignments to variables of different types. |
285 | | void assignment(VariableDeclaration const& _variable, smtutil::Expression const& _value); |
286 | | /// Handles assignments between generic expressions. |
287 | | /// Will also be used for assignments of tuple components. |
288 | | void assignment(Expression const& _left, smtutil::Expression const& _right); |
289 | | void assignment( |
290 | | Expression const& _left, |
291 | | smtutil::Expression const& _right, |
292 | | Type const* _type |
293 | | ); |
294 | | /// Handle assignments between tuples. |
295 | | void tupleAssignment(Expression const& _left, Expression const& _right); |
296 | | /// Computes the right hand side of a compound assignment. |
297 | | smtutil::Expression compoundAssignment(Assignment const& _assignment); |
298 | | /// Handles assignment of an expression to a tuple of variables. |
299 | | void expressionToTupleAssignment(std::vector<std::shared_ptr<VariableDeclaration>> const& _variables, Expression const& _rhs); |
300 | | |
301 | | /// Maps a variable to an SSA index. |
302 | | using VariableIndices = std::unordered_map<VariableDeclaration const*, unsigned>; |
303 | | |
304 | | /// Visits the branch given by the statement, pushes and pops the current path conditions. |
305 | | /// @param _condition if present, asserts that this condition is true within the branch. |
306 | | /// @returns the variable indices after visiting the branch and the expression representing |
307 | | /// the path condition at the end of the branch. |
308 | | std::pair<VariableIndices, smtutil::Expression> visitBranch(ASTNode const* _statement, smtutil::Expression const* _condition = nullptr); |
309 | | std::pair<VariableIndices, smtutil::Expression> visitBranch(ASTNode const* _statement, smtutil::Expression _condition); |
310 | | |
311 | | using CallStackEntry = std::pair<CallableDeclaration const*, ASTNode const*>; |
312 | | |
313 | | void createStateVariables(ContractDefinition const& _contract); |
314 | | void initializeStateVariables(ContractDefinition const& _contract); |
315 | | void createLocalVariables(FunctionDefinition const& _function); |
316 | | void initializeLocalVariables(FunctionDefinition const& _function); |
317 | | void initializeFunctionCallParameters(CallableDeclaration const& _function, std::vector<smtutil::Expression> const& _callArgs); |
318 | | void resetStateVariables(); |
319 | | void resetStorageVariables(); |
320 | | void resetMemoryVariables(); |
321 | | void resetBalances(); |
322 | | /// Resets all references/pointers that have the same type or have |
323 | | /// a subexpression of the same type as _varDecl. |
324 | | void resetReferences(VariableDeclaration const& _varDecl); |
325 | | /// Resets all references/pointers that have type _type. |
326 | | void resetReferences(Type const* _type); |
327 | | /// @returns the type without storage pointer information if it has it. |
328 | | Type const* typeWithoutPointer(Type const* _type); |
329 | | /// @returns whether _a or a subtype of _a is the same as _b. |
330 | | bool sameTypeOrSubtype(Type const* _a, Type const* _b); |
331 | | |
332 | | bool isSupportedType(Type const& _type) const; |
333 | | |
334 | | /// Given the state of the symbolic variables at the end of two different branches, |
335 | | /// create a merged state using the given branch condition. |
336 | | void mergeVariables(smtutil::Expression const& _condition, VariableIndices const& _indicesEndTrue, VariableIndices const& _indicesEndFalse); |
337 | | /// Tries to create an uninitialized variable and returns true on success. |
338 | | bool createVariable(VariableDeclaration const& _varDecl); |
339 | | |
340 | | /// @returns an expression denoting the value of the variable declared in @a _decl |
341 | | /// at the current point. |
342 | | smtutil::Expression currentValue(VariableDeclaration const& _decl) const; |
343 | | /// @returns an expression denoting the value of the variable declared in @a _decl |
344 | | /// at the given index. Does not ensure that this index exists. |
345 | | smtutil::Expression valueAtIndex(VariableDeclaration const& _decl, unsigned _index) const; |
346 | | /// Returns the expression corresponding to the AST node. |
347 | | /// If _targetType is not null apply conversion. |
348 | | /// Throws if the expression does not exist. |
349 | | smtutil::Expression expr(Expression const& _e, Type const* _targetType = nullptr); |
350 | | /// Creates the expression (value can be arbitrary) |
351 | | void createExpr(Expression const& _e); |
352 | | /// Creates the expression and sets its value. |
353 | | void defineExpr(Expression const& _e, smtutil::Expression _value); |
354 | | /// Creates the tuple expression and sets its value. |
355 | | void defineExpr(Expression const& _e, std::vector<std::optional<smtutil::Expression>> const& _values); |
356 | | /// Overwrites the current path condition |
357 | | void setPathCondition(smtutil::Expression const& _e); |
358 | | /// Adds a new path condition |
359 | | void pushPathCondition(smtutil::Expression const& _e); |
360 | | /// Remove the last path condition |
361 | | void popPathCondition(); |
362 | | /// Returns the conjunction of all path conditions or True if empty |
363 | | smtutil::Expression currentPathConditions(); |
364 | | /// @returns a human-readable call stack. Used for models. |
365 | | langutil::SecondarySourceLocation callStackMessage(std::vector<CallStackEntry> const& _callStack); |
366 | | /// Copies and pops the last called node. |
367 | | CallStackEntry popCallStack(); |
368 | | /// Adds (_definition, _node) to the callstack. |
369 | | void pushCallStack(CallStackEntry _entry); |
370 | | /// Add to the solver: the given expression implied by the current path conditions |
371 | | void addPathImpliedExpression(smtutil::Expression const& _e); |
372 | | |
373 | | /// Copy the SSA indices of m_variables. |
374 | | VariableIndices copyVariableIndices(); |
375 | | /// Resets the variable indices. |
376 | | void resetVariableIndices(VariableIndices const& _indices); |
377 | | /// Used when starting a new block. |
378 | | virtual void clearIndices(ContractDefinition const* _contract, FunctionDefinition const* _function = nullptr); |
379 | | |
380 | | |
381 | | /// @returns variables that are touched in _node's subtree. |
382 | | std::set<VariableDeclaration const*> touchedVariables(ASTNode const& _node); |
383 | | |
384 | | /// @returns the declaration referenced by _expr, if any, |
385 | | /// and nullptr otherwise. |
386 | | Declaration const* expressionToDeclaration(Expression const& _expr) const; |
387 | | |
388 | | /// @returns the VariableDeclaration referenced by an Expression or nullptr. |
389 | | VariableDeclaration const* identifierToVariable(Expression const& _expr) const; |
390 | | |
391 | | /// @returns the MemberAccess <expression>.push if _expr is an empty array push call, |
392 | | /// otherwise nullptr. |
393 | | MemberAccess const* isEmptyPush(Expression const& _expr) const; |
394 | | |
395 | | /// @returns true if the given identifier is a contract which is known and trusted. |
396 | | /// This means we don't have to abstract away effects of external function calls to this contract. |
397 | | static bool isTrustedExternalCall(Expression const* _expr); |
398 | | |
399 | | /// Creates symbolic expressions for the returned values |
400 | | /// and set them as the components of the symbolic tuple. |
401 | | void createReturnedExpressions(FunctionCall const& _funCall, ContractDefinition const* _contextContract); |
402 | | |
403 | | /// @returns the symbolic arguments for a function call, |
404 | | /// taking into account bound functions and |
405 | | /// type conversion. |
406 | | std::vector<smtutil::Expression> symbolicArguments(FunctionCall const& _funCall, ContractDefinition const* _contextContract); |
407 | | |
408 | | smtutil::Expression constantExpr(Expression const& _expr, VariableDeclaration const& _var); |
409 | | |
410 | | /// Traverses all source units available collecting free functions |
411 | | /// and internal library functions in m_freeFunctions. |
412 | | void collectFreeFunctions(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources); |
413 | 57.1k | std::set<FunctionDefinition const*, ASTNode::CompareByID> const& allFreeFunctions() const { return m_freeFunctions; } |
414 | | /// Create symbolic variables for the free constants in all @param _sources. |
415 | | void createFreeConstants(std::set<SourceUnit const*, ASTNode::CompareByID> const& _sources); |
416 | | |
417 | | /// @returns a note to be added to warnings. |
418 | | std::string extraComment(); |
419 | | |
420 | | struct VerificationTarget |
421 | | { |
422 | | VerificationTargetType type; |
423 | | smtutil::Expression value; |
424 | | smtutil::Expression constraints; |
425 | | }; |
426 | | |
427 | | smt::VariableUsage m_variableUsage; |
428 | | bool m_arrayAssignmentHappened = false; |
429 | | |
430 | | /// Stores the instances of an Uninterpreted Function applied to arguments. |
431 | | /// These may be direct application of UFs or Array index access. |
432 | | /// Used to retrieve models. |
433 | | std::set<Expression const*> m_uninterpretedTerms; |
434 | | std::vector<smtutil::Expression> m_pathConditions; |
435 | | |
436 | | /// Whether the currently visited block uses checked |
437 | | /// or unchecked arithmetic. |
438 | | bool m_checked = true; |
439 | | |
440 | | langutil::UniqueErrorReporter& m_errorReporter; |
441 | | |
442 | | /// Stores the current function/modifier call/invocation path. |
443 | | std::vector<CallStackEntry> m_callStack; |
444 | | |
445 | | /// Stack of scopes. |
446 | | std::vector<ScopeOpener const*> m_scopes; |
447 | | |
448 | | /// Returns true if the current function was not visited by |
449 | | /// a function call. |
450 | | bool isRootFunction(); |
451 | | /// Returns true if _funDef was already visited. |
452 | | bool visitedFunction(FunctionDefinition const* _funDef); |
453 | | /// @returns the contract that contains the current FunctionDefinition that is being visited, |
454 | | /// or nullptr if the analysis is not inside a FunctionDefinition. |
455 | | ContractDefinition const* currentScopeContract(); |
456 | | |
457 | | /// @returns FunctionDefinitions of the given contract (including its constructor and inherited methods), |
458 | | /// taking into account overriding of the virtual functions. |
459 | | std::set<FunctionDefinition const*, ASTNode::CompareByID> const& contractFunctions(ContractDefinition const& _contract); |
460 | | /// Cache for the method contractFunctions. |
461 | | std::map<ContractDefinition const*, std::set<FunctionDefinition const*, ASTNode::CompareByID>> m_contractFunctions; |
462 | | |
463 | | /// @returns FunctionDefinitions of the given contract (including its constructor and methods of bases), |
464 | | /// without taking into account overriding of the virtual functions. |
465 | | std::set<FunctionDefinition const*, ASTNode::CompareByID> const& contractFunctionsWithoutVirtual(ContractDefinition const& _contract); |
466 | | /// Cache for the method contractFunctionsWithoutVirtual. |
467 | | std::map<ContractDefinition const*, std::set<FunctionDefinition const*, ASTNode::CompareByID>> m_contractFunctionsWithoutVirtual; |
468 | | |
469 | | /// Depth of visit to modifiers. |
470 | | /// When m_modifierDepth == #modifiers the function can be visited |
471 | | /// when placeholder is visited. |
472 | | /// Needs to be a stack because of function calls. |
473 | | std::vector<int> m_modifierDepthStack; |
474 | | |
475 | | std::map<ContractDefinition const*, ModifierInvocation const*> m_baseConstructorCalls; |
476 | | |
477 | | ContractDefinition const* m_currentContract = nullptr; |
478 | | |
479 | | /// Stores the free functions and internal library functions. |
480 | | /// Those need to be encoded repeatedely for every analyzed contract. |
481 | | std::set<FunctionDefinition const*, ASTNode::CompareByID> m_freeFunctions; |
482 | | |
483 | | /// Stores the context of the encoding. |
484 | | smt::EncodingContext& m_context; |
485 | | |
486 | | ModelCheckerSettings const& m_settings; |
487 | | |
488 | | /// Character stream for each source, |
489 | | /// used for retrieving source text of expressions for e.g. counter-examples. |
490 | | langutil::CharStreamProvider const& m_charStreamProvider; |
491 | | |
492 | | smt::SymbolicState& state(); |
493 | | }; |
494 | | |
495 | | } |