aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-08 06:45:26 +0800
committerChristian <c@ethdev.com>2015-01-10 01:23:10 +0800
commit501ad14ed1a6b1c40e0b0437683bae6246a6eeeb (patch)
treef188cbb93a43067dde5a166f200b8e00ba1f8f23 /ExpressionCompiler.cpp
parent396f638ce19206144ce32dcf3926fc13fa9a89b7 (diff)
downloaddexon-solidity-501ad14ed1a6b1c40e0b0437683bae6246a6eeeb.tar.gz
dexon-solidity-501ad14ed1a6b1c40e0b0437683bae6246a6eeeb.tar.zst
dexon-solidity-501ad14ed1a6b1c40e0b0437683bae6246a6eeeb.zip
Correct type conversions.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp47
1 files changed, 34 insertions, 13 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 5667098d..33c10aa3 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -194,13 +194,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
solAssert(_functionCall.getArguments().size() == 1, "");
Expression const& firstArgument = *_functionCall.getArguments().front();
firstArgument.accept(*this);
- if (firstArgument.getType()->getCategory() == Type::Category::CONTRACT &&
- _functionCall.getType()->getCategory() == Type::Category::INTEGER)
- {
- // explicit type conversion contract -> address, nothing to do.
- }
- else
- appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
+ appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
}
else
{
@@ -250,13 +244,17 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
FunctionCallOptions options;
options.bare = true;
options.obtainAddress = [&]() { _functionCall.getExpression().accept(*this); };
- options.obtainValue = [&]() { arguments.front()->accept(*this); };
+ options.obtainValue = [&]()
+ {
+ arguments.front()->accept(*this);
+ appendTypeConversion(*arguments.front()->getType(),
+ *function.getParameterTypes().front(), true);
+ };
appendExternalFunctionCall(FunctionType({}, {}, Location::EXTERNAL), {}, options);
break;
}
case Location::SUICIDE:
arguments.front()->accept(*this);
- //@todo might not be necessary
appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true);
m_context << eth::Instruction::SUICIDE;
break;
@@ -362,6 +360,8 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
break;
case Type::Category::CONTRACT:
{
+ appendTypeConversion(*_memberAccess.getExpression().getType(),
+ IntegerType(0, IntegerType::Modifier::ADDRESS), true);
ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.getExpression().getType());
m_context << type.getFunctionIdentifier(member);
break;
@@ -592,15 +592,36 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
return;
Type::Category stackTypeCategory = _typeOnStack.getCategory();
Type::Category targetTypeCategory = _targetType.getCategory();
- if (stackTypeCategory == Type::Category::INTEGER)
+ if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
+ stackTypeCategory == Type::Category::INTEGER_CONSTANT)
{
solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
- appendHighBitsCleanup(dynamic_cast<IntegerType const&>(_typeOnStack));
+ IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
+ IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
+ ? dynamic_cast<IntegerType const&>(_targetType) : addressType;
+ if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
+ {
+ IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack);
+ // We know that the stack is clean, we only have to clean for a narrowing conversion
+ // where cleanup is forced.
+ if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded)
+ appendHighBitsCleanup(targetType);
+ }
+ else
+ {
+ IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER
+ ? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType;
+ // Widening: clean up according to source type width
+ // Non-widening and force: clean up according to target type bits
+ if (targetType.getNumBits() > typeOnStack.getNumBits())
+ appendHighBitsCleanup(typeOnStack);
+ else if (_cleanupNeeded)
+ appendHighBitsCleanup(targetType);
+ }
}
- else if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
- solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
else if (stackTypeCategory == Type::Category::STRING)
{
+ solAssert(targetTypeCategory == Type::Category::STRING, "");
// nothing to do, strings are high-order-bit-aligned
//@todo clear lower-order bytes if we allow explicit conversion to shorter strings
}