mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
ConstantEvaluator respecting integer type annotations
This commit is contained in:
parent
f1846b57a2
commit
8afee28eea
@ -29,6 +29,7 @@ Bugfixes:
|
||||
* SMTChecker: Fix internal error when ``array.push()`` is used as the LHS of an assignment.
|
||||
* SMTChecker: Fix CHC false positives when branches are used inside modifiers.
|
||||
* Code generator: Fix missing creation dependency tracking for abstract contracts.
|
||||
* Constant Evaluator: Fix evaluation integer type operations.
|
||||
|
||||
|
||||
### 0.7.4 (2020-10-19)
|
||||
|
@ -34,15 +34,16 @@ using namespace solidity::langutil;
|
||||
|
||||
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
|
||||
{
|
||||
auto sub = type(_operation.subExpression());
|
||||
auto sub = type(_operation.subExpression()).value;
|
||||
if (sub)
|
||||
setType(_operation, sub->unaryOperatorResult(_operation.getOperator()));
|
||||
}
|
||||
|
||||
void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
|
||||
{
|
||||
auto left = type(_operation.leftExpression());
|
||||
auto right = type(_operation.rightExpression());
|
||||
auto left = type(_operation.leftExpression()).value;
|
||||
auto right = type(_operation.rightExpression()).value;
|
||||
|
||||
if (left && right)
|
||||
{
|
||||
TypePointer commonType = left->binaryOperatorResult(_operation.getOperator(), right);
|
||||
@ -57,6 +58,24 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
|
||||
" and " +
|
||||
right->toString()
|
||||
);
|
||||
|
||||
if (auto const rationalCommonType = dynamic_cast<RationalNumberType const*>(commonType))
|
||||
{
|
||||
auto const leftType = type(_operation.leftExpression()).type;
|
||||
auto const rightType = type(_operation.rightExpression()).type;
|
||||
auto const leftInteger = leftType && leftType->category() == Type::Category::Integer;
|
||||
auto const rightInteger = rightType && rightType->category() == Type::Category::Integer;
|
||||
if (leftInteger || rightInteger)
|
||||
{
|
||||
rational const frac = rationalCommonType->value();
|
||||
bigint const num = frac.numerator() / frac.denominator();
|
||||
auto const value = TypeProvider::rationalNumber(rational(num, 1));
|
||||
auto const type = value->integerType();
|
||||
setType(_operation, TypedValue{type, value});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setType(
|
||||
_operation,
|
||||
TokenTraits::isCompareOp(_operation.getOperator()) ?
|
||||
@ -89,7 +108,7 @@ void ConstantEvaluator::endVisit(Identifier const& _identifier)
|
||||
ConstantEvaluator(m_errorReporter, m_depth + 1, m_types).evaluate(*value);
|
||||
}
|
||||
|
||||
setType(_identifier, type(*value));
|
||||
setType(_identifier, TypedValue{variableDeclaration->annotation().type, type(*value).value});
|
||||
}
|
||||
|
||||
void ConstantEvaluator::endVisit(TupleExpression const& _tuple)
|
||||
@ -98,13 +117,13 @@ void ConstantEvaluator::endVisit(TupleExpression const& _tuple)
|
||||
setType(_tuple, type(*_tuple.components().front()));
|
||||
}
|
||||
|
||||
void ConstantEvaluator::setType(ASTNode const& _node, TypePointer const& _type)
|
||||
void ConstantEvaluator::setType(ASTNode const& _node, TypedValue const& _type)
|
||||
{
|
||||
if (_type && _type->category() == Type::Category::RationalNumber)
|
||||
if (_type.value && _type.value->category() == Type::Category::RationalNumber)
|
||||
(*m_types)[&_node] = _type;
|
||||
}
|
||||
|
||||
TypePointer ConstantEvaluator::type(ASTNode const& _node)
|
||||
ConstantEvaluator::TypedValue ConstantEvaluator::type(ASTNode const& _node)
|
||||
{
|
||||
return (*m_types)[&_node];
|
||||
}
|
||||
@ -112,5 +131,5 @@ TypePointer ConstantEvaluator::type(ASTNode const& _node)
|
||||
TypePointer ConstantEvaluator::evaluate(Expression const& _expr)
|
||||
{
|
||||
_expr.accept(*this);
|
||||
return type(_expr);
|
||||
return type(_expr).value;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <libsolidity/ast/ASTVisitor.h>
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace solidity::langutil
|
||||
@ -43,10 +44,12 @@ class TypeChecker;
|
||||
class ConstantEvaluator: private ASTConstVisitor
|
||||
{
|
||||
public:
|
||||
struct TypedValue { TypePointer type; TypePointer value; };
|
||||
|
||||
ConstantEvaluator(
|
||||
langutil::ErrorReporter& _errorReporter,
|
||||
size_t _newDepth = 0,
|
||||
std::shared_ptr<std::map<ASTNode const*, TypePointer>> _types = std::make_shared<std::map<ASTNode const*, TypePointer>>()
|
||||
std::shared_ptr<std::map<ASTNode const*, TypedValue>> _types = std::make_shared<std::map<ASTNode const*, TypedValue>>()
|
||||
):
|
||||
m_errorReporter(_errorReporter),
|
||||
m_depth(_newDepth),
|
||||
@ -63,13 +66,14 @@ private:
|
||||
void endVisit(Identifier const& _identifier) override;
|
||||
void endVisit(TupleExpression const& _tuple) override;
|
||||
|
||||
void setType(ASTNode const& _node, TypePointer const& _type);
|
||||
TypePointer type(ASTNode const& _node);
|
||||
void setType(ASTNode const& _node, TypedValue const& _type);
|
||||
void setType(ASTNode const& _node, TypePointer _type) { setType(_node, {_type, _type}); };
|
||||
TypedValue type(ASTNode const& _node);
|
||||
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
/// Current recursion depth.
|
||||
size_t m_depth = 0;
|
||||
std::shared_ptr<std::map<ASTNode const*, TypePointer>> m_types;
|
||||
std::shared_ptr<std::map<ASTNode const*, TypedValue>> m_types;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -568,6 +568,11 @@ public:
|
||||
u256 literalValue(Literal const* _literal) const override;
|
||||
TypePointer mobileType() const override;
|
||||
|
||||
/// @returns the underlying raw literal value.
|
||||
///
|
||||
/// @see literalValue(Literal const*))
|
||||
rational const& value() const noexcept { return m_value; }
|
||||
|
||||
/// @returns the smallest integer type that can hold the value or an empty pointer if not possible.
|
||||
IntegerType const* integerType() const;
|
||||
/// @returns the smallest fixed type that can hold the value or incurs the least precision loss,
|
||||
|
14
test/libsolidity/semanticTests/consteval_array_length.sol
Normal file
14
test/libsolidity/semanticTests/consteval_array_length.sol
Normal file
@ -0,0 +1,14 @@
|
||||
contract C {
|
||||
uint constant a = 12;
|
||||
uint constant b = 10;
|
||||
|
||||
function f() public pure returns (uint) {
|
||||
uint[(a / b) * b] memory x;
|
||||
return x.length;
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// constructor() ->
|
||||
// f() -> 10
|
Loading…
Reference in New Issue
Block a user