mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1634 from chriseth/sol_overloadingFunctions
Function overloading.
This commit is contained in:
commit
e65b9825d6
@ -302,7 +302,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"
|
||||
@ -1147,26 +1146,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
|
||||
@ -3674,6 +3653,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_CASE(packed_storage_signed)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
@ -78,7 +78,9 @@ Declaration const& resolveDeclaration(
|
||||
// bracers are required, cause msvc couldnt handle this macro in for statement
|
||||
for (string const& namePart: _namespacedName)
|
||||
{
|
||||
BOOST_REQUIRE(declaration = _resolver.resolveName(namePart, declaration));
|
||||
auto declarations = _resolver.resolveName(namePart, declaration);
|
||||
BOOST_REQUIRE(!declarations.empty());
|
||||
BOOST_REQUIRE(declaration = *declarations.begin());
|
||||
}
|
||||
BOOST_REQUIRE(declaration);
|
||||
return *declaration;
|
||||
|
@ -623,23 +623,23 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance)
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(illegal_override_direct)
|
||||
BOOST_AUTO_TEST_CASE(legal_override_direct)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract B { function f() {} }
|
||||
contract C is B { function f(uint i) {} }
|
||||
)";
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(illegal_override_indirect)
|
||||
BOOST_AUTO_TEST_CASE(legal_override_indirect)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract A { function f(uint a) {} }
|
||||
contract B { function f() {} }
|
||||
contract C is A, B { }
|
||||
)";
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(illegal_override_visibility)
|
||||
@ -1654,6 +1654,103 @@ BOOST_AUTO_TEST_CASE(bytes0_array)
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract test {
|
||||
function f() returns(uint) { return 1; }
|
||||
function f(uint a) returns(uint) { return a; }
|
||||
function g() returns(uint) { return f(3, 5); }
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function)
|
||||
{
|
||||
// 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; }
|
||||
function f(uint a) returns(uint) { return 2*a; }
|
||||
function g() returns(uint) { return f(1); }
|
||||
}
|
||||
)";
|
||||
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_CASE(uninitialized_var)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
@ -134,6 +134,31 @@ BOOST_AUTO_TEST_CASE(missing_argument_in_named_args)
|
||||
BOOST_CHECK_THROW(parseText(text), ParserError);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_exact_functions)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function fun(uint a) returns(uint r) { return a; }
|
||||
function fun(uint a) returns(uint r) { return a; }
|
||||
}
|
||||
)";
|
||||
// with support of overloaded functions, during parsing,
|
||||
// we can't determine whether they match exactly, however
|
||||
// it will throw DeclarationError in following stage.
|
||||
BOOST_CHECK_NO_THROW(parseText(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(overloaded_functions)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function fun(uint a) returns(uint r) { return a; }
|
||||
function fun(uint a, uint b) returns(uint r) { return a + b; }
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK_NO_THROW(parseText(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(function_natspec_documentation)
|
||||
{
|
||||
ASTPointer<ContractDefinition> contract;
|
||||
|
Loading…
Reference in New Issue
Block a user