aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/TypeChecker.cpp31
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp51
2 files changed, 61 insertions, 21 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 669a7e4a..3fb7303f 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -783,10 +783,13 @@ bool TypeChecker::visit(Assignment const& _assignment)
bool TypeChecker::visit(TupleExpression const& _tuple)
{
vector<ASTPointer<Expression>> const& components = _tuple.components();
- solAssert(!_tuple.isInlineArray(), "Tuple type not properly declared");
TypePointers types;
+ 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)
{
@@ -813,18 +816,34 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
{
components[i]->accept(*this);
types.push_back(type(*components[i]));
+ 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)
- _tuple.annotation().type = type(*components[0]);
+ 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 b0e92b59..f0dab41a 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -219,25 +219,46 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
bool ExpressionCompiler::visit(TupleExpression const& _tuple)
{
- vector<unique_ptr<LValue>> lvalues;
- for (auto const& component: _tuple.components())
- if (component)
+ if (_tuple.isInlineArray())
+ {
+ ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type);
+
+ solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array.");
+ m_context << max(u256(32u), arrayType.memorySize());
+ utils().allocateMemory();
+ m_context << eth::Instruction::DUP1;
+
+ for (auto const& component: _tuple.components())
{
component->accept(*this);
- if (_tuple.annotation().lValueRequested)
+ utils().convertType(*component->annotation().type, *arrayType.baseType(), true);
+ utils().storeInMemoryDynamic(*arrayType.baseType(), true);
+ }
+
+ m_context << eth::Instruction::POP;
+ }
+ else
+ {
+ vector<unique_ptr<LValue>> lvalues;
+ for (auto const& component: _tuple.components())
+ if (component)
{
- solAssert(!!m_currentLValue, "");
- lvalues.push_back(move(m_currentLValue));
+ component->accept(*this);
+ if (_tuple.annotation().lValueRequested)
+ {
+ solAssert(!!m_currentLValue, "");
+ lvalues.push_back(move(m_currentLValue));
+ }
}
+ else if (_tuple.annotation().lValueRequested)
+ lvalues.push_back(unique_ptr<LValue>());
+ if (_tuple.annotation().lValueRequested)
+ {
+ if (_tuple.components().size() == 1)
+ m_currentLValue = move(lvalues[0]);
+ else
+ m_currentLValue.reset(new TupleObject(m_context, move(lvalues)));
}
- else if (_tuple.annotation().lValueRequested)
- lvalues.push_back(unique_ptr<LValue>());
- if (_tuple.annotation().lValueRequested)
- {
- if (_tuple.components().size() == 1)
- m_currentLValue = move(lvalues[0]);
- else
- m_currentLValue.reset(new TupleObject(m_context, move(lvalues)));
}
return false;
}
@@ -774,7 +795,6 @@ bool ExpressionCompiler::visit(NewExpression const&)
void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
{
CompilerContext::LocationSetter locationSetter(m_context, _memberAccess);
-
// Check whether the member is a bound function.
ASTString const& member = _memberAccess.memberName();
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get()))
@@ -1123,6 +1143,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
{
CompilerContext::LocationSetter locationSetter(m_context, _literal);
TypePointer type = _literal.annotation().type;
+
switch (type->category())
{
case Type::Category::IntegerConstant: