[SMTChecker] Apply const eval to arithmetic binary expressions

This commit is contained in:
Leonardo Alt
2020-12-16 14:58:00 +01:00
parent e347545597
commit 80e85b772b
6 changed files with 67 additions and 13 deletions
+31 -12
View File
@@ -22,6 +22,8 @@
#include <libsolidity/formal/SymbolicState.h>
#include <libsolidity/formal/SymbolicTypes.h>
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libsmtutil/SMTPortfolio.h>
#include <libsmtutil/Helpers.h>
@@ -600,7 +602,8 @@ bool SMTEncoder::visit(BinaryOperation const& _op)
void SMTEncoder::endVisit(BinaryOperation const& _op)
{
if (_op.annotation().type->category() == Type::Category::RationalNumber)
/// If _op is const evaluated the RationalNumber shortcut was taken.
if (isConstant(_op))
return;
if (TokenTraits::isBooleanOp(_op.getOperator()))
return;
@@ -1628,17 +1631,17 @@ void SMTEncoder::defineGlobalVariable(string const& _name, Expression const& _ex
bool SMTEncoder::shortcutRationalNumber(Expression const& _expr)
{
if (_expr.annotation().type->category() == Type::Category::RationalNumber)
{
auto rationalType = dynamic_cast<RationalNumberType const*>(_expr.annotation().type);
solAssert(rationalType, "");
if (rationalType->isNegative())
defineExpr(_expr, smtutil::Expression(u2s(rationalType->literalValue(nullptr))));
else
defineExpr(_expr, smtutil::Expression(rationalType->literalValue(nullptr)));
return true;
}
return false;
auto type = isConstant(_expr);
if (!type)
return false;
solAssert(type->category() == Type::Category::RationalNumber, "");
auto const& rationalType = dynamic_cast<RationalNumberType const&>(*type);
if (rationalType.isNegative())
defineExpr(_expr, smtutil::Expression(u2s(rationalType.literalValue(nullptr))));
else
defineExpr(_expr, smtutil::Expression(rationalType.literalValue(nullptr)));
return true;
}
void SMTEncoder::arithmeticOperation(BinaryOperation const& _op)
@@ -2660,6 +2663,22 @@ map<ContractDefinition const*, vector<ASTPointer<frontend::Expression>>> SMTEnco
return baseArgs;
}
TypePointer SMTEncoder::isConstant(Expression const& _expr)
{
if (
auto type = _expr.annotation().type;
type->category() == Type::Category::RationalNumber
)
return type;
// _expr may not be constant evaluable.
// In that case we ignore any warnings emitted by the constant evaluator,
// as it will return nullptr in case of failure.
ErrorList l;
ErrorReporter e(l);
return ConstantEvaluator(e).evaluate(_expr);
}
void SMTEncoder::createReturnedExpressions(FunctionCall const& _funCall)
{
FunctionDefinition const* funDef = functionCallToDefinition(_funCall);
+4
View File
@@ -83,6 +83,10 @@ public:
/// @returns the arguments for each base constructor call in the hierarchy of @a _contract.
std::map<ContractDefinition const*, std::vector<ASTPointer<frontend::Expression>>> baseArguments(ContractDefinition const& _contract);
/// @returns a valid RationalNumberType pointer if _expr has type
/// RationalNumberType or can be const evaluated, and nullptr otherwise.
static TypePointer isConstant(Expression const& _expr);
protected:
// TODO: Check that we do not have concurrent reads and writes to a variable,
// because the order of expression evaluation is undefined