mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Fixed function overloads.
Added tests, disallowed non-calling usage of non-unique function references.
This commit is contained in:
		
							parent
							
								
									367d0367ee
								
							
						
					
					
						commit
						c19d10321a
					
				| @ -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() | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -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() | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user