diff options
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 25 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.h | 3 |
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; |