aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md2
-rw-r--r--libsolidity/analysis/TypeChecker.cpp34
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp25
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp23
4 files changed, 78 insertions, 6 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/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 43930125..43a77002 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -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;
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()
}