aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Bond <federicobond@gmail.com>2016-12-13 10:59:53 +0800
committerFederico Bond <federicobond@gmail.com>2016-12-13 11:32:37 +0800
commitde720e643d8c54c613356bfcdcb6c49984460a17 (patch)
tree68cf22d6ab999f316ff3ec967029015b3aae6df5
parent1c3605362d6018f5ab72cc84c7511fb49c15d126 (diff)
downloaddexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.tar
dexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.tar.gz
dexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.tar.bz2
dexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.tar.lz
dexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.tar.xz
dexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.tar.zst
dexon-solidity-de720e643d8c54c613356bfcdcb6c49984460a17.zip
Improve error message when trying to modify constant variables
-rw-r--r--libsolidity/analysis/TypeChecker.cpp7
-rw-r--r--libsolidity/ast/ASTAnnotations.h2
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp11
3 files changed, 19 insertions, 1 deletions
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<VariableDeclaration const*>(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()
}