Fixed function overloads.

Added tests, disallowed non-calling usage of non-unique function
references.
This commit is contained in:
chriseth 2015-04-15 17:40:50 +02:00
parent 367d0367ee
commit c19d10321a
2 changed files with 161 additions and 115 deletions

View File

@ -304,7 +304,6 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr)
BOOST_AUTO_TEST_CASE(calling_other_functions)
{
// note that the index of a function is its index in the sorted sequence of functions
char const* sourceCode = "contract collatz {\n"
" function run(uint x) returns(uint y) {\n"
" while ((y = x) > 1) {\n"
@ -1095,26 +1094,6 @@ BOOST_AUTO_TEST_CASE(now)
BOOST_CHECK(callContractFunction("someInfo()") == encodeArgs(true));
}
BOOST_AUTO_TEST_CASE(function_types)
{
char const* sourceCode = "contract test {\n"
" function a(bool selector) returns (uint b) {\n"
" var f = fun1;\n"
" if (selector) f = fun2;\n"
" return f(9);\n"
" }\n"
" function fun1(uint x) returns (uint b) {\n"
" return 11;\n"
" }\n"
" function fun2(uint x) returns (uint b) {\n"
" return 12;\n"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("a(bool)", false) == encodeArgs(11));
BOOST_CHECK(callContractFunction("a(bool)", true) == encodeArgs(12));
}
BOOST_AUTO_TEST_CASE(type_conversions_cleanup)
{
// 22-byte integer converted to a contract (i.e. address, 20 bytes), converted to a 32 byte
@ -3571,99 +3550,6 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_bytes)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(true));
}
BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_first)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint d) { return k; }
function f(uint a, uint b) returns(uint d) { return a + b; }
function g() returns(uint d) { return f(3); }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g()") == encodeArgs(3));
}
BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second)
{
char const* sourceCode = R"(
contract test {
function f(uint a, uint b) returns(uint d) { return a + b; }
function f(uint k) returns(uint d) { return k; }
function g() returns(uint d) { return f(3, 7); }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g()") == encodeArgs(10));
}
BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else)
{
char const* sourceCode = R"(
contract test {
function f(uint a, uint b) returns(uint d) { return a + b; }
function f(uint k) returns(uint d) { return k; }
function g(bool flag) returns(uint d) {
if (flag)
return f(3);
else
return f(3, 7);
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(3));
BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs(10));
}
BOOST_AUTO_TEST_CASE(overloaded_function_with_var)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint d) { return k; }
function f(uint a, uint b) returns(uint d) { return a + b; }
function g(bool flag) returns(uint d) {
var x = f;
if (flag)
return x(3);
else
return x(3, 7);
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(3));
BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs(10));
}
BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct)
{
char const* sourceCode = R"(
contract B { function f() returns(uint) { return 10; } }
contract C is B {
function f(uint i) returns(uint) { return 2 * i; }
function g() returns(uint) { return f(1); }
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("g()") == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect)
{
char const* sourceCode = R"(
contract A { function f(uint a) returns(uint) { return 2 * a; } }
contract B { function f() returns(uint) { return 10; } }
contract C is A, B {
function g() returns(uint) { return f(); }
function h() returns(uint) { return f(1); }
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("g()") == encodeArgs(10));
BOOST_CHECK(callContractFunction("h()") == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(packed_storage_structs_delete)
{
char const* sourceCode = R"(
@ -3719,6 +3605,94 @@ BOOST_AUTO_TEST_CASE(packed_storage_structs_with_bytes0)
BOOST_CHECK(callContractFunction("test()") == encodeArgs(true));
}
BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_first)
{
char const* sourceCode = R"(
contract test {
function f(uint k) returns(uint d) { return k; }
function f(uint a, uint b) returns(uint d) { return a + b; }
function g() returns(uint d) { return f(3); }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g()") == encodeArgs(3));
}
BOOST_AUTO_TEST_CASE(overloaded_function_call_resolve_to_second)
{
char const* sourceCode = R"(
contract test {
function f(uint a, uint b) returns(uint d) { return a + b; }
function f(uint k) returns(uint d) { return k; }
function g() returns(uint d) { return f(3, 7); }
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g()") == encodeArgs(10));
}
BOOST_AUTO_TEST_CASE(overloaded_function_call_with_if_else)
{
char const* sourceCode = R"(
contract test {
function f(uint a, uint b) returns(uint d) { return a + b; }
function f(uint k) returns(uint d) { return k; }
function g(bool flag) returns(uint d) {
if (flag)
return f(3);
else
return f(3, 7);
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(3));
BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs(10));
}
BOOST_AUTO_TEST_CASE(derived_overload_base_function_direct)
{
char const* sourceCode = R"(
contract B { function f() returns(uint) { return 10; } }
contract C is B {
function f(uint i) returns(uint) { return 2 * i; }
function g() returns(uint) { return f(1); }
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("g()") == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(derived_overload_base_function_indirect)
{
char const* sourceCode = R"(
contract A { function f(uint a) returns(uint) { return 2 * a; } }
contract B { function f() returns(uint) { return 10; } }
contract C is A, B {
function g() returns(uint) { return f(); }
function h() returns(uint) { return f(1); }
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("g()") == encodeArgs(10));
BOOST_CHECK(callContractFunction("h()") == encodeArgs(2));
}
BOOST_AUTO_TEST_CASE(super_overload)
{
char const* sourceCode = R"(
contract A { function f(uint a) returns(uint) { return 2 * a; } }
contract B { function f(bool b) returns(uint) { return 10; } }
contract C is A, B {
function g() returns(uint) { return super.f(true); }
function h() returns(uint) { return super.f(1); }
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("g()") == encodeArgs(10));
BOOST_CHECK(callContractFunction("h()") == encodeArgs(2));
}
BOOST_AUTO_TEST_SUITE_END()
}

View File

@ -1637,7 +1637,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve)
BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function)
{
// literal 1 can be both converted to uint8 and uint8, so it's ambiguous.
// literal 1 can be both converted to uint and uint8, so the call is ambiguous.
char const* sourceCode = R"(
contract test {
function f(uint8 a) returns(uint) { return a; }
@ -1648,6 +1648,78 @@ BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function)
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function)
{
char const* sourceCode = R"(
contract test {
function f(uint a) returns(uint) { return 2 * a; }
function g() returns(uint) { var x = f; return x(7); }
}
)";
ETH_TEST_REQUIRE_NO_THROW(parseTextAndResolveNames(sourceCode), "Type resolving failed");
}
BOOST_AUTO_TEST_CASE(assignment_of_overloaded_function)
{
char const* sourceCode = R"(
contract test {
function f() returns(uint) { return 1; }
function f(uint a) returns(uint) { return 2 * a; }
function g() returns(uint) { var x = f; return x(7); }
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(external_types_clash)
{
char const* sourceCode = R"(
contract base {
enum a { X }
function f(a) { }
}
contract test is base {
function f(uint8 a) { }
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(override_changes_return_types)
{
char const* sourceCode = R"(
contract base {
function f(uint a) returns (uint) { }
}
contract test is base {
function f(uint a) returns (uint8) { }
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
}
BOOST_AUTO_TEST_CASE(multiple_constructors)
{
char const* sourceCode = R"(
contract test {
function test(uint a) { }
function test() {}
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), DeclarationError);
}
BOOST_AUTO_TEST_CASE(equal_overload)
{
char const* sourceCode = R"(
contract test {
function test(uint a) returns (uint b) { }
function test(uint a) external {}
}
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), DeclarationError);
}
BOOST_AUTO_TEST_SUITE_END()
}