diff options
author | chriseth <chris@ethereum.org> | 2017-09-29 16:23:56 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-29 16:23:56 +0800 |
commit | b92184688002c73fece4e8beb0beaa897649de4e (patch) | |
tree | f6b93119c1ae7934a38fbc6246af6a5fd817be64 | |
parent | 010189d58eca560dd319aab07daa43bda0911a40 (diff) | |
parent | d5d1a08b09bec098851afc48fc0f115eac193955 (diff) | |
download | dexon-solidity-b92184688002c73fece4e8beb0beaa897649de4e.tar.gz dexon-solidity-b92184688002c73fece4e8beb0beaa897649de4e.tar.zst dexon-solidity-b92184688002c73fece4e8beb0beaa897649de4e.zip |
Merge pull request #2936 from ethereum/proper-address-overload-resolution
Fix overload resolution when conflict is with members of address
-rw-r--r-- | Changelog.md | 2 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 39 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 2 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 25 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 23 |
5 files changed, 89 insertions, 2 deletions
diff --git a/Changelog.md b/Changelog.md index b1643810..a83c6ddb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,8 @@ Features: Bugfixes: * Parser: Fix source location of VariableDeclarationStatement. + * Type Checker: Properly support overwriting members inherited from ``address`` in a contract + (such as ``balance``, ``transfer``, etc.) ### 0.4.17 (2017-09-21) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index ebf2cd8b..a39b5775 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1618,8 +1618,7 @@ string ContractType::canonicalName() const MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const { - // All address members and all interface functions - MemberList::MemberMap members(IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr)); + MemberList::MemberMap members; if (m_super) { // add the most derived of all functions which are visible in derived contracts @@ -1661,9 +1660,45 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) con &it.second->declaration() )); } + addNonConflictingAddressMembers(members); return members; } +void ContractType::addNonConflictingAddressMembers(MemberList::MemberMap& _members) +{ + MemberList::MemberMap addressMembers = IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr); + for (auto const& addressMember: addressMembers) + { + bool clash = false; + for (auto const& member: _members) + { + if ( + member.name == addressMember.name && + ( + // Members with different types are not allowed + member.type->category() != addressMember.type->category() || + // Members must overload functions without clash + ( + member.type->category() == Type::Category::Function && + dynamic_cast<FunctionType const&>(*member.type).hasEqualArgumentTypes(dynamic_cast<FunctionType const&>(*addressMember.type)) + ) + ) + ) + { + clash = true; + break; + } + } + + if (!clash) + _members.push_back(MemberList::Member( + addressMember.name, + addressMember.type, + addressMember.declaration + )); + } +} + shared_ptr<FunctionType const> const& ContractType::newExpressionType() const { if (!m_constructorType) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 8ba55521..ce29975e 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -716,6 +716,8 @@ public: std::vector<std::tuple<VariableDeclaration const*, u256, unsigned>> stateVariables() const; private: + static void addNonConflictingAddressMembers(MemberList::MemberMap& _members); + ContractDefinition const& m_contract; /// If true, it is the "super" type of the current contract, i.e. it contains only inherited /// members. diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index df9332c4..35916ec7 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10151,6 +10151,31 @@ BOOST_AUTO_TEST_CASE(constant_string) ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello"))); } +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* sourceCode = R"( + contract C { + function balance() returns (uint) { + return 1; + } + function transfer(uint amount) returns (uint) { + return amount; + } + } + contract D { + function f() returns (uint) { + return (new C()).balance(); + } + function g() returns (uint) { + return (new C()).transfer(5); + } + } + )"; + compileAndRun(sourceCode, 0, "D"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(5))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 39c47f9c..959bc4ff 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -6953,6 +6953,29 @@ BOOST_AUTO_TEST_CASE(warn_about_suicide) CHECK_WARNING(text, "\"suicide\" has been deprecated in favour of \"selfdestruct\""); } +BOOST_AUTO_TEST_CASE(address_overload_resolution) +{ + char const* text = R"( + contract C { + function balance() returns (uint) { + this.balance; // to avoid pureness warning + return 1; + } + function transfer(uint amount) { + address(this).transfer(amount); // to avoid pureness warning + } + } + contract D { + function f() { + var x = (new C()).balance(); + x; + (new C()).transfer(5); + } + } + )"; + CHECK_SUCCESS(text); +} + BOOST_AUTO_TEST_SUITE_END() } |