Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ class Declaration: public ASTNode, public Scopable
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(); }

Expand Down
4 changes: 2 additions & 2 deletions libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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),
Expand Down
15 changes: 15 additions & 0 deletions test/libsolidity/SolidityEndToEndTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"(
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
// ----