Make external library functions accessible.

This commit is contained in:
chriseth 2018-03-13 17:18:21 +01:00
parent 8ad0fb3be3
commit eecc26deec
5 changed files with 33 additions and 2 deletions

View File

@ -6,6 +6,7 @@ Bugfixes:
* Code Generator: Properly skip unneeded storgae array cleanup when not reducing length. * Code Generator: Properly skip unneeded storgae array cleanup when not reducing length.
* Commandline interface: Support ``--evm-version constantinople`` properly. * Commandline interface: Support ``--evm-version constantinople`` properly.
* Standard JSON: Support ``constantinople`` as ``evmVersion`` properly. * Standard JSON: Support ``constantinople`` as ``evmVersion`` properly.
* Type System: Make external library functions accessible.
### 0.4.21 (2018-03-07) ### 0.4.21 (2018-03-07)

View File

@ -203,6 +203,7 @@ public:
bool isPublic() const { return visibility() >= Visibility::Public; } bool isPublic() const { return visibility() >= Visibility::Public; }
virtual bool isVisibleInContract() const { return visibility() != Visibility::External; } virtual bool isVisibleInContract() const { return visibility() != Visibility::External; }
bool isVisibleInDerivedContracts() const { return isVisibleInContract() && visibility() >= Visibility::Internal; } bool isVisibleInDerivedContracts() const { return isVisibleInContract() && visibility() >= Visibility::Internal; }
bool isVisibleAsLibraryMember() const { return visibility() >= Visibility::Internal; }
std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); } std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); }

View File

@ -304,7 +304,7 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
); );
for (FunctionDefinition const* function: library.definedFunctions()) for (FunctionDefinition const* function: library.definedFunctions())
{ {
if (!function->isVisibleInDerivedContracts() || seenFunctions.count(function)) if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function))
continue; continue;
seenFunctions.insert(function); seenFunctions.insert(function);
FunctionType funType(*function, false); FunctionType funType(*function, false);
@ -2875,7 +2875,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
} }
if (contract.isLibrary()) if (contract.isLibrary())
for (FunctionDefinition const* function: contract.definedFunctions()) for (FunctionDefinition const* function: contract.definedFunctions())
if (function->isVisibleInDerivedContracts()) if (function->isVisibleAsLibraryMember())
members.push_back(MemberList::Member( members.push_back(MemberList::Member(
function->name(), function->name(),
FunctionType(*function).asMemberFunction(true), FunctionType(*function).asMemberFunction(true),

View File

@ -6955,6 +6955,21 @@ BOOST_AUTO_TEST_CASE(library_call)
ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9)); 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) BOOST_AUTO_TEST_CASE(library_stray_values)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(

View File

@ -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();
}
}
// ----