mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #2936 from ethereum/proper-address-overload-resolution
Fix overload resolution when conflict is with members of address
This commit is contained in:
commit
b921846880
@ -5,6 +5,8 @@ Features:
|
|||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* Parser: Fix source location of VariableDeclarationStatement.
|
* 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)
|
### 0.4.17 (2017-09-21)
|
||||||
|
|
||||||
|
@ -1618,8 +1618,7 @@ string ContractType::canonicalName() const
|
|||||||
|
|
||||||
MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const
|
MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const*) const
|
||||||
{
|
{
|
||||||
// All address members and all interface functions
|
MemberList::MemberMap members;
|
||||||
MemberList::MemberMap members(IntegerType(160, IntegerType::Modifier::Address).nativeMembers(nullptr));
|
|
||||||
if (m_super)
|
if (m_super)
|
||||||
{
|
{
|
||||||
// add the most derived of all functions which are visible in derived contracts
|
// 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()
|
&it.second->declaration()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
addNonConflictingAddressMembers(members);
|
||||||
return 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
|
shared_ptr<FunctionType const> const& ContractType::newExpressionType() const
|
||||||
{
|
{
|
||||||
if (!m_constructorType)
|
if (!m_constructorType)
|
||||||
|
@ -716,6 +716,8 @@ public:
|
|||||||
std::vector<std::tuple<VariableDeclaration const*, u256, unsigned>> stateVariables() const;
|
std::vector<std::tuple<VariableDeclaration const*, u256, unsigned>> stateVariables() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void addNonConflictingAddressMembers(MemberList::MemberMap& _members);
|
||||||
|
|
||||||
ContractDefinition const& m_contract;
|
ContractDefinition const& m_contract;
|
||||||
/// If true, it is the "super" type of the current contract, i.e. it contains only inherited
|
/// If true, it is the "super" type of the current contract, i.e. it contains only inherited
|
||||||
/// members.
|
/// members.
|
||||||
|
@ -10151,6 +10151,31 @@ BOOST_AUTO_TEST_CASE(constant_string)
|
|||||||
ABI_CHECK(callContractFunction("h()"), encodeDyn(string("hello")));
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6953,6 +6953,29 @@ BOOST_AUTO_TEST_CASE(warn_about_suicide)
|
|||||||
CHECK_WARNING(text, "\"suicide\" has been deprecated in favour of \"selfdestruct\"");
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user