aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/analysis/TypeChecker.cpp25
-rw-r--r--libsolidity/analysis/TypeChecker.h3
-rw-r--r--test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol12
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/assignment_local.sol15
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol14
-rw-r--r--test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol17
7 files changed, 70 insertions, 17 deletions
diff --git a/Changelog.md b/Changelog.md
index e5306dc0..576b3d3f 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -79,6 +79,7 @@ Bugfixes:
* Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions.
* References Resolver: Enforce ``storage`` as data location for mappings.
* References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter.
+ * Type Checker: Disallow assignments to mappings within tuple assignments as well.
* Type Checker: Consider fixed size arrays when checking for recursive structs.
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
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;
diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol
deleted file mode 100644
index 27b1ea96..00000000
--- a/test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol
+++ /dev/null
@@ -1,12 +0,0 @@
-contract test {
- struct str {
- mapping(uint=>uint) map;
- }
- str data;
- function fun() public {
- mapping(uint=>uint) storage a = data.map;
- data.map = a;
- }
-}
-// ----
-// TypeError: (172-184): Mappings cannot be assigned to.
diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol
new file mode 100644
index 00000000..ba01c44a
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol
@@ -0,0 +1,15 @@
+contract test {
+ mapping(uint=>uint) map;
+ function fun() public view {
+ mapping(uint=>uint) storage a = map;
+ mapping(uint=>uint) storage b = map;
+ b = a;
+ (b) = a;
+ (b, b) = (a, a);
+ }
+}
+// ----
+// TypeError: (176-177): Mappings cannot be assigned to.
+// TypeError: (192-193): Mappings cannot be assigned to.
+// TypeError: (209-210): Mappings cannot be assigned to.
+// TypeError: (212-213): Mappings cannot be assigned to.
diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol
new file mode 100644
index 00000000..1323afe6
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol
@@ -0,0 +1,14 @@
+contract test {
+ mapping(uint=>uint) map;
+ function fun() public {
+ mapping(uint=>uint) storage a = map;
+ map = a;
+ (map) = a;
+ (map, map) = (a, a);
+ }
+}
+// ----
+// TypeError: (126-129): Mappings cannot be assigned to.
+// TypeError: (144-147): Mappings cannot be assigned to.
+// TypeError: (163-166): Mappings cannot be assigned to.
+// TypeError: (168-171): Mappings cannot be assigned to.
diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol
new file mode 100644
index 00000000..b89241ed
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol
@@ -0,0 +1,17 @@
+contract test {
+ struct str {
+ mapping(uint=>uint) map;
+ }
+ str data;
+ function fun() public {
+ mapping(uint=>uint) storage a = data.map;
+ data.map = a;
+ (data.map) = a;
+ (data.map, data.map) = (a, a);
+ }
+}
+// ----
+// TypeError: (172-180): Mappings cannot be assigned to.
+// TypeError: (195-203): Mappings cannot be assigned to.
+// TypeError: (219-227): Mappings cannot be assigned to.
+// TypeError: (229-237): Mappings cannot be assigned to.