Improve error message when trying to modify constant variables

This commit is contained in:
Federico Bond 2016-12-12 23:59:53 -03:00
parent 1c3605362d
commit de720e643d
3 changed files with 19 additions and 1 deletions

View File

@ -1529,6 +1529,8 @@ bool TypeChecker::visit(Identifier const& _identifier)
!!annotation.referencedDeclaration, !!annotation.referencedDeclaration,
"Referenced declaration is null after overload resolution." "Referenced declaration is null after overload resolution."
); );
auto variableDeclaration = dynamic_cast<VariableDeclaration const*>(annotation.referencedDeclaration);
annotation.isConstant = variableDeclaration != nullptr && variableDeclaration->isConstant();
annotation.isLValue = annotation.referencedDeclaration->isLValue(); annotation.isLValue = annotation.referencedDeclaration->isLValue();
annotation.type = annotation.referencedDeclaration->type(); annotation.type = annotation.referencedDeclaration->type();
if (!annotation.type) if (!annotation.type)
@ -1612,7 +1614,10 @@ void TypeChecker::requireLValue(Expression const& _expression)
{ {
_expression.annotation().lValueRequested = true; _expression.annotation().lValueRequested = true;
_expression.accept(*this); _expression.accept(*this);
if (!_expression.annotation().isLValue)
if (_expression.annotation().isConstant)
typeError(_expression.location(), "Cannot assign to a constant variable.");
else if (!_expression.annotation().isLValue)
typeError(_expression.location(), "Expression has to be an lvalue."); typeError(_expression.location(), "Expression has to be an lvalue.");
} }

View File

@ -154,6 +154,8 @@ struct ExpressionAnnotation: ASTAnnotation
{ {
/// Inferred type of the expression. /// Inferred type of the expression.
TypePointer type; TypePointer type;
/// Whether the expression is a constant variable
bool isConstant = false;
/// Whether it is an LValue (i.e. something that can be assigned to). /// Whether it is an LValue (i.e. something that can be assigned to).
bool isLValue = false; bool isLValue = false;
/// Whether the expression is used in a context where the LValue is actually required. /// Whether the expression is used in a context where the LValue is actually required.

View File

@ -4865,6 +4865,17 @@ BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_p
CHECK_SUCCESS_NO_WARNINGS(text); CHECK_SUCCESS_NO_WARNINGS(text);
} }
BOOST_AUTO_TEST_CASE(assignment_to_constant)
{
char const* text = R"(
contract c {
uint constant a = 1;
function f() { a = 2; }
}
)";
CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }