From 644a402166e3feaebb684795801706c3b0b1238f Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 3 Sep 2019 18:31:17 +0200 Subject: [PATCH] Tests. --- test/libsolidity/ASTJSON/address_payable.json | 2 + .../ASTJSON/address_payable_legacy.json | 2 + test/libsolidity/SolidityEndToEndTest.cpp | 53 ++++++ .../tryCatch/invalid_error_encoding.sol | 168 ++++++++++++++++++ .../semanticTests/tryCatch/lowLevel.sol | 18 ++ .../semanticTests/tryCatch/nested.sol | 33 ++++ .../tryCatch/return_function.sol | 17 ++ .../semanticTests/tryCatch/simple.sol | 18 ++ .../semanticTests/tryCatch/structured.sol | 19 ++ .../tryCatch/structuredAndLowLevel.sol | 23 +++ .../semanticTests/tryCatch/trivial.sol | 16 ++ .../syntaxTests/tryCatch/catch_error.sol | 11 ++ .../tryCatch/catch_error_named.sol | 11 ++ .../syntaxTests/tryCatch/catch_low_level.sol | 11 ++ .../syntaxTests/tryCatch/empty_catch.sol | 11 ++ .../syntaxTests/tryCatch/empty_returns.sol | 11 ++ .../tryCatch/error_with_wrong_type.sol | 12 ++ .../tryCatch/invalid_error_name.sol | 11 ++ .../syntaxTests/tryCatch/invalid_returns.sol | 13 ++ .../syntaxTests/tryCatch/library_call.sol | 40 +++++ .../tryCatch/low_level_pre-byzantium.sol | 13 ++ .../tryCatch/low_level_with_wrong_type.sol | 12 ++ .../syntaxTests/tryCatch/no_catch.sol | 8 + .../syntaxTests/tryCatch/no_external_call.sol | 9 + .../syntaxTests/tryCatch/no_returns.sol | 9 + .../syntaxTests/tryCatch/returns.sol | 10 ++ .../syntaxTests/tryCatch/returns_memory.sol | 11 ++ .../tryCatch/returns_memory_anonymous.sol | 11 ++ .../syntaxTests/tryCatch/simple_catch.sol | 9 + .../tryCatch/structured_pre_byzantium.sol | 13 ++ .../tryCatch/two_catch_clauses.sol | 14 ++ .../tryCatch/two_error_catch_clauses.sol | 15 ++ .../tryCatch/two_low_level_catch_clauses.sol | 14 ++ .../syntaxTests/unusedVariables/try_catch.sol | 18 ++ 34 files changed, 666 insertions(+) create mode 100644 test/libsolidity/semanticTests/tryCatch/invalid_error_encoding.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/lowLevel.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/nested.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/return_function.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/simple.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/structured.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/structuredAndLowLevel.sol create mode 100644 test/libsolidity/semanticTests/tryCatch/trivial.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/catch_error.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/catch_error_named.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/catch_low_level.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/empty_catch.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/empty_returns.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/error_with_wrong_type.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_error_name.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/invalid_returns.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/library_call.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/low_level_pre-byzantium.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/low_level_with_wrong_type.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/no_catch.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/no_external_call.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/no_returns.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/returns.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/returns_memory.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/returns_memory_anonymous.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/simple_catch.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/structured_pre_byzantium.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/two_catch_clauses.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/two_error_catch_clauses.sol create mode 100644 test/libsolidity/syntaxTests/tryCatch/two_low_level_catch_clauses.sol create mode 100644 test/libsolidity/syntaxTests/unusedVariables/try_catch.sol diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index 834fb1cc9..738d8371d 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -321,6 +321,7 @@ "names" : [], "nodeType" : "FunctionCall", "src" : "209:13:1", + "tryCall" : false, "typeDescriptions" : { "typeIdentifier" : "t_address", @@ -444,6 +445,7 @@ "names" : [], "nodeType" : "FunctionCall", "src" : "239:10:1", + "tryCall" : false, "typeDescriptions" : { "typeIdentifier" : "t_address_payable", diff --git a/test/libsolidity/ASTJSON/address_payable_legacy.json b/test/libsolidity/ASTJSON/address_payable_legacy.json index 0b1072460..afcf195a5 100644 --- a/test/libsolidity/ASTJSON/address_payable_legacy.json +++ b/test/libsolidity/ASTJSON/address_payable_legacy.json @@ -396,6 +396,7 @@ [ null ], + "tryCall" : false, "type" : "address", "type_conversion" : true }, @@ -526,6 +527,7 @@ [ null ], + "tryCall" : false, "type" : "address payable", "type_conversion" : true }, diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 1c14b95a0..f9e5f6fc3 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14784,6 +14784,59 @@ BOOST_AUTO_TEST_CASE(dirty_scratch_space_prior_to_constant_optimiser) ); } +BOOST_AUTO_TEST_CASE(try_catch_library_call) +{ + char const* sourceCode = R"( + library L { + struct S { uint x; } + function integer(uint t, bool b) public view returns (uint) { + if (b) { + return t; + } else { + revert("failure"); + } + } + function stru(S storage t, bool b) public view returns (uint) { + if (b) { + return t.x; + } else { + revert("failure"); + } + } + } + contract C { + using L for L.S; + L.S t; + function f(bool b) public returns (uint, string memory) { + uint x = 8; + try L.integer(x, b) returns (uint _x) { + return (_x, ""); + } catch Error(string memory message) { + return (18, message); + } + } + function g(bool b) public returns (uint, string memory) { + t.x = 9; + try t.stru(b) returns (uint x) { + return (x, ""); + } catch Error(string memory message) { + return (19, message); + } + } + } + )"; + if (dev::test::Options::get().evmVersion().supportsReturndata()) + { + compileAndRun(sourceCode, 0, "L", bytes()); + compileAndRun(sourceCode, 0, "C", bytes(), map{{"L", m_contractAddress}}); + + ABI_CHECK(callContractFunction("f(bool)", true), encodeArgs(8, 0x40, 0)); + ABI_CHECK(callContractFunction("f(bool)", false), encodeArgs(18, 0x40, 7, "failure")); + ABI_CHECK(callContractFunction("g(bool)", true), encodeArgs(9, 0x40, 0)); + ABI_CHECK(callContractFunction("g(bool)", false), encodeArgs(19, 0x40, 7, "failure")); + } +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/semanticTests/tryCatch/invalid_error_encoding.sol b/test/libsolidity/semanticTests/tryCatch/invalid_error_encoding.sol new file mode 100644 index 000000000..2bfc23191 --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/invalid_error_encoding.sol @@ -0,0 +1,168 @@ +contract C { + function g(bytes memory revertMsg) public pure returns (uint, uint) { + assembly { revert(add(revertMsg, 0x20), mload(revertMsg)) } + } + function f1() public returns (uint x) { + // Invalid signature + try this.g(abi.encodeWithSelector(0x12345678, uint(0), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch (bytes memory) { + return 2; + } + } + function f1a() public returns (uint x) { + // Invalid signature + try this.g(abi.encodeWithSelector(0x12345678, uint(0), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch { + return 2; + } + } + function f1b() public returns (uint x) { + // Invalid signature + try this.g(abi.encodeWithSelector(0x12345678, uint(0), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } + } + function f1c() public returns (uint x) { + // Invalid signature + try this.g(abi.encodeWithSelector(0x12345678, uint(0), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch { + return 2; + } + } + function f2() public returns (uint x) { + // Valid signature but illegal offset + try this.g(abi.encodeWithSignature("Error(string)", uint(0x100), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch (bytes memory) { + return 2; + } + } + function f2a() public returns (uint x) { + // Valid signature but illegal offset + try this.g(abi.encodeWithSignature("Error(string)", uint(0x100), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch { + return 2; + } + } + function f2b() public returns (uint x) { + // Valid signature but illegal offset + try this.g(abi.encodeWithSignature("Error(string)", uint(0x100), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } + } + function f2c() public returns (uint x) { + // Valid signature but illegal offset + try this.g(abi.encodeWithSignature("Error(string)", uint(0x100), uint(0), uint(0))) returns (uint a, uint b) { + return 0; + } catch { + return 1; + } + } + function f3() public returns (uint x) { + // Valid up to length + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x30), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch (bytes memory) { + return 2; + } + } + function f3a() public returns (uint x) { + // Valid up to length + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x30), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch (bytes memory) { + return 2; + } + } + function f3b() public returns (uint x) { + // Valid up to length + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x30), uint(0))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } + } + function f3c() public returns (uint x) { + // Valid up to length + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x30), uint(0))) returns (uint a, uint b) { + return 0; + } catch { + return 1; + } + } + function f4() public returns (uint x) { + // Fully valid + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x7), bytes7("abcdefg"))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch (bytes memory) { + return 2; + } + } + function f4a() public returns (uint x) { + // Fully valid + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x7), bytes7("abcdefg"))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } catch { + return 2; + } + } + function f4b() public returns (uint x) { + // Fully valid + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x7), bytes7("abcdefg"))) returns (uint a, uint b) { + return 0; + } catch Error(string memory) { + return 1; + } + } + function f4c() public returns (uint x) { + // Fully valid + try this.g(abi.encodeWithSignature("Error(string)", uint(0x20), uint(0x7), bytes7("abcdefg"))) returns (uint a, uint b) { + return 0; + } catch { + return 1; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// f1() -> 2 +// f1a() -> 2 +// f1b() -> FAILURE, hex"12345678", 0x0, 0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +// f1c() -> 2 +// f2() -> 2 +// f2a() -> 2 +// f2b() -> FAILURE, hex"08c379a0", 0x100, 0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +// f2c() -> 1 +// f3() -> 2 +// f3a() -> 2 +// f3b() -> FAILURE, hex"08c379a0", 0x20, 48, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +// f3c() -> 1 +// f4() -> 1 +// f4a() -> 1 +// f4b() -> 1 +// f4c() -> 1 diff --git a/test/libsolidity/semanticTests/tryCatch/lowLevel.sol b/test/libsolidity/semanticTests/tryCatch/lowLevel.sol new file mode 100644 index 000000000..ac275522d --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/lowLevel.sol @@ -0,0 +1,18 @@ +contract C { + function g(bool b) public pure returns (uint, uint) { + require(b, "message"); + return (1, 2); + } + function f(bool b) public returns (uint x, uint y, bytes memory txt) { + try this.g(b) returns (uint a, uint b) { + (x, y) = (a, b); + } catch (bytes memory s) { + txt = s; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// f(bool): true -> 1, 2, 96, 0 +// f(bool): false -> 0, 0, 96, 100, 0x8c379a000000000000000000000000000000000000000000000000000000000, 0x2000000000000000000000000000000000000000000000000000000000, 0x76d657373616765000000000000000000000000000000000000000000, 0 diff --git a/test/libsolidity/semanticTests/tryCatch/nested.sol b/test/libsolidity/semanticTests/tryCatch/nested.sol new file mode 100644 index 000000000..7c56a81b7 --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/nested.sol @@ -0,0 +1,33 @@ +contract C { + function g(bool b) public pure returns (uint, uint) { + require(b, "failure"); + return (1, 2); + } + function f(bool cond1, bool cond2) public returns (uint x, uint y, bytes memory txt) { + try this.g(cond1) returns (uint a, uint b) { + try this.g(cond2) returns (uint a2, uint b2) { + (x, y) = (a, b); + txt = "success"; + } catch Error(string memory s) { + x = 12; + txt = bytes(s); + } catch (bytes memory s) { + x = 13; + txt = s; + } + } catch Error(string memory s) { + x = 99; + txt = bytes(s); + } catch (bytes memory s) { + x = 98; + txt = s; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// f(bool,bool): true, true -> 1, 2, 96, 7, "success" +// f(bool,bool): true, false -> 12, 0, 96, 7, "failure" +// f(bool,bool): false, true -> 99, 0, 96, 7, "failure" +// f(bool,bool): false, false -> 99, 0, 96, 7, "failure" diff --git a/test/libsolidity/semanticTests/tryCatch/return_function.sol b/test/libsolidity/semanticTests/tryCatch/return_function.sol new file mode 100644 index 000000000..82d5dc821 --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/return_function.sol @@ -0,0 +1,17 @@ +contract C { + function g() public returns (uint a, function() external h, uint b) { + a = 1; + h = this.fun; + b = 9; + } + function f() public returns (uint, function() external, uint) { + // Note that the function type uses two stack slots. + try this.g() returns (uint a, function() external h, uint b) { + return (a, h, b); + } catch { + } + } + function fun() public pure {} +} +// ---- +// f() -> 0x1, 0xfdd67305928fcac8d213d1e47bfa6165cd0b87b946644cd0000000000000000, 9 diff --git a/test/libsolidity/semanticTests/tryCatch/simple.sol b/test/libsolidity/semanticTests/tryCatch/simple.sol new file mode 100644 index 000000000..b7f367016 --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/simple.sol @@ -0,0 +1,18 @@ +contract C { + function g(bool b) public pure returns (uint, uint) { + require(b); + return (1, 2); + } + function f(bool b) public returns (uint x, uint y) { + try this.g(b) returns (uint a, uint b) { + (x, y) = (a, b); + } catch { + (x, y) = (9, 10); + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// f(bool): true -> 1, 2 +// f(bool): false -> 9, 10 diff --git a/test/libsolidity/semanticTests/tryCatch/structured.sol b/test/libsolidity/semanticTests/tryCatch/structured.sol new file mode 100644 index 000000000..e5aa238b3 --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/structured.sol @@ -0,0 +1,19 @@ +contract C { + function g(bool b) public pure returns (uint, uint) { + require(b, "message"); + return (1, 2); + } + function f(bool b) public returns (uint x, uint y, string memory txt) { + try this.g(b) returns (uint a, uint b) { + (x, y) = (a, b); + txt = "success"; + } catch Error(string memory s) { + txt = s; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// f(bool): true -> 1, 2, 0x60, 7, "success" +// f(bool): false -> 0, 0, 0x60, 7, "message" diff --git a/test/libsolidity/semanticTests/tryCatch/structuredAndLowLevel.sol b/test/libsolidity/semanticTests/tryCatch/structuredAndLowLevel.sol new file mode 100644 index 000000000..8a8cb3d1b --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/structuredAndLowLevel.sol @@ -0,0 +1,23 @@ +contract C { + function g(bool b) public pure returns (uint, uint) { + require(b, "message longer than 32 bytes 32 bytes 32 bytes 32 bytes 32 bytes 32 bytes 32 bytes"); + return (1, 2); + } + function f(bool cond) public returns (uint x, uint y, bytes memory txt) { + try this.g(cond) returns (uint a, uint b) { + (x, y) = (a, b); + txt = "success"; + } catch Error(string memory s) { + x = 99; + txt = bytes(s); + } catch (bytes memory s) { + x = 98; + txt = s; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// f(bool): true -> 1, 2, 96, 7, "success" +// f(bool): false -> 99, 0, 96, 82, "message longer than 32 bytes 32 ", "bytes 32 bytes 32 bytes 32 bytes", " 32 bytes 32 bytes" diff --git a/test/libsolidity/semanticTests/tryCatch/trivial.sol b/test/libsolidity/semanticTests/tryCatch/trivial.sol new file mode 100644 index 000000000..e2f8739bd --- /dev/null +++ b/test/libsolidity/semanticTests/tryCatch/trivial.sol @@ -0,0 +1,16 @@ +contract C { + function g(bool x) public pure { + require(x); + } + function f(bool x) public returns (uint) { + // Set the gas to make this work on pre-byzantium VMs + try this.g.gas(8000)(x) { + return 1; + } catch { + return 2; + } + } +} +// ---- +// f(bool): true -> 1 +// f(bool): false -> 2 diff --git a/test/libsolidity/syntaxTests/tryCatch/catch_error.sol b/test/libsolidity/syntaxTests/tryCatch/catch_error.sol new file mode 100644 index 000000000..34fc2431e --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/catch_error.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch Error(string memory) { + + } + } +} +// ==== +// EVMVersion: >=byzantium \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/catch_error_named.sol b/test/libsolidity/syntaxTests/tryCatch/catch_error_named.sol new file mode 100644 index 000000000..1a4a1273a --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/catch_error_named.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch Error(string memory x) { + x; + } + } +} +// ==== +// EVMVersion: >=byzantium \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/catch_low_level.sol b/test/libsolidity/syntaxTests/tryCatch/catch_low_level.sol new file mode 100644 index 000000000..58948e211 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/catch_low_level.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch (bytes memory x) { + x; + } + } +} +// ==== +// EVMVersion: >=byzantium \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/empty_catch.sol b/test/libsolidity/syntaxTests/tryCatch/empty_catch.sol new file mode 100644 index 000000000..ee887fe1a --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/empty_catch.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch () { + + } + } +} +// ---- +// ParserError: (101-102): Expected type name diff --git a/test/libsolidity/syntaxTests/tryCatch/empty_returns.sol b/test/libsolidity/syntaxTests/tryCatch/empty_returns.sol new file mode 100644 index 000000000..ba1ba2202 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/empty_returns.sol @@ -0,0 +1,11 @@ +contract C { + function f() public { + try this.f() returns () { + + } catch { + + } + } +} +// ---- +// ParserError: (69-70): Expected type name diff --git a/test/libsolidity/syntaxTests/tryCatch/error_with_wrong_type.sol b/test/libsolidity/syntaxTests/tryCatch/error_with_wrong_type.sol new file mode 100644 index 000000000..05878ba5b --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/error_with_wrong_type.sol @@ -0,0 +1,12 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch Error(uint) { + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// TypeError: (94-123): Expected `catch Error(string memory ...) { ... }`. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_error_name.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_error_name.sol new file mode 100644 index 000000000..164da567d --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_error_name.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + } catch Error2() { + } catch abc() { + } + } +} +// ---- +// TypeError: (93-119): Invalid catch clause name. Expected either `catch (...)` or `catch Error(...)`. +// TypeError: (120-143): Invalid catch clause name. Expected either `catch (...)` or `catch Error(...)`. diff --git a/test/libsolidity/syntaxTests/tryCatch/invalid_returns.sol b/test/libsolidity/syntaxTests/tryCatch/invalid_returns.sol new file mode 100644 index 000000000..e1d22f05f --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/invalid_returns.sol @@ -0,0 +1,13 @@ +contract C { + function f() public returns (uint8, uint) { + // Implicitly convertible, but not exactly the same type. + try this.f() returns (uint, int x) { + + } catch { + + } + } +} +// ---- +// TypeError: (157-161): Invalid type, expected uint8 but got uint256. +// TypeError: (163-168): Invalid type, expected uint256 but got int256. diff --git a/test/libsolidity/syntaxTests/tryCatch/library_call.sol b/test/libsolidity/syntaxTests/tryCatch/library_call.sol new file mode 100644 index 000000000..b2ceaa6a5 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/library_call.sol @@ -0,0 +1,40 @@ +library L { + struct S { uint x; } + function integer(uint t, bool b) public pure returns (uint) { + if (b) { + return t; + } else { + revert("failure"); + } + } + function stru(S storage t, bool b) public view returns (uint) { + if (b) { + return t.x; + } else { + revert("failure"); + } + } +} +contract C { + using L for L.S; + L.S t; + function f(bool b) public pure returns (uint, string memory) { + uint x = 8; + try L.integer(x, b) returns (uint _x) { + return (_x, ""); + } catch Error(string memory message) { + return (18, message); + } + } + function g(bool b) public returns (uint, string memory) { + t.x = 9; + try t.stru(b) returns (uint x) { + return (x, ""); + } catch Error(string memory message) { + return (19, message); + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- diff --git a/test/libsolidity/syntaxTests/tryCatch/low_level_pre-byzantium.sol b/test/libsolidity/syntaxTests/tryCatch/low_level_pre-byzantium.sol new file mode 100644 index 000000000..3dd16df11 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/low_level_pre-byzantium.sol @@ -0,0 +1,13 @@ +contract C { + function f() public { + try this.f() { + + } catch (bytes memory) { + + } + } +} +// ==== +// EVMVersion: =byzantium +// ---- +// TypeError: (94-118): Expected `catch (bytes memory ...) { ... }` or `catch { ... }`. diff --git a/test/libsolidity/syntaxTests/tryCatch/no_catch.sol b/test/libsolidity/syntaxTests/tryCatch/no_catch.sol new file mode 100644 index 000000000..28938d3dd --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/no_catch.sol @@ -0,0 +1,8 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + } + } +} +// ---- +// ParserError: (97-98): Expected reserved keyword 'catch' but got '}' diff --git a/test/libsolidity/syntaxTests/tryCatch/no_external_call.sol b/test/libsolidity/syntaxTests/tryCatch/no_external_call.sol new file mode 100644 index 000000000..1ae24a802 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/no_external_call.sol @@ -0,0 +1,9 @@ +contract C { + function f() public returns (uint, uint) { + try f() { + } catch { + } + } +} +// ---- +// TypeError: (72-75): Try can only be used with external function calls and contract creation calls. diff --git a/test/libsolidity/syntaxTests/tryCatch/no_returns.sol b/test/libsolidity/syntaxTests/tryCatch/no_returns.sol new file mode 100644 index 000000000..bfda49ab9 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/no_returns.sol @@ -0,0 +1,9 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch { + + } + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/returns.sol b/test/libsolidity/syntaxTests/tryCatch/returns.sol new file mode 100644 index 000000000..507a83905 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/returns.sol @@ -0,0 +1,10 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() returns (uint a, uint b) { + a = 1; + b = 2; + } catch { + + } + } +} diff --git a/test/libsolidity/syntaxTests/tryCatch/returns_memory.sol b/test/libsolidity/syntaxTests/tryCatch/returns_memory.sol new file mode 100644 index 000000000..f71a4af25 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/returns_memory.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint[] memory, uint) { + try this.f() returns (uint[] memory x, uint y) { + return (x, y); + } catch { + + } + } +} +// ==== +// EVMVersion: >=byzantium diff --git a/test/libsolidity/syntaxTests/tryCatch/returns_memory_anonymous.sol b/test/libsolidity/syntaxTests/tryCatch/returns_memory_anonymous.sol new file mode 100644 index 000000000..9eb8f86c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/returns_memory_anonymous.sol @@ -0,0 +1,11 @@ +contract C { + function f() public returns (uint[] memory, uint) { + try this.f() returns (uint[] memory, uint) { + + } catch { + + } + } +} +// ==== +// EVMVersion: >=byzantium \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/simple_catch.sol b/test/libsolidity/syntaxTests/tryCatch/simple_catch.sol new file mode 100644 index 000000000..df33d2a50 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/simple_catch.sol @@ -0,0 +1,9 @@ +contract C { + function f() public { + try this.f() { + + } catch { + + } + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/structured_pre_byzantium.sol b/test/libsolidity/syntaxTests/tryCatch/structured_pre_byzantium.sol new file mode 100644 index 000000000..34c7e5011 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/structured_pre_byzantium.sol @@ -0,0 +1,13 @@ +contract C { + function f() public { + try this.f() { + + } catch Error(string memory) { + + } + } +} +// ==== +// EVMVersion: =byzantium \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/tryCatch/two_error_catch_clauses.sol b/test/libsolidity/syntaxTests/tryCatch/two_error_catch_clauses.sol new file mode 100644 index 000000000..72f77c4a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/two_error_catch_clauses.sol @@ -0,0 +1,15 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch Error(string memory x) { + x; + } catch Error(string memory y) { + y; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// TypeError: (150-205): This try statement already has an "Error" catch clause. diff --git a/test/libsolidity/syntaxTests/tryCatch/two_low_level_catch_clauses.sol b/test/libsolidity/syntaxTests/tryCatch/two_low_level_catch_clauses.sol new file mode 100644 index 000000000..108160aae --- /dev/null +++ b/test/libsolidity/syntaxTests/tryCatch/two_low_level_catch_clauses.sol @@ -0,0 +1,14 @@ +contract C { + function f() public returns (uint, uint) { + try this.f() { + + } catch { + } catch (bytes memory y) { + y; + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// TypeError: (112-161): This try statement already has a low-level catch clause. diff --git a/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol b/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol new file mode 100644 index 000000000..d829cfc7d --- /dev/null +++ b/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol @@ -0,0 +1,18 @@ +contract test { + function f() public returns (uint b) { + try this.f() returns (uint a) { + + } catch Error(string memory message) { + + } catch (bytes memory error) { + + } + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// Warning: (49-55): Unused function parameter. Remove or comment out the variable name to silence this warning. +// Warning: (89-95): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. +// Warning: (122-143): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. +// Warning: (165-183): Unused try/catch parameter. Remove or comment out the variable name to silence this warning.