Merge pull request #2542 from federicobond/disallow-non-pure-constant

Disallow non-pure constant state variables (0.5.0)
This commit is contained in:
Alex Beregszaszi 2017-10-03 17:58:12 +01:00 committed by GitHub
commit cfc4e5dde3
3 changed files with 42 additions and 9 deletions

View File

@ -3,6 +3,7 @@
Features: Features:
* Parser: Better error message for unexpected trailing comma in parameter lists. * Parser: Better error message for unexpected trailing comma in parameter lists.
* Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature.
* Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature.
Bugfixes: Bugfixes:
* Parser: Fix source location of VariableDeclarationStatement. * Parser: Fix source location of VariableDeclarationStatement.

View File

@ -645,15 +645,24 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
if (!allowed) if (!allowed)
m_errorReporter.typeError(_variable.location(), "Constants of non-value type not yet implemented."); m_errorReporter.typeError(_variable.location(), "Constants of non-value type not yet implemented.");
} }
if (!_variable.value()) if (!_variable.value())
m_errorReporter.typeError(_variable.location(), "Uninitialized \"constant\" variable."); m_errorReporter.typeError(_variable.location(), "Uninitialized \"constant\" variable.");
else if (!_variable.value()->annotation().isPure) else if (!_variable.value()->annotation().isPure)
{
if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050))
m_errorReporter.typeError(
_variable.value()->location(),
"Initial value for constant variable has to be compile-time constant."
);
else
m_errorReporter.warning( m_errorReporter.warning(
_variable.value()->location(), _variable.value()->location(),
"Initial value for constant variable has to be compile-time constant. " "Initial value for constant variable has to be compile-time constant. "
"This will fail to compile with the next breaking version change." "This will fail to compile with the next breaking version change."
); );
} }
}
if (!_variable.isStateVariable()) if (!_variable.isStateVariable())
{ {
if (varType->dataStoredIn(DataLocation::Memory) || varType->dataStoredIn(DataLocation::CallData)) if (varType->dataStoredIn(DataLocation::Memory) || varType->dataStoredIn(DataLocation::CallData))

View File

@ -2361,17 +2361,28 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable)
CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
} }
BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable) BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable_0_4_x)
{ {
char const* text = R"( char const* text = R"(
contract C { contract C {
address constant x = msg.sender; address constant x = msg.sender;
} }
)"; )";
// Change to TypeError for 0.5.0.
CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant.");
} }
BOOST_AUTO_TEST_CASE(assigning_state_to_const_variable)
{
char const* text = R"(
pragma experimental "v0.5.0";
contract C {
address constant x = msg.sender;
}
)";
CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant.");
}
BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment) BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment)
{ {
char const* text = R"( char const* text = R"(
@ -2388,7 +2399,7 @@ BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment)
CHECK_ERROR(text, TypeError, "Index access for string is not possible."); 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_0_4_x)
{ {
char const* text = R"( char const* text = R"(
contract C { contract C {
@ -2396,10 +2407,22 @@ BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
uint constant y = x(); uint constant y = x();
} }
)"; )";
// Change to TypeError for 0.5.0.
CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant."); CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant.");
} }
BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
{
char const* text = R"(
pragma experimental "v0.5.0";
contract C {
function () constant returns (uint) x;
uint constant y = x();
}
)";
CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant.");
}
BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion) BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion)
{ {
char const* text = R"( char const* text = R"(