aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis
diff options
context:
space:
mode:
authorDaniel Kirchner <daniel@ekpyron.org>2018-08-03 20:32:37 +0800
committerDaniel Kirchner <daniel@ekpyron.org>2018-08-03 21:46:26 +0800
commitc0a169ca90b780d102442aca98d1c510dac47464 (patch)
tree409d04e77d426d57dd2a53167a962b35abe2fd62 /libsolidity/analysis
parentda6cefd475210a9bcae0aad80c03f3679ae00f56 (diff)
downloaddexon-solidity-c0a169ca90b780d102442aca98d1c510dac47464.tar.gz
dexon-solidity-c0a169ca90b780d102442aca98d1c510dac47464.tar.zst
dexon-solidity-c0a169ca90b780d102442aca98d1c510dac47464.zip
Disallow assignments to mappings within tuple assignments.
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r--libsolidity/analysis/TypeChecker.cpp25
-rw-r--r--libsolidity/analysis/TypeChecker.h3
2 files changed, 23 insertions, 5 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 8c84e4dc..f9604794 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -1318,11 +1318,31 @@ bool TypeChecker::visit(Conditional const& _conditional)
return false;
}
+void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& _expression)
+{
+ if (auto const* tupleExpression = dynamic_cast<TupleExpression const*>(&_expression))
+ {
+ if (auto const* tupleType = dynamic_cast<TupleType const*>(&_type))
+ {
+ for (size_t i = 0; i < min(tupleExpression->components().size(), tupleType->components().size()); i++)
+ if (tupleType->components()[i] && tupleExpression->components()[i])
+ checkExpressionAssignment(*tupleType->components()[i], *tupleExpression->components()[i]);
+ }
+ else if (!tupleExpression->components().empty())
+ checkExpressionAssignment(_type, *tupleExpression->components().front());
+ }
+ else if (_type.category() == Type::Category::Mapping)
+ m_errorReporter.typeError(_expression.location(), "Mappings cannot be assigned to.");
+}
+
bool TypeChecker::visit(Assignment const& _assignment)
{
requireLValue(_assignment.leftHandSide());
TypePointer t = type(_assignment.leftHandSide());
_assignment.annotation().type = t;
+
+ checkExpressionAssignment(*t, _assignment.leftHandSide());
+
if (TupleType const* tupleType = dynamic_cast<TupleType const*>(t.get()))
{
if (_assignment.assignmentOperator() != Token::Assign)
@@ -1339,11 +1359,6 @@ bool TypeChecker::visit(Assignment const& _assignment)
if (dynamic_cast<TupleType const*>(type(_assignment.rightHandSide()).get()))
checkDoubleStorageAssignment(_assignment);
}
- else if (t->category() == Type::Category::Mapping)
- {
- m_errorReporter.typeError(_assignment.location(), "Mappings cannot be assigned to.");
- _assignment.rightHandSide().accept(*this);
- }
else if (_assignment.assignmentOperator() == Token::Assign)
expectType(_assignment.rightHandSide(), *t);
else
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index 8dc6b376..47892a3f 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -87,6 +87,9 @@ private:
/// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage.
/// Should only be called if the left hand side is tuple-typed.
void checkDoubleStorageAssignment(Assignment const& _assignment);
+ // Checks whether the expression @arg _expression can be assigned from type @arg _type
+ // and reports an error, if not.
+ void checkExpressionAssignment(Type const& _type, Expression const& _expression);
virtual void endVisit(InheritanceSpecifier const& _inheritance) override;
virtual void endVisit(UsingForDirective const& _usingFor) override;