Skip to content

Commit

Permalink
Merge pull request #2936 from ethereum/proper-address-overload-resolu…
Browse files Browse the repository at this point in the history
…tion

Fix overload resolution when conflict is with members of address
  • Loading branch information
chriseth authored Sep 29, 2017
2 parents 010189d + d5d1a08 commit b921846
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
39 changes: 37 additions & 2 deletions libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,8 @@ class ContractType: public Type
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.
Expand Down
25 changes: 25 additions & 0 deletions test/libsolidity/SolidityEndToEndTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()

}
Expand Down
23 changes: 23 additions & 0 deletions test/libsolidity/SolidityNameAndTypeResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()

}
Expand Down

0 comments on commit b921846

Please sign in to comment.