aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/analysis/TypeChecker.cpp40
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp15
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp25
3 files changed, 57 insertions, 23 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 20b3ad6c..75a9632e 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -781,10 +781,12 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
{
vector<ASTPointer<Expression>> const& components = _tuple.components();
TypePointers types;
- TypePointer internalArrayType;
- bool isArray = _tuple.isInlineArray();
+ TypePointer inlineArrayType;
+
if (_tuple.annotation().lValueRequested)
{
+ if (_tuple.isInlineArray())
+ fatalTypeError(_tuple.location(), "Inline array type cannot be declared as LValue.");
for (auto const& component: components)
if (component)
{
@@ -811,26 +813,34 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
{
components[i]->accept(*this);
types.push_back(type(*components[i]));
- if (i == 0 && isArray)
- internalArrayType = types[i]->mobileType();
- else if (isArray && internalArrayType && types[i]->mobileType())
- internalArrayType = Type::commonType(internalArrayType, types[i]->mobileType());
+ if (_tuple.isInlineArray())
+ solAssert(!!types[i], "Inline array cannot have empty components");
+ if (i == 0 && _tuple.isInlineArray())
+ inlineArrayType = types[i]->mobileType();
+ else if (_tuple.isInlineArray() && inlineArrayType)
+ inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType());
}
else
types.push_back(TypePointer());
}
- if (components.size() == 1 && !isArray)
- _tuple.annotation().type = type(*components[0]);
- else if (!internalArrayType && isArray)
- fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements.");
- else if (isArray)
- _tuple.annotation().type = make_shared<ArrayType>(DataLocation::Memory, internalArrayType, types.size());
+ if (_tuple.isInlineArray())
+ {
+ if (!inlineArrayType)
+ fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements.");
+ _tuple.annotation().type = make_shared<ArrayType>(DataLocation::Memory, inlineArrayType, types.size());
+ }
else
{
- if (components.size() == 2 && !components[1])
- types.pop_back();
- _tuple.annotation().type = make_shared<TupleType>(types);
+ if (components.size() == 1)
+ _tuple.annotation().type = type(*components[0]);
+ else
+ {
+ if (components.size() == 2 && !components[1])
+ types.pop_back();
+ _tuple.annotation().type = make_shared<TupleType>(types);
+ }
}
+
}
return false;
}
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index c5f0f97e..f0dab41a 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -186,7 +186,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
_assignment.leftHandSide().annotation().type
);
utils().convertType(*_assignment.rightHandSide().annotation().type, *type);
-
+
_assignment.leftHandSide().accept(*this);
solAssert(!!m_currentLValue, "LValue not retrieved.");
@@ -222,18 +222,17 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple)
if (_tuple.isInlineArray())
{
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
- auto components = _tuple.components();
+ solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
m_context << max(u256(32u), arrayType.memorySize());
utils().allocateMemory();
m_context << eth::Instruction::DUP1;
- for (unsigned i = 0; i < components.size(); ++i)
+ for (auto const& component: _tuple.components())
{
- components[i]->accept(*this);
- utils().convertType(*components[i]->annotation().type, *arrayType.baseType(), true);
- components[i]->annotation().type = arrayType.baseType(); //force conversion
- utils().storeInMemoryDynamic(*components[i]->annotation().type, true);
+ component->accept(*this);
+ utils().convertType(*component->annotation().type, *arrayType.baseType(), true);
+ utils().storeInMemoryDynamic(*arrayType.baseType(), true);
}
m_context << eth::Instruction::POP;
@@ -1155,7 +1154,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
break; // will be done during conversion
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now."));
- }
+ }
}
void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation)
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index c63d8297..3909fc6c 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -2862,6 +2862,31 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array)
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
+BOOST_AUTO_TEST_CASE(dynamic_inline_array)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ uint[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]];
+ }
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
+BOOST_AUTO_TEST_CASE(lvalues_as_inline_array)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ [1, 2, 3]++;
+ [1, 2, 3] = [4, 5, 6];
+ }
+ }
+ )";
+ BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}