Coverage Report

Created: 2026-08-14 07:35

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