Disallow constants that are neither value types nor strings.

This commit is contained in:
chriseth 2017-03-03 19:26:54 +01:00
parent 4077e56a2f
commit 592cec7e90
4 changed files with 55 additions and 26 deletions

View File

@ -433,6 +433,9 @@ assigned a value or expression which is a constant at compile time. The compiler
not reserve a storage slot for these variables and every occurrence is not reserve a storage slot for these variables and every occurrence is
replaced by their constant value (which might be computed by the optimizer). replaced by their constant value (which might be computed by the optimizer).
Not all types for constants are implemented at this time. The only supported types are
value types and strings.
:: ::
pragma solidity ^0.4.0; pragma solidity ^0.4.0;

View File

@ -473,6 +473,14 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
{ {
if (!_variable.isStateVariable()) if (!_variable.isStateVariable())
typeError(_variable.location(), "Illegal use of \"constant\" specifier."); typeError(_variable.location(), "Illegal use of \"constant\" specifier.");
if (!_variable.type()->isValueType())
{
bool allowed = false;
if (auto arrayType = dynamic_cast<ArrayType const*>(_variable.type().get()))
allowed = arrayType->isString();
if (!allowed)
typeError(_variable.location(), "Constants of non-value type not yet implemented.");
}
if (!_variable.value()) if (!_variable.value())
typeError(_variable.location(), "Uninitialized \"constant\" variable."); typeError(_variable.location(), "Uninitialized \"constant\" variable.");
else if (!_variable.value()->annotation().isPure) else if (!_variable.value()->annotation().isPure)

View File

@ -4576,31 +4576,33 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_keccak)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(dev::keccak256("abc"))); BOOST_CHECK(callContractFunction("f()") == encodeArgs(dev::keccak256("abc")));
} }
BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars) // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented
{ //BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars)
char const* sourceCode = R"( //{
contract C { // char const* sourceCode = R"(
uint[3] constant x = [uint(1), 2, 3]; // contract C {
uint constant y = x[0] + x[1] + x[2]; // uint[3] constant x = [uint(1), 2, 3];
function f() returns (uint) { return y; } // uint constant y = x[0] + x[1] + x[2];
} // function f() returns (uint) { return y; }
)"; // }
compileAndRun(sourceCode); // )";
BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 + 2 + 3)); // compileAndRun(sourceCode);
} // BOOST_CHECK(callContractFunction("f()") == encodeArgs(1 + 2 + 3));
//}
BOOST_AUTO_TEST_CASE(constant_struct) // Disabled until https://github.com/ethereum/solidity/issues/715 is implemented
{ //BOOST_AUTO_TEST_CASE(constant_struct)
char const* sourceCode = R"( //{
contract C { // char const* sourceCode = R"(
struct S { uint x; uint[] y; } // contract C {
S constant x = S(5, new uint[](4)); // struct S { uint x; uint[] y; }
function f() returns (uint) { return x.x; } // S constant x = S(5, new uint[](4));
} // function f() returns (uint) { return x.x; }
)"; // }
compileAndRun(sourceCode); // )";
BOOST_CHECK(callContractFunction("f()") == encodeArgs(5)); // compileAndRun(sourceCode);
} // BOOST_CHECK(callContractFunction("f()") == encodeArgs(5));
//}
BOOST_AUTO_TEST_CASE(packed_storage_structs_uint) BOOST_AUTO_TEST_CASE(packed_storage_structs_uint)
{ {

View File

@ -2183,6 +2183,22 @@ BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable)
CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant."); CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant.");
} }
BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment)
{
char const* text = R"(
contract Test {
string constant x = "abefghijklmnopqabcdefghijklmnopqabcdefghijklmnopqabca";
function f() {
x[0] = "f";
}
}
)";
// Even if this is made possible in the future, we should not allow assignment
// to elements of constant arrays.
CHECK_ERROR(text, TypeError, "Index access for string is not possible.");
}
BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant) BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
{ {
char const* text = R"( char const* text = R"(
@ -2231,7 +2247,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_const_array_vars)
uint[3] constant x = [uint(1), 2, 3]; uint[3] constant x = [uint(1), 2, 3];
} }
)"; )";
CHECK_SUCCESS(text); CHECK_ERROR(text, TypeError, "implemented");
} }
BOOST_AUTO_TEST_CASE(constant_struct) BOOST_AUTO_TEST_CASE(constant_struct)
@ -2242,7 +2258,7 @@ BOOST_AUTO_TEST_CASE(constant_struct)
S constant x = S(5, new uint[](4)); S constant x = S(5, new uint[](4));
} }
)"; )";
CHECK_SUCCESS(text); CHECK_ERROR(text, TypeError, "implemented");
} }
BOOST_AUTO_TEST_CASE(uninitialized_const_variable) BOOST_AUTO_TEST_CASE(uninitialized_const_variable)