diff --git a/Changelog.md b/Changelog.md index 6df11f275..1612fe3bd 100644 --- a/Changelog.md +++ b/Changelog.md @@ -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. diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 83f37f474..8659bbfdc 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -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) diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 77a357b65..ac3a24a1f 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -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); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index fcee0df3a..293f5f44e 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -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"( diff --git a/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol b/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol new file mode 100644 index 000000000..11d40f26d --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol new file mode 100644 index 000000000..92536dd50 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol @@ -0,0 +1,8 @@ +contract C { + uint constant LEN = 10; + function f() public pure { + uint[LEN] memory a; + a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol new file mode 100644 index 000000000..89e174f2d --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol @@ -0,0 +1,7 @@ +contract C { + uint constant LEN = 10; + struct Test { + uint[LEN] ids; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol b/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol new file mode 100644 index 000000000..6810a9d6a --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol @@ -0,0 +1,6 @@ +contract C { + uint constant L = 5; + uint constant LEN = L + 4 * L; + uint[LEN] ids; +} +// ---- diff --git a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol new file mode 100644 index 000000000..ac3abc4c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol @@ -0,0 +1,6 @@ +contract C { + function f() {} + uint[f] ids; +} +// ---- +// TypeError: (42-43): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol new file mode 100644 index 000000000..a68639556 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol b/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol new file mode 100644 index 000000000..254f9f020 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol @@ -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). diff --git a/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol b/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol new file mode 100644 index 000000000..397bbbcd8 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol @@ -0,0 +1,6 @@ +contract C { + fixed constant L = 10.5; + uint[L] ids; +} +// ---- +// TypeError: (51-52): Array with fractional length specified. diff --git a/test/libsolidity/syntaxTests/arrayLength/constant_var.sol b/test/libsolidity/syntaxTests/arrayLength/constant_var.sol new file mode 100644 index 000000000..41750250e --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/constant_var.sol @@ -0,0 +1,5 @@ +contract C { + uint constant LEN = 10; + uint[LEN] ids; +} +// ---- \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol b/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol new file mode 100644 index 000000000..91ba9045d --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol @@ -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). diff --git a/test/libsolidity/syntaxTests/arrayLength/inline_array.sol b/test/libsolidity/syntaxTests/arrayLength/inline_array.sol new file mode 100644 index 000000000..a30745d32 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/inline_array.sol @@ -0,0 +1,5 @@ +contract C { + uint[[2]] a15; +} +// ---- +// TypeError: (22-25): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol new file mode 100644 index 000000000..c92861eb4 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol @@ -0,0 +1,5 @@ +contract C { + uint[-true] ids; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol new file mode 100644 index 000000000..92e3c3cfb --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol @@ -0,0 +1,5 @@ +contract C { + uint[true/1] ids; +} +// ---- +// TypeError: (22-28): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol new file mode 100644 index 000000000..26add45ca --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol @@ -0,0 +1,5 @@ +contract C { + uint[1/true] ids; +} +// ---- +// TypeError: (22-28): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol new file mode 100644 index 000000000..a0d58f4a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol @@ -0,0 +1,5 @@ +contract C { + uint[1.111111E1111111111111] ids; +} +// ---- +// TypeError: (22-44): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol new file mode 100644 index 000000000..38a80867d --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol @@ -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 diff --git a/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol b/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol new file mode 100644 index 000000000..7a853a345 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol b/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol new file mode 100644 index 000000000..b44ccfe93 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol @@ -0,0 +1,5 @@ +contract C { + uint[true] ids; +} +// ---- +// TypeError: (22-26): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/parentheses.sol b/test/libsolidity/syntaxTests/arrayLength/parentheses.sol new file mode 100644 index 000000000..40f55ad63 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/parentheses.sol @@ -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; +} diff --git a/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol b/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol new file mode 100644 index 000000000..b620db763 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/arrayLength/too_large.sol b/test/libsolidity/syntaxTests/arrayLength/too_large.sol new file mode 100644 index 000000000..c90a7494e --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/too_large.sol @@ -0,0 +1,5 @@ +contract C { + uint[8**90] ids; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/tuples.sol b/test/libsolidity/syntaxTests/arrayLength/tuples.sol new file mode 100644 index 000000000..bc10b3b5d --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/tuples.sol @@ -0,0 +1,5 @@ +contract C { + uint[(1,2)] a15; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression.