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
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;

View File

@ -473,6 +473,14 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
{
if (!_variable.isStateVariable())
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())
typeError(_variable.location(), "Uninitialized \"constant\" variable.");
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_AUTO_TEST_CASE(assignment_to_const_array_vars)
{
char const* sourceCode = R"(
contract C {
uint[3] constant x = [uint(1), 2, 3];
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));
}
// 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 {
// uint[3] constant x = [uint(1), 2, 3];
// 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));
//}
BOOST_AUTO_TEST_CASE(constant_struct)
{
char const* sourceCode = R"(
contract C {
struct S { uint x; uint[] y; }
S constant x = S(5, new uint[](4));
function f() returns (uint) { return x.x; }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f()") == encodeArgs(5));
}
// Disabled until https://github.com/ethereum/solidity/issues/715 is implemented
//BOOST_AUTO_TEST_CASE(constant_struct)
//{
// char const* sourceCode = R"(
// contract C {
// struct S { uint x; uint[] y; }
// S constant x = S(5, new uint[](4));
// function f() returns (uint) { return x.x; }
// }
// )";
// compileAndRun(sourceCode);
// BOOST_CHECK(callContractFunction("f()") == encodeArgs(5));
//}
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.");
}
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)
{
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];
}
)";
CHECK_SUCCESS(text);
CHECK_ERROR(text, TypeError, "implemented");
}
BOOST_AUTO_TEST_CASE(constant_struct)
@ -2242,7 +2258,7 @@ BOOST_AUTO_TEST_CASE(constant_struct)
S constant x = S(5, new uint[](4));
}
)";
CHECK_SUCCESS(text);
CHECK_ERROR(text, TypeError, "implemented");
}
BOOST_AUTO_TEST_CASE(uninitialized_const_variable)