From de720e643d8c54c613356bfcdcb6c49984460a17 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Mon, 12 Dec 2016 23:59:53 -0300 Subject: Improve error message when trying to modify constant variables --- libsolidity/analysis/TypeChecker.cpp | 7 ++++++- libsolidity/ast/ASTAnnotations.h | 2 ++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7235b57a..e414e27c 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1529,6 +1529,8 @@ bool TypeChecker::visit(Identifier const& _identifier) !!annotation.referencedDeclaration, "Referenced declaration is null after overload resolution." ); + auto variableDeclaration = dynamic_cast(annotation.referencedDeclaration); + annotation.isConstant = variableDeclaration != nullptr && variableDeclaration->isConstant(); annotation.isLValue = annotation.referencedDeclaration->isLValue(); annotation.type = annotation.referencedDeclaration->type(); if (!annotation.type) @@ -1612,7 +1614,10 @@ void TypeChecker::requireLValue(Expression const& _expression) { _expression.annotation().lValueRequested = true; _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."); } diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 768e56db..9c4c3ae8 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -154,6 +154,8 @@ struct ExpressionAnnotation: ASTAnnotation { /// Inferred type of the expression. 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). bool isLValue = false; /// Whether the expression is used in a context where the LValue is actually required. diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index a4e601f7..576421fd 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4865,6 +4865,17 @@ BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_p 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() } -- cgit