aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2016-10-19 20:44:09 +0800
committerGitHub <noreply@github.com>2016-10-19 20:44:09 +0800
commit4f191d1f6fbdf9b424c4292db0ec10f5040a0b09 (patch)
tree4a35828ea3554c3cfa9dd616581dab9439551082
parentf9e92b37ba6d71991979f3d6782287980df6b026 (diff)
parentfdd1108c1c2e316d143f44d048f1686be2e2eb3a (diff)
downloaddexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.tar
dexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.tar.gz
dexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.tar.bz2
dexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.tar.lz
dexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.tar.xz
dexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.tar.zst
dexon-solidity-4f191d1f6fbdf9b424c4292db0ec10f5040a0b09.zip
Merge pull request #1194 from ethereum/bound-functions
Proper type checking for bound functions
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/ast/Types.cpp6
-rw-r--r--libsolidity/ast/Types.h10
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp19
4 files changed, 33 insertions, 3 deletions
diff --git a/Changelog.md b/Changelog.md
index fb3b23c7..a5a85eb5 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -8,6 +8,7 @@ Features:
Bugfixes:
* Disallow unknown options in `solc`
+ * Proper type checking for bound functions.
* Code Generator: expect zero stack increase after `super` as an expression
* Inline assembly: support the `address` opcode
* Inline assembly: fix parsing of assignment after a label.
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index edb0fbe4..068cc138 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -241,7 +241,8 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
seenFunctions.insert(function);
FunctionType funType(*function, false);
if (auto fun = funType.asMemberFunction(true, true))
- members.push_back(MemberList::Member(function->name(), fun, function));
+ if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
+ members.push_back(MemberList::Member(function->name(), fun, function));
}
}
return members;
@@ -2069,6 +2070,9 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con
FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) const
{
+ if (_bound && m_parameterTypes.empty())
+ return FunctionTypePointer();
+
TypePointers parameterTypes;
for (auto const& t: m_parameterTypes)
{
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index f65d25fb..3f94d11a 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -872,7 +872,12 @@ public:
m_isConstant(_isConstant),
m_isPayable(_isPayable),
m_declaration(_declaration)
- {}
+ {
+ solAssert(
+ !m_bound || !m_parameterTypes.empty(),
+ "Attempted construction of bound function without self type"
+ );
+ }
TypePointers parameterTypes() const;
std::vector<std::string> parameterNames() const;
@@ -940,8 +945,9 @@ public:
/// removed and the location of reference types is changed from CallData to Memory.
/// This is needed if external functions are called on other contracts, as they cannot return
/// dynamic values.
+ /// Returns empty shared pointer on a failure. Namely, if a bound function has no parameters.
/// @param _inLibrary if true, uses DelegateCall as location.
- /// @param _bound if true, the argumenst are placed as `arg1.functionName(arg2, ..., argn)`.
+ /// @param _bound if true, the arguments are placed as `arg1.functionName(arg2, ..., argn)`.
FunctionTypePointer asMemberFunction(bool _inLibrary, bool _bound = false) const;
private:
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 76141f41..1691b1c5 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -4020,6 +4020,25 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
}
+BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype)
+{
+ char const* text = R"(
+ library B {
+ function b() {}
+ }
+
+ contract A {
+ using B for bytes;
+
+ function a() {
+ bytes memory x;
+ x.b();
+ }
+ }
+ )";
+ BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}