mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #3862 from ethereum/fixConstantEvaluatorTuples
Fix ConstantEvaluator to correctly handle single element tuples (i.e. parenthesis).
This commit is contained in:
commit
418e2725b5
@ -4,6 +4,7 @@ Features:
|
||||
* Code Generator: Initialize arrays without using ``msize()``.
|
||||
* Code Generator: More specialized and thus optimized implementation for ``x.push(...)``
|
||||
* Commandline interface: Error when missing or inaccessible file detected. Suppress it with the ``--ignore-missing`` flag.
|
||||
* Constant Evaluator: Fix evaluation of single element tuples.
|
||||
* General: Limit the number of errors output in a single run to 256.
|
||||
* General: Support accessing dynamic return data in post-byzantium EVMs.
|
||||
* Interfaces: Allow overriding external functions in interfaces with public in an implementing contract.
|
||||
|
@ -87,6 +87,12 @@ void ConstantEvaluator::endVisit(Identifier const& _identifier)
|
||||
setType(_identifier, type(*value));
|
||||
}
|
||||
|
||||
void ConstantEvaluator::endVisit(TupleExpression const& _tuple)
|
||||
{
|
||||
if (!_tuple.isInlineArray() && _tuple.components().size() == 1)
|
||||
setType(_tuple, type(*_tuple.components().front()));
|
||||
}
|
||||
|
||||
void ConstantEvaluator::setType(ASTNode const& _node, TypePointer const& _type)
|
||||
{
|
||||
if (_type && _type->category() == Type::Category::RationalNumber)
|
||||
|
@ -56,6 +56,7 @@ private:
|
||||
virtual void endVisit(UnaryOperation const& _operation);
|
||||
virtual void endVisit(Literal const& _literal);
|
||||
virtual void endVisit(Identifier const& _identifier);
|
||||
virtual void endVisit(TupleExpression const& _tuple);
|
||||
|
||||
void setType(ASTNode const& _node, TypePointer const& _type);
|
||||
TypePointer type(ASTNode const& _node);
|
||||
|
@ -7720,171 +7720,6 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution)
|
||||
CHECK_SUCCESS(text);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_too_large)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint[8**90] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_not_convertible_to_integer)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint[true] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_constant_var)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant LEN = 10;
|
||||
uint[LEN] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_SUCCESS(text);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_non_integer_constant_var)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
bool constant LEN = true;
|
||||
uint[LEN] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_cannot_be_function)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
function f() {}
|
||||
uint[f] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_can_be_recursive_constant)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant L = 5;
|
||||
uint constant LEN = L + 4 * L;
|
||||
uint[LEN] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_SUCCESS(text);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_cannot_be_function_call)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
function f(uint x) {}
|
||||
uint constant LEN = f();
|
||||
uint[LEN] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_const_cannot_be_fractional)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
fixed constant L = 10.5;
|
||||
uint[L] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Array with fractional length specified");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_can_be_constant_in_struct)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant LEN = 10;
|
||||
struct Test {
|
||||
uint[LEN] ids;
|
||||
}
|
||||
}
|
||||
)";
|
||||
CHECK_SUCCESS(text);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_can_be_constant_in_function)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant LEN = 10;
|
||||
function f() {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
CHECK_SUCCESS(text);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_cannot_be_constant_function_parameter)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
function f(uint constant LEN) {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_with_cyclic_constant)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant LEN = LEN;
|
||||
function f() {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Cyclic constant definition (or maximum recursion depth exhausted).");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_with_complex_cyclic_constant)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant L2 = LEN - 10;
|
||||
uint constant L1 = L2 / 10;
|
||||
uint constant LEN = 10 + L1 * 5;
|
||||
function f() {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Cyclic constant definition (or maximum recursion depth exhausted).");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_with_pure_functions)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract C {
|
||||
uint constant LEN = keccak256(ripemd160(33));
|
||||
uint[LEN] ids;
|
||||
}
|
||||
)";
|
||||
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression.");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_length_invalid_expression)
|
||||
{
|
||||
char const* text = R"(
|
||||
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f(uint constant LEN) {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (62-65): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,8 @@
|
||||
contract C {
|
||||
uint constant LEN = 10;
|
||||
function f() public pure {
|
||||
uint[LEN] memory a;
|
||||
a;
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
uint constant LEN = 10;
|
||||
struct Test {
|
||||
uint[LEN] ids;
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
uint constant L = 5;
|
||||
uint constant LEN = L + 4 * L;
|
||||
uint[LEN] ids;
|
||||
}
|
||||
// ----
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
function f() {}
|
||||
uint[f] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (42-43): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f(uint x) {}
|
||||
uint constant LEN = f();
|
||||
uint[LEN] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (77-80): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,10 @@
|
||||
contract C {
|
||||
uint constant L2 = LEN - 10;
|
||||
uint constant L1 = L2 / 10;
|
||||
uint constant LEN = 10 + L1 * 5;
|
||||
function f() {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (36-39): Cyclic constant definition (or maximum recursion depth exhausted).
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
fixed constant L = 10.5;
|
||||
uint[L] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (51-52): Array with fractional length specified.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint constant LEN = 10;
|
||||
uint[LEN] ids;
|
||||
}
|
||||
// ----
|
@ -0,0 +1,8 @@
|
||||
contract C {
|
||||
uint constant LEN = LEN;
|
||||
function f() {
|
||||
uint[LEN] a;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (37-40): Cyclic constant definition (or maximum recursion depth exhausted).
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[[2]] a15;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-25): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[-true] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-27): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[true/1] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-28): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[1/true] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-28): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[1.111111E1111111111111] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-44): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[3/0] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-25): Operator / not compatible with types int_const 3 and int_const 0
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
bool constant LEN = true;
|
||||
uint[LEN] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (52-55): Invalid array length, expected integer literal or constant expression.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[true] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-26): Invalid array length, expected integer literal or constant expression.
|
25
test/libsolidity/syntaxTests/arrayLength/parentheses.sol
Normal file
25
test/libsolidity/syntaxTests/arrayLength/parentheses.sol
Normal file
@ -0,0 +1,25 @@
|
||||
contract C {
|
||||
uint constant L1 = (2);
|
||||
uint constant L2 = ((2));
|
||||
uint constant L3 = ((((2))));
|
||||
uint constant L4 = (2 + 1);
|
||||
uint constant L5 = ((2 + 1));
|
||||
uint constant L6 = (((2) + ((1))));
|
||||
uint constant L7 = (2 + 1) / 1;
|
||||
uint constant L8 = (2 + ((1))) / (1);
|
||||
uint[L1] a1;
|
||||
uint[L2] a2;
|
||||
uint[L3] a3;
|
||||
uint[L4] a4;
|
||||
uint[L5] a5;
|
||||
uint[L6] a6;
|
||||
uint[L7] a7;
|
||||
uint[L8] a8;
|
||||
uint[(2)] a9;
|
||||
uint[(2 + 1)] a10;
|
||||
uint[(2 + 1) + 1] a11;
|
||||
uint[((2) + 1) + 1] a12;
|
||||
uint[(2 + 1) + ((1))] a13;
|
||||
uint[(((2) + 1)) + (((1)))] a14;
|
||||
uint[((((2) + 1)) + (((1))))%1] a15;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
uint constant LEN = keccak256(ripemd160(33));
|
||||
uint[LEN] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (72-75): Invalid array length, expected integer literal or constant expression.
|
5
test/libsolidity/syntaxTests/arrayLength/too_large.sol
Normal file
5
test/libsolidity/syntaxTests/arrayLength/too_large.sol
Normal file
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[8**90] ids;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-27): Invalid array length, expected integer literal or constant expression.
|
5
test/libsolidity/syntaxTests/arrayLength/tuples.sol
Normal file
5
test/libsolidity/syntaxTests/arrayLength/tuples.sol
Normal file
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
uint[(1,2)] a15;
|
||||
}
|
||||
// ----
|
||||
// TypeError: (22-27): Invalid array length, expected integer literal or constant expression.
|
Loading…
Reference in New Issue
Block a user