diff options
author | Christian <c@ethdev.com> | 2015-01-08 06:45:26 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-01-10 01:23:10 +0800 |
commit | 501ad14ed1a6b1c40e0b0437683bae6246a6eeeb (patch) | |
tree | f188cbb93a43067dde5a166f200b8e00ba1f8f23 /ExpressionCompiler.cpp | |
parent | 396f638ce19206144ce32dcf3926fc13fa9a89b7 (diff) | |
download | dexon-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.cpp | 47 |
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 } |