aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-09-29 16:23:56 +0800
committerGitHub <noreply@github.com>2017-09-29 16:23:56 +0800
commitb92184688002c73fece4e8beb0beaa897649de4e (patch)
treef6b93119c1ae7934a38fbc6246af6a5fd817be64
parent010189d58eca560dd319aab07daa43bda0911a40 (diff)
parentd5d1a08b09bec098851afc48fc0f115eac193955 (diff)
downloaddexon-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.md2
-rw-r--r--libsolidity/ast/Types.cpp39
-rw-r--r--libsolidity/ast/Types.h2
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp25
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp23
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()
}