diff --git a/TestHelper.cpp b/TestHelper.cpp index 873ea21e2..733ccb6d0 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -352,6 +352,8 @@ void ImportTest::exportTest(bytes const& _output, State const& _statePost) BOOST_CHECK_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); else BOOST_WARN_MESSAGE((m_TestObject["out"].get_str() == m_TestObject["expectOut"].get_str()), warning); + + m_TestObject.erase(m_TestObject.find("expectOut")); } // export logs diff --git a/libsolidity/SolidityNameAndTypeResolution.cpp b/libsolidity/SolidityNameAndTypeResolution.cpp index 3948a4a23..fced12848 100644 --- a/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1889,6 +1889,93 @@ BOOST_AUTO_TEST_CASE(storage_location_local_variables) BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); } +BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) +{ + char const* sourceCode = R"( + contract C { + uint[] data; + function f(uint[] x) { + var dataRef = data; + dataRef = x; + } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) +{ + char const* sourceCode = R"( + contract C { + uint[] data; + uint8[] otherData; + function f() { + uint8[] storage x = otherData; + uint[] storage y = data; + y = x; + // note that data = otherData works + } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly) +{ + char const* sourceCode = R"( + contract C { + uint[] data; + function f(uint[] x) { + data = x; + } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage) +{ + char const* sourceCode = R"( + contract C { + function f(uint[] storage x) private { + } + function g(uint[] x) { + f(x); + } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + +BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem) +{ + char const* sourceCode = R"( + contract C { + function f(uint[] storage x) private { + g(x); + } + function g(uint[] x) { + } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCode)); +} + +BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) +{ + // Such an assignment is possible in storage, but not in memory + // (because it would incur an otherwise unnecessary copy). + // This requirement might be lifted, though. + char const* sourceCode = R"( + contract C { + function f(uint8[] memory x) private { + uint[] memory y = x; + } + } + )"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/libsolidity/SolidityOptimizer.cpp b/libsolidity/SolidityOptimizer.cpp index 397ee6316..85a88c030 100644 --- a/libsolidity/SolidityOptimizer.cpp +++ b/libsolidity/SolidityOptimizer.cpp @@ -944,6 +944,14 @@ BOOST_AUTO_TEST_CASE(cse_access_previous_sequence) // 0, SLOAD, 1, ADD, SSTORE, 0 SLOAD } +BOOST_AUTO_TEST_CASE(cse_optimise_return) +{ + checkCSE( + AssemblyItems{u256(0), u256(7), Instruction::RETURN}, + AssemblyItems{Instruction::STOP} + ); +} + BOOST_AUTO_TEST_CASE(control_flow_graph_remove_unused) { // remove parts of the code that are unused