diff options
author | Leonardo Alt <leo@ethereum.org> | 2018-07-19 01:51:24 +0800 |
---|---|---|
committer | Leonardo Alt <leo@ethereum.org> | 2018-07-19 01:51:24 +0800 |
commit | faa9c221d41c45e12411c654919f318f6e7fc98f (patch) | |
tree | 4393a4143da54f183e0459c59b0f3687bc5fbe37 | |
parent | 25fa1142bc2ba74e75f24f8267d7fcb282423335 (diff) | |
download | dexon-solidity-faa9c221d41c45e12411c654919f318f6e7fc98f.tar.gz dexon-solidity-faa9c221d41c45e12411c654919f318f6e7fc98f.tar.zst dexon-solidity-faa9c221d41c45e12411c654919f318f6e7fc98f.zip |
Changes in ExpressionCompiler
-rw-r--r-- | Changelog.md | 4 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 5 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 89 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/types/address_members_in_contract.sol | 6 |
4 files changed, 50 insertions, 54 deletions
diff --git a/Changelog.md b/Changelog.md index c18b589e..6776de7e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,7 @@ How to update your code: * Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``. * Make your fallback functions ``external``. * Explicitly state the storage location for local variables of struct and array types, e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``. - * Explicitly convert ``contract`` to ``address`` before using an ``address`` member. Example: if ``c`` is a variable of type ``contract``, change ``c.transfer(...)`` to ``address(c).transfer(...)``. + * Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``. Breaking Changes: @@ -47,7 +47,7 @@ Breaking Changes: * Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``. * Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode. * Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode. - * Type Checker: ``Contract`` does not have access to ``address`` members anymore. An explicit conversion is now required before invoking an ``address`` member from a ``contract``. + * Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract. * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. * References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Named return values in function types are an error. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index fc5a3608..8536e934 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1957,8 +1957,9 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) for (auto const& addressMember: IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr)) if (addressMember.name == memberName) { - Identifier const& var = dynamic_cast<Identifier const&>(_memberAccess.expression()); - errorMsg += " Use \"address(" + var.name() + ")." + memberName + "\" to access this address member."; + Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression()); + string varName = var ? var->name() : "..."; + errorMsg += " Use \"address(" + varName + ")." + memberName + "\" to access this address member."; break; } m_errorReporter.fatalTypeError( diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 4cec69c8..54518906 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1214,63 +1214,52 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) switch (_memberAccess.expression().annotation().type->category()) { case Type::Category::Contract: - case Type::Category::Integer: { - bool alsoSearchInteger = false; - if (_memberAccess.expression().annotation().type->category() == Type::Category::Contract) + ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type); + if (type.isSuper()) { - ContractType const& type = dynamic_cast<ContractType const&>(*_memberAccess.expression().annotation().type); - if (type.isSuper()) - { - solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); - utils().pushCombinedFunctionEntryLabel(m_context.superFunction( - dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration), - type.contractDefinition() - )); - } + solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved."); + utils().pushCombinedFunctionEntryLabel(m_context.superFunction( + dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration), + type.contractDefinition() + )); + } + // ordinary contract type + else if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) + { + u256 identifier; + if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration)) + identifier = FunctionType(*variable).externalIdentifier(); + else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration)) + identifier = FunctionType(*function).externalIdentifier(); else - { - // ordinary contract type - if (Declaration const* declaration = _memberAccess.annotation().referencedDeclaration) - { - u256 identifier; - if (auto const* variable = dynamic_cast<VariableDeclaration const*>(declaration)) - identifier = FunctionType(*variable).externalIdentifier(); - else if (auto const* function = dynamic_cast<FunctionDefinition const*>(declaration)) - identifier = FunctionType(*function).externalIdentifier(); - else - solAssert(false, "Contract member is neither variable nor function."); - utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true); - m_context << identifier; - } - else - // not found in contract, search in members inherited from address - alsoSearchInteger = true; - } + solAssert(false, "Contract member is neither variable nor function."); + utils().convertType(type, IntegerType(160, IntegerType::Modifier::Address), true); + m_context << identifier; } else - alsoSearchInteger = true; - - if (alsoSearchInteger) + solAssert(false, "Invalid member access in contract"); + break; + } + case Type::Category::Integer: + { + if (member == "balance") { - if (member == "balance") - { - utils().convertType( - *_memberAccess.expression().annotation().type, - IntegerType(160, IntegerType::Modifier::Address), - true - ); - m_context << Instruction::BALANCE; - } - else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) - utils().convertType( - *_memberAccess.expression().annotation().type, - IntegerType(160, IntegerType::Modifier::Address), - true - ); - else - solAssert(false, "Invalid member access to integer"); + utils().convertType( + *_memberAccess.expression().annotation().type, + IntegerType(160, IntegerType::Modifier::Address), + true + ); + m_context << Instruction::BALANCE; } + else if ((set<string>{"send", "transfer", "call", "callcode", "delegatecall"}).count(member)) + utils().convertType( + *_memberAccess.expression().annotation().type, + IntegerType(160, IntegerType::Modifier::Address), + true + ); + else + solAssert(false, "Invalid member access to integer"); break; } case Type::Category::Function: diff --git a/test/libsolidity/syntaxTests/types/address_members_in_contract.sol b/test/libsolidity/syntaxTests/types/address_members_in_contract.sol new file mode 100644 index 00000000..eafc8268 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address_members_in_contract.sol @@ -0,0 +1,6 @@ +contract C { + function f() public returns (C) { return this; } + function g() public returns (uint) { return f().balance(); } +} +// ---- +// TypeError: (114-125): Member "balance" not found or not visible after argument-dependent lookup in contract C. Use "address(...).balance" to access this address member. |