diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 1 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 15 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/visibility/external_library_function.sol | 14 |
5 files changed, 33 insertions, 2 deletions
diff --git a/Changelog.md b/Changelog.md index 648af66c..58b93972 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Bugfixes: * Code Generator: Properly skip unneeded storgae array cleanup when not reducing length. * Commandline interface: Support ``--evm-version constantinople`` properly. * Standard JSON: Support ``constantinople`` as ``evmVersion`` properly. + * Type System: Make external library functions accessible. ### 0.4.21 (2018-03-07) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 863ad2fe..a25df64b 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -203,6 +203,7 @@ public: bool isPublic() const { return visibility() >= Visibility::Public; } virtual bool isVisibleInContract() const { return visibility() != Visibility::External; } bool isVisibleInDerivedContracts() const { return isVisibleInContract() && visibility() >= Visibility::Internal; } + bool isVisibleAsLibraryMember() const { return visibility() >= Visibility::Internal; } std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c08e0e67..b2881bea 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -304,7 +304,7 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition ); for (FunctionDefinition const* function: library.definedFunctions()) { - if (!function->isVisibleInDerivedContracts() || seenFunctions.count(function)) + if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function)) continue; seenFunctions.insert(function); FunctionType funType(*function, false); @@ -2875,7 +2875,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current } if (contract.isLibrary()) for (FunctionDefinition const* function: contract.definedFunctions()) - if (function->isVisibleInDerivedContracts()) + if (function->isVisibleAsLibraryMember()) members.push_back(MemberList::Member( function->name(), FunctionType(*function).asMemberFunction(true), diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 33cd1419..d8c8b8ad 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6955,6 +6955,21 @@ BOOST_AUTO_TEST_CASE(library_call) ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9)); } +BOOST_AUTO_TEST_CASE(library_function_external) +{ + char const* sourceCode = R"( + library Lib { function m(bytes b) external pure returns (byte) { return b[2]; } } + contract Test { + function f(bytes b) public pure returns (byte) { + return Lib.m(b); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), "abcde"), encodeArgs("c")); +} + BOOST_AUTO_TEST_CASE(library_stray_values) { char const* sourceCode = R"( diff --git a/test/libsolidity/syntaxTests/visibility/external_library_function.sol b/test/libsolidity/syntaxTests/visibility/external_library_function.sol new file mode 100644 index 00000000..110e74db --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/external_library_function.sol @@ -0,0 +1,14 @@ +library L { + function f(uint) pure external {} +} + +contract C { + using L for *; + + function f() public pure { + L.f(2); + uint x; + x.f(); + } +} +// ---- |