aboutsummaryrefslogtreecommitdiffstats
path: root/ExpressionCompiler.cpp
diff options
context:
space:
mode:
authorGav Wood <g@ethdev.com>2015-01-11 18:07:36 +0800
committerGav Wood <g@ethdev.com>2015-01-11 18:07:36 +0800
commit94cff9684f8b1d4a5e2eeba58444a99e32e8a7ae (patch)
treeb14986766ba825f33176c82c66be8f10887d6517 /ExpressionCompiler.cpp
parent26f9cd7f682b9d26252ab13f2a12178dc238abee (diff)
parentc5c893319285993dd9a1c6a790537e7acc35e5d0 (diff)
downloaddexon-solidity-94cff9684f8b1d4a5e2eeba58444a99e32e8a7ae.tar.gz
dexon-solidity-94cff9684f8b1d4a5e2eeba58444a99e32e8a7ae.tar.zst
dexon-solidity-94cff9684f8b1d4a5e2eeba58444a99e32e8a7ae.zip
Merge pull request #768 from chriseth/sol_contractsAreAddresses
Contracts inherit all address members
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r--ExpressionCompiler.cpp63
1 files changed, 44 insertions, 19 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 1ce5ca5b..4fdea332 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;
@@ -347,6 +345,18 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
ASTString const& member = _memberAccess.getMemberName();
switch (_memberAccess.getExpression().getType()->getCategory())
{
+ case Type::Category::CONTRACT:
+ {
+ ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.getExpression().getType());
+ u256 identifier = type.getFunctionIdentifier(member);
+ if (identifier != Invalid256)
+ {
+ appendTypeConversion(type, IntegerType(0, IntegerType::Modifier::ADDRESS), true);
+ m_context << identifier;
+ break;
+ }
+ // fall-through to "integer" otherwise (address)
+ }
case Type::Category::INTEGER:
if (member == "balance")
{
@@ -360,12 +370,6 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
else
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to integer."));
break;
- case Type::Category::CONTRACT:
- {
- ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.getExpression().getType());
- m_context << type.getFunctionIdentifier(member);
- break;
- }
case Type::Category::MAGIC:
// we can ignore the kind of magic and only look at the name of the member
if (member == "coinbase")
@@ -592,15 +596,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
}