From 57ada1d69e311f847b4581a0e487aebd1b0e468f Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 10 Aug 2018 15:13:12 +0200 Subject: Allow mapping arguments and return values in internal library functions. --- test/libsolidity/SolidityEndToEndTest.cpp | 156 +++++++++++++++++++++ .../types/mapping/argument_external.sol | 7 + .../types/mapping/argument_internal.sol | 7 + .../syntaxTests/types/mapping/argument_private.sol | 7 + .../syntaxTests/types/mapping/argument_public.sol | 7 + .../types/mapping/library_argument_external.sol | 6 + .../types/mapping/library_argument_internal.sol | 4 + .../types/mapping/library_argument_private.sol | 4 + .../types/mapping/library_argument_public.sol | 6 + .../types/mapping/library_return_external.sol | 10 ++ .../types/mapping/library_return_internal.sol | 6 + .../types/mapping/library_return_private.sol | 6 + .../types/mapping/library_return_public.sol | 10 ++ 13 files changed, 236 insertions(+) create mode 100644 test/libsolidity/syntaxTests/types/mapping/argument_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/argument_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/argument_private.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/argument_public.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_return_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_return_private.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_return_public.sol (limited to 'test') diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e487f0ae..cc89a307 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7961,6 +7961,162 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(4), u256(17))); } +BOOST_AUTO_TEST_CASE(mapping_arguments_in_library) +{ + char const* sourceCode = R"( + library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) internal + { + m[key] = value; + } + function get(mapping(uint => uint) storage m, uint key) internal view returns (uint) + { + return m[key]; + } + } + contract Test { + mapping(uint => uint) m; + function set(uint256 key, uint256 value) public returns (uint) + { + uint oldValue = Lib.get(m, key); + Lib.set(m, key, value); + return oldValue; + } + function get(uint256 key) public view returns (uint) { + return Lib.get(m, key); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(42)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(84)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(7)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(1), u256(21)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(2), u256(42)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("set(uint256,uint256)", u256(21), u256(14)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("get(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(uint256)", u256(1)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("get(uint256)", u256(2)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(uint256)", u256(21)), encodeArgs(u256(14))); +} + +BOOST_AUTO_TEST_CASE(mapping_returns_in_library) +{ + char const* sourceCode = R"( + library Lib { + function choose_mapping(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint=>uint) storage) + { + return c ? a : b; + } + } + contract Test { + mapping(uint => uint) a; + mapping(uint => uint) b; + function set(bool choice, uint256 key, uint256 value) public returns (uint) + { + mapping(uint => uint) storage m = Lib.choose_mapping(a, b, choice); + uint oldValue = m[key]; + m[key] = value; + return oldValue; + } + function get(bool choice, uint256 key) public view returns (uint) { + return Lib.choose_mapping(a, b, choice)[key]; + } + function get_a(uint256 key) public view returns (uint) { + return a[key]; + } + function get_b(uint256 key) public view returns (uint) { + return b[key]; + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(42)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(84)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(7)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(10)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(11)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(12)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(1), u256(21)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(2), u256(42)), encodeArgs(u256(84))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", true, u256(21), u256(14)), encodeArgs(u256(7))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(1), u256(30)), encodeArgs(u256(10))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(2), u256(31)), encodeArgs(u256(11))); + ABI_CHECK(callContractFunction("set(bool,uint256,uint256)", false, u256(21), u256(32)), encodeArgs(u256(12))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(1)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(2)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get_a(uint256)", u256(21)), encodeArgs(u256(14))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(1)), encodeArgs(u256(21))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(2)), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("get(bool,uint256)", true, u256(21)), encodeArgs(u256(14))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(1)), encodeArgs(u256(30))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(2)), encodeArgs(u256(31))); + ABI_CHECK(callContractFunction("get_b(uint256)", u256(21)), encodeArgs(u256(32))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(0)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(1)), encodeArgs(u256(30))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(2)), encodeArgs(u256(31))); + ABI_CHECK(callContractFunction("get(bool,uint256)", false, u256(21)), encodeArgs(u256(32))); +} + +BOOST_AUTO_TEST_CASE(mapping_returns_in_library_named) +{ + char const* sourceCode = R"( + library Lib { + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b) internal returns(mapping(uint=>uint) storage r) + { + r = a; + r[1] = 42; + r = b; + r[1] = 21; + } + } + contract Test { + mapping(uint => uint) a; + mapping(uint => uint) b; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.f(a, b)[2] = 84; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + function g() public returns (uint, uint, uint, uint, uint, uint) + { + mapping(uint => uint) storage m = Lib.f(a, b); + m[2] = 17; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(84))); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(17))); +} + BOOST_AUTO_TEST_CASE(using_library_structs) { char const* sourceCode = R"( diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol new file mode 100644 index 00000000..0354893f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol @@ -0,0 +1,7 @@ +contract C { + function f(mapping(uint => uint) storage) external pure { + } +} +// ---- +// TypeError: (28-49): Type is required to live outside storage. +// TypeError: (28-49): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol new file mode 100644 index 00000000..395f5808 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol @@ -0,0 +1,7 @@ +// This is expected to fail now, but may work in the future. +contract C { + function f(mapping(uint => uint) storage) internal pure { + } +} +// ---- +// TypeError: (89-110): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol new file mode 100644 index 00000000..0360514e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol @@ -0,0 +1,7 @@ +// This is expected to fail now, but may work in the future. +contract C { + function f(mapping(uint => uint) storage) private pure { + } +} +// ---- +// TypeError: (89-110): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol new file mode 100644 index 00000000..e4121c7f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol @@ -0,0 +1,7 @@ +contract C { + function f(mapping(uint => uint) storage) public pure { + } +} +// ---- +// TypeError: (28-49): Type is required to live outside storage. +// TypeError: (28-49): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol new file mode 100644 index 00000000..e78c6930 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint) storage) external pure { + } +} +// ---- +// TypeError: (27-48): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol new file mode 100644 index 00000000..1228b6b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_internal.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint) storage) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol new file mode 100644 index 00000000..5eaff16b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_private.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint) storage) private pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol new file mode 100644 index 00000000..56393b68 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint) storage) public pure { + } +} +// ---- +// TypeError: (27-48): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol new file mode 100644 index 00000000..a3bb1c32 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol @@ -0,0 +1,10 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) external pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} +// ---- +// TypeError: (27-58): Type is required to live outside storage. +// TypeError: (60-91): Type is required to live outside storage. +// TypeError: (123-144): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol new file mode 100644 index 00000000..d0fca6bf --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_internal.sol @@ -0,0 +1,6 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) internal pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol new file mode 100644 index 00000000..13c2000f --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_private.sol @@ -0,0 +1,6 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) private pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol new file mode 100644 index 00000000..ac52d677 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol @@ -0,0 +1,10 @@ +library L +{ + function f(mapping(uint => uint) storage a, mapping(uint => uint) storage b, bool c) public pure returns(mapping(uint => uint) storage) { + return c ? a : b; + } +} +// ---- +// TypeError: (27-58): Type is required to live outside storage. +// TypeError: (60-91): Type is required to live outside storage. +// TypeError: (121-142): Type is required to live outside storage. -- cgit v1.2.3 From a9f31da41146221c674356d5678030616110d471 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 10 Aug 2018 15:56:29 +0200 Subject: Allow mapping arguments and return values in all internal functions. --- test/libsolidity/SolidityEndToEndTest.cpp | 56 ++++++++++++++++++++++ .../types/mapping/argument_internal.sol | 2 - .../syntaxTests/types/mapping/argument_private.sol | 2 - .../types/mapping/mapping_return_internal.sol | 5 -- 4 files changed, 56 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index cc89a307..09e94028 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1543,6 +1543,62 @@ BOOST_AUTO_TEST_CASE(mapping_local_compound_assignment) ABI_CHECK(callContractFunction("f()"), encodeArgs(byte(42), byte(0), byte(0), byte(21))); } +BOOST_AUTO_TEST_CASE(mapping_internal_argument) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) a; + mapping(uint8 => uint8) b; + function set_internal(mapping(uint8 => uint8) storage m, uint8 key, uint8 value) internal returns (uint8) { + uint8 oldValue = m[key]; + m[key] = value; + return oldValue; + } + function set(uint8 key, uint8 value_a, uint8 value_b) public returns (uint8 old_a, uint8 old_b) { + old_a = set_internal(a, key, value_a); + old_b = set_internal(b, key, value_b); + } + function get(uint8 key) public returns (uint8, uint8) { + return (a[key], b[key]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", byte(1), byte(21), byte(42)), encodeArgs(byte(0), byte(0))); + ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(21), byte(42))); + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8)", byte(1), byte(10), byte(11)), encodeArgs(byte(21), byte(42))); + ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(10), byte(11))); +} + +BOOST_AUTO_TEST_CASE(mapping_internal_return) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) a; + mapping(uint8 => uint8) b; + function f() internal returns (mapping(uint8 => uint8) storage r) { + r = a; + r[1] = 42; + r = b; + r[1] = 84; + } + function g() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { + f()[2] = 21; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + function h() public returns (uint8, uint8, uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = f(); + m[2] = 17; + return (a[0], a[1], a[2], b[0], b[1], b[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("g()"), encodeArgs(byte(0), byte(42), byte(0), byte(0), byte(84), byte (21))); + ABI_CHECK(callContractFunction("h()"), encodeArgs(byte(0), byte(42), byte(0), byte(0), byte(84), byte (17))); +} BOOST_AUTO_TEST_CASE(structs) { diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol index 395f5808..3c021515 100644 --- a/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol +++ b/test/libsolidity/syntaxTests/types/mapping/argument_internal.sol @@ -1,7 +1,5 @@ -// This is expected to fail now, but may work in the future. contract C { function f(mapping(uint => uint) storage) internal pure { } } // ---- -// TypeError: (89-110): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol index 0360514e..63733d71 100644 --- a/test/libsolidity/syntaxTests/types/mapping/argument_private.sol +++ b/test/libsolidity/syntaxTests/types/mapping/argument_private.sol @@ -1,7 +1,5 @@ -// This is expected to fail now, but may work in the future. contract C { function f(mapping(uint => uint) storage) private pure { } } // ---- -// TypeError: (89-110): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol index a46003f8..4912836e 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol @@ -1,4 +1,3 @@ -// This should be allowed in a future release. contract C { mapping(uint=>uint) m; function f() internal view returns (mapping(uint=>uint) storage) { @@ -15,7 +14,3 @@ contract C { } } // ---- -// TypeError: (127-146): Type is required to live outside storage. -// TypeError: (221-240): Type is required to live outside storage. -// TypeError: (316-345): Type is required to live outside storage. -// TypeError: (409-438): Type is required to live outside storage. -- cgit v1.2.3 From 4ae59acc098c2ede9a2dc44e741a28df49cc59d2 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 10 Aug 2018 16:15:39 +0200 Subject: Consider mappings return values in control flow analysis. --- test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol | 5 +++++ .../libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol | 5 +++++ .../syntaxTests/controlFlow/mappingReturn/unnamed_err.sol | 5 +++++ .../syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol | 5 +++++ 4 files changed, 20 insertions(+) create mode 100644 test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol create mode 100644 test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol create mode 100644 test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol create mode 100644 test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol (limited to 'test') diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol new file mode 100644 index 00000000..35420b6d --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol @@ -0,0 +1,5 @@ +contract C { + function f() internal pure returns (mapping(uint=>uint) storage r) { } +} +// ---- +// TypeError: (53-82): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol new file mode 100644 index 00000000..4146192f --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_fine.sol @@ -0,0 +1,5 @@ +contract C { + mapping(uint=>uint) m; + function f() internal view returns (mapping(uint=>uint) storage r) { r = m; } +} +// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol new file mode 100644 index 00000000..7e8c4501 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol @@ -0,0 +1,5 @@ +contract C { + function f() internal pure returns (mapping(uint=>uint) storage) {} +} +// ---- +// TypeError: (53-72): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol new file mode 100644 index 00000000..9c5e3149 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_fine.sol @@ -0,0 +1,5 @@ +contract C { + mapping(uint=>uint) m; + function f() internal view returns (mapping(uint=>uint) storage) { return m; } +} +// ---- -- cgit v1.2.3 From 341128962f001eb78e5e3e3a83beadbef8d697b0 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 13 Aug 2018 16:25:28 +0200 Subject: Allow mappings of arrays as arguments and return values of internal functions. --- test/libsolidity/SolidityEndToEndTest.cpp | 30 ++++++++++++++++++++++ .../types/mapping/array_argument_external.sol | 6 +++++ .../types/mapping/array_argument_internal.sol | 5 ++++ .../types/mapping/array_argument_private.sol | 5 ++++ .../types/mapping/array_argument_public.sol | 6 +++++ .../mapping/library_array_argument_external.sol | 6 +++++ .../mapping/library_array_argument_internal.sol | 4 +++ .../mapping/library_array_argument_private.sol | 4 +++ .../mapping/library_array_argument_public.sol | 6 +++++ .../mapping/mapping_array_return_external.sol | 6 +++++ .../mapping/mapping_array_return_internal.sol | 16 ++++++++++++ .../types/mapping/mapping_array_return_public.sol | 6 +++++ 12 files changed, 100 insertions(+) create mode 100644 test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol (limited to 'test') diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 09e94028..a978a654 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1571,6 +1571,36 @@ BOOST_AUTO_TEST_CASE(mapping_internal_argument) ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(10), byte(11))); } +BOOST_AUTO_TEST_CASE(mapping_array_internal_argument) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8)[2] a; + mapping(uint8 => uint8)[2] b; + function set_internal(mapping(uint8 => uint8)[2] storage m, uint8 key, uint8 value1, uint8 value2) internal returns (uint8, uint8) { + uint8 oldValue1 = m[0][key]; + uint8 oldValue2 = m[1][key]; + m[0][key] = value1; + m[1][key] = value2; + return (oldValue1, oldValue2); + } + function set(uint8 key, uint8 value_a1, uint8 value_a2, uint8 value_b1, uint8 value_b2) public returns (uint8 old_a1, uint8 old_a2, uint8 old_b1, uint8 old_b2) { + (old_a1, old_a2) = set_internal(a, key, value_a1, value_a2); + (old_b1, old_b2) = set_internal(b, key, value_b1, value_b2); + } + function get(uint8 key) public returns (uint8, uint8, uint8, uint8) { + return (a[0][key], a[1][key], b[0][key], b[1][key]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", byte(1), byte(21), byte(22), byte(42), byte(43)), encodeArgs(byte(0), byte(0), byte(0), byte(0))); + ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(21), byte(22), byte(42), byte(43))); + ABI_CHECK(callContractFunction("set(uint8,uint8,uint8,uint8,uint8)", byte(1), byte(10), byte(30), byte(11), byte(31)), encodeArgs(byte(21), byte(22), byte(42), byte(43))); + ABI_CHECK(callContractFunction("get(uint8)", byte(1)), encodeArgs(byte(10), byte(30), byte(11), byte(31))); +} + BOOST_AUTO_TEST_CASE(mapping_internal_return) { char const* sourceCode = R"( diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol new file mode 100644 index 00000000..8dea6907 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol @@ -0,0 +1,6 @@ +contract C { + function f(mapping(uint => uint)[] storage) external pure { + } +} +// ---- +// TypeError: (28-51): Location has to be calldata for external functions (remove the "memory" or "storage" keyword). diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol new file mode 100644 index 00000000..352d0982 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_internal.sol @@ -0,0 +1,5 @@ +contract C { + function f(mapping(uint => uint)[] storage) internal pure { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol new file mode 100644 index 00000000..332dbe6c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_private.sol @@ -0,0 +1,5 @@ +contract C { + function f(mapping(uint => uint)[] storage) private pure { + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol new file mode 100644 index 00000000..69dcec01 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol @@ -0,0 +1,6 @@ +contract C { + function f(mapping(uint => uint)[] storage) public pure { + } +} +// ---- +// TypeError: (28-51): Location has to be memory for publicly visible functions (remove the "storage" or "calldata" keyword). diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol new file mode 100644 index 00000000..f5691675 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint)[] storage) external pure { + } +} +// ---- +// TypeError: (27-50): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol new file mode 100644 index 00000000..55c1cea0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_internal.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint)[] storage) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol new file mode 100644 index 00000000..d37d6504 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_private.sol @@ -0,0 +1,4 @@ +library L { + function f(mapping(uint => uint)[] storage) private pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol new file mode 100644 index 00000000..bb06d4bc --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol @@ -0,0 +1,6 @@ +library L { + function f(mapping(uint => uint)[] storage) public pure { + } +} +// ---- +// TypeError: (27-50): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol new file mode 100644 index 00000000..dbe030fb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_external.sol @@ -0,0 +1,6 @@ +contract C { + function f() external pure returns (mapping(uint=>uint)[] storage m) { + } +} +// ---- +// TypeError: (53-84): Location has to be memory for publicly visible functions (remove the "storage" or "calldata" keyword). diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol new file mode 100644 index 00000000..8837c745 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_internal.sol @@ -0,0 +1,16 @@ +contract C { + mapping(uint=>uint)[] m; + function f() internal view returns (mapping(uint=>uint)[] storage) { + return m; + } + function g() private view returns (mapping(uint=>uint)[] storage) { + return m; + } + function h() internal view returns (mapping(uint=>uint)[] storage r) { + r = m; + } + function i() private view returns (mapping(uint=>uint)[] storage r) { + (r,r) = (m,m); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol new file mode 100644 index 00000000..7dfecf19 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_return_public.sol @@ -0,0 +1,6 @@ +contract C { + function f() public pure returns (mapping(uint=>uint)[] storage m) { + } +} +// ---- +// TypeError: (51-82): Location has to be memory for publicly visible functions (remove the "storage" or "calldata" keyword). -- cgit v1.2.3 From dfcfc4c35bca01b6a70c1a03be3997c37ffb5d35 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 13 Aug 2018 16:29:47 +0200 Subject: Add tests for mappings in function types. --- .../syntaxTests/types/mapping/function_type_argument_external.sol | 6 ++++++ .../syntaxTests/types/mapping/function_type_argument_internal.sol | 4 ++++ .../syntaxTests/types/mapping/function_type_return_external.sol | 6 ++++++ .../syntaxTests/types/mapping/function_type_return_internal.sol | 4 ++++ 4 files changed, 20 insertions(+) create mode 100644 test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol create mode 100644 test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol (limited to 'test') diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol new file mode 100644 index 00000000..7fe74fb6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol @@ -0,0 +1,6 @@ +contract C { + function f(function(mapping(uint=>uint) storage) external) public pure { + } +} +// ---- +// TypeError: (37-56): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol new file mode 100644 index 00000000..01e2322e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_internal.sol @@ -0,0 +1,4 @@ +contract C { + function f(function(mapping(uint=>uint) storage) internal) internal pure { + } +} diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol new file mode 100644 index 00000000..f0f8dea6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol @@ -0,0 +1,6 @@ +contract C { + function f(function() external returns (mapping(uint=>uint) storage)) public pure { + } +} +// ---- +// TypeError: (57-76): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol new file mode 100644 index 00000000..bd298e5d --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_internal.sol @@ -0,0 +1,4 @@ +contract C { + function f(function() internal returns (mapping(uint=>uint) storage)) internal pure { + } +} -- cgit v1.2.3