Fix overload resolution when conflict is with members of address (balance, transfer, etc)

This commit is contained in:
Alex Beregszaszi 2017-09-20 11:14:28 +01:00
parent 010189d58e
commit 7cb4d714c7
4 changed files with 78 additions and 6 deletions

View File

@ -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)

View File

@ -1720,12 +1720,34 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
);
}
else if (possibleMembers.size() > 1)
m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" not unique "
"after argument-dependent lookup in " + exprType->toString() +
(memberName == "value" ? " - did you forget the \"payable\" modifier?" : "")
);
{
// Remove builtins (i.e. not having a declaration) first
for (auto it = possibleMembers.begin(); it != possibleMembers.end();)
if (
(
// Overloaded functions without declaration (e.g. transfer(), send(), call(), etc.)
it->type->category() == Type::Category::Function &&
!dynamic_cast<FunctionType const&>(*it->type).hasDeclaration()
)
||
(
// Overloaded members (e.g. balance)
it->type->category() == Type::Category::Integer &&
memberName == "balance"
)
)
it = possibleMembers.erase(it);
else
++it;
if (possibleMembers.size() > 1)
m_errorReporter.fatalTypeError(
_memberAccess.location(),
"Member \"" + memberName + "\" not unique "
"after argument-dependent lookup in " + exprType->toString() +
(memberName == "value" ? " - did you forget the \"payable\" modifier?" : "")
);
}
auto& annotation = _memberAccess.annotation();
annotation.referencedDeclaration = possibleMembers.front().declaration;

View File

@ -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()
}

View File

@ -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()
}