diff options
author | chriseth <chris@ethereum.org> | 2018-12-20 01:06:13 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-20 01:06:13 +0800 |
commit | 1df8f40cd2fd7b47698d847907b8ca7b47eb488d (patch) | |
tree | 5ed5816fe2d1a8a207e750d39884aca7957c8289 /test | |
parent | c8a2cb62832afb2dc09ccee6fd42c1516dfdb981 (diff) | |
parent | ddf54b21d1d002903624f61173ab4af197f50053 (diff) | |
download | dexon-solidity-1df8f40cd2fd7b47698d847907b8ca7b47eb488d.tar.gz dexon-solidity-1df8f40cd2fd7b47698d847907b8ca7b47eb488d.tar.zst dexon-solidity-1df8f40cd2fd7b47698d847907b8ca7b47eb488d.zip |
Merge pull request #5697 from ethereum/develop
Merge develop into release for 0.5.2
Diffstat (limited to 'test')
309 files changed, 3351 insertions, 682 deletions
diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h new file mode 100644 index 00000000..be076059 --- /dev/null +++ b/test/InteractiveTests.h @@ -0,0 +1,63 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <test/TestCase.h> +#include <test/libsolidity/ASTJSONTest.h> +#include <test/libsolidity/SyntaxTest.h> +#include <test/libsolidity/SMTCheckerJSONTest.h> +#include <test/libyul/YulOptimizerTest.h> +#include <test/libyul/ObjectCompilerTest.h> + +#include <boost/filesystem.hpp> + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +/** Container for all information regarding a testsuite */ +struct Testsuite +{ + char const* title; + boost::filesystem::path const path; + boost::filesystem::path const subpath; + bool smt; + bool ipc; + TestCase::TestCaseCreator testCaseCreator; +}; + + +/// Array of testsuits that can be run interactively as well as automatically +Testsuite const g_interactiveTestsuites[] = { +/* + Title Path Subpath SMT IPC Creator function */ + {"Yul Optimizer", "libyul", "yulOptimizerTests", false, false, &yul::test::YulOptimizerTest::create}, + {"Yul Object Compiler", "libyul", "objectCompiler", false, false, &yul::test::ObjectCompilerTest::create}, + {"Syntax", "libsolidity", "syntaxTests", false, false, &SyntaxTest::create}, + {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create}, + {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SyntaxTest::create}, + {"SMT Checker JSON", "libsolidity", "smtCheckerTestsJSON", true, false, &SMTCheckerTest::create} +}; + +} +} +} + diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 0aae21a7..60848118 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -296,40 +296,7 @@ void RPCSession::test_mineBlocks(int _number) { u256 startBlock = fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())); BOOST_REQUIRE(rpcCall("test_mineBlocks", { to_string(_number) }, true) == true); - - // We auto-calibrate the time it takes to mine the transaction. - // It would be better to go without polling, but that would probably need a change to the test client - - auto startTime = std::chrono::steady_clock::now(); - unsigned sleepTime = m_sleepTime; - size_t tries = 0; - for (; ; ++tries) - { - std::this_thread::sleep_for(chrono::milliseconds(sleepTime)); - auto endTime = std::chrono::steady_clock::now(); - unsigned timeSpent = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count(); - if (timeSpent > m_maxMiningTime) - BOOST_FAIL("Error in test_mineBlocks: block mining timeout!"); - if (fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) >= startBlock + _number) - break; - else - sleepTime *= 2; - } - if (tries > 1) - { - m_successfulMineRuns = 0; - m_sleepTime += 2; - } - else if (tries == 1) - { - m_successfulMineRuns++; - if (m_successfulMineRuns > 5) - { - m_successfulMineRuns = 0; - if (m_sleepTime > 2) - m_sleepTime--; - } - } + BOOST_REQUIRE(fromBigEndian<u256>(fromHex(rpcCall("eth_blockNumber").asString())) == startBlock + _number); } void RPCSession::test_modifyTimestamp(size_t _timestamp) diff --git a/test/RPCSession.h b/test/RPCSession.h index 6e1391b4..92f9da4a 100644 --- a/test/RPCSession.h +++ b/test/RPCSession.h @@ -136,9 +136,6 @@ private: IPCSocket m_ipcSocket; size_t m_rpcSequence = 1; - unsigned m_maxMiningTime = 6000000; // 600 seconds - unsigned m_sleepTime = 10; // 10 milliseconds - unsigned m_successfulMineRuns = 0; bool m_receiptHasStatusField = false; std::vector<std::string> m_accounts; diff --git a/test/TestCase.h b/test/TestCase.h index 3c05ae4e..27320009 100644 --- a/test/TestCase.h +++ b/test/TestCase.h @@ -36,7 +36,7 @@ class TestCase public: using TestCaseCreator = std::unique_ptr<TestCase>(*)(std::string const&); - virtual ~TestCase() {} + virtual ~TestCase() = default; /// Runs the test case. /// Outputs error messages to @arg _stream. Each line of output is prefixed with @arg _linePrefix. diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 7cb0c143..d6e75cb9 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -35,15 +35,13 @@ #pragma GCC diagnostic pop +#include <test/InteractiveTests.h> #include <test/Options.h> -#include <test/libsolidity/ASTJSONTest.h> -#include <test/libsolidity/SyntaxTest.h> -#include <test/libsolidity/SMTCheckerJSONTest.h> -#include <test/libyul/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/predicate.hpp> #include <boost/filesystem.hpp> +#include <string> using namespace boost::unit_test; using namespace dev::solidity::test; @@ -128,40 +126,26 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) master_test_suite_t& master = framework::master_test_suite(); master.p_name.value = "SolidityTests"; dev::test::Options::get().validate(); - solAssert(registerTests( - master, - dev::test::Options::get().testPath / "libsolidity", - "syntaxTests", - SyntaxTest::create - ) > 0, "no syntax tests found"); - solAssert(registerTests( - master, - dev::test::Options::get().testPath / "libsolidity", - "ASTJSON", - ASTJSONTest::create - ) > 0, "no JSON AST tests found"); - solAssert(registerTests( - master, - dev::test::Options::get().testPath / "libyul", - "yulOptimizerTests", - yul::test::YulOptimizerTest::create - ) > 0, "no Yul Optimizer tests found"); - if (!dev::test::Options::get().disableSMT) + + // Include the interactive tests in the automatic tests as well + for (auto const& ts: g_interactiveTestsuites) { - solAssert(registerTests( - master, - dev::test::Options::get().testPath / "libsolidity", - "smtCheckerTests", - SyntaxTest::create - ) > 0, "no SMT checker tests found"); + auto const& options = dev::test::Options::get(); + + if (ts.smt && options.disableSMT) + continue; + + if (ts.ipc && options.disableIPC) + continue; solAssert(registerTests( master, - dev::test::Options::get().testPath / "libsolidity", - "smtCheckerTestsJSON", - SMTCheckerTest::create - ) > 0, "no SMT checker JSON tests found"); + options.testPath / ts.path, + ts.subpath, + ts.testCaseCreator + ) > 0, std::string("no ") + ts.title + " tests found"); } + if (dev::test::Options::get().disableIPC) { for (auto suite: { @@ -176,11 +160,13 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "LLLEndToEndTest", #endif "GasMeterTests", + "GasCostTests", "SolidityEndToEndTest", "SolidityOptimizer" }) removeTestSuite(suite); } + if (dev::test::Options::get().disableSMT) removeTestSuite("SMTChecker"); diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index fdc9fbe3..9d2ffa5f 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -110,30 +110,42 @@ printTask "Testing unknown options..." # General helper function for testing SOLC behaviour, based on file name, compile opts, exit code, stdout and stderr. # An failure is expected. -test_solc_file_input_failures() { +test_solc_behaviour() { local filename="${1}" local solc_args="${2}" - local stdout_expected="${3}" - local stderr_expected="${4}" + local solc_stdin="${3}" + local stdout_expected="${4}" + local exit_code_expected="${5}" + local stderr_expected="${6}" local stdout_path=`mktemp` local stderr_path=`mktemp` + if [[ "$exit_code_expected" = "" ]]; then exit_code_expected="0"; fi set +e - "$SOLC" "${filename}" ${solc_args} 1>$stdout_path 2>$stderr_path + if [[ "$solc_stdin" = "" ]]; then + "$SOLC" "${filename}" ${solc_args} 1>$stdout_path 2>$stderr_path + else + "$SOLC" "${filename}" ${solc_args} <$solc_stdin 1>$stdout_path 2>$stderr_path + fi exitCode=$? set -e - sed -i -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path" - sed -i -e 's/ Consider adding "pragma .*$//' "$stderr_path" + if [[ "$solc_args" == *"--standard-json"* ]]; then + sed -i -e 's/{[^{]*Warning: This is a pre-release compiler version[^}]*},\{0,1\}//' "$stdout_path" + sed -i -e 's/"errors":\[\],\{0,1\}//' "$stdout_path" + else + sed -i -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path" + sed -i -e 's/ Consider adding "pragma .*$//' "$stderr_path" + fi - if [[ $exitCode -eq 0 ]]; then - printError "Incorrect exit code. Expected failure (non-zero) but got success (0)." + if [[ $exitCode -ne "$exit_code_expected" ]]; then + printError "Incorrect exit code. Expected $exit_code_expected but got $exitCode." rm -f $stdout_path $stderr_path exit 1 fi if [[ "$(cat $stdout_path)" != "${stdout_expected}" ]]; then - printError "Incorrect output on stderr received. Expected:" + printError "Incorrect output on stdout received. Expected:" echo -e "${stdout_expected}" printError "But got:" @@ -156,22 +168,41 @@ test_solc_file_input_failures() { } printTask "Testing passing files that are not found..." -test_solc_file_input_failures "file_not_found.sol" "" "" "\"file_not_found.sol\" is not found." +test_solc_behaviour "file_not_found.sol" "" "" "" 1 "\"file_not_found.sol\" is not found." printTask "Testing passing files that are not files..." -test_solc_file_input_failures "." "" "" "\".\" is not a valid file." +test_solc_behaviour "." "" "" "" 1 "\".\" is not a valid file." printTask "Testing passing empty remappings..." -test_solc_file_input_failures "${0}" "=/some/remapping/target" "" "Invalid remapping: \"=/some/remapping/target\"." -test_solc_file_input_failures "${0}" "ctx:=/some/remapping/target" "" "Invalid remapping: \"ctx:=/some/remapping/target\"." +test_solc_behaviour "${0}" "=/some/remapping/target" "" "" 1 "Invalid remapping: \"=/some/remapping/target\"." +test_solc_behaviour "${0}" "ctx:=/some/remapping/target" "" "" 1 "Invalid remapping: \"ctx:=/some/remapping/target\"." + +printTask "Running standard JSON commandline tests..." +( +cd "$REPO_ROOT"/test/cmdlineTests/ +for file in *.json +do + args="--standard-json" + stdin="$REPO_ROOT/test/cmdlineTests/$file" + stdout=$(cat $file.stdout 2>/dev/null || true) + exitCode=$(cat $file.exit 2>/dev/null || true) + err=$(cat $file.err 2>/dev/null || true) + printTask " - $file" + test_solc_behaviour "" "$args" "$stdin" "$stdout" "$exitCode" "$err" +done +) -printTask "Testing passing location printing..." +printTask "Running general commandline tests..." ( -cd "$REPO_ROOT"/test/cmdlineErrorReports/ +cd "$REPO_ROOT"/test/cmdlineTests/ for file in *.sol do - ret=`cat $file.ref` - test_solc_file_input_failures "$file" "" "" "$ret" + args=$(cat $file.args 2>/dev/null || true) + stdout=$(cat $file.stdout 2>/dev/null || true) + exitCode=$(cat $file.exit 2>/dev/null || true) + err=$(cat $file.err 2>/dev/null || true) + printTask " - $file" + test_solc_behaviour "$file" "$args" "" "$stdout" "$exitCode" "$err" done ) diff --git a/test/cmdlineTests/data_storage.sol b/test/cmdlineTests/data_storage.sol new file mode 100644 index 00000000..cc602cc9 --- /dev/null +++ b/test/cmdlineTests/data_storage.sol @@ -0,0 +1,15 @@ +pragma solidity >=0.0; + +contract C { + function f() pure public { + require(false, "1234567890123456789012345678901"); + require(false, "12345678901234567890123456789012"); + require(false, "123456789012345678901234567890123"); + require(false, "1234567890123456789012345678901234"); + require(false, "12345678901234567890123456789012345"); + require(false, "123456789012345678901234567890123456"); + require(false, "123456789012345678901234567890121234567890123456789012345678901"); + require(false, "1234567890123456789012345678901212345678901234567890123456789012"); + require(false, "12345678901234567890123456789012123456789012345678901234567890123"); + } +} diff --git a/test/cmdlineTests/data_storage.sol.args b/test/cmdlineTests/data_storage.sol.args new file mode 100644 index 00000000..3684987e --- /dev/null +++ b/test/cmdlineTests/data_storage.sol.args @@ -0,0 +1 @@ +--gas diff --git a/test/cmdlineTests/data_storage.sol.stdout b/test/cmdlineTests/data_storage.sol.stdout new file mode 100644 index 00000000..4a5250f7 --- /dev/null +++ b/test/cmdlineTests/data_storage.sol.stdout @@ -0,0 +1,7 @@ + +======= data_storage.sol:C ======= +Gas estimation: +construction: + 306 + 264400 = 264706 +external: + f(): 263 diff --git a/test/cmdlineTests/gas_test_dispatch.sol b/test/cmdlineTests/gas_test_dispatch.sol new file mode 100644 index 00000000..a5ca9e7d --- /dev/null +++ b/test/cmdlineTests/gas_test_dispatch.sol @@ -0,0 +1,43 @@ +pragma solidity >=0.0; + +contract Large { + uint public a; + uint[] public b; + function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function f2(uint x) public returns (uint) { b[uint8(msg.data[1])] = x; } + function f3(uint x) public returns (uint) { b[uint8(msg.data[2])] = x; } + function f4(uint x) public returns (uint) { b[uint8(msg.data[3])] = x; } + function f5(uint x) public returns (uint) { b[uint8(msg.data[4])] = x; } + function f6(uint x) public returns (uint) { b[uint8(msg.data[5])] = x; } + function f7(uint x) public returns (uint) { b[uint8(msg.data[6])] = x; } + function f8(uint x) public returns (uint) { b[uint8(msg.data[7])] = x; } + function f9(uint x) public returns (uint) { b[uint8(msg.data[8])] = x; } + function f0(uint x) public pure returns (uint) { require(x > 10); } + function g1(uint x) public payable returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function g2(uint x) public payable returns (uint) { b[uint8(msg.data[1])] = x; } + function g3(uint x) public payable returns (uint) { b[uint8(msg.data[2])] = x; } + function g4(uint x) public payable returns (uint) { b[uint8(msg.data[3])] = x; } + function g5(uint x) public payable returns (uint) { b[uint8(msg.data[4])] = x; } + function g6(uint x) public payable returns (uint) { b[uint8(msg.data[5])] = x; } + function g7(uint x) public payable returns (uint) { b[uint8(msg.data[6])] = x; } + function g8(uint x) public payable returns (uint) { b[uint8(msg.data[7])] = x; } + function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } + function g0(uint x) public payable returns (uint) { require(x > 10); } +} +contract Medium { + uint public a; + uint[] public b; + function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function f2(uint x) public returns (uint) { b[uint8(msg.data[1])] = x; } + function f3(uint x) public returns (uint) { b[uint8(msg.data[2])] = x; } + function g7(uint x) public payable returns (uint) { b[uint8(msg.data[6])] = x; } + function g8(uint x) public payable returns (uint) { b[uint8(msg.data[7])] = x; } + function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } + function g0(uint x) public payable returns (uint) { require(x > 10); } +} +contract Small { + uint public a; + uint[] public b; + function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function () external payable {} +} diff --git a/test/cmdlineTests/gas_test_dispatch.sol.args b/test/cmdlineTests/gas_test_dispatch.sol.args new file mode 100644 index 00000000..3684987e --- /dev/null +++ b/test/cmdlineTests/gas_test_dispatch.sol.args @@ -0,0 +1 @@ +--gas diff --git a/test/cmdlineTests/gas_test_dispatch.sol.stdout b/test/cmdlineTests/gas_test_dispatch.sol.stdout new file mode 100644 index 00000000..117affad --- /dev/null +++ b/test/cmdlineTests/gas_test_dispatch.sol.stdout @@ -0,0 +1,53 @@ + +======= gas_test_dispatch.sol:Large ======= +Gas estimation: +construction: + 1034 + 998400 = 999434 +external: + a(): 456 + b(uint256): 857 + f0(uint256): 438 + f1(uint256): 40781 + f2(uint256): 20722 + f3(uint256): 20810 + f4(uint256): 20788 + f5(uint256): 20766 + f6(uint256): 20789 + f7(uint256): 20701 + f8(uint256): 20701 + f9(uint256): 20723 + g0(uint256): 324 + g1(uint256): 40736 + g2(uint256): 20699 + g3(uint256): 20787 + g4(uint256): 20765 + g5(uint256): 20721 + g6(uint256): 20744 + g7(uint256): 20743 + g8(uint256): 20721 + g9(uint256): 20678 + +======= gas_test_dispatch.sol:Medium ======= +Gas estimation: +construction: + 411 + 376600 = 377011 +external: + a(): 433 + b(uint256): 857 + f1(uint256): 40692 + f2(uint256): 20722 + f3(uint256): 20766 + g0(uint256): 324 + g7(uint256): 20721 + g8(uint256): 20699 + g9(uint256): 20655 + +======= gas_test_dispatch.sol:Small ======= +Gas estimation: +construction: + 153 + 107800 = 107953 +external: + fallback: 123 + a(): 388 + b(uint256): 813 + f1(uint256): 40692 diff --git a/test/cmdlineTests/gas_test_dispatch_optimize.sol b/test/cmdlineTests/gas_test_dispatch_optimize.sol new file mode 100644 index 00000000..a5ca9e7d --- /dev/null +++ b/test/cmdlineTests/gas_test_dispatch_optimize.sol @@ -0,0 +1,43 @@ +pragma solidity >=0.0; + +contract Large { + uint public a; + uint[] public b; + function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function f2(uint x) public returns (uint) { b[uint8(msg.data[1])] = x; } + function f3(uint x) public returns (uint) { b[uint8(msg.data[2])] = x; } + function f4(uint x) public returns (uint) { b[uint8(msg.data[3])] = x; } + function f5(uint x) public returns (uint) { b[uint8(msg.data[4])] = x; } + function f6(uint x) public returns (uint) { b[uint8(msg.data[5])] = x; } + function f7(uint x) public returns (uint) { b[uint8(msg.data[6])] = x; } + function f8(uint x) public returns (uint) { b[uint8(msg.data[7])] = x; } + function f9(uint x) public returns (uint) { b[uint8(msg.data[8])] = x; } + function f0(uint x) public pure returns (uint) { require(x > 10); } + function g1(uint x) public payable returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function g2(uint x) public payable returns (uint) { b[uint8(msg.data[1])] = x; } + function g3(uint x) public payable returns (uint) { b[uint8(msg.data[2])] = x; } + function g4(uint x) public payable returns (uint) { b[uint8(msg.data[3])] = x; } + function g5(uint x) public payable returns (uint) { b[uint8(msg.data[4])] = x; } + function g6(uint x) public payable returns (uint) { b[uint8(msg.data[5])] = x; } + function g7(uint x) public payable returns (uint) { b[uint8(msg.data[6])] = x; } + function g8(uint x) public payable returns (uint) { b[uint8(msg.data[7])] = x; } + function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } + function g0(uint x) public payable returns (uint) { require(x > 10); } +} +contract Medium { + uint public a; + uint[] public b; + function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function f2(uint x) public returns (uint) { b[uint8(msg.data[1])] = x; } + function f3(uint x) public returns (uint) { b[uint8(msg.data[2])] = x; } + function g7(uint x) public payable returns (uint) { b[uint8(msg.data[6])] = x; } + function g8(uint x) public payable returns (uint) { b[uint8(msg.data[7])] = x; } + function g9(uint x) public payable returns (uint) { b[uint8(msg.data[8])] = x; } + function g0(uint x) public payable returns (uint) { require(x > 10); } +} +contract Small { + uint public a; + uint[] public b; + function f1(uint x) public returns (uint) { a = x; b[uint8(msg.data[0])] = x; } + function () external payable {} +} diff --git a/test/cmdlineTests/gas_test_dispatch_optimize.sol.args b/test/cmdlineTests/gas_test_dispatch_optimize.sol.args new file mode 100644 index 00000000..814e0591 --- /dev/null +++ b/test/cmdlineTests/gas_test_dispatch_optimize.sol.args @@ -0,0 +1 @@ +--optimize --optimize-runs 2 --gas diff --git a/test/cmdlineTests/gas_test_dispatch_optimize.sol.stdout b/test/cmdlineTests/gas_test_dispatch_optimize.sol.stdout new file mode 100644 index 00000000..76fa086e --- /dev/null +++ b/test/cmdlineTests/gas_test_dispatch_optimize.sol.stdout @@ -0,0 +1,53 @@ + +======= gas_test_dispatch_optimize.sol:Large ======= +Gas estimation: +construction: + 300 + 262000 = 262300 +external: + a(): 463 + b(uint256): 1173 + f0(uint256): 399 + f1(uint256): 41164 + f2(uint256): 21224 + f3(uint256): 21312 + f4(uint256): 21290 + f5(uint256): 21268 + f6(uint256): 21180 + f7(uint256): 20960 + f8(uint256): 21092 + f9(uint256): 21114 + g0(uint256): 639 + g1(uint256): 40876 + g2(uint256): 20958 + g3(uint256): 21046 + g4(uint256): 21024 + g5(uint256): 21112 + g6(uint256): 20892 + g7(uint256): 21002 + g8(uint256): 20980 + g9(uint256): 20826 + +======= gas_test_dispatch_optimize.sol:Medium ======= +Gas estimation: +construction: + 190 + 143000 = 143190 +external: + a(): 463 + b(uint256): 931 + f1(uint256): 40944 + f2(uint256): 20982 + f3(uint256): 21026 + g0(uint256): 397 + g7(uint256): 20892 + g8(uint256): 20870 + g9(uint256): 20826 + +======= gas_test_dispatch_optimize.sol:Small ======= +Gas estimation: +construction: + 117 + 67400 = 67517 +external: + fallback: 183 + a(): 441 + b(uint256): 821 + f1(uint256): 40878 diff --git a/test/cmdlineTests/standard.json b/test/cmdlineTests/standard.json new file mode 100644 index 00000000..826253b8 --- /dev/null +++ b/test/cmdlineTests/standard.json @@ -0,0 +1,10 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard.json.exit b/test/cmdlineTests/standard.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard.json.stdout b/test/cmdlineTests/standard.json.stdout new file mode 100644 index 00000000..59b90c8c --- /dev/null +++ b/test/cmdlineTests/standard.json.stdout @@ -0,0 +1 @@ +{"sources":{"A":{"id":0}}} diff --git a/test/cmdlineTests/standard_binaries_requested.json b/test/cmdlineTests/standard_binaries_requested.json new file mode 100644 index 00000000..65f19543 --- /dev/null +++ b/test/cmdlineTests/standard_binaries_requested.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["evm.gasEstimates"] } + } + } +} diff --git a/test/cmdlineTests/standard_binaries_requested.json.stdout b/test/cmdlineTests/standard_binaries_requested.json.stdout new file mode 100644 index 00000000..2baef22a --- /dev/null +++ b/test/cmdlineTests/standard_binaries_requested.json.stdout @@ -0,0 +1 @@ +{"contracts":{"A":{"C":{"evm":{"gasEstimates":{"creation":{"codeDepositCost":"25600","executionCost":"75","totalCost":"25675"},"external":{"f()":"127"}}}}}},"sources":{"A":{"id":0}}}
\ No newline at end of file diff --git a/test/cmdlineTests/standard_methodIdentifiersRequested.json b/test/cmdlineTests/standard_methodIdentifiersRequested.json new file mode 100644 index 00000000..79a3c75d --- /dev/null +++ b/test/cmdlineTests/standard_methodIdentifiersRequested.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["evm.methodIdentifiers"] } + } + } +} diff --git a/test/cmdlineTests/standard_methodIdentifiersRequested.json.stdout b/test/cmdlineTests/standard_methodIdentifiersRequested.json.stdout new file mode 100644 index 00000000..7e3f139f --- /dev/null +++ b/test/cmdlineTests/standard_methodIdentifiersRequested.json.stdout @@ -0,0 +1 @@ +{"contracts":{"A":{"C":{"evm":{"methodIdentifiers":{"f()":"26121ff0"}}}}},"sources":{"A":{"id":0}}} diff --git a/test/cmdlineTests/standard_only_ast_requested.json b/test/cmdlineTests/standard_only_ast_requested.json new file mode 100644 index 00000000..7abd6da5 --- /dev/null +++ b/test/cmdlineTests/standard_only_ast_requested.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "": ["ast"] } + } + } +} diff --git a/test/cmdlineTests/standard_only_ast_requested.json.stdout b/test/cmdlineTests/standard_only_ast_requested.json.stdout new file mode 100644 index 00000000..b884ab7d --- /dev/null +++ b/test/cmdlineTests/standard_only_ast_requested.json.stdout @@ -0,0 +1 @@ +{"sources":{"A":{"ast":{"absolutePath":"A","exportedSymbols":{"C":[6]},"id":7,"nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"0:22:0"},{"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":6,"linearizedBaseContracts":[6],"name":"C","nodeType":"ContractDefinition","nodes":[{"body":{"id":4,"nodeType":"Block","src":"61:2:0","statements":[]},"documentation":null,"id":5,"implemented":true,"kind":"function","modifiers":[],"name":"f","nodeType":"FunctionDefinition","parameters":{"id":2,"nodeType":"ParameterList","parameters":[],"src":"46:2:0"},"returnParameters":{"id":3,"nodeType":"ParameterList","parameters":[],"src":"61:0:0"},"scope":6,"src":"36:27:0","stateMutability":"pure","superFunction":null,"visibility":"public"}],"scope":7,"src":"23:42:0"}],"src":"0:65:0"},"id":0}}} diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input.json b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json new file mode 100644 index 00000000..51dbce41 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json @@ -0,0 +1,14 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "auxiliaryInput": + { + "key1": "test" + } +} diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_auxiliary_input.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_metadata.json b/test/cmdlineTests/standard_wrong_key_metadata.json new file mode 100644 index 00000000..490e489a --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_metadata.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { + "key1": "test", + "useLiteralContent": true + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_metadata.json.exit b/test/cmdlineTests/standard_wrong_key_metadata.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_metadata.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_metadata.json.stdout b/test/cmdlineTests/standard_wrong_key_metadata.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_metadata.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_optimizer.json b/test/cmdlineTests/standard_wrong_key_optimizer.json new file mode 100644 index 00000000..c28c3a92 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_optimizer.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "optimizer": { + "key1": "test", + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_optimizer.json.exit b/test/cmdlineTests/standard_wrong_key_optimizer.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_optimizer.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_optimizer.json.stdout b/test/cmdlineTests/standard_wrong_key_optimizer.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_optimizer.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_root.json b/test/cmdlineTests/standard_wrong_key_root.json new file mode 100644 index 00000000..4689c50c --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_root.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "key1": "test", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_root.json.exit b/test/cmdlineTests/standard_wrong_key_root.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_root.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_root.json.stdout b/test/cmdlineTests/standard_wrong_key_root.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_root.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_settings.json b/test/cmdlineTests/standard_wrong_key_settings.json new file mode 100644 index 00000000..d7809b1c --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_settings.json @@ -0,0 +1,22 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { + "useLiteralContent": true + }, + "key1": "test" + } +} diff --git a/test/cmdlineTests/standard_wrong_key_settings.json.exit b/test/cmdlineTests/standard_wrong_key_settings.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_settings.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_settings.json.stdout b/test/cmdlineTests/standard_wrong_key_settings.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_settings.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_key_source.json b/test/cmdlineTests/standard_wrong_key_source.json new file mode 100644 index 00000000..d8a8aa16 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_source.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "key1": "test", + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard_wrong_key_source.json.exit b/test/cmdlineTests/standard_wrong_key_source.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_source.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_key_source.json.stdout b/test/cmdlineTests/standard_wrong_key_source.json.stdout new file mode 100644 index 00000000..077ac47e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_key_source.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Unknown key \"key1\"","message":"Unknown key \"key1\"","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input.json b/test/cmdlineTests/standard_wrong_type_auxiliary_input.json new file mode 100644 index 00000000..8d2c7593 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "auxiliaryInput": [1, 2, 3] +} diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input.json.exit b/test/cmdlineTests/standard_wrong_type_auxiliary_input.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input.json.stdout b/test/cmdlineTests/standard_wrong_type_auxiliary_input.json.stdout new file mode 100644 index 00000000..046cb6d9 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input.json.stdout @@ -0,0 +1,2 @@ +{"errors":[{"component":"general","formattedMessage":"\"auxiliaryInput\" must be an object","message":"\"auxiliaryInput\" must be an object","severity":"error","type":"JSONError"}]} + diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json new file mode 100644 index 00000000..9175050f --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json @@ -0,0 +1,20 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "evm.legacyAssembly", "metadata" ], + "": [ "legacyAST" ] + } + } + }, + "auxiliaryInput": + { + "smtlib2responses": "not an object" + } +} diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json.exit b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json.stdout b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json.stdout new file mode 100644 index 00000000..3efaea20 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"auxiliaryInput.smtlib2responses\" must be an object.","message":"\"auxiliaryInput.smtlib2responses\" must be an object.","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json new file mode 100644 index 00000000..aa7d451b --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json @@ -0,0 +1,23 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "evm.legacyAssembly", "metadata" ], + "": [ "legacyAST" ] + } + } + }, + "auxiliaryInput": + { + "smtlib2responses": + { + "abc": ["not a string"] + } + } +} diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json.exit b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json.stdout b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json.stdout new file mode 100644 index 00000000..a05176be --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_auxiliary_input_smtlib2responses_member.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"smtlib2Responses.abc\" must be a string.","message":"\"smtlib2Responses.abc\" must be a string.","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_metadata.json b/test/cmdlineTests/standard_wrong_type_metadata.json new file mode 100644 index 00000000..d4dd06a1 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_metadata.json @@ -0,0 +1,19 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": ["meta1", "meta2", "meta3"] + } +} diff --git a/test/cmdlineTests/standard_wrong_type_metadata.json.exit b/test/cmdlineTests/standard_wrong_type_metadata.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_metadata.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_metadata.json.stdout b/test/cmdlineTests/standard_wrong_type_metadata.json.stdout new file mode 100644 index 00000000..7b997cec --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_metadata.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.metadata\" must be an object","message":"\"settings.metadata\" must be an object","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_optimizer.json b/test/cmdlineTests/standard_wrong_type_optimizer.json new file mode 100644 index 00000000..b42ca550 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_optimizer.json @@ -0,0 +1,18 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + { + "optimizer": 1, + "evmVersion": "byzantium", + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/test/cmdlineTests/standard_wrong_type_optimizer.json.exit b/test/cmdlineTests/standard_wrong_type_optimizer.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_optimizer.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_optimizer.json.stdout b/test/cmdlineTests/standard_wrong_type_optimizer.json.stdout new file mode 100644 index 00000000..d43b6470 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_optimizer.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.optimizer\" must be an object","message":"\"settings.optimizer\" must be an object","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection.json b/test/cmdlineTests/standard_wrong_type_output_selection.json new file mode 100644 index 00000000..a7b615d1 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection.json @@ -0,0 +1,11 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": "not an object" + } +} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection.json.exit b/test/cmdlineTests/standard_wrong_type_output_selection.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_output_selection.json.stdout b/test/cmdlineTests/standard_wrong_type_output_selection.json.stdout new file mode 100644 index 00000000..39e74882 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.outputSelection\" must be an object","message":"\"settings.outputSelection\" must be an object","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_contract.json b/test/cmdlineTests/standard_wrong_type_output_selection_contract.json new file mode 100644 index 00000000..9840a97e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_contract.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": "it's a contract, but not an array!", + "": [ "legacyAST" ] + } + } + } +} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_contract.json.exit b/test/cmdlineTests/standard_wrong_type_output_selection_contract.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_contract.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_contract.json.stdout b/test/cmdlineTests/standard_wrong_type_output_selection_contract.json.stdout new file mode 100644 index 00000000..a4ba320e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_contract.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.outputSelection.fileA.A\" must be a string array","message":"\"settings.outputSelection.fileA.A\" must be a string array","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_file.json b/test/cmdlineTests/standard_wrong_type_output_selection_file.json new file mode 100644 index 00000000..7ab12ba8 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_file.json @@ -0,0 +1,13 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": "awesome file!" + } + } +} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_file.json.exit b/test/cmdlineTests/standard_wrong_type_output_selection_file.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_file.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_file.json.stdout b/test/cmdlineTests/standard_wrong_type_output_selection_file.json.stdout new file mode 100644 index 00000000..8874e636 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_file.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.outputSelection.fileA\" must be an object","message":"\"settings.outputSelection.fileA\" must be an object","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_output.json b/test/cmdlineTests/standard_wrong_type_output_selection_output.json new file mode 100644 index 00000000..3e5cd661 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_output.json @@ -0,0 +1,16 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": [ 1, 2, 3 ,4], + "": [ "legacyAST" ] + } + } + } +} diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_output.json.exit b/test/cmdlineTests/standard_wrong_type_output_selection_output.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_output.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_output_selection_output.json.stdout b/test/cmdlineTests/standard_wrong_type_output_selection_output.json.stdout new file mode 100644 index 00000000..a4ba320e --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_output_selection_output.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.outputSelection.fileA.A\" must be a string array","message":"\"settings.outputSelection.fileA.A\" must be a string array","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_remappings.json b/test/cmdlineTests/standard_wrong_type_remappings.json new file mode 100644 index 00000000..1436e014 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_remappings.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "evm.legacyAssembly", "metadata" ], + "": [ "legacyAST" ] + } + }, + "remappings": "not an object" + } +} diff --git a/test/cmdlineTests/standard_wrong_type_remappings.json.exit b/test/cmdlineTests/standard_wrong_type_remappings.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_remappings.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_remappings.json.stdout b/test/cmdlineTests/standard_wrong_type_remappings.json.stdout new file mode 100644 index 00000000..b5e4ea5c --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_remappings.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.remappings\" must be an array of strings.","message":"\"settings.remappings\" must be an array of strings.","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_remappings_entry.json b/test/cmdlineTests/standard_wrong_type_remappings_entry.json new file mode 100644 index 00000000..c96611f3 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_remappings_entry.json @@ -0,0 +1,17 @@ +{ + "language": "Solidity", + "sources": { + "fileA": { + "content": "contract A { }" + } + }, + "settings": { + "outputSelection": { + "fileA": { + "A": [ "abi", "devdoc", "userdoc", "evm.bytecode", "evm.assembly", "evm.gasEstimates", "evm.legacyAssembly", "metadata" ], + "": [ "legacyAST" ] + } + }, + "remappings": [1, 2 ,3 ,4] + } +} diff --git a/test/cmdlineTests/standard_wrong_type_remappings_entry.json.exit b/test/cmdlineTests/standard_wrong_type_remappings_entry.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_remappings_entry.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_remappings_entry.json.stdout b/test/cmdlineTests/standard_wrong_type_remappings_entry.json.stdout new file mode 100644 index 00000000..0fc71ded --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_remappings_entry.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings.remappings\" must be an array of strings","message":"\"settings.remappings\" must be an array of strings","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_root.json b/test/cmdlineTests/standard_wrong_type_root.json new file mode 100644 index 00000000..4763607a --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_root.json @@ -0,0 +1 @@ +["abc"] diff --git a/test/cmdlineTests/standard_wrong_type_root.json.exit b/test/cmdlineTests/standard_wrong_type_root.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_root.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_root.json.stdout b/test/cmdlineTests/standard_wrong_type_root.json.stdout new file mode 100644 index 00000000..15c12e77 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_root.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"Input is not a JSON object.","message":"Input is not a JSON object.","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_settings.json b/test/cmdlineTests/standard_wrong_type_settings.json new file mode 100644 index 00000000..7cdb0881 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_settings.json @@ -0,0 +1,23 @@ +{ + "language": "Solidity", + "sources": + { + "A": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + }, + "settings": + [ + { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "byzantium", + "metadata": { + "useLiteralContent": true + } + } + ] +} diff --git a/test/cmdlineTests/standard_wrong_type_settings.json.exit b/test/cmdlineTests/standard_wrong_type_settings.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_settings.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_settings.json.stdout b/test/cmdlineTests/standard_wrong_type_settings.json.stdout new file mode 100644 index 00000000..c78c6086 --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_settings.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"settings\" must be an object","message":"\"settings\" must be an object","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_source.json b/test/cmdlineTests/standard_wrong_type_source.json new file mode 100644 index 00000000..d58504fe --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_source.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": + { + "A": "not an object :o", + "B": [1, 2, 3], + "C": + { + "content": "pragma solidity >=0.0; contract C { function f() public pure {} }" + } + } +} diff --git a/test/cmdlineTests/standard_wrong_type_source.json.exit b/test/cmdlineTests/standard_wrong_type_source.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_source.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_source.json.stdout b/test/cmdlineTests/standard_wrong_type_source.json.stdout new file mode 100644 index 00000000..98fe32fd --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_source.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"sources.A\" must be an object","message":"\"sources.A\" must be an object","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineTests/standard_wrong_type_sources.json b/test/cmdlineTests/standard_wrong_type_sources.json new file mode 100644 index 00000000..76e1ae7d --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_sources.json @@ -0,0 +1,4 @@ +{ + "language": "Solidity", + "sources": ["source1", "source2", "source3"] +} diff --git a/test/cmdlineTests/standard_wrong_type_sources.json.exit b/test/cmdlineTests/standard_wrong_type_sources.json.exit new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_sources.json.exit @@ -0,0 +1 @@ +0 diff --git a/test/cmdlineTests/standard_wrong_type_sources.json.stdout b/test/cmdlineTests/standard_wrong_type_sources.json.stdout new file mode 100644 index 00000000..ac6c613f --- /dev/null +++ b/test/cmdlineTests/standard_wrong_type_sources.json.stdout @@ -0,0 +1 @@ +{"errors":[{"component":"general","formattedMessage":"\"sources\" is not a JSON object.","message":"\"sources\" is not a JSON object.","severity":"error","type":"JSONError"}]} diff --git a/test/cmdlineErrorReports/too_long_line.sol b/test/cmdlineTests/too_long_line.sol index 7df1057a..7df1057a 100644 --- a/test/cmdlineErrorReports/too_long_line.sol +++ b/test/cmdlineTests/too_long_line.sol diff --git a/test/cmdlineErrorReports/too_long_line.sol.ref b/test/cmdlineTests/too_long_line.sol.err index 55cd1935..55cd1935 100644 --- a/test/cmdlineErrorReports/too_long_line.sol.ref +++ b/test/cmdlineTests/too_long_line.sol.err diff --git a/test/cmdlineTests/too_long_line.sol.exit b/test/cmdlineTests/too_long_line.sol.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/cmdlineTests/too_long_line.sol.exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineErrorReports/too_long_line_both_sides_short.sol b/test/cmdlineTests/too_long_line_both_sides_short.sol index 062f0292..062f0292 100644 --- a/test/cmdlineErrorReports/too_long_line_both_sides_short.sol +++ b/test/cmdlineTests/too_long_line_both_sides_short.sol diff --git a/test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref b/test/cmdlineTests/too_long_line_both_sides_short.sol.err index 9a5ebfba..9a5ebfba 100644 --- a/test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref +++ b/test/cmdlineTests/too_long_line_both_sides_short.sol.err diff --git a/test/cmdlineTests/too_long_line_both_sides_short.sol.exit b/test/cmdlineTests/too_long_line_both_sides_short.sol.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/cmdlineTests/too_long_line_both_sides_short.sol.exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineErrorReports/too_long_line_edge_in.sol b/test/cmdlineTests/too_long_line_edge_in.sol index 6f181c83..6f181c83 100644 --- a/test/cmdlineErrorReports/too_long_line_edge_in.sol +++ b/test/cmdlineTests/too_long_line_edge_in.sol diff --git a/test/cmdlineErrorReports/too_long_line_edge_in.sol.ref b/test/cmdlineTests/too_long_line_edge_in.sol.err index ad3b7805..ad3b7805 100644 --- a/test/cmdlineErrorReports/too_long_line_edge_in.sol.ref +++ b/test/cmdlineTests/too_long_line_edge_in.sol.err diff --git a/test/cmdlineTests/too_long_line_edge_in.sol.exit b/test/cmdlineTests/too_long_line_edge_in.sol.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/cmdlineTests/too_long_line_edge_in.sol.exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineErrorReports/too_long_line_edge_out.sol b/test/cmdlineTests/too_long_line_edge_out.sol index 29d3cee6..29d3cee6 100644 --- a/test/cmdlineErrorReports/too_long_line_edge_out.sol +++ b/test/cmdlineTests/too_long_line_edge_out.sol diff --git a/test/cmdlineErrorReports/too_long_line_edge_out.sol.ref b/test/cmdlineTests/too_long_line_edge_out.sol.err index d8495c11..d8495c11 100644 --- a/test/cmdlineErrorReports/too_long_line_edge_out.sol.ref +++ b/test/cmdlineTests/too_long_line_edge_out.sol.err diff --git a/test/cmdlineTests/too_long_line_edge_out.sol.exit b/test/cmdlineTests/too_long_line_edge_out.sol.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/cmdlineTests/too_long_line_edge_out.sol.exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineErrorReports/too_long_line_left_short.sol b/test/cmdlineTests/too_long_line_left_short.sol index 2accfcce..2accfcce 100644 --- a/test/cmdlineErrorReports/too_long_line_left_short.sol +++ b/test/cmdlineTests/too_long_line_left_short.sol diff --git a/test/cmdlineErrorReports/too_long_line_left_short.sol.ref b/test/cmdlineTests/too_long_line_left_short.sol.err index 00b6be5c..00b6be5c 100644 --- a/test/cmdlineErrorReports/too_long_line_left_short.sol.ref +++ b/test/cmdlineTests/too_long_line_left_short.sol.err diff --git a/test/cmdlineTests/too_long_line_left_short.sol.exit b/test/cmdlineTests/too_long_line_left_short.sol.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/cmdlineTests/too_long_line_left_short.sol.exit @@ -0,0 +1 @@ +1 diff --git a/test/cmdlineErrorReports/too_long_line_right_short.sol b/test/cmdlineTests/too_long_line_right_short.sol index 936b3961..936b3961 100644 --- a/test/cmdlineErrorReports/too_long_line_right_short.sol +++ b/test/cmdlineTests/too_long_line_right_short.sol diff --git a/test/cmdlineErrorReports/too_long_line_right_short.sol.ref b/test/cmdlineTests/too_long_line_right_short.sol.err index 88072d95..88072d95 100644 --- a/test/cmdlineErrorReports/too_long_line_right_short.sol.ref +++ b/test/cmdlineTests/too_long_line_right_short.sol.err diff --git a/test/cmdlineTests/too_long_line_right_short.sol.exit b/test/cmdlineTests/too_long_line_right_short.sol.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/cmdlineTests/too_long_line_right_short.sol.exit @@ -0,0 +1 @@ +1 diff --git a/test/externalTests.sh b/test/externalTests.sh index 93581925..16f9e55a 100755 --- a/test/externalTests.sh +++ b/test/externalTests.sh @@ -79,6 +79,7 @@ function test_truffle fi # Change "compileStandard" to "compile" sed -i s/solc.compileStandard/solc.compile/ "node_modules/truffle/build/cli.bundled.js" + npx truffle compile npm run test ) rm -rf "$DIR" @@ -89,3 +90,5 @@ test_truffle Zeppelin https://github.com/axic/openzeppelin-solidity.git solidity # Disabled temporarily as it needs to be updated to latest Truffle first. #test_truffle Gnosis https://github.com/axic/pm-contracts.git solidity-050 + +test_truffle GnosisSafe https://github.com/gnosis/safe-contracts.git development diff --git a/test/libdevcore/CommonData.cpp b/test/libdevcore/CommonData.cpp new file mode 100644 index 00000000..8da937de --- /dev/null +++ b/test/libdevcore/CommonData.cpp @@ -0,0 +1,87 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Unit tests for the StringUtils routines. + */ + + +#include <libdevcore/CommonData.h> +#include <libdevcore/FixedHash.h> +#include <libsolidity/ast/Types.h> // for IntegerType + +#include <test/Options.h> + +using namespace std; +using namespace dev::solidity; + +namespace dev +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(CommonData) + +BOOST_AUTO_TEST_CASE(test_to_hex) +{ + BOOST_CHECK_EQUAL(toHex(fromHex("FF"), HexPrefix::DontAdd, HexCase::Lower), "ff"); +} + +BOOST_AUTO_TEST_CASE(test_format_number) +{ + BOOST_CHECK_EQUAL(formatNumber(u256(0x8000000)), "0x08000000"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x80000000)), "0x80000000"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x800000000)), "0x0800000000"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x8000000000)), "0x8000000000"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x80000000000)), "0x080000000000"); + + BOOST_CHECK_EQUAL(formatNumber(u256(0x7ffffff)), "0x07ffffff"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x7fffffff)), "0x7fffffff"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x7ffffffff)), "0x07ffffffff"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x7fffffffff)), "0x7fffffffff"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x7ffffffffff)), "0x07ffffffffff"); + + BOOST_CHECK_EQUAL(formatNumber(u256(0x88000000)), "0x88000000"); + BOOST_CHECK_EQUAL(formatNumber(u256(0x8888888888000000)), "0x8888888888000000"); + + u256 b = 0; + for (int i = 0; i < 32; i++) + { + b <<= 8; + b |= 0x55; + } + u256 c = u256(FixedHash<32>( + fromHex("0xabcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789") + )); + u256 d = u256(0xAAAAaaaaAAAAaaaa) << 192 | + u256(0xFFFFffffFFFFffff) << 128 | + u256(0xFFFFffffFFFFffff) << 64 | + u256(0xFFFFffffFFFFffff); + BOOST_CHECK_EQUAL(formatNumber(b), "0x5555555555555555555555555555555555555555555555555555555555555555"); + BOOST_CHECK_EQUAL(formatNumber(c), "0xabcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"); + BOOST_CHECK_EQUAL(formatNumber(d), "0xaaaaaaaaaaaaaaaaffffffffffffffffffffffffffffffffffffffffffffffff"); + + BOOST_CHECK_EQUAL(formatNumber(IntegerType(256).minValue()), "0"); + BOOST_CHECK_EQUAL( + formatNumber(IntegerType(256).maxValue()), + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + ); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} diff --git a/test/libdevcore/StringUtils.cpp b/test/libdevcore/StringUtils.cpp index 76c11b82..0baeb964 100644 --- a/test/libdevcore/StringUtils.cpp +++ b/test/libdevcore/StringUtils.cpp @@ -18,8 +18,12 @@ * Unit tests for the StringUtils routines. */ +#include <libdevcore/CommonData.h> +#include <libdevcore/FixedHash.h> #include <libdevcore/StringUtils.h> +#include <libsolidity/ast/Types.h> // for IntegerType + #include <test/Options.h> using namespace std; @@ -100,6 +104,59 @@ BOOST_AUTO_TEST_CASE(test_human_readable_join) BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b", "c"}), "; ", " or "), "a; b or c"); } +BOOST_AUTO_TEST_CASE(test_format_number_readable) +{ + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x8000000)), "0x08 * 2**24"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x80000000)), "0x80 * 2**24"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x800000000)), "0x08 * 2**32"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x8000000000)), "0x80 * 2**32"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x80000000000)), "0x08 * 2**40"); + + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x7ffffff)), "0x08 * 2**24 - 1"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x7fffffff)), "0x80 * 2**24 - 1"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x7ffffffff)), "0x08 * 2**32 - 1"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x7fffffffff)), "0x80 * 2**32 - 1"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x7ffffffffff)), "0x08 * 2**40 - 1"); + + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x88000000)), "0x88 * 2**24"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x8888888888000000)), "0x8888888888 * 2**24"); + + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0x100000000)), "2**32"); + BOOST_CHECK_EQUAL(formatNumberReadable(u256(0xFFFFffff)), "2**32 - 1"); + + u160 a = 0; + for (int i = 0; i < 20; i++) + { + a <<= 8; + a |= 0x55; + } + u256 b = 0; + for (int i = 0; i < 32; i++) + { + b <<= 8; + b |= 0x55; + } + u256 c = (u256)FixedHash<32>( + fromHex("0xabcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789") + ); + u256 d = u256(0xAAAAaaaaAAAAaaaa) << 192 | + u256(0xFFFFffffFFFFffff) << 128 | + u256(0xFFFFffffFFFFffff) << 64 | + u256(0xFFFFffffFFFFffff); + BOOST_CHECK_EQUAL(formatNumberReadable(a, true), "0x5555...{+32 more}...5555"); + BOOST_CHECK_EQUAL(formatNumberReadable(b, true), "0x5555...{+56 more}...5555"); + BOOST_CHECK_EQUAL(formatNumberReadable(c, true), "0xABCD...{+56 more}...6789"); + BOOST_CHECK_EQUAL(formatNumberReadable(d, true), "0xAAAAaaaaAAAAaaab * 2**192 - 1"); + + //for codegen/ExpressionCompiler + BOOST_CHECK_EQUAL(formatNumberReadable(u256(-1)), "2**256 - 1"); + + // for formal/SMTChecker + BOOST_CHECK_EQUAL( + formatNumberReadable(solidity::IntegerType(256).minValue()), "0"); + BOOST_CHECK_EQUAL( + formatNumberReadable(solidity::IntegerType(256).maxValue()), "2**256 - 1"); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index bece2be4..4e9040b9 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -56,11 +56,11 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) { Assembly _assembly; auto root_asm = make_shared<CharStream>("", "root.asm"); - _assembly.setSourceLocation(SourceLocation(1, 3, root_asm)); + _assembly.setSourceLocation({1, 3, root_asm}); Assembly _subAsm; auto sub_asm = make_shared<CharStream>("", "sub.asm"); - _subAsm.setSourceLocation(SourceLocation(6, 8, sub_asm)); + _subAsm.setSourceLocation({6, 8, sub_asm}); _subAsm.append(Instruction::INVALID); shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm); @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items) _assembly.assemblyString(), " /* \"root.asm\":1:3 */\n" "tag_1:\n" - " keccak256(0x2, 0x1)\n" + " keccak256(0x02, 0x01)\n" " bytecodeSize\n" " linkerSymbol(\"bf005014d9d0f534b8fcb268bd84c491a2380f4acd260d1ccfe9cd8201f7e994\")\n" " jump(tag_1)\n" diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 7d102948..c65d28d3 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -53,7 +53,7 @@ namespace // add dummy locations to each item so that we can check that they are not deleted AssemblyItems input = _input; for (AssemblyItem& item: input) - item.setLocation(SourceLocation(1, 3, nullptr)); + item.setLocation({1, 3, nullptr}); return input; } diff --git a/test/liblangutil/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp index ef4103da..5bdce88e 100644 --- a/test/liblangutil/SourceLocation.cpp +++ b/test/liblangutil/SourceLocation.cpp @@ -37,12 +37,12 @@ BOOST_AUTO_TEST_CASE(test_fail) auto const sourceA = std::make_shared<CharStream>("", "sourceA"); auto const sourceB = std::make_shared<CharStream>("", "sourceB"); - BOOST_CHECK(SourceLocation() == SourceLocation()); - BOOST_CHECK(SourceLocation(0, 3, sourceA) != SourceLocation(0, 3, sourceB)); - BOOST_CHECK(SourceLocation(0, 3, source) == SourceLocation(0, 3, source)); - BOOST_CHECK(SourceLocation(3, 7, source).contains(SourceLocation(4, 6, source))); - BOOST_CHECK(!SourceLocation(3, 7, sourceA).contains(SourceLocation(4, 6, sourceB))); - BOOST_CHECK(SourceLocation(3, 7, sourceA) < SourceLocation(4, 6, sourceB)); + BOOST_CHECK(SourceLocation{} == SourceLocation{}); + BOOST_CHECK((SourceLocation{0, 3, sourceA} != SourceLocation{0, 3, sourceB})); + BOOST_CHECK((SourceLocation{0, 3, source} == SourceLocation{0, 3, source})); + BOOST_CHECK((SourceLocation{3, 7, source}.contains(SourceLocation{4, 6, source}))); + BOOST_CHECK((!SourceLocation{3, 7, sourceA}.contains(SourceLocation{4, 6, sourceB}))); + BOOST_CHECK((SourceLocation{3, 7, sourceA} < SourceLocation{4, 6, sourceB})); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index aad89b91..85ce65a1 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -1008,7 +1008,7 @@ BOOST_AUTO_TEST_CASE(sub_assemblies) compileAndRun(sourceCode); bytes ret = callFallback(); BOOST_REQUIRE(ret.size() == 32); - u256 rVal = u256(toHex(ret, 2, HexPrefix::Add)); + u256 rVal = u256(toHex(ret, HexPrefix::Add)); BOOST_CHECK(rVal != 0); BOOST_CHECK(rVal < u256("0x10000000000000000000000000000000000000000")); } diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index bd24115c..abeecd32 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -52,7 +52,7 @@ AnalysisFramework::parseAnalyseAndReturnError( m_compiler.setEVMVersion(dev::test::Options::get().evmVersion()); if (!m_compiler.parse()) { - BOOST_ERROR("Parsing contract failed in analysis test suite:" + formatErrors()); + BOOST_FAIL("Parsing contract failed in analysis test suite:" + formatErrors()); } m_compiler.analyze(); @@ -127,8 +127,7 @@ string AnalysisFramework::formatError(Error const& _error) const { return SourceReferenceFormatter::formatExceptionInformation( _error, - (_error.type() == Error::Type::Warning) ? "Warning" : "Error", - [&](std::string const& _sourceName) -> Scanner const& { return m_compiler.scanner(_sourceName); } + (_error.type() == Error::Type::Warning) ? "Warning" : "Error" ); } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index aa10147c..baa9bff1 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -165,19 +165,19 @@ BOOST_AUTO_TEST_CASE(location_test) auto codegenCharStream = make_shared<CharStream>("", "--CODEGEN--"); vector<SourceLocation> locations = - vector<SourceLocation>(hasShifts ? 21 : 22, SourceLocation(2, 82, sourceCode)) + - vector<SourceLocation>(2, SourceLocation(20, 79, sourceCode)) + - vector<SourceLocation>(1, SourceLocation(8, 17, codegenCharStream)) + - vector<SourceLocation>(3, SourceLocation(5, 7, codegenCharStream)) + - vector<SourceLocation>(1, SourceLocation(30, 31, codegenCharStream)) + - vector<SourceLocation>(1, SourceLocation(27, 28, codegenCharStream)) + - vector<SourceLocation>(1, SourceLocation(20, 32, codegenCharStream)) + - vector<SourceLocation>(1, SourceLocation(5, 7, codegenCharStream)) + - vector<SourceLocation>(24, SourceLocation(20, 79, sourceCode)) + - vector<SourceLocation>(1, SourceLocation(49, 58, sourceCode)) + - vector<SourceLocation>(1, SourceLocation(72, 74, sourceCode)) + - vector<SourceLocation>(2, SourceLocation(65, 74, sourceCode)) + - vector<SourceLocation>(2, SourceLocation(20, 79, sourceCode)); + vector<SourceLocation>(4, SourceLocation{2, 82, sourceCode}) + + vector<SourceLocation>(1, SourceLocation{8, 17, codegenCharStream}) + + vector<SourceLocation>(3, SourceLocation{5, 7, codegenCharStream}) + + vector<SourceLocation>(1, SourceLocation{30, 31, codegenCharStream}) + + vector<SourceLocation>(1, SourceLocation{27, 28, codegenCharStream}) + + vector<SourceLocation>(1, SourceLocation{20, 32, codegenCharStream}) + + vector<SourceLocation>(1, SourceLocation{5, 7, codegenCharStream}) + + vector<SourceLocation>(hasShifts ? 19 : 20, SourceLocation{2, 82, sourceCode}) + + vector<SourceLocation>(24, SourceLocation{20, 79, sourceCode}) + + vector<SourceLocation>(1, SourceLocation{49, 58, sourceCode}) + + vector<SourceLocation>(1, SourceLocation{72, 74, sourceCode}) + + vector<SourceLocation>(2, SourceLocation{65, 74, sourceCode}) + + vector<SourceLocation>(2, SourceLocation{20, 79, sourceCode}); checkAssemblyLocations(items, locations); } diff --git a/test/libsolidity/GasCosts.cpp b/test/libsolidity/GasCosts.cpp new file mode 100644 index 00000000..c7da3ca0 --- /dev/null +++ b/test/libsolidity/GasCosts.cpp @@ -0,0 +1,132 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Tests that check that the cost of certain operations stay within range. + */ + +#include <test/libsolidity/SolidityExecutionFramework.h> + +#include <cmath> + +using namespace std; +using namespace langutil; +using namespace dev::eth; +using namespace dev::solidity; +using namespace dev::test; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +#define CHECK_GAS(_gasNoOpt, _gasOpt, _tolerance) \ + do \ + { \ + u256 gasOpt{_gasOpt}; \ + u256 gasNoOpt{_gasNoOpt}; \ + u256 tolerance{_tolerance}; \ + u256 gas = m_optimize ? gasOpt : gasNoOpt; \ + u256 diff = gas < m_gasUsed ? m_gasUsed - gas : gas - m_gasUsed; \ + BOOST_CHECK_MESSAGE( \ + diff <= tolerance, \ + "Gas used: " + \ + m_gasUsed.str() + \ + " - expected: " + \ + gas.str() + \ + " (tolerance: " + \ + tolerance.str() + \ + ")" \ + ); \ + } while(0) + +BOOST_FIXTURE_TEST_SUITE(GasCostTests, SolidityExecutionFramework) + +BOOST_AUTO_TEST_CASE(string_storage) +{ + char const* sourceCode = R"( + contract C { + function f() pure public { + require(false, "Not Authorized. This function can only be called by the custodian or owner of this contract"); + } + } + )"; + compileAndRun(sourceCode); + + if (Options::get().evmVersion() <= EVMVersion::byzantium()) + CHECK_GAS(134435, 130591, 100); + else + CHECK_GAS(127225, 124873, 100); + if (Options::get().evmVersion() >= EVMVersion::byzantium()) + { + callContractFunction("f()"); + if (Options::get().evmVersion() == EVMVersion::byzantium()) + CHECK_GAS(21551, 21526, 20); + else + CHECK_GAS(21546, 21526, 20); + } +} + +BOOST_AUTO_TEST_CASE(single_callvaluecheck) +{ + string sourceCode = R"( + // All functions nonpayable, we can check callvalue at the beginning + contract Nonpayable { + address a; + function f(address b) public { + a = b; + } + function f1(address b) public pure returns (uint c) { + return uint(b) + 2; + } + function f2(address b) public pure returns (uint) { + return uint(b) + 8; + } + function f3(address, uint c) pure public returns (uint) { + return c - 5; + } + } + // At least on payable function, we cannot do the optimization. + contract Payable { + address a; + function f(address b) public { + a = b; + } + function f1(address b) public pure returns (uint c) { + return uint(b) + 2; + } + function f2(address b) public pure returns (uint) { + return uint(b) + 8; + } + function f3(address, uint c) payable public returns (uint) { + return c - 5; + } + } + )"; + compileAndRun(sourceCode); + size_t bytecodeSizeNonpayable = m_compiler.object("Nonpayable").bytecode.size(); + size_t bytecodeSizePayable = m_compiler.object("Payable").bytecode.size(); + + BOOST_CHECK_EQUAL(bytecodeSizePayable - bytecodeSizeNonpayable, 26); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 601948bc..d765d440 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -44,7 +44,6 @@ namespace test class GasMeterTestFramework: public SolidityExecutionFramework { public: - GasMeterTestFramework() { } void compile(string const& _sourceCode) { m_compiler.reset(false); @@ -62,7 +61,7 @@ public: ); } - void testCreationTimeGas(string const& _sourceCode) + void testCreationTimeGas(string const& _sourceCode, u256 const& _tolerance = u256(0)) { compileAndRun(_sourceCode); auto state = make_shared<KnownState>(); @@ -75,12 +74,13 @@ public: gas += gasForTransaction(m_compiler.object(m_compiler.lastContractName()).bytecode, true); BOOST_REQUIRE(!gas.isInfinite); - BOOST_CHECK_EQUAL(gas.value, m_gasUsed); + BOOST_CHECK_LE(m_gasUsed, gas.value); + BOOST_CHECK_LE(gas.value - _tolerance, m_gasUsed); } /// Compares the gas computed by PathGasMeter for the given signature (but unknown arguments) /// against the actual gas usage computed by the VM on the given set of argument variants. - void testRunTimeGas(string const& _sig, vector<bytes> _argumentVariants) + void testRunTimeGas(string const& _sig, vector<bytes> _argumentVariants, u256 const& _tolerance = u256(0)) { u256 gasUsed = 0; GasMeter::GasConsumption gas; @@ -98,7 +98,8 @@ public: _sig ); BOOST_REQUIRE(!gas.isInfinite); - BOOST_CHECK_EQUAL(gas.value, m_gasUsed); + BOOST_CHECK_LE(m_gasUsed, gas.value); + BOOST_CHECK_LE(gas.value - _tolerance, m_gasUsed); } static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation) @@ -138,8 +139,7 @@ BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs) if (first->first->location().intersects(second->first->location())) { BOOST_CHECK_MESSAGE(false, "Source locations should not overlap!"); - auto scannerFromSource = [&](string const& _sourceName) -> Scanner const& { return m_compiler.scanner(_sourceName); }; - SourceReferenceFormatter formatter(cout, scannerFromSource); + SourceReferenceFormatter formatter(cout); formatter.printSourceLocation(&first->first->location()); formatter.printSourceLocation(&second->first->location()); @@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE(updating_store) } } )"; - testCreationTimeGas(sourceCode); + testCreationTimeGas(sourceCode, m_evmVersion < EVMVersion::constantinople() ? u256(0) : u256(9600)); } BOOST_AUTO_TEST_CASE(branches) diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 11d4c59f..b6986041 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -433,8 +433,7 @@ BOOST_AUTO_TEST_CASE(variable_access_cross_functions) BOOST_AUTO_TEST_CASE(invalid_tuple_assignment) { - /// The push(42) is added here to silence the unbalanced stack error, so that there's only one error reported. - CHECK_PARSE_ERROR("{ 42 let x, y := 1 }", DeclarationError, "Variable count mismatch."); + CHECK_PARSE_ERROR("{ let x, y := 1 }", DeclarationError, "Variable count mismatch: 2 variables and 1 values"); } BOOST_AUTO_TEST_CASE(instruction_too_few_arguments) diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp index 09c08700..ec97f22f 100644 --- a/test/libsolidity/LibSolc.cpp +++ b/test/libsolidity/LibSolc.cpp @@ -81,7 +81,9 @@ BOOST_AUTO_TEST_CASE(standard_compilation) // Only tests some assumptions. The StandardCompiler is tested properly in another suite. BOOST_CHECK(result.isMember("sources")); - BOOST_CHECK(result.isMember("contracts")); + // This used to test that it is a member, but we did not actually request any output, + // so there should not be a contract member. + BOOST_CHECK(!result.isMember("contracts")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index a8a67bca..63f2b3a6 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -38,8 +38,6 @@ namespace test class JSONInterfaceChecker { public: - JSONInterfaceChecker(): m_compilerStack() {} - void checkInterface(std::string const& _code, std::string const& _contractName, std::string const& _expectedInterfaceString) { m_compilerStack.reset(false); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c6135a72..8d219d16 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -3039,7 +3039,8 @@ BOOST_AUTO_TEST_CASE(gaslimit) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs(gasLimit())); + auto result = callContractFunction("f()"); + ABI_CHECK(result, encodeArgs(gasLimit())); } BOOST_AUTO_TEST_CASE(gasprice) @@ -12245,7 +12246,7 @@ BOOST_AUTO_TEST_CASE(include_creation_bytecode_only_once) compileAndRun(sourceCode); BOOST_CHECK_LE( double(m_compiler.object("Double").bytecode.size()), - 1.1 * double(m_compiler.object("Single").bytecode.size()) + 1.2 * double(m_compiler.object("Single").bytecode.size()) ); } diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index cedbf51a..73377eb9 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -72,8 +72,7 @@ public: m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); if (!m_compiler.compile()) { - auto scannerFromSourceName = [&](std::string const& _sourceName) -> langutil::Scanner const& { return m_compiler.scanner(_sourceName); }; - langutil::SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); + langutil::SourceReferenceFormatter formatter(std::cerr); for (auto const& error: m_compiler.errors()) formatter.printExceptionInformation( diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 8bce26c1..f5c4dc5e 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -366,7 +366,7 @@ BOOST_AUTO_TEST_CASE(unary_operators) { char const* sourceCode = R"( contract test { - function f(int y) { !(~+- y == 2); } + function f(int y) { !(~- y == 2); } } )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}}); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 75726027..774f67fe 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -376,18 +376,6 @@ BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file does not specify required compiler version!")); } -BOOST_AUTO_TEST_CASE(unsatisfied_version) -{ - char const* text = R"( - pragma solidity ^99.99.0; - )"; - auto sourceAndError = parseAnalyseAndReturnError(text, false, false, false); - BOOST_REQUIRE(!sourceAndError.second.empty()); - BOOST_REQUIRE(!!sourceAndError.first); - BOOST_CHECK(sourceAndError.second.front()->type() == Error::Type::SyntaxError); - BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file requires different compiler version")); -} - BOOST_AUTO_TEST_CASE(returndatasize_as_variable) { char const* text = R"( diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index d930f697..000a7938 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -39,8 +39,6 @@ namespace test class DocumentationChecker { public: - DocumentationChecker(): m_compilerStack() {} - void checkNatspec( std::string const& _code, std::string const& _contractName, diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index f925d36e..b5ce6f2a 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -45,8 +45,6 @@ namespace test class OptimizerTestFramework: public SolidityExecutionFramework { public: - OptimizerTestFramework() { } - bytes const& compileAndRunWithOptimizer( std::string const& _sourceCode, u256 const& _value = 0, diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index d86d3d39..a33c6134 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -113,6 +113,23 @@ while(0) BOOST_AUTO_TEST_SUITE(SolidityParser) +BOOST_AUTO_TEST_CASE(unsatisfied_version) +{ + char const* text = R"( + pragma solidity ^99.99.0; + )"; + CHECK_PARSE_ERROR(text, "Source file requires different compiler version"); +} + +BOOST_AUTO_TEST_CASE(unsatisfied_version_followed_by_invalid_syntax) +{ + char const* text = R"( + pragma solidity ^99.99.0; + this is surely invalid + )"; + CHECK_PARSE_ERROR(text, "Source file requires different compiler version"); +} + BOOST_AUTO_TEST_CASE(function_natspec_documentation) { char const* text = R"( diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 1570a9d2..118d8210 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -333,11 +333,11 @@ BOOST_AUTO_TEST_CASE(basic_compilation) " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n " "callvalue\n /* \"--CODEGEN--\":8:17 */\n dup1\n " "/* \"--CODEGEN--\":5:7 */\n iszero\n tag_1\n jumpi\n " - "/* \"--CODEGEN--\":30:31 */\n 0x0\n /* \"--CODEGEN--\":27:28 */\n " + "/* \"--CODEGEN--\":30:31 */\n 0x00\n /* \"--CODEGEN--\":27:28 */\n " "dup1\n /* \"--CODEGEN--\":20:32 */\n revert\n /* \"--CODEGEN--\":5:7 */\n" "tag_1:\n /* \"fileA\":0:14 contract A { } */\n pop\n dataSize(sub_0)\n dup1\n " - "dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n return\nstop\n\nsub_0: assembly {\n " - "/* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n 0x0\n " + "dataOffset(sub_0)\n 0x00\n codecopy\n 0x00\n return\nstop\n\nsub_0: assembly {\n " + "/* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n 0x00\n " "dup1\n revert\n\n auxdata: 0xa165627a7a72305820" ) == 0); BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol index 3793f411..2ecff63e 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple.sol @@ -12,3 +12,4 @@ contract C } // ---- +// Warning: (153-156): Assertion checker does not yet implement tuples and inline arrays. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol index e3c80594..a9bde9e4 100644 --- a/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol +++ b/test/libsolidity/smtCheckerTests/functions/functions_identity_as_tuple_fail.sol @@ -12,4 +12,5 @@ contract C } // ---- +// Warning: (153-156): Assertion checker does not yet implement tuples and inline arrays. // Warning: (163-176): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/do_while_1_fail.sol b/test/libsolidity/smtCheckerTests/loops/do_while_1_fail.sol new file mode 100644 index 00000000..df6eaaa7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/do_while_1_fail.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + require(x < 100); + do { + // Overflows due to resetting x. + x = x + 1; + } while (x < 10); + assert(x < 14); + } +} +// ---- +// Warning: (150-155): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (146-155): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (179-193): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/do_while_1_false_positives.sol b/test/libsolidity/smtCheckerTests/loops/do_while_1_false_positives.sol new file mode 100644 index 00000000..49a1e0a5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/do_while_1_false_positives.sol @@ -0,0 +1,19 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + require(x < 100); + do { + // Overflows due to resetting x. + x = x + 1; + } while (x < 1000); + // The assertion is true but we can't infer so + // because x is touched in the loop. + assert(x > 0); + } +} +// ---- +// Warning: (150-155): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (146-155): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (269-282): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_1_fail.sol b/test/libsolidity/smtCheckerTests/loops/for_1_fail.sol new file mode 100644 index 00000000..2be01c2d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_1_fail.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + require(x < 100); + for(uint i = 0; i < 10; ++i) { + // Overflows due to resetting x. + x = x + 1; + } + assert(x < 14); + } +} +// ---- +// Warning: (176-181): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (172-181): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (189-203): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_1_false_positive.sol b/test/libsolidity/smtCheckerTests/loops/for_1_false_positive.sol new file mode 100644 index 00000000..c8232ab6 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_1_false_positive.sol @@ -0,0 +1,18 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + require(x < 100); + for(uint i = 0; i < 10; ++i) { + // Overflows due to resetting x. + x = x + 1; + } + // The assertion is true but x is touched and reset. + assert(x > 0); + } +} +// ---- +// Warning: (176-181): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (172-181): Overflow (resulting value larger than 2**256 - 1) happens here +// Warning: (244-257): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol index 2c84960f..eb62d36e 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol @@ -9,4 +9,4 @@ contract C { } } // ---- -// Warning: (167-181): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). +// Warning: (167-181): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol index 90c4c328..b0c3cae4 100644 --- a/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol @@ -5,8 +5,9 @@ contract C { for (y = 2; x < 10; ) { y = 3; } - assert(y == 2); + // False positive due to resetting y. + assert(y < 4); } } // ---- -// Warning: (167-181): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). +// Warning: (213-226): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_1.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_1.sol new file mode 100644 index 00000000..21e6c91e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_1.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + require(x == 2); + for (; x == 2;) {} + assert(x == 2); + } +} +// ---- +// Warning: (122-128): For loop condition is always true. diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_2.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_2.sol new file mode 100644 index 00000000..6184c441 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_2.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + require(x == 2); + uint y; + for (; x == 2;) { + y = 7; + } + assert(x == 2); + } +} +// ---- +// Warning: (138-144): For loop condition is always true. diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_3.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_3.sol new file mode 100644 index 00000000..eec59ded --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_trivial_condition_3.sol @@ -0,0 +1,18 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + require(x == 2); + uint y; + // The loop condition is always true, + // but since x is touched in the body + // we can't infer that. + for (; x == 2;) { + x = 2; + } + // False positive due to resetting x. + assert(x == 2); + } +} +// ---- +// Warning: (115-121): Unused local variable. +// Warning: (356-370): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_unreachable_1.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_unreachable_1.sol new file mode 100644 index 00000000..f367d8d9 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_unreachable_1.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + require(x == 2); + for (; x > 2;) {} + assert(x == 2); + } +} +// ---- +// Warning: (122-127): For loop condition is always false. diff --git a/test/libsolidity/smtCheckerTests/loops/while_1.sol b/test/libsolidity/smtCheckerTests/loops/while_1.sol new file mode 100644 index 00000000..871ed929 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_1.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x, bool b) public pure { + require(x < 100); + while (x < 10) { + if (b) + x = x + 1; + else + x = 0; + } + assert(x > 0); + } +} +// ---- +// Warning: (177-190): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/while_1_fail.sol b/test/libsolidity/smtCheckerTests/loops/while_1_fail.sol new file mode 100644 index 00000000..6964f7c8 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_1_fail.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + require(x < 100); + while (x < 10) { + x = x + 1; + } + assert(x < 14); + } +} +// ---- +// Warning: (139-153): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/while_2_fail.sol b/test/libsolidity/smtCheckerTests/loops/while_2_fail.sol new file mode 100644 index 00000000..4c52287d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_2_fail.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + x = 2; + while (x > 1) { + if (x > 10) + x = 2; + else + x = 10; + } + assert(x == 2); + } +} +// ---- +// Warning: (158-172): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol index 074be86f..9b5d04c3 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol @@ -4,10 +4,10 @@ contract C { function f(uint x) public pure { x = 2; while (x > 1) { - x = 2; + x = 1; } assert(x == 2); } } // ---- -// Warning: (194-208): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). +// Warning: (194-208): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol index a37df888..f3634edb 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol @@ -8,4 +8,4 @@ contract C { } } // ---- -// Warning: (187-201): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). +// Warning: (187-201): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol index f71da865..5a3aee9e 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol @@ -8,4 +8,4 @@ contract C { } } // ---- -// Warning: (199-213): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). +// Warning: (199-213): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol index 41559c99..6c81e36f 100644 --- a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol @@ -9,4 +9,4 @@ contract C { } } // ---- -// Warning: (216-230): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). +// Warning: (216-230): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol b/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol index 894ff1a4..ec819b80 100644 --- a/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol +++ b/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol @@ -3,4 +3,4 @@ contract C { function f(uint a, uint b) public pure returns (uint) { return a + b; } } // ---- -// Warning: (112-117): Overflow (resulting value larger than 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) happens here +// Warning: (112-117): Overflow (resulting value larger than 2**256 - 1) happens here diff --git a/test/libsolidity/smtCheckerTests/special/many.sol b/test/libsolidity/smtCheckerTests/special/many.sol index 40e5d987..ae60b1e5 100644 --- a/test/libsolidity/smtCheckerTests/special/many.sol +++ b/test/libsolidity/smtCheckerTests/special/many.sol @@ -20,6 +20,6 @@ contract C // Warning: (165-204): Assertion violation happens here // Warning: (208-240): Assertion violation happens here // Warning: (244-275): Assertion violation happens here -// Warning: (311-316): Overflow (resulting value larger than 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) happens here +// Warning: (311-316): Overflow (resulting value larger than 2**256 - 1) happens here // Warning: (336-352): Assertion violation happens here // Warning: (356-379): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/special/msg_data.sol b/test/libsolidity/smtCheckerTests/special/msg_data.sol index 7e748f09..b667f971 100644 --- a/test/libsolidity/smtCheckerTests/special/msg_data.sol +++ b/test/libsolidity/smtCheckerTests/special/msg_data.sol @@ -8,7 +8,6 @@ contract C } // ---- // Warning: (86-101): Assertion checker does not yet support this expression. -// Warning: (86-94): Assertion checker does not yet support this special variable. -// Warning: (86-94): Assertion checker does not yet implement this type. +// Warning: (86-94): Assertion checker does not yet support this global variable. // Warning: (86-101): Internal error: Expression undefined for SMT solver. // Warning: (79-106): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/bytes_1.sol b/test/libsolidity/smtCheckerTests/types/bytes_1.sol new file mode 100644 index 00000000..fb957421 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bytes_1.sol @@ -0,0 +1,16 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(bytes memory b) public pure returns (bytes memory) { + bytes memory c = b; + return b; + } +} +// ---- +// Warning: (113-127): Unused local variable. +// Warning: (113-127): Assertion checker does not yet support the type of this variable. +// Warning: (58-72): Assertion checker does not yet support the type of this variable. +// Warning: (95-107): Assertion checker does not yet support the type of this variable. +// Warning: (130-131): Internal error: Expression undefined for SMT solver. +// Warning: (130-131): Assertion checker does not yet implement this type. diff --git a/test/libsolidity/smtCheckerTests/types/mapping_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_1.sol new file mode 100644 index 00000000..4d71ff38 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_1.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => uint) map; + function f(uint x) public { + map[2] = x; + assert(x == map[2]); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/mapping_1_fail.sol b/test/libsolidity/smtCheckerTests/types/mapping_1_fail.sol new file mode 100644 index 00000000..83c963ad --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_1_fail.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => uint) map; + function f(uint x) public { + map[2] = x; + map[2] = 3; + assert(x != map[2]); + } +} +// ---- +// Warning: (134-153): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_2.sol b/test/libsolidity/smtCheckerTests/types/mapping_2.sol new file mode 100644 index 00000000..06d618bd --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_2.sol @@ -0,0 +1,11 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => bool) map; + function f(bool x) public view { + assert(x != map[2]); + } +} +// ---- +// Warning: (111-130): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_2d_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_2d_1.sol new file mode 100644 index 00000000..b6474903 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_2d_1.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => mapping (uint => uint)) map; + function f(uint x) public { + x = 42; + map[13][14] = 42; + assert(x == map[13][14]); + } +} +// ---- +// Warning: (134-145): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays. +// Warning: (154-178): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_2d_1_fail.sol b/test/libsolidity/smtCheckerTests/types/mapping_2d_1_fail.sol new file mode 100644 index 00000000..dd4d568e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_2d_1_fail.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => mapping (uint => uint)) map; + function f(uint x) public { + x = 41; + map[13][14] = 42; + assert(x == map[13][14]); + } +} +// ---- +// Warning: (134-145): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays. +// Warning: (154-178): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_3.sol b/test/libsolidity/smtCheckerTests/types/mapping_3.sol new file mode 100644 index 00000000..985ed3a3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_3.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => uint) map; + function f() public { + map[1] = 111; + uint x = map[2]; + map[1] = 112; + assert(map[2] == x); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/mapping_3d_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_3d_1.sol new file mode 100644 index 00000000..6c5f439a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_3d_1.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => mapping (uint => mapping (uint => uint))) map; + function f(uint x) public { + x = 42; + map[13][14][15] = 42; + assert(x == map[13][14][15]); + } +} +// ---- +// Warning: (152-167): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays. +// Warning: (176-204): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_3d_1_fail.sol b/test/libsolidity/smtCheckerTests/types/mapping_3d_1_fail.sol new file mode 100644 index 00000000..dfd4ddaf --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_3d_1_fail.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => mapping (uint => mapping (uint => uint))) map; + function f(uint x) public { + x = 41; + map[13][14][15] = 42; + assert(x == map[13][14][15]); + } +} +// ---- +// Warning: (152-167): Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays. +// Warning: (176-204): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_4.sol b/test/libsolidity/smtCheckerTests/types/mapping_4.sol new file mode 100644 index 00000000..d0204211 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_4.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (bool => bool) map; + function f(bool x) public view { + require(x); + assert(x != map[x]); + } +} +// ---- +// Warning: (125-144): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_5.sol b/test/libsolidity/smtCheckerTests/types/mapping_5.sol new file mode 100644 index 00000000..4acea501 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_5.sol @@ -0,0 +1,11 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (address => uint) map; + function f(address a, uint x) public view { + assert(x != map[a]); + } +} +// ---- +// Warning: (125-144): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_aliasing_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_aliasing_1.sol new file mode 100644 index 00000000..39d096f5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_aliasing_1.sol @@ -0,0 +1,18 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => uint) a; + mapping (uint => uint) b; + + function f() public { + require(a[1] == b[1]); + a[1] = 2; + mapping (uint => uint) storage c = a; + assert(c[1] == 2); + // False negative! Needs aliasing. + assert(a[1] == b[1]); + } +} +// ---- +// Warning: (261-281): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_as_local_var_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_as_local_var_1.sol new file mode 100644 index 00000000..e005fbef --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_as_local_var_1.sol @@ -0,0 +1,21 @@ +pragma experimental SMTChecker; + +contract c { + mapping(uint => uint) x; + mapping(uint => uint) y; + function f(bool cond) public { + mapping(uint => uint) storage a = cond ? x : y; + x[2] = 1; + y[2] = 2; + a[2] = 3; + // False positive since aliasing is not yet supported. + if (cond) + assert(a[2] == x[2] && a[2] != y[2]); + else + assert(a[2] == y[2] && a[2] != x[2]); + } +} +// ---- +// Warning: (166-178): Internal error: Expression undefined for SMT solver. +// Warning: (288-324): Assertion violation happens here +// Warning: (336-372): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_as_parameter_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_as_parameter_1.sol new file mode 100644 index 00000000..9aeed32b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_as_parameter_1.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; + +contract c { + mapping(uint => uint) x; + function f(mapping(uint => uint) storage map, uint index, uint value) internal { + map[index] = value; + } + function g(uint a, uint b) public { + f(x, a, b); + // False positive since aliasing is not yet supported. + assert(x[a] == b); + } +} +// ---- +// Warning: (289-306): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_equal_keys_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_equal_keys_1.sol new file mode 100644 index 00000000..188bc59a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_equal_keys_1.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => uint) map; + function f(uint x, uint y) public view { + require(x == y); + assert(map[x] == map[y]); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/mapping_equal_keys_2.sol b/test/libsolidity/smtCheckerTests/types/mapping_equal_keys_2.sol new file mode 100644 index 00000000..93b249df --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_equal_keys_2.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (uint => uint) map; + function f(uint x, uint y) public view { + assert(x == y); + assert(map[x] == map[y]); + } +} +// ---- +// Warning: (119-133): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/mapping_unsupported_key_type_1.sol b/test/libsolidity/smtCheckerTests/types/mapping_unsupported_key_type_1.sol new file mode 100644 index 00000000..f4e3a65f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/mapping_unsupported_key_type_1.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; + +contract C +{ + mapping (string => uint) map; + function f(string memory s, uint x) public { + map[s] = x; + assert(x == map[s]); + } +} +// ---- +// Warning: (89-104): Assertion checker does not yet support the type of this variable. +// Warning: (129-130): Internal error: Expression undefined for SMT solver. +// Warning: (129-130): Assertion checker does not yet implement this type. +// Warning: (155-156): Internal error: Expression undefined for SMT solver. +// Warning: (155-156): Assertion checker does not yet implement this type. +// Warning: (139-158): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTestsJSON/multi.json b/test/libsolidity/smtCheckerTestsJSON/multi.json index 2ed5150d..df45fbf4 100644 --- a/test/libsolidity/smtCheckerTestsJSON/multi.json +++ b/test/libsolidity/smtCheckerTestsJSON/multi.json @@ -1,11 +1,11 @@ { - "auxiliaryInput": - { - "smtlib2responses": - { - "0x0426cd198d1e7123a28ffac2b759a666b86508ad046babf5166500dd6d8ed308": "unsat\n(error \"line 31 column 26: model is not available\")", - "0xa51ca41ae407f5a727f27101cbc079834743cc8955f9f585582034ca634953f6": "sat\n((|EVALEXPR_0| 1))", - "0xe9477f683ff20aa57fcb08682150f86c5917e1d4c0686b278ab9b73446d0682c": "sat\n((|EVALEXPR_0| 0))" - } - } + "auxiliaryInput": + { + "smtlib2responses": + { + "0x47826ec8b83cfec30171b34f944aed6c33ecd12f02b9ad522ca45317c9bd5f45": "sat\n((|EVALEXPR_0| 1))", + "0x734c058efe9d6ec224de3cf2bdfa6c936a1c9c159c040c128d631145b2fed195": "unsat\n", + "0xa0c072acdbe5181dd56cbad8960cb5bb0b9e97fd598cfd895467bd73bbcca028": "sat\n((|EVALEXPR_0| 0))" + } + } } diff --git a/test/libsolidity/smtCheckerTestsJSON/simple.json b/test/libsolidity/smtCheckerTestsJSON/simple.json index fd976b63..b82d93b8 100644 --- a/test/libsolidity/smtCheckerTestsJSON/simple.json +++ b/test/libsolidity/smtCheckerTestsJSON/simple.json @@ -1,9 +1,9 @@ { - "auxiliaryInput": - { - "smtlib2responses": - { - "0xe9477f683ff20aa57fcb08682150f86c5917e1d4c0686b278ab9b73446d0682c": "sat\n((|EVALEXPR_0| 0))" - } - } + "auxiliaryInput": + { + "smtlib2responses": + { + "0xa0c072acdbe5181dd56cbad8960cb5bb0b9e97fd598cfd895467bd73bbcca028": "sat\n((|EVALEXPR_0| 0))\n" + } + } } diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol index 35420b6d..dbd3db08 100644 --- a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/named_err.sol @@ -2,4 +2,4 @@ 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. +// TypeError: (53-82): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol index 52a8b3d7..476e799b 100644 --- a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol @@ -2,4 +2,4 @@ contract C { function f() internal pure returns (mapping(uint=>uint) storage) {} } // ---- -// TypeError: (53-80): 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. +// TypeError: (53-80): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol index cad9b8e8..a6df889d 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// TypeError: (87-96): 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. +// TypeError: (87-96): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol deleted file mode 100644 index 0d3db856..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol +++ /dev/null @@ -1,26 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal returns (S storage c) { - assembly { - sstore(c_slot, sload(s_slot)) - } - } - function g(bool flag) internal returns (S storage c) { - // control flow in assembly will not be analyzed for now, - // so this will not issue an error - assembly { - if flag { - sstore(c_slot, sload(s_slot)) - } - } - } - function h() internal returns (S storage c) { - // any reference from assembly will be sufficient for now, - // so this will not issue an error - assembly { - sstore(s_slot, sload(c_slot)) - } - } -} -// ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol index eb574c96..b868d61d 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol @@ -45,8 +45,8 @@ contract C { } } // ---- -// TypeError: (87-98): 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. -// TypeError: (223-234): 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. -// TypeError: (440-451): 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. -// TypeError: (654-665): 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. -// TypeError: (871-882): 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. +// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (223-234): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (440-451): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (654-665): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (871-882): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol index 9aa580a4..d2dec9c1 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol @@ -12,5 +12,5 @@ contract C { } } // ---- -// TypeError: (87-98): 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. -// TypeError: (182-193): 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. +// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (182-193): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol index f3e55318..12ec31e4 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol @@ -14,5 +14,5 @@ contract C { } } // ---- -// TypeError: (96-107): 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. -// TypeError: (186-197): 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. +// TypeError: (96-107): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (186-197): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol index 42342979..ee1e08fd 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol @@ -18,5 +18,5 @@ contract C { } } // ---- -// TypeError: (249-258): 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. -// TypeError: (367-376): 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. +// TypeError: (249-258): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (367-376): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol index d0ad8245..e3579628 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol @@ -13,6 +13,6 @@ contract C { } } // ---- -// TypeError: (87-98): 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. -// TypeError: (176-187): 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. -// TypeError: (264-275): 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. +// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (176-187): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (264-275): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol index 6d10287b..d5ad73c5 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol @@ -9,5 +9,5 @@ contract C { } } // ---- -// TypeError: (96-107): 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. -// TypeError: (200-211): 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. +// TypeError: (96-107): This variable is of storage pointer type and can be returned without prior assignment. +// TypeError: (200-211): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol index e7b4fae7..aabb76dd 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol @@ -8,4 +8,4 @@ contract C { } } // ---- -// TypeError: (87-98): 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. +// TypeError: (87-98): This variable is of storage pointer type and can be returned without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/always_revert.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/always_revert.sol new file mode 100644 index 00000000..96767402 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/always_revert.sol @@ -0,0 +1,8 @@ +contract C { + function f() internal view returns(uint[] storage a) + { + uint b = a[0]; + revert(); + b; + } +}
\ No newline at end of file diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/assembly.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/assembly.sol new file mode 100644 index 00000000..bfcbbef5 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/assembly.sol @@ -0,0 +1,9 @@ +contract C { + uint[] r; + function f() internal view returns (uint[] storage s) { + assembly { pop(s_slot) } + s = r; + } +} +// ---- +// TypeError: (92-126): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/functionType.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/functionType.sol new file mode 100644 index 00000000..1d683eff --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/functionType.sol @@ -0,0 +1,8 @@ +contract C { + // Make sure function parameters and return values are not considered + // for uninitialized return detection in the control flow analysis. + function f(function(uint[] storage) internal returns (uint[] storage)) internal pure + returns (function(uint[] storage) internal returns (uint[] storage)) + { + } +} diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_order_fail.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_order_fail.sol new file mode 100644 index 00000000..90d228fa --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_order_fail.sol @@ -0,0 +1,8 @@ +contract C { + modifier m1(uint[] storage a) { _; } + modifier m2(uint[] storage a) { _; } + uint[] s; + function f() m1(b) m2(b = s) internal view returns (uint[] storage b) {} +} +// ---- +// TypeError: (129-130): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_order_fine.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_order_fine.sol new file mode 100644 index 00000000..af133929 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_order_fine.sol @@ -0,0 +1,6 @@ +contract C { + modifier m1(uint[] storage a) { _; } + modifier m2(uint[] storage a) { _; } + uint[] s; + function f() m1(b = s) m2(b) internal view returns (uint[] storage b) {} +}
\ No newline at end of file diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_post_access.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_post_access.sol new file mode 100644 index 00000000..b9f08615 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_post_access.sol @@ -0,0 +1,13 @@ +contract C { + uint[] s; + modifier mod(uint[] storage b) { + _; + b[0] = 0; + } + function f() mod(a) internal returns (uint[] storage a) + { + a = s; + } +} +// ---- +// TypeError: (120-121): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_pre_access.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_pre_access.sol new file mode 100644 index 00000000..81618aec --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/modifier_pre_access.sol @@ -0,0 +1,13 @@ +contract C { + uint[] s; + modifier mod(uint[] storage b) { + b[0] = 0; + _; + } + function f() mod(a) internal returns (uint[] storage a) + { + a = s; + } +} +// ---- +// TypeError: (120-121): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/smoke.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/smoke.sol new file mode 100644 index 00000000..41ced51d --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/smoke.sol @@ -0,0 +1,10 @@ +contract C { + uint[] s; + function f() internal returns (uint[] storage a) + { + a[0] = 0; + a = s; + } +} +// ---- +// TypeError: (94-95): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/struct.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/struct.sol new file mode 100644 index 00000000..b4f2be5d --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/struct.sol @@ -0,0 +1,11 @@ +contract C { + struct S { uint a; } + S s; + function f() internal returns (S storage r) + { + r.a = 0; + r = s; + } +} +// ---- +// TypeError: (109-110): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/unreachable.sol b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/unreachable.sol new file mode 100644 index 00000000..b941ad34 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/uninitializedAccess/unreachable.sol @@ -0,0 +1,10 @@ +contract C { + uint[] s; + function f() internal returns (uint[] storage a) + { + revert(); + a[0] = 0; + a = s; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol index 7a276f95..95d4e02a 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraries/library_function_with_data_location_fine.sol @@ -8,3 +8,9 @@ library L { function i(uint[] calldata, uint[] storage) external pure returns (S storage x) {return x; } } // ---- +// TypeError: (197-198): This variable is of storage pointer type and can be accessed without prior assignment. +// TypeError: (203-204): This variable is of storage pointer type and can be accessed without prior assignment. +// TypeError: (359-360): This variable is of storage pointer type and can be accessed without prior assignment. +// TypeError: (365-366): This variable is of storage pointer type and can be accessed without prior assignment. +// TypeError: (460-461): This variable is of storage pointer type and can be accessed without prior assignment. +// TypeError: (557-558): This variable is of storage pointer type and can be accessed without prior assignment. diff --git a/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol b/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol index e7d2c9a9..65198706 100644 --- a/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol +++ b/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol @@ -18,9 +18,3 @@ contract test { function(uint) pure internal h = fh; } // ---- -// Warning: (20-47): Function state mutability can be restricted to pure -// Warning: (52-81): Function state mutability can be restricted to pure -// Warning: (86-115): Function state mutability can be restricted to pure -// Warning: (120-149): Function state mutability can be restricted to pure -// Warning: (154-183): Function state mutability can be restricted to pure -// Warning: (188-217): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol index ac1f541e..2d36bedd 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol @@ -10,7 +10,5 @@ contract C { } } // ---- -// TypeError: (87-88): Expected 1 arguments but got 0. -// SyntaxError: (87-90): Top-level expressions are not supposed to return values (this expression returns -1 values). Use ``pop()`` or assign them. -// TypeError: (108-109): Expected 1 arguments but got 2. -// SyntaxError: (108-115): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// TypeError: (87-88): Function expects 1 arguments but got 0. +// TypeError: (108-109): Function expects 1 arguments but got 2. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol index e112e16c..a554d3ab 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/004_reference_to_later_declaration.sol @@ -3,4 +3,3 @@ contract test { function f() public {} } // ---- -// Warning: (53-75): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol index abe2beac..3872b1c3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/009_type_checking_function_call.sol @@ -3,4 +3,3 @@ contract test { function g(uint256, bool) public returns (uint256) { } } // ---- -// Warning: (88-142): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol index ec72adeb..bda0b946 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/049_function_external_call_allowed_conversion.sol @@ -7,5 +7,3 @@ contract Test { function g (C c) external {} } // ---- -// Warning: (125-128): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (113-141): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol index aedc7b0b..5a9616ac 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/051_function_internal_allowed_conversion.sol @@ -9,5 +9,3 @@ contract Test { } } // ---- -// Warning: (68-71): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (56-82): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol index c07e59e2..2e235ee0 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/055_inheritance_diamond_basic.sol @@ -5,5 +5,3 @@ contract derived is root, inter2, inter1 { function g() public { f(); rootFunction(); } } // ---- -// Warning: (16-49): Function state mutability can be restricted to pure -// Warning: (129-151): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol index 062507ee..bf6459cb 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/057_legal_override_direct.sol @@ -1,6 +1,3 @@ contract B { function f() public {} } contract C is B { function f(uint i) public {} } // ---- -// Warning: (67-73): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (13-35): Function state mutability can be restricted to pure -// Warning: (56-84): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol index f59da472..461bbbf2 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/058_legal_override_indirect.sol @@ -2,6 +2,3 @@ contract A { function f(uint a) public {} } contract B { function f() public {} } contract C is A, B { } // ---- -// Warning: (24-30): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (13-41): Function state mutability can be restricted to pure -// Warning: (57-79): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol index c7e42238..ce3b622b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/060_complex_inheritance.sol @@ -3,4 +3,3 @@ contract B { function f() public {} function g() public returns (uint8) {} } contract C is A, B { } // ---- // Warning: (35-42): Unused local variable. -// Warning: (95-133): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol index 8ebb46aa..31be70ca 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol @@ -1,4 +1,3 @@ contract A { constructor(uint a) public { } } contract B is A { } // ---- -// Warning: (25-31): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol index 8ebb46aa..31be70ca 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol @@ -1,4 +1,3 @@ contract A { constructor(uint a) public { } } contract B is A { } // ---- -// Warning: (25-31): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol index 9251df73..4f89e69e 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/096_access_to_default_function_visibility.sol @@ -5,4 +5,3 @@ contract d { function g() public { c(0).f(); } } // ---- -// Warning: (17-39): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol index 824543ef..af392402 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/104_empty_name_input_parameter.sol @@ -2,4 +2,3 @@ contract test { function f(uint) public { } } // ---- -// Warning: (20-47): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol index a2ffc6e1..b524cd97 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/106_empty_name_return_parameter.sol @@ -2,4 +2,3 @@ contract test { function f() public returns (bool) { } } // ---- -// Warning: (20-58): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol index 93e5f065..9d2951b8 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/201_integer_signed_exp_signed.sol @@ -1,3 +1,9 @@ -contract test { function() external { int x = -3; int y = -4; x ** y; } } +contract test { + function f() public { int x = 3; int y = 4; x ** y; } + function g() public { int16 x = 3; uint8 y = 4; x ** y; } + function h() public { uint8 x = 3; int16 y = 4; x ** y; } +} // ---- -// TypeError: (62-68): Operator ** not compatible with types int256 and int256 +// TypeError: (64-70): Operator ** not compatible with types int256 and int256. Exponentiation is not allowed for signed integer types. +// TypeError: (126-132): Operator ** not compatible with types int16 and uint8. Exponentiation is not allowed for signed integer types. +// TypeError: (188-194): Operator ** not compatible with types uint8 and int16. Exponentiation is not allowed for signed integer types. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol index c5175a41..0f4388d0 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/216_function_argument_storage_to_mem.sol @@ -6,5 +6,3 @@ contract C { } } // ---- -// Warning: (91-106): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (80-122): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol index 155281f5..f033b85b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/256_using_for_overload.sol @@ -11,4 +11,3 @@ contract C { } } // ---- -// Warning: (128-189): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol index 20d8afa5..ee5bcda9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/260_library_memory_struct.sol @@ -5,4 +5,3 @@ library c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// Warning: (75-116): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol index e9ab08ba..a92c07f3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/288_conditional_with_all_types.sol @@ -85,7 +85,5 @@ contract C { } // ---- // Warning: (1005-1019): This declaration shadows an existing declaration. -// Warning: (90-116): Function state mutability can be restricted to pure -// Warning: (121-147): Function state mutability can be restricted to pure // Warning: (257-642): Function state mutability can be restricted to pure // Warning: (647-1227): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol index 441cf81e..295cf4ea 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/313_fixed_type_size_capabilities.sol @@ -10,4 +10,5 @@ contract test { } } // ---- -// Warning: (20-707): Function state mutability can be restricted to pure +// TypeError: (153-250): Type rational_const 9208...(70 digits omitted)...7637 / 1000...(71 digits omitted)...0000 is not implicitly convertible to expected type ufixed256x77, but it can be explicitly converted. +// TypeError: (470-566): Type rational_const -933...(70 digits omitted)...0123 / 1000...(70 digits omitted)...0000 is not implicitly convertible to expected type fixed256x76, but it can be explicitly converted. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol index 7f640505..109e8dfb 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/345_unused_return_value.sol @@ -5,4 +5,3 @@ contract test { } } // ---- -// Warning: (20-57): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol index 0032f99e..87a7b28d 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol @@ -10,4 +10,3 @@ contract test { } } // ---- -// Warning: (122-151): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol index 2575954e..b4088068 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/403_return_structs.sol @@ -7,4 +7,3 @@ contract C { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// Warning: (112-164): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol index 8a36eaad..4227cbb9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/437_warn_unused_function_parameter.sol @@ -3,4 +3,3 @@ contract C { } } // ---- -// Warning: (28-34): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol index b1422c4f..b4c9be35 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/439_warn_unused_return_parameter.sol @@ -3,4 +3,3 @@ contract C { } } // ---- -// Warning: (51-57): Unused function parameter. Remove or comment out the variable name to silence this warning. diff --git a/test/libsolidity/syntaxTests/parsing/empty_function.sol b/test/libsolidity/syntaxTests/parsing/empty_function.sol index 320a0bcc..3f42e4e3 100644 --- a/test/libsolidity/syntaxTests/parsing/empty_function.sol +++ b/test/libsolidity/syntaxTests/parsing/empty_function.sol @@ -3,7 +3,3 @@ contract test { function functionName(bytes20 arg1, address addr) public view returns (int id) { } } // ---- -// Warning: (58-70): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (72-84): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (107-113): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (36-118): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/external_function.sol b/test/libsolidity/syntaxTests/parsing/external_function.sol index 3aa3ceec..0315b200 100644 --- a/test/libsolidity/syntaxTests/parsing/external_function.sol +++ b/test/libsolidity/syntaxTests/parsing/external_function.sol @@ -2,4 +2,3 @@ contract c { function x() external {} } // ---- -// Warning: (17-41): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol b/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol index 94e1e60a..231be9c2 100644 --- a/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol +++ b/test/libsolidity/syntaxTests/parsing/function_normal_comments.sol @@ -4,6 +4,3 @@ contract test { function functionName(bytes32 input) public returns (bytes32 out) {} } // ---- -// Warning: (97-110): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (128-139): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (75-143): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol b/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol index 11e77f25..42d8717a 100644 --- a/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol +++ b/test/libsolidity/syntaxTests/parsing/function_type_as_storage_variable_with_assignment.sol @@ -3,7 +3,3 @@ contract test { function (uint, uint) internal returns (uint) f1 = f; } // ---- -// Warning: (31-37): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (39-45): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (63-69): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (20-73): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol b/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol index 3defb5ea..000c2011 100644 --- a/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol +++ b/test/libsolidity/syntaxTests/parsing/function_type_in_expression.sol @@ -5,9 +5,5 @@ contract test { } } // ---- -// Warning: (31-37): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (39-45): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (63-69): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning: (108-156): Unused local variable. -// Warning: (20-73): Function state mutability can be restricted to pure // Warning: (78-167): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/library_simple.sol b/test/libsolidity/syntaxTests/parsing/library_simple.sol index 006ff307..c892e3ed 100644 --- a/test/libsolidity/syntaxTests/parsing/library_simple.sol +++ b/test/libsolidity/syntaxTests/parsing/library_simple.sol @@ -2,4 +2,3 @@ library Lib { function f() public { } } // ---- -// Warning: (18-41): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol b/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol index cf986efe..6fa007c7 100644 --- a/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol +++ b/test/libsolidity/syntaxTests/parsing/modifier_invocation.sol @@ -4,4 +4,3 @@ contract c { function f() public mod1(7) mod2 { } } // ---- -// Warning: (135-171): Function state mutability can be restricted to view diff --git a/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol b/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol index 85d9e6a8..ba090c53 100644 --- a/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol +++ b/test/libsolidity/syntaxTests/parsing/multiple_functions_natspec_documentation.sol @@ -10,15 +10,3 @@ contract test { function functionName4(bytes32 input) public returns (bytes32 out) {} } // ---- -// Warning: (97-110): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (128-139): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (203-216): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (234-245): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (304-317): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (335-346): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (410-423): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (441-452): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (74-143): Function state mutability can be restricted to pure -// Warning: (180-249): Function state mutability can be restricted to pure -// Warning: (281-350): Function state mutability can be restricted to pure -// Warning: (387-456): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/no_function_params.sol b/test/libsolidity/syntaxTests/parsing/no_function_params.sol index 5a024bdb..1f7c85a3 100644 --- a/test/libsolidity/syntaxTests/parsing/no_function_params.sol +++ b/test/libsolidity/syntaxTests/parsing/no_function_params.sol @@ -3,4 +3,3 @@ contract test { function functionName() public {} } // ---- -// Warning: (36-69): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/single_function_param.sol b/test/libsolidity/syntaxTests/parsing/single_function_param.sol index 955f20f0..8dbac272 100644 --- a/test/libsolidity/syntaxTests/parsing/single_function_param.sol +++ b/test/libsolidity/syntaxTests/parsing/single_function_param.sol @@ -3,6 +3,3 @@ contract test { function functionName(bytes32 input) public returns (bytes32 out) {} } // ---- -// Warning: (58-71): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (89-100): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (36-104): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol b/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol index 5646c43b..f2542d90 100644 --- a/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol +++ b/test/libsolidity/syntaxTests/parsing/unary_plus_expression.sol @@ -6,3 +6,4 @@ contract test { } // ---- // SyntaxError: (70-72): Use of unary + is disallowed. +// TypeError: (70-72): Unary operator + cannot be applied to type uint256 diff --git a/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol b/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol index db890b37..24071388 100644 --- a/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol +++ b/test/libsolidity/syntaxTests/parsing/visibility_specifiers.sol @@ -9,6 +9,3 @@ contract c { } // ---- // Warning: (58-71): This declaration shadows an existing declaration. -// Warning: (89-111): Function state mutability can be restricted to pure -// Warning: (116-144): Function state mutability can be restricted to pure -// Warning: (149-182): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol b/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol new file mode 100644 index 00000000..f721f4a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/address/address_binary_operators.sol @@ -0,0 +1,15 @@ +contract C { + address a; + function f() public pure returns(bool) { + a = address(0) + address(0); + a = address(0) - address(0); + a = address(0) * address(0); + a = address(0) / address(0); + return address(0) == address(0); + } +} +// ---- +// TypeError: (85-108): Operator + not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError: (122-145): Operator - not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError: (159-182): Operator * not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. +// TypeError: (196-219): Operator / not compatible with types address payable and address payable. Arithmetic operations on addresses are not supported. Convert to integer first before using them. diff --git a/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol index 1b0b5f94..31226781 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol @@ -5,5 +5,5 @@ contract c { } } // ---- -// TypeError: (71-92): Operator / not compatible with types rational_const 1 / 5221...(1225 digits omitted)...5168 and int_const 5221...(1225 digits omitted)...5168 +// TypeError: (71-92): Operator / not compatible with types rational_const 1 / 5221...(1225 digits omitted)...5168 and int_const 5221...(1225 digits omitted)...5168. Precision of rational constants is limited to 4096 bits. // TypeError: (71-92): Type rational_const 1 / 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. Try converting to type ufixed8x80 or use an explicit conversion. diff --git a/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol index 058db2e9..80b23eff 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol @@ -19,23 +19,23 @@ contract c { } } // ---- -// TypeError: (71-102): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 +// TypeError: (71-102): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. // TypeError: (71-102): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. -// TypeError: (116-148): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 -// TypeError: (116-153): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 +// TypeError: (116-148): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. +// TypeError: (116-153): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. // TypeError: (116-153): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. // TypeError: (167-203): Operator ** not compatible with types int_const 4 and int_const -179...(302 digits omitted)...7216 // TypeError: (217-228): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 // TypeError: (242-254): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 // TypeError: (268-280): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 // TypeError: (294-307): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 -// TypeError: (321-332): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 +// TypeError: (321-332): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits. // TypeError: (321-332): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (346-358): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2 +// TypeError: (346-358): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits. // TypeError: (346-358): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (372-384): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2 +// TypeError: (372-384): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits. // TypeError: (372-384): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. -// TypeError: (398-411): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2 +// TypeError: (398-411): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits. // TypeError: (398-411): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. // TypeError: (425-441): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 // TypeError: (425-441): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol new file mode 100644 index 00000000..ca50e03b --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_to_fixed_implicit.sol @@ -0,0 +1,15 @@ +contract C { + function literalToUFixed() public pure { + ufixed8x2 a = 0.10; + ufixed8x2 b = 0.00; + ufixed8x2 c = 2.55; + a; b; c; + } + function literalToFixed() public pure { + fixed8x1 a = 0.1; + fixed8x1 b = 12.7; + fixed8x1 c = -12.8; + a; b; c; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol index bbed94b5..d725b43a 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol @@ -5,5 +5,5 @@ contract c { } } // ---- -// TypeError: (71-90): Operator * not compatible with types int_const 5221...(1225 digits omitted)...5168 and int_const 5221...(1225 digits omitted)...5168 +// TypeError: (71-90): Operator * not compatible with types int_const 5221...(1225 digits omitted)...5168 and int_const 5221...(1225 digits omitted)...5168. Precision of rational constants is limited to 4096 bits. // TypeError: (71-90): Type int_const 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol index 66bd9a8e..f86ffcdd 100644 --- a/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol +++ b/test/libsolidity/syntaxTests/types/too_small_negative_numbers.sol @@ -2,3 +2,4 @@ contract C { fixed8x80 a = -1e-100; } // ---- +// TypeError: (29-36): Type rational_const -1 / 1000...(93 digits omitted)...0000 is not implicitly convertible to expected type fixed8x80, but it can be explicitly converted. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol index 87719eb3..5ec6d06f 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/suggest_pure.sol @@ -2,4 +2,3 @@ contract C { function g() view public { } } // ---- -// Warning: (17-45): Function state mutability can be restricted to pure diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index a247a169..a337fa8d 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -29,6 +29,7 @@ #include <libyul/AsmParser.h> #include <libyul/AsmAnalysis.h> #include <libyul/AsmPrinter.h> +#include <libyul/backends/evm/EVMDialect.h> #include <liblangutil/Scanner.h> #include <liblangutil/ErrorReporter.h> @@ -40,9 +41,9 @@ using namespace langutil; using namespace yul; using namespace dev::solidity; -void yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) +void yul::test::printErrors(ErrorList const& _errors) { - SourceReferenceFormatter formatter(cout, [&](std::string const&) -> Scanner const& { return _scanner; }); + SourceReferenceFormatter formatter(cout); for (auto const& error: _errors) formatter.printExceptionInformation( @@ -54,11 +55,11 @@ void yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul) { - auto flavour = _yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; + shared_ptr<Dialect> dialect = _yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(); ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = make_shared<Scanner>(CharStream(_source, "")); - auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false); + auto parserResult = yul::Parser(errorReporter, dialect).parse(scanner, false); if (parserResult) { BOOST_REQUIRE(errorReporter.errors().empty()); @@ -68,7 +69,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin errorReporter, dev::test::Options::get().evmVersion(), boost::none, - flavour + dialect ); if (analyzer.analyze(*parserResult)) { @@ -76,7 +77,7 @@ pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(strin return make_pair(parserResult, analysisInfo); } } - printErrors(errors, *scanner); + printErrors(errors); BOOST_FAIL("Invalid source."); // Unreachable. diff --git a/test/libyul/Common.h b/test/libyul/Common.h index a1c64ca5..01fc416a 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -29,7 +29,6 @@ namespace langutil { -class Scanner; class Error; using ErrorList = std::vector<std::shared_ptr<Error const>>; } @@ -44,7 +43,7 @@ namespace yul namespace test { -void printErrors(langutil::ErrorList const& _errors, langutil::Scanner const& _scanner); +void printErrors(langutil::ErrorList const& _errors); std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>> parse(std::string const& _source, bool _yul = true); Block disambiguate(std::string const& _source, bool _yul = true); diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp new file mode 100644 index 00000000..e60f718d --- /dev/null +++ b/test/libyul/ObjectCompilerTest.cpp @@ -0,0 +1,134 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <test/libyul/ObjectCompilerTest.h> + +#include <test/libsolidity/FormattedScope.h> + +#include <libsolidity/interface/AssemblyStack.h> + +#include <libevmasm/Instruction.h> + +#include <liblangutil/SourceReferenceFormatter.h> + +#include <boost/algorithm/string.hpp> + +#include <fstream> + +using namespace dev; +using namespace langutil; +using namespace yul; +using namespace yul::test; +using namespace dev::solidity; +using namespace dev::solidity::test; +using namespace std; + +ObjectCompilerTest::ObjectCompilerTest(string const& _filename) +{ + boost::filesystem::path path(_filename); + + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test case: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + string line; + while (getline(file, line)) + { + if (boost::algorithm::starts_with(line, "// ----")) + break; + if (m_source.empty() && boost::algorithm::starts_with(line, "// optimize")) + m_optimize = true; + m_source += line + "\n"; + } + while (getline(file, line)) + if (boost::algorithm::starts_with(line, "//")) + m_expectation += line.substr((line.size() >= 3 && line[2] == ' ') ? 3 : 2) + "\n"; + else + m_expectation += line + "\n"; +} + +bool ObjectCompilerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + AssemblyStack stack(EVMVersion(), AssemblyStack::Language::StrictAssembly); + if (!stack.parseAndAnalyze("source", m_source)) + { + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; + printErrors(_stream, stack.errors()); + return false; + } + if (m_optimize) + stack.optimize(); + + MachineAssemblyObject obj = stack.assemble(AssemblyStack::Machine::EVM); + solAssert(obj.bytecode, ""); + + m_obtainedResult = "Assembly:\n" + obj.assembly; + if (obj.bytecode->bytecode.empty()) + m_obtainedResult += "-- empty bytecode --\n"; + else + m_obtainedResult += + "Bytecode: " + + toHex(obj.bytecode->bytecode) + + "\nOpcodes: " + + boost::trim_copy(solidity::disassemble(obj.bytecode->bytecode)) + + "\n"; + + if (m_expectation != m_obtainedResult) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Expected result:" << endl; + printIndented(_stream, m_expectation, nextIndentLevel); + FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::CYAN}) << _linePrefix << "Obtained result:" << endl; + printIndented(_stream, m_obtainedResult, nextIndentLevel); + return false; + } + return true; +} + +void ObjectCompilerTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + printIndented(_stream, m_source, _linePrefix); +} + +void ObjectCompilerTest::printUpdatedExpectations(ostream& _stream, string const& _linePrefix) const +{ + printIndented(_stream, m_obtainedResult, _linePrefix); +} + +void ObjectCompilerTest::printIndented(ostream& _stream, string const& _output, string const& _linePrefix) const +{ + stringstream output(_output); + string line; + while (getline(output, line)) + if (line.empty()) + // Avoid trailing spaces. + _stream << boost::trim_right_copy(_linePrefix) << endl; + else + _stream << _linePrefix << line << endl; +} + +void ObjectCompilerTest::printErrors(ostream& _stream, ErrorList const& _errors) +{ + SourceReferenceFormatter formatter(_stream); + + for (auto const& error: _errors) + formatter.printExceptionInformation( + *error, + (error->type() == Error::Type::Warning) ? "Warning" : "Error" + ); +} diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h new file mode 100644 index 00000000..a5f8d777 --- /dev/null +++ b/test/libyul/ObjectCompilerTest.h @@ -0,0 +1,69 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <test/TestCase.h> + +namespace langutil +{ +class Scanner; +class Error; +using ErrorList = std::vector<std::shared_ptr<Error const>>; +} + +namespace yul +{ +struct AsmAnalysisInfo; +struct Block; +} + +namespace yul +{ +namespace test +{ + +class ObjectCompilerTest: public dev::solidity::test::TestCase +{ +public: + static std::unique_ptr<TestCase> create(std::string const& _filename) + { + return std::unique_ptr<TestCase>(new ObjectCompilerTest(_filename)); + } + + explicit ObjectCompilerTest(std::string const& _filename); + + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + + void printSource(std::ostream& _stream, std::string const &_linePrefix = "", bool const _formatted = false) const override; + void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; + +private: + void printIndented(std::ostream& _stream, std::string const& _output, std::string const& _linePrefix = "") const; + bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); + void disambiguate(); + + static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors); + + std::string m_source; + bool m_optimize = false; + std::string m_expectation; + std::string m_obtainedResult; +}; + +} +} diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index caaf2719..df7e32a1 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -22,10 +22,12 @@ #include <test/Options.h> #include <test/libsolidity/ErrorCheck.h> +#include <test/libyul/Common.h> #include <libyul/AsmParser.h> #include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysisInfo.h> +#include <libyul/Dialect.h> #include <liblangutil/Scanner.h> #include <liblangutil/ErrorReporter.h> @@ -47,12 +49,12 @@ namespace test namespace { -bool parse(string const& _source, ErrorReporter& errorReporter) +bool parse(string const& _source, std::shared_ptr<Dialect> _dialect, ErrorReporter& errorReporter) { try { auto scanner = make_shared<Scanner>(CharStream(_source, "")); - auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Yul).parse(scanner, false); + auto parserResult = yul::Parser(errorReporter, _dialect).parse(scanner, false); if (parserResult) { yul::AsmAnalysisInfo analysisInfo; @@ -61,7 +63,7 @@ bool parse(string const& _source, ErrorReporter& errorReporter) errorReporter, dev::test::Options::get().evmVersion(), boost::none, - yul::AsmFlavour::Yul + _dialect )).analyze(*parserResult); } } @@ -72,13 +74,14 @@ bool parse(string const& _source, ErrorReporter& errorReporter) return false; } -boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true) +boost::optional<Error> parseAndReturnFirstError(string const& _source, shared_ptr<Dialect> _dialect, bool _allowWarnings = true) { ErrorList errors; ErrorReporter errorReporter(errors); - if (!parse(_source, errorReporter)) + if (!parse(_source, _dialect, errorReporter)) { - BOOST_REQUIRE_EQUAL(errors.size(), 1); + BOOST_REQUIRE(!errors.empty()); + BOOST_CHECK_EQUAL(errors.size(), 1); return *errors.front(); } else @@ -96,29 +99,31 @@ boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _all return {}; } -bool successParse(std::string const& _source, bool _allowWarnings = true) +bool successParse(std::string const& _source, shared_ptr<Dialect> _dialect = Dialect::yul(), bool _allowWarnings = true) { - return !parseAndReturnFirstError(_source, _allowWarnings); + return !parseAndReturnFirstError(_source, _dialect, _allowWarnings); } -Error expectError(std::string const& _source, bool _allowWarnings = false) +Error expectError(std::string const& _source, shared_ptr<Dialect> _dialect = Dialect::yul(), bool _allowWarnings = false) { - auto error = parseAndReturnFirstError(_source, _allowWarnings); + auto error = parseAndReturnFirstError(_source, _dialect, _allowWarnings); BOOST_REQUIRE(error); return *error; } } -#define CHECK_ERROR(text, typ, substring) \ +#define CHECK_ERROR_DIALECT(text, typ, substring, dialect) \ do \ { \ - Error err = expectError((text), false); \ + Error err = expectError((text), dialect, false); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ BOOST_CHECK(dev::solidity::searchErrorMessage(err, (substring))); \ } while(0) +#define CHECK_ERROR(text, typ, substring) CHECK_ERROR_DIALECT(text, typ, substring, Dialect::yul()) + BOOST_AUTO_TEST_SUITE(YulParser) BOOST_AUTO_TEST_CASE(smoke_test) @@ -299,6 +304,42 @@ BOOST_AUTO_TEST_CASE(if_statement_invalid) BOOST_CHECK(successParse("{ if 42:u256 { } }")); } +BOOST_AUTO_TEST_CASE(builtins_parser) +{ + struct SimpleDialect: public Dialect + { + SimpleDialect(): Dialect(AsmFlavour::Strict) {} + BuiltinFunction const* builtin(YulString _name) const override + { + return _name == "builtin"_yulstring ? &f : nullptr; + } + BuiltinFunction f; + }; + + shared_ptr<Dialect> dialect = make_shared<SimpleDialect>(); + CHECK_ERROR_DIALECT("{ let builtin := 6 }", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect); + CHECK_ERROR_DIALECT("{ function builtin() {} }", ParserError, "Cannot use builtin function name \"builtin\" as identifier name.", dialect); + CHECK_ERROR_DIALECT("{ builtin := 6 }", ParserError, "Cannot assign to builtin function \"builtin\".", dialect); +} + +BOOST_AUTO_TEST_CASE(builtins_analysis) +{ + struct SimpleDialect: public Dialect + { + SimpleDialect(): Dialect(AsmFlavour::Strict) {} + BuiltinFunction const* builtin(YulString _name) const override + { + return _name == "builtin"_yulstring ? &f : nullptr; + } + BuiltinFunction f{"builtin"_yulstring, vector<Type>(2), vector<Type>(3), false}; + }; + + shared_ptr<Dialect> dialect = make_shared<SimpleDialect>(); + BOOST_CHECK(successParse("{ let a, b, c := builtin(1, 2) }", dialect)); + CHECK_ERROR_DIALECT("{ let a, b, c := builtin(1) }", TypeError, "Function expects 2 arguments but got 1", dialect); + CHECK_ERROR_DIALECT("{ let a, b := builtin(1, 2) }", DeclarationError, "Variable count mismatch: 2 variables and 3 values.", dialect); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libyul/StackReuseCodegen.cpp b/test/libyul/StackReuseCodegen.cpp new file mode 100644 index 00000000..97be11d3 --- /dev/null +++ b/test/libyul/StackReuseCodegen.cpp @@ -0,0 +1,353 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * Unit tests for stack-reusing code generator. + */ + +#include <test/Options.h> + +#include <libsolidity/interface/AssemblyStack.h> +#include <libevmasm/Instruction.h> + +using namespace std; + +namespace dev +{ +namespace yul +{ +namespace test +{ + +namespace +{ +string assemble(string const& _input) +{ + solidity::AssemblyStack asmStack; + BOOST_REQUIRE_MESSAGE(asmStack.parseAndAnalyze("", _input), "Source did not parse: " + _input); + return solidity::disassemble(asmStack.assemble(solidity::AssemblyStack::Machine::EVM, true).bytecode->bytecode); +} +} + +BOOST_AUTO_TEST_SUITE(StackReuseCodegen) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + string out = assemble("{}"); + BOOST_CHECK_EQUAL(out, ""); +} + +BOOST_AUTO_TEST_CASE(single_var) +{ + string out = assemble("{ let x }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x0 POP "); +} + +BOOST_AUTO_TEST_CASE(single_var_assigned) +{ + string out = assemble("{ let x := 1 }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x1 POP "); +} + +BOOST_AUTO_TEST_CASE(single_var_assigned_plus_code) +{ + string out = assemble("{ let x := 1 mstore(3, 4) }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x1 POP PUSH1 0x4 PUSH1 0x3 MSTORE "); +} + +BOOST_AUTO_TEST_CASE(single_var_assigned_plus_code_and_reused) +{ + string out = assemble("{ let x := 1 mstore(3, 4) pop(mload(x)) }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x1 PUSH1 0x4 PUSH1 0x3 MSTORE DUP1 MLOAD POP POP "); +} + +BOOST_AUTO_TEST_CASE(multi_reuse_single_slot) +{ + string out = assemble("{ let x := 1 x := 6 let y := 2 y := 4 }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x1 PUSH1 0x6 SWAP1 POP POP PUSH1 0x2 PUSH1 0x4 SWAP1 POP POP "); +} + +BOOST_AUTO_TEST_CASE(multi_reuse_single_slot_nested) +{ + string out = assemble("{ let x := 1 x := 6 { let y := 2 y := 4 } }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x1 PUSH1 0x6 SWAP1 POP POP PUSH1 0x2 PUSH1 0x4 SWAP1 POP POP "); +} + +BOOST_AUTO_TEST_CASE(multi_reuse_same_variable_name) +{ + string out = assemble("{ let z := mload(0) { let x := 1 x := 6 z := x } { let x := 2 z := x x := 4 } }"); + BOOST_CHECK_EQUAL(out, + "PUSH1 0x0 MLOAD " + "PUSH1 0x1 PUSH1 0x6 SWAP1 POP DUP1 SWAP2 POP POP " + "PUSH1 0x2 DUP1 SWAP2 POP PUSH1 0x4 SWAP1 POP POP " + "POP " + ); +} + +BOOST_AUTO_TEST_CASE(last_use_in_nested_block) +{ + string out = assemble("{ let z := 0 { pop(z) } let x := 1 }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x0 DUP1 POP POP PUSH1 0x1 POP "); +} + +BOOST_AUTO_TEST_CASE(if_) +{ + // z is only removed after the if (after the jumpdest) + string out = assemble("{ let z := mload(0) if z { let x := z } let t := 3 }"); + BOOST_CHECK_EQUAL(out, "PUSH1 0x0 MLOAD DUP1 ISZERO PUSH1 0xA JUMPI DUP1 POP JUMPDEST POP PUSH1 0x3 POP "); +} + +BOOST_AUTO_TEST_CASE(switch_) +{ + string out = assemble("{ let z := 0 switch z case 0 { let x := 2 let y := 3 } default { z := 3 } let t := 9 }"); + BOOST_CHECK_EQUAL(out, + "PUSH1 0x0 DUP1 " + "PUSH1 0x0 DUP2 EQ PUSH1 0x11 JUMPI " + "PUSH1 0x3 SWAP2 POP PUSH1 0x18 JUMP " + "JUMPDEST PUSH1 0x2 POP PUSH1 0x3 POP " + "JUMPDEST POP POP " // This is where z and its copy (switch condition) can be removed. + "PUSH1 0x9 POP " + ); +} + +BOOST_AUTO_TEST_CASE(reuse_slots) +{ + // x and y should reuse the slots of b and d + string out = assemble("{ let a, b, c, d let x := 2 let y := 3 mstore(x, a) mstore(y, c) }"); + BOOST_CHECK_EQUAL(out, + "PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 " + "POP " // d is removed right away + "PUSH1 0x2 SWAP2 POP " // x is stored at b's slot + "PUSH1 0x3 DUP4 DUP4 MSTORE " + "DUP2 DUP2 MSTORE " + "POP POP POP POP " + ); +} + +BOOST_AUTO_TEST_CASE(for_1) +{ + // Special scoping rules, but can remove z early + string out = assemble("{ for { let z := 0 } 1 { } { let x := 3 } let t := 2 }"); + BOOST_CHECK_EQUAL(out, + "PUSH1 0x0 POP " + "JUMPDEST PUSH1 0x1 ISZERO PUSH1 0x11 JUMPI " + "PUSH1 0x3 POP JUMPDEST PUSH1 0x3 JUMP " + "JUMPDEST PUSH1 0x2 POP " + ); +} + +BOOST_AUTO_TEST_CASE(for_2) +{ + // Special scoping rules, cannot remove z until after the loop! + string out = assemble("{ for { let z := 0 } 1 { } { z := 8 let x := 3 } let t := 2 }"); + BOOST_CHECK_EQUAL(out, + "PUSH1 0x0 " + "JUMPDEST PUSH1 0x1 ISZERO PUSH1 0x14 JUMPI " + "PUSH1 0x8 SWAP1 POP " + "PUSH1 0x3 POP " + "JUMPDEST PUSH1 0x2 JUMP " + "JUMPDEST POP " // z is removed + "PUSH1 0x2 POP " + ); +} + +BOOST_AUTO_TEST_CASE(function_trivial) +{ + string in = R"({ + function f() { } + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x5 JUMP JUMPDEST JUMP JUMPDEST " + ); +} + +BOOST_AUTO_TEST_CASE(function_retparam) +{ + string in = R"({ + function f() -> x, y { } + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0xB JUMP " + "JUMPDEST PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 JUMP " + "JUMPDEST " + ); +} + +BOOST_AUTO_TEST_CASE(function_params) +{ + string in = R"({ + function f(a, b) { } + })"; + BOOST_CHECK_EQUAL(assemble(in), "PUSH1 0x7 JUMP JUMPDEST POP POP JUMP JUMPDEST "); +} + +BOOST_AUTO_TEST_CASE(function_params_and_retparams) +{ + string in = R"({ + function f(a, b, c, d) -> x, y { } + })"; + // This does not re-use the parameters for the return parameters + // We do not expect parameters to be fully unused, so the stack + // layout for a function is still fixed, even though parameters + // can be re-used. + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x10 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 SWAP5 POP SWAP5 SWAP3 POP POP POP JUMP JUMPDEST " + ); +} + +BOOST_AUTO_TEST_CASE(function_params_and_retparams_partly_unused) +{ + string in = R"({ + function f(a, b, c, d) -> x, y { b := 3 let s := 9 y := 2 mstore(s, y) } + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x1E JUMP " + "JUMPDEST PUSH1 0x0 PUSH1 0x0 " + "PUSH1 0x3 SWAP4 POP " + "PUSH1 0x9 PUSH1 0x2 SWAP2 POP " + "DUP2 DUP2 MSTORE " + "POP SWAP5 POP SWAP5 SWAP3 POP POP POP JUMP " + "JUMPDEST " + ); +} + +BOOST_AUTO_TEST_CASE(function_with_body_embedded) +{ + string in = R"({ + let b := 3 + function f(a, r) -> t { + // r could be removed right away, but a cannot - this is not implemented, though + let x := a a := 3 t := a + } + b := 7 + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x3 PUSH1 " + "0x16 JUMP " + "JUMPDEST PUSH1 0x0 " // start of f, initialize t + "DUP2 POP " // let x := a + "PUSH1 0x3 SWAP2 POP " + "DUP2 SWAP1 POP " + "SWAP3 SWAP2 POP POP JUMP " + "JUMPDEST PUSH1 0x7 SWAP1 " + "POP POP " + ); +} + +BOOST_AUTO_TEST_CASE(function_call) +{ + string in = R"({ + let b := f(1, 2) + function f(a, r) -> t { } + b := f(3, 4) + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x9 PUSH1 0x2 PUSH1 0x1 PUSH1 0xD JUMP " + "JUMPDEST PUSH1 0x15 JUMP " // jump over f + "JUMPDEST PUSH1 0x0 SWAP3 SWAP2 POP POP JUMP " // f + "JUMPDEST PUSH1 0x1F PUSH1 0x4 PUSH1 0x3 PUSH1 0xD JUMP " + "JUMPDEST SWAP1 POP POP " + ); +} + + +BOOST_AUTO_TEST_CASE(functions_multi_return) +{ + string in = R"({ + function f(a, b) -> t { } + function g() -> r, s { } + let x := f(1, 2) + x := f(3, 4) + let y, z := g() + y, z := g() + let unused := 7 + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0xB JUMP " + "JUMPDEST PUSH1 0x0 SWAP3 SWAP2 POP POP JUMP " // f + "JUMPDEST PUSH1 0x17 JUMP " + "JUMPDEST PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 JUMP " // g + "JUMPDEST PUSH1 0x21 PUSH1 0x2 PUSH1 0x1 PUSH1 0x3 JUMP " // f(1, 2) + "JUMPDEST PUSH1 0x2B PUSH1 0x4 PUSH1 0x3 PUSH1 0x3 JUMP " // f(3, 4) + "JUMPDEST SWAP1 POP " // assignment to x + "POP " // remove x + "PUSH1 0x34 PUSH1 0xF JUMP " // g() + "JUMPDEST PUSH1 0x3A PUSH1 0xF JUMP " // g() + "JUMPDEST SWAP2 POP SWAP2 POP " // assignments + "POP POP " // removal of y and z + "PUSH1 0x7 POP " + ); +} + +BOOST_AUTO_TEST_CASE(reuse_slots_function) +{ + string in = R"({ + function f() -> x, y, z, t {} + let a, b, c, d := f() let x1 := 2 let y1 := 3 mstore(x1, a) mstore(y1, c) + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x11 JUMP " + "JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 SWAP3 SWAP4 JUMP " + "JUMPDEST PUSH1 0x17 PUSH1 0x3 JUMP " + // Stack: a b c d + "JUMPDEST POP " // d is unused + // Stack: a b c + "PUSH1 0x2 SWAP2 POP " // x1 reuses b's slot + "PUSH1 0x3 " + // Stack: a x1 c y1 + "DUP4 DUP4 MSTORE " + "DUP2 DUP2 MSTORE " + "POP POP POP POP " + ); +} + +BOOST_AUTO_TEST_CASE(reuse_slots_function_with_gaps) +{ + string in = R"({ + // Only x3 is actually used, the slots of + // x1 and x2 will be reused right away. + let x1 := 5 let x2 := 6 let x3 := 7 + mstore(x1, x2) + function f() -> x, y, z, t {} + let a, b, c, d := f() mstore(x3, a) mstore(c, d) + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x5 PUSH1 0x6 PUSH1 0x7 " + "DUP2 DUP4 MSTORE " + "PUSH1 0x1A JUMP " // jump across function + "JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 SWAP1 SWAP2 SWAP3 SWAP4 JUMP " + "JUMPDEST PUSH1 0x20 PUSH1 0xC JUMP " + // stack: x1 x2 x3 a b c d + "JUMPDEST SWAP6 POP " // move d into x1 + // stack: d x2 x3 a b c + "SWAP4 POP " + // stack: d c x3 a b + "POP " + // stack: d c x3 a + "DUP1 DUP3 MSTORE " + "POP POP " + // stack: d c + "DUP2 DUP2 MSTORE " + "POP POP " + ); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 15d70faa..9643a1e9 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -22,7 +22,7 @@ #include <test/Options.h> #include <libyul/optimiser/BlockFlattener.h> -#include <libyul/optimiser/VarDeclPropagator.h> +#include <libyul/optimiser/VarDeclInitializer.h> #include <libyul/optimiser/Disambiguator.h> #include <libyul/optimiser/CommonSubexpressionEliminator.h> #include <libyul/optimiser/NameCollector.h> @@ -39,7 +39,9 @@ #include <libyul/optimiser/ExpressionJoiner.h> #include <libyul/optimiser/SSATransform.h> #include <libyul/optimiser/RedundantAssignEliminator.h> +#include <libyul/optimiser/StructuralSimplifier.h> #include <libyul/optimiser/Suite.h> +#include <libyul/backends/evm/EVMDialect.h> #include <libyul/AsmPrinter.h> #include <libyul/AsmParser.h> #include <libyul/AsmAnalysis.h> @@ -105,11 +107,8 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); BlockFlattener{}(*m_ast); } - else if (m_optimizerStep == "varDeclPropagator") - { - disambiguate(); - VarDeclPropagator{}(*m_ast); - } + else if (m_optimizerStep == "varDeclInitializer") + VarDeclInitializer{}(*m_ast); else if (m_optimizerStep == "forLoopInitRewriter") { disambiguate(); @@ -213,6 +212,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con SSATransform::run(*m_ast, nameDispenser); RedundantAssignEliminator::run(*m_ast); } + else if (m_optimizerStep == "structuralSimplifier") + { + disambiguate(); + StructuralSimplifier{}(*m_ast); + } else if (m_optimizerStep == "fullSuite") OptimiserSuite::run(*m_ast, *m_analysisInfo); else @@ -256,15 +260,15 @@ void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, st bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted) { - yul::AsmFlavour flavour = m_yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; + shared_ptr<yul::Dialect> dialect = m_yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVM(); ErrorList errors; ErrorReporter errorReporter(errors); shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, "")); - m_ast = yul::Parser(errorReporter, flavour).parse(scanner, false); + m_ast = yul::Parser(errorReporter, dialect).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; - printErrors(_stream, errorReporter.errors(), *scanner); + printErrors(_stream, errorReporter.errors()); return false; } m_analysisInfo = make_shared<yul::AsmAnalysisInfo>(); @@ -273,12 +277,12 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c errorReporter, dev::test::Options::get().evmVersion(), boost::none, - flavour + dialect ); if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error analyzing source." << endl; - printErrors(_stream, errorReporter.errors(), *scanner); + printErrors(_stream, errorReporter.errors()); return false; } return true; @@ -290,9 +294,9 @@ void YulOptimizerTest::disambiguate() m_analysisInfo.reset(); } -void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors, Scanner const& _scanner) +void YulOptimizerTest::printErrors(ostream& _stream, ErrorList const& _errors) { - SourceReferenceFormatter formatter(_stream, [&](string const&) -> Scanner const& { return _scanner; }); + SourceReferenceFormatter formatter(_stream); for (auto const& error: _errors) formatter.printExceptionInformation( diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 90026e24..5648e995 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -57,7 +57,7 @@ private: bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); void disambiguate(); - static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors, langutil::Scanner const& _scanner); + static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors); std::string m_source; bool m_yul = false; diff --git a/test/libyul/objectCompiler/data.yul b/test/libyul/objectCompiler/data.yul new file mode 100644 index 00000000..daa22d21 --- /dev/null +++ b/test/libyul/objectCompiler/data.yul @@ -0,0 +1,11 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + data "str" "Hello, World!" +} +// ---- +// Assembly: +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: fe +// Opcodes: INVALID diff --git a/test/libyul/objectCompiler/datacopy.yul b/test/libyul/objectCompiler/datacopy.yul new file mode 100644 index 00000000..2259e5dc --- /dev/null +++ b/test/libyul/objectCompiler/datacopy.yul @@ -0,0 +1,48 @@ +object "a" { + code { + datacopy(0, dataoffset("sub"), datasize("sub")) + return(0, datasize("sub")) + } + object "sub" { + code { + sstore(0, dataoffset("sub")) + mstore(0, datasize("data1")) + } + data "data1" "Hello, World!" + } +} +// ---- +// Assembly: +// /* "source":26:73 */ +// dataSize(sub_0) +// dataOffset(sub_0) +// /* "source":35:36 */ +// 0x00 +// /* "source":26:73 */ +// codecopy +// /* "source":78:104 */ +// dataSize(sub_0) +// /* "source":85:86 */ +// 0x00 +// /* "source":78:104 */ +// return +// stop +// +// sub_0: assembly { +// /* "source":143:171 */ +// 0x00 +// /* "source":150:151 */ +// 0x00 +// /* "source":143:171 */ +// sstore +// /* "source":178:206 */ +// 0x0d +// /* "source":185:186 */ +// 0x00 +// /* "source":178:206 */ +// mstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// } +// Bytecode: 600b600d600039600b6000f3fe6000600055600d600052fe +// Opcodes: PUSH1 0xB PUSH1 0xD PUSH1 0x0 CODECOPY PUSH1 0xB PUSH1 0x0 RETURN INVALID PUSH1 0x0 PUSH1 0x0 SSTORE PUSH1 0xD PUSH1 0x0 MSTORE INVALID diff --git a/test/libyul/objectCompiler/dataoffset_code.yul b/test/libyul/objectCompiler/dataoffset_code.yul new file mode 100644 index 00000000..725267f2 --- /dev/null +++ b/test/libyul/objectCompiler/dataoffset_code.yul @@ -0,0 +1,29 @@ +object "a" { + code { sstore(0, dataoffset("sub")) } + object "sub" { + code { sstore(0, 8) } + data "data1" "Hello, World!" + } +} +// ---- +// Assembly: +// /* "source":22:50 */ +// dataOffset(sub_0) +// /* "source":29:30 */ +// 0x00 +// /* "source":22:50 */ +// sstore +// stop +// +// sub_0: assembly { +// /* "source":91:92 */ +// 0x08 +// /* "source":88:89 */ +// 0x00 +// /* "source":81:93 */ +// sstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// } +// Bytecode: 6006600055fe6008600055fe +// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID PUSH1 0x8 PUSH1 0x0 SSTORE INVALID diff --git a/test/libyul/objectCompiler/dataoffset_data.yul b/test/libyul/objectCompiler/dataoffset_data.yul new file mode 100644 index 00000000..9a0a461d --- /dev/null +++ b/test/libyul/objectCompiler/dataoffset_data.yul @@ -0,0 +1,16 @@ +object "a" { + code { sstore(0, dataoffset("data1")) } + data "data1" "Hello, World!" +} +// ---- +// Assembly: +// /* "source":22:52 */ +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f +// /* "source":29:30 */ +// 0x00 +// /* "source":22:52 */ +// sstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: 6006600055fe48656c6c6f2c20576f726c6421 +// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID 0x48 PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000 diff --git a/test/libyul/objectCompiler/dataoffset_self.yul b/test/libyul/objectCompiler/dataoffset_self.yul new file mode 100644 index 00000000..b7740735 --- /dev/null +++ b/test/libyul/objectCompiler/dataoffset_self.yul @@ -0,0 +1,16 @@ +object "a" { + code { sstore(0, dataoffset("a")) } + data "data1" "Hello, World!" +} +// ---- +// Assembly: +// /* "source":22:48 */ +// 0x00 +// /* "source":29:30 */ +// 0x00 +// /* "source":22:48 */ +// sstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: 6000600055fe +// Opcodes: PUSH1 0x0 PUSH1 0x0 SSTORE INVALID diff --git a/test/libyul/objectCompiler/datasize_code.yul b/test/libyul/objectCompiler/datasize_code.yul new file mode 100644 index 00000000..cff68515 --- /dev/null +++ b/test/libyul/objectCompiler/datasize_code.yul @@ -0,0 +1,29 @@ +object "a" { + code { sstore(0, datasize("sub")) } + object "sub" { + code { sstore(0, 8) } + data "data1" "Hello, World!" + } +} +// ---- +// Assembly: +// /* "source":22:48 */ +// dataSize(sub_0) +// /* "source":29:30 */ +// 0x00 +// /* "source":22:48 */ +// sstore +// stop +// +// sub_0: assembly { +// /* "source":89:90 */ +// 0x08 +// /* "source":86:87 */ +// 0x00 +// /* "source":79:91 */ +// sstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// } +// Bytecode: 6006600055fe +// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID diff --git a/test/libyul/objectCompiler/datasize_data.yul b/test/libyul/objectCompiler/datasize_data.yul new file mode 100644 index 00000000..f8341469 --- /dev/null +++ b/test/libyul/objectCompiler/datasize_data.yul @@ -0,0 +1,16 @@ +object "a" { + code { sstore(0, datasize("data1")) } + data "data1" "Hello, World!" +} +// ---- +// Assembly: +// /* "source":22:50 */ +// 0x0d +// /* "source":29:30 */ +// 0x00 +// /* "source":22:50 */ +// sstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: 600d600055fe +// Opcodes: PUSH1 0xD PUSH1 0x0 SSTORE INVALID diff --git a/test/libyul/objectCompiler/datasize_self.yul b/test/libyul/objectCompiler/datasize_self.yul new file mode 100644 index 00000000..4579fe67 --- /dev/null +++ b/test/libyul/objectCompiler/datasize_self.yul @@ -0,0 +1,16 @@ +object "a" { + code { sstore(0, datasize("a")) } + data "data1" "Hello, World!" +} +// ---- +// Assembly: +// /* "source":22:46 */ +// bytecodeSize +// /* "source":29:30 */ +// 0x00 +// /* "source":22:46 */ +// sstore +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// Bytecode: 6006600055fe +// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID diff --git a/test/libyul/objectCompiler/namedObject.yul b/test/libyul/objectCompiler/namedObject.yul new file mode 100644 index 00000000..940160fd --- /dev/null +++ b/test/libyul/objectCompiler/namedObject.yul @@ -0,0 +1,6 @@ +object "a" { + code {} +} +// ---- +// Assembly: +// -- empty bytecode -- diff --git a/test/libyul/objectCompiler/namedObjectCode.yul b/test/libyul/objectCompiler/namedObjectCode.yul new file mode 100644 index 00000000..4fc6891c --- /dev/null +++ b/test/libyul/objectCompiler/namedObjectCode.yul @@ -0,0 +1,13 @@ +object "a" { + code { sstore(0, 1) } +} +// ---- +// Assembly: +// /* "source":32:33 */ +// 0x01 +// /* "source":29:30 */ +// 0x00 +// /* "source":22:34 */ +// sstore +// Bytecode: 6001600055 +// Opcodes: PUSH1 0x1 PUSH1 0x0 SSTORE diff --git a/test/libyul/objectCompiler/nested_optimizer.yul b/test/libyul/objectCompiler/nested_optimizer.yul new file mode 100644 index 00000000..7739ce61 --- /dev/null +++ b/test/libyul/objectCompiler/nested_optimizer.yul @@ -0,0 +1,49 @@ +// optimize +object "a" { + code { + let x := calldataload(0) + let y := calldataload(0) + let z := sub(y, x) + sstore(add(x, 0), z) + } + object "sub" { + code { + let x := calldataload(0) + let y := calldataload(0) + let z := sub(y, x) + sstore(add(x, 0), z) + } + } +} +// ---- +// Assembly: +// /* "source":60:61 */ +// 0x00 +// /* "source":137:138 */ +// dup1 +// /* "source":60:61 */ +// dup2 +// /* "source":47:62 */ +// calldataload +// /* "source":119:139 */ +// sstore +// /* "source":32:143 */ +// pop +// stop +// +// sub_0: assembly { +// /* "source":200:201 */ +// 0x00 +// /* "source":283:284 */ +// dup1 +// /* "source":200:201 */ +// dup2 +// /* "source":187:202 */ +// calldataload +// /* "source":265:285 */ +// sstore +// /* "source":170:291 */ +// pop +// } +// Bytecode: 60008081355550fe +// Opcodes: PUSH1 0x0 DUP1 DUP2 CALLDATALOAD SSTORE POP INVALID diff --git a/test/libyul/objectCompiler/simple.yul b/test/libyul/objectCompiler/simple.yul new file mode 100644 index 00000000..d41b527c --- /dev/null +++ b/test/libyul/objectCompiler/simple.yul @@ -0,0 +1,13 @@ +{ + sstore(0, 1) +} +// ---- +// Assembly: +// /* "source":14:15 */ +// 0x01 +// /* "source":11:12 */ +// 0x00 +// /* "source":4:16 */ +// sstore +// Bytecode: 6001600055 +// Opcodes: PUSH1 0x1 PUSH1 0x0 SSTORE diff --git a/test/libyul/objectCompiler/simple_optimizer.yul b/test/libyul/objectCompiler/simple_optimizer.yul new file mode 100644 index 00000000..43b33553 --- /dev/null +++ b/test/libyul/objectCompiler/simple_optimizer.yul @@ -0,0 +1,23 @@ +// optimize +{ + let x := calldataload(0) + let y := calldataload(0) + let z := sub(y, x) + sstore(add(x, 0), z) +} +// ---- +// Assembly: +// /* "source":38:39 */ +// 0x00 +// /* "source":109:110 */ +// dup1 +// /* "source":38:39 */ +// dup2 +// /* "source":25:40 */ +// calldataload +// /* "source":91:111 */ +// sstore +// /* "source":12:113 */ +// pop +// Bytecode: 60008081355550 +// Opcodes: PUSH1 0x0 DUP1 DUP2 CALLDATALOAD SSTORE POP diff --git a/test/libyul/objectCompiler/smoke.yul b/test/libyul/objectCompiler/smoke.yul new file mode 100644 index 00000000..b2e44d4d --- /dev/null +++ b/test/libyul/objectCompiler/smoke.yul @@ -0,0 +1,5 @@ +{ +} +// ---- +// Assembly: +// -- empty bytecode -- diff --git a/test/libyul/objectCompiler/subObject.yul b/test/libyul/objectCompiler/subObject.yul new file mode 100644 index 00000000..98ea4d07 --- /dev/null +++ b/test/libyul/objectCompiler/subObject.yul @@ -0,0 +1,21 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + data "str" "Hello, World!" + object "sub" { code { sstore(0, 1) } } +} +// ---- +// Assembly: +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// +// sub_0: assembly { +// /* "source":149:150 */ +// 0x01 +// /* "source":146:147 */ +// 0x00 +// /* "source":139:151 */ +// sstore +// } +// Bytecode: fe +// Opcodes: INVALID diff --git a/test/libyul/objectCompiler/subSubObject.yul b/test/libyul/objectCompiler/subSubObject.yul new file mode 100644 index 00000000..5e01f6dd --- /dev/null +++ b/test/libyul/objectCompiler/subSubObject.yul @@ -0,0 +1,39 @@ +object "a" { + code {} + // Unreferenced data is not added to the assembled bytecode. + data "str" "Hello, World!" + object "sub" { + code { sstore(0, 1) } + object "subsub" { + code { sstore(2, 3) } + data "str" hex"123456" + } + } +} +// ---- +// Assembly: +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// +// sub_0: assembly { +// /* "source":153:154 */ +// 0x01 +// /* "source":150:151 */ +// 0x00 +// /* "source":143:155 */ +// sstore +// stop +// +// sub_0: assembly { +// /* "source":203:204 */ +// 0x03 +// /* "source":200:201 */ +// 0x02 +// /* "source":193:205 */ +// sstore +// stop +// data_6adf031833174bbe4c85eafe59ddb54e6584648c2c962c6f94791ab49caa0ad4 123456 +// } +// } +// Bytecode: fe +// Opcodes: INVALID diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul new file mode 100644 index 00000000..5283ef9a --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_return.yul @@ -0,0 +1,23 @@ +{ + function f() -> x { + // can re-use x + let y := 0 + mstore(y, 7) + } + let a + // can re-use a + let b := 0 + sstore(a, b) +} +// ---- +// commonSubexpressionEliminator +// { +// function f() -> x +// { +// let y := x +// mstore(x, 7) +// } +// let a +// let b := a +// sstore(a, a) +// } diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul new file mode 100644 index 00000000..a790ca65 --- /dev/null +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/unassigned_variables.yul @@ -0,0 +1,14 @@ +{ + // This does not replace b by a because there is no + // explicit assignment, even though both hold the same value. + let a + let b + mstore(sub(a, b), 7) +} +// ---- +// commonSubexpressionEliminator +// { +// let a +// let b +// mstore(sub(a, b), 7) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul new file mode 100644 index 00000000..51f5df40 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/assigned_vars_multi.yul @@ -0,0 +1,14 @@ +{ + function f() -> x, z {} + let c, d := f() + let y := add(d, add(c, 7)) +} +// ---- +// expressionSimplifier +// { +// function f() -> x, z +// { +// } +// let c, d := f() +// let y := add(add(d, c), 7) +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul new file mode 100644 index 00000000..46f9bc40 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/return_vars_zero.yul @@ -0,0 +1,14 @@ +// return variables are assumed to be zero initially. +{ + function f() -> c, d { + let y := add(d, add(c, 7)) + } +} +// ---- +// expressionSimplifier +// { +// function f() -> c, d +// { +// let y := 7 +// } +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul new file mode 100644 index 00000000..f260db0b --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigend_vars_multi.yul @@ -0,0 +1,11 @@ +// Unassigned variables are assumed to be zero. +{ + let c, d + let y := add(d, add(c, 7)) +} +// ---- +// expressionSimplifier +// { +// let c, d +// let y := 7 +// } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul new file mode 100644 index 00000000..7b1430f3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/unassigned_vars.yul @@ -0,0 +1,13 @@ +// Unassigned variables are assumed to be zero. +{ + let c + let d + let y := add(d, add(c, 7)) +} +// ---- +// expressionSimplifier +// { +// let c +// let d +// let y := 7 +// } diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul new file mode 100644 index 00000000..3f7aa089 --- /dev/null +++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/nested.yul @@ -0,0 +1,48 @@ +{ + let random := 42 + for { + for { let a := 1} iszero(eq(a,10)) {} { + a := add(a, 1) + } + let b := 1 + } iszero(eq(b, 10)) { + for { let c := 1 } iszero(eq(c,2)) { c := add(c, 1) } { + b := add(b, 1) + } + } { + mstore(b,b) + } +} +// ---- +// forLoopInitRewriter +// { +// let random := 42 +// let a := 1 +// for { +// } +// iszero(eq(a, 10)) +// { +// } +// { +// a := add(a, 1) +// } +// let b := 1 +// for { +// } +// iszero(eq(b, 10)) +// { +// let c := 1 +// for { +// } +// iszero(eq(c, 2)) +// { +// c := add(c, 1) +// } +// { +// b := add(b, 1) +// } +// } +// { +// mstore(b, b) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul index ee7f5bf5..b3f51593 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/double_inline.yul @@ -9,14 +9,14 @@ // { // { // let f_a := calldataload(0) -// let f_b -// let f_c +// let f_b := 0 +// let f_c := 0 // f_b := sload(mload(f_a)) // f_c := 3 // let b3 := f_b // let f_a_2 := f_c -// let f_b_3 -// let f_c_4 +// let f_b_3 := 0 +// let f_c_4 := 0 // f_b_3 := sload(mload(f_a_2)) // f_c_4 := 3 // let b4 := f_b_3 diff --git a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul index 00bb6577..9e6c4e76 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/inside_condition.yul @@ -14,7 +14,7 @@ // { // let _2 := mload(0) // let f_a := mload(1) -// let f_r +// let f_r := 0 // f_a := mload(f_a) // f_r := add(f_a, calldatasize()) // if gt(f_r, _2) diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul index 0972ac56..c00b1163 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_multi_use.yul @@ -2,8 +2,6 @@ function f(a) -> b { let x := mload(a) b := sload(x) - let c := 3 - mstore(mul(a, b), mload(x)) let y := add(a, x) sstore(y, 10) } @@ -13,6 +11,9 @@ let r := f(a) // This should be inlined because it is a constant let t := f(a2) + let a3 + // This should be inlined because it is a constant as well (zero) + let s := f(a3) } // ---- // fullInliner @@ -22,21 +23,25 @@ // let a2 := 2 // let r := f(a_1) // let f_a := a2 -// let f_b +// let f_b := 0 // let f_x := mload(f_a) // f_b := sload(f_x) -// let f_c := 3 -// mstore(mul(f_a, f_b), mload(f_x)) // let f_y := add(f_a, f_x) // sstore(f_y, 10) // let t := f_b +// let a3 +// let f_a_3 := a3 +// let f_b_4 := 0 +// let f_x_5 := mload(f_a_3) +// f_b_4 := sload(f_x_5) +// let f_y_6 := add(f_a_3, f_x_5) +// sstore(f_y_6, 10) +// let s := f_b_4 // } // function f(a) -> b // { // let x := mload(a) // b := sload(x) -// let c := 3 -// mstore(mul(a, b), mload(x)) // let y := add(a, x) // sstore(y, 10) // } diff --git a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul index 3302a35c..72beb8b1 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/large_function_single_use.yul @@ -15,7 +15,7 @@ // { // { // let f_a := mload(1) -// let f_b +// let f_b := 0 // let f_x := mload(f_a) // f_b := sload(f_x) // let f_c := 3 diff --git a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul index 644e9126..869abbc9 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/long_names.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/long_names.yul @@ -13,7 +13,7 @@ // { // let verylongvariablename2_1 := 3 // let verylongfu_verylongvariablename := verylongvariablename2_1 -// let verylongfu_verylongvariablename2 +// let verylongfu_verylongvariablename2 := 0 // verylongfu_verylongvariablename2 := add(verylongfu_verylongvariablename, verylongfu_verylongvariablename) // mstore(0, verylongfu_verylongvariablename2) // mstore(1, verylongvariablename2_1) diff --git a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul index f3d0b286..0b46a3c6 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul @@ -15,7 +15,7 @@ // let f_a := mload(2) // let f_b := _6 // let f_c := _4 -// let f_x +// let f_x := 0 // f_x := add(f_a, f_b) // f_x := mul(f_x, f_c) // let _10 := add(f_x, _2) diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul index 8bc6ec58..5d658e96 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun.yul @@ -9,11 +9,11 @@ // { // let _1 := 7 // let f_a := 3 -// let f_x +// let f_x := 0 // f_x := add(f_a, f_a) // let g_b := f_x // let g_c := _1 -// let g_y +// let g_y := 0 // g_y := mul(mload(g_c), f(g_b)) // let y_1 := g_y // } @@ -24,7 +24,7 @@ // function g(b, c) -> y // { // let f_a_6 := b -// let f_x_7 +// let f_x_7 := 0 // f_x_7 := add(f_a_6, f_a_6) // y := mul(mload(c), f_x_7) // } diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul index 19ac945e..6e4acb97 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_fun_callback.yul @@ -37,7 +37,7 @@ // function f(x) // { // mstore(0, x) -// let h_t +// let h_t := 0 // h_t := 2 // mstore(7, h_t) // let g_x_1 := 10 diff --git a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul index eebdec38..a4cbbef0 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/multi_return.yul @@ -11,8 +11,8 @@ // { // { // let f_a := mload(0) -// let f_x -// let f_y +// let f_x := 0 +// let f_y := 0 // f_x := mul(f_a, f_a) // f_y := add(f_a, f_x) // let r := f_x diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul new file mode 100644 index 00000000..f59e2c11 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_function.yul @@ -0,0 +1,44 @@ +{ + function f(a) -> b { + let x := mload(a) + b := sload(x) + } + // This will stop inlining at some point because + // the function gets too big. + function g() -> x { + x := f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(2))))))))))))))))))) + } +} +// ---- +// fullInliner +// { +// function f(a) -> b +// { +// b := sload(mload(a)) +// } +// function g() -> x_1 +// { +// let f_a := 2 +// let f_b := 0 +// f_b := sload(mload(f_a)) +// let f_a_20 := f_b +// let f_b_21 := 0 +// f_b_21 := sload(mload(f_a_20)) +// let f_a_23 := f_b_21 +// let f_b_24 := 0 +// f_b_24 := sload(mload(f_a_23)) +// let f_a_26 := f_b_24 +// let f_b_27 := 0 +// f_b_27 := sload(mload(f_a_26)) +// let f_a_29 := f_b_27 +// let f_b_30 := 0 +// f_b_30 := sload(mload(f_a_29)) +// let f_a_32 := f_b_30 +// let f_b_33 := 0 +// f_b_33 := sload(mload(f_a_32)) +// let f_a_35 := f_b_33 +// let f_b_36 := 0 +// f_b_36 := sload(mload(f_a_35)) +// x_1 := f(f(f(f(f(f(f(f(f(f(f(f(f_b_36)))))))))))) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul new file mode 100644 index 00000000..f20b7221 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullInliner/no_inline_into_big_global_context.yul @@ -0,0 +1,41 @@ +{ + function f(a) -> b { + let x := mload(a) + b := sload(x) + } + // This will stop inlining at some point because + // the global context gets too big. + let x := f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(2))))))))))))))))))) +} +// ---- +// fullInliner +// { +// { +// let f_a := 2 +// let f_b := 0 +// f_b := sload(mload(f_a)) +// let f_a_20 := f_b +// let f_b_21 := 0 +// f_b_21 := sload(mload(f_a_20)) +// let f_a_23 := f_b_21 +// let f_b_24 := 0 +// f_b_24 := sload(mload(f_a_23)) +// let f_a_26 := f_b_24 +// let f_b_27 := 0 +// f_b_27 := sload(mload(f_a_26)) +// let f_a_29 := f_b_27 +// let f_b_30 := 0 +// f_b_30 := sload(mload(f_a_29)) +// let f_a_32 := f_b_30 +// let f_b_33 := 0 +// f_b_33 := sload(mload(f_a_32)) +// let f_a_35 := f_b_33 +// let f_b_36 := 0 +// f_b_36 := sload(mload(f_a_35)) +// let x_1 := f(f(f(f(f(f(f(f(f(f(f(f(f_b_36)))))))))))) +// } +// function f(a) -> b +// { +// b := sload(mload(a)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul index 9644e6c1..96d806bd 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul @@ -14,7 +14,7 @@ // { // for { // let f_a := 0 -// let f_r +// let f_r := 0 // sstore(f_a, 0) // f_r := f_a // let x := f_r @@ -22,14 +22,14 @@ // f(x) // { // let f_a_3 := x -// let f_r_4 +// let f_r_4 := 0 // sstore(f_a_3, 0) // f_r_4 := f_a_3 // x := f_r_4 // } // { // let f_a_6 := x -// let f_r_7 +// let f_r_7 := 0 // sstore(f_a_6, 0) // f_r_7 := f_a_6 // let t := f_r_7 diff --git a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul index cd9e2746..c1bed208 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/pop_result.yul @@ -14,7 +14,7 @@ // { // let _1 := 2 // let f_a := 7 -// let f_x +// let f_x := 0 // let f_r := mul(f_a, f_a) // f_x := add(f_r, f_r) // pop(add(f_x, _1)) diff --git a/test/libyul/yulOptimizerTests/fullInliner/simple.yul b/test/libyul/yulOptimizerTests/fullInliner/simple.yul index fcdf453b..1ada8f53 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/simple.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/simple.yul @@ -11,7 +11,7 @@ // { // let _2 := mload(7) // let f_a := sload(mload(2)) -// let f_x +// let f_x := 0 // let f_r := mul(f_a, f_a) // f_x := add(f_r, f_r) // let y := add(f_x, _2) diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul index a34da198..efb846f2 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi_example1.yul @@ -465,178 +465,166 @@ // let abi_encode_pos := _1 // let abi_encode_length_68 := mload(_485) // mstore(_1, abi_encode_length_68) -// let abi_encode_pos_590 := 64 -// abi_encode_pos := abi_encode_pos_590 +// abi_encode_pos := 64 // let abi_encode_srcPtr := add(_485, _1) +// let abi_encode_i_69 := _2 // for { -// let abi_encode_i_69 := _2 // } // lt(abi_encode_i_69, abi_encode_length_68) // { // abi_encode_i_69 := add(abi_encode_i_69, 1) // } // { -// let _931 := mload(abi_encode_srcPtr) -// let abi_encode_pos_71_1037 := abi_encode_pos -// let abi_encode_length_72_1038 := 0x3 -// let abi_encode_srcPtr_73_1039 := _931 +// let _863 := mload(abi_encode_srcPtr) +// let abi_encode_pos_71_971 := abi_encode_pos +// let abi_encode_length_72_972 := 0x3 +// let abi_encode_srcPtr_73_973 := _863 +// let abi_encode_i_74_974 := _2 // for { -// let abi_encode_i_74_1040 := _2 // } -// lt(abi_encode_i_74_1040, abi_encode_length_72_1038) +// lt(abi_encode_i_74_974, abi_encode_length_72_972) // { -// abi_encode_i_74_1040 := add(abi_encode_i_74_1040, 1) +// abi_encode_i_74_974 := add(abi_encode_i_74_974, 1) // } // { -// mstore(abi_encode_pos_71_1037, and(mload(abi_encode_srcPtr_73_1039), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) -// abi_encode_srcPtr_73_1039 := add(abi_encode_srcPtr_73_1039, _1) -// abi_encode_pos_71_1037 := add(abi_encode_pos_71_1037, _1) +// mstore(abi_encode_pos_71_971, and(mload(abi_encode_srcPtr_73_973), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) +// abi_encode_srcPtr_73_973 := add(abi_encode_srcPtr_73_973, _1) +// abi_encode_pos_71_971 := add(abi_encode_pos_71_971, _1) // } // abi_encode_srcPtr := add(abi_encode_srcPtr, _1) // abi_encode_pos := add(abi_encode_pos, 0x60) // } -// let _933 := 0x40 -// let _487 := mload(_933) -// let _488 := mload(_1) -// let abi_decode_value0_60_618 -// let abi_decode_value0_60 := abi_decode_value0_60_618 -// let abi_decode_value1_61_619 -// let abi_decode_value1_61 := abi_decode_value1_61_619 -// let abi_decode_value2_620 -// let abi_decode_value2 := abi_decode_value2_620 -// let abi_decode_value3_621 -// let abi_decode_value3 := abi_decode_value3_621 -// if slt(sub(_487, _488), 128) +// let a, b, c, d := abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(mload(_1), mload(0x40)) +// sstore(a, b) +// sstore(c, d) +// sstore(_2, abi_encode_pos) +// } +// function abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(offset_3, end_4) -> array_5 +// { +// if iszero(slt(add(offset_3, 0x1f), end_4)) // { -// revert(_2, _2) +// revert(array_5, array_5) // } +// let length_6 := calldataload(offset_3) +// let array_5_254 := allocateMemory(array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_6)) +// array_5 := array_5_254 +// let dst_7 := array_5_254 +// mstore(array_5_254, length_6) +// let _36 := 0x20 +// let offset_3_256 := add(offset_3, _36) +// dst_7 := add(array_5_254, _36) +// let src_8 := offset_3_256 +// let _38 := 0x40 +// if gt(add(add(offset_3, mul(length_6, _38)), _36), end_4) // { -// abi_decode_value0_60 := calldataload(_488) +// let _42 := 0 +// revert(_42, _42) +// } +// let i_9 := 0 +// for { // } +// lt(i_9, length_6) // { -// abi_decode_value1_61 := calldataload(add(_488, 32)) +// i_9 := add(i_9, 1) // } // { -// let abi_decode_offset_64 := calldataload(add(_488, abi_encode_pos_590)) -// let _940 := 0xffffffffffffffff -// if gt(abi_decode_offset_64, _940) -// { -// revert(_2, _2) -// } -// let _942 := add(_488, abi_decode_offset_64) -// if iszero(slt(add(_942, 0x1f), _487)) -// { -// revert(_2, _2) -// } -// let abi_decode_length_30_1046 := calldataload(_942) -// if gt(abi_decode_length_30_1046, _940) -// { -// revert(_2, _2) -// } -// let abi_decode_array_allo__561 := mul(abi_decode_length_30_1046, _1) -// let abi_decode_array_29_279_1047 := allocateMemory(add(abi_decode_array_allo__561, _1)) -// let abi_decode_dst_31_1048 := abi_decode_array_29_279_1047 -// mstore(abi_decode_array_29_279_1047, abi_decode_length_30_1046) -// let abi_decode_offset_27_281_1049 := add(_942, _1) -// abi_decode_dst_31_1048 := add(abi_decode_array_29_279_1047, _1) -// let abi_decode_src_32_1050 := abi_decode_offset_27_281_1049 -// if gt(add(add(_942, abi_decode_array_allo__561), _1), _487) -// { -// revert(_2, _2) -// } -// for { -// let abi_decode_i_33_1052 := _2 -// } -// lt(abi_decode_i_33_1052, abi_decode_length_30_1046) -// { -// abi_decode_i_33_1052 := add(abi_decode_i_33_1052, 1) -// } -// { -// mstore(abi_decode_dst_31_1048, calldataload(abi_decode_src_32_1050)) -// abi_decode_dst_31_1048 := add(abi_decode_dst_31_1048, _1) -// abi_decode_src_32_1050 := add(abi_decode_src_32_1050, _1) -// } -// abi_decode_value2 := abi_decode_array_29_279_1047 +// mstore(dst_7, abi_decode_t_array$_t_uint256_$2_memory(src_8, end_4)) +// dst_7 := add(dst_7, _36) +// src_8 := add(src_8, _38) // } +// } +// function abi_decode_t_array$_t_uint256_$2_memory(offset_11, end_12) -> array_13 +// { +// if iszero(slt(add(offset_11, 0x1f), end_12)) // { -// let abi_decode_offset_65 := calldataload(add(_488, 96)) -// let _945 := 0xffffffffffffffff -// if gt(abi_decode_offset_65, _945) -// { -// revert(_2, _2) -// } -// let _947 := add(_488, abi_decode_offset_65) -// let abi_decode__489_1056 := 0x1f -// if iszero(slt(add(_947, abi_decode__489_1056), _487)) -// { -// revert(_2, _2) -// } -// let abi_decode_length_6_1058 := calldataload(_947) -// if gt(abi_decode_length_6_1058, _945) -// { -// revert(_2, _2) -// } -// let abi_decode_array_5_254_1061 := allocateMemory(add(mul(abi_decode_length_6_1058, _1), _1)) -// let abi_decode_dst_7_1062 := abi_decode_array_5_254_1061 -// mstore(abi_decode_array_5_254_1061, abi_decode_length_6_1058) -// let abi_decode_offset_3_256_1063 := add(_947, _1) -// abi_decode_dst_7_1062 := add(abi_decode_array_5_254_1061, _1) -// let abi_decode_src_8_1064 := abi_decode_offset_3_256_1063 -// if gt(add(add(_947, mul(abi_decode_length_6_1058, _933)), _1), _487) -// { -// revert(_2, _2) -// } -// for { -// let abi_decode_i_9_1068 := _2 -// } -// lt(abi_decode_i_9_1068, abi_decode_length_6_1058) +// revert(array_13, array_13) +// } +// let length_14 := 0x2 +// let array_allo__559 := 0x20 +// let array_allo_size_95_605 := 64 +// let array_13_263 := allocateMemory(array_allo_size_95_605) +// array_13 := array_13_263 +// let dst_15 := array_13_263 +// let src_16 := offset_11 +// if gt(add(offset_11, array_allo_size_95_605), end_12) +// { +// let _59 := 0 +// revert(_59, _59) +// } +// let i_17 := 0 +// for { +// } +// lt(i_17, length_14) +// { +// i_17 := add(i_17, 1) +// } +// { +// mstore(dst_15, calldataload(src_16)) +// dst_15 := add(dst_15, array_allo__559) +// src_16 := add(src_16, array_allo__559) +// } +// } +// function abi_decode_t_array$_t_uint256_$dyn_memory_ptr(offset_27, end_28) -> array_29 +// { +// if iszero(slt(add(offset_27, 0x1f), end_28)) +// { +// revert(array_29, array_29) +// } +// let length_30 := calldataload(offset_27) +// let array_29_279 := allocateMemory(array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_30)) +// array_29 := array_29_279 +// let dst_31 := array_29_279 +// mstore(array_29_279, length_30) +// let _91 := 0x20 +// let offset_27_281 := add(offset_27, _91) +// dst_31 := add(array_29_279, _91) +// let src_32 := offset_27_281 +// if gt(add(add(offset_27, mul(length_30, _91)), _91), end_28) +// { +// let _97 := 0 +// revert(_97, _97) +// } +// let i_33 := 0 +// for { +// } +// lt(i_33, length_30) +// { +// i_33 := add(i_33, 1) +// } +// { +// mstore(dst_31, calldataload(src_32)) +// dst_31 := add(dst_31, _91) +// src_32 := add(src_32, _91) +// } +// } +// function abi_decode_tuple_t_uint256t_uint256t_array$_t_uint256_$dyn_memory_ptrt_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(headStart_58, dataEnd_59) -> value0_60, value1_61, value2, value3 +// { +// if slt(sub(dataEnd_59, headStart_58), 128) +// { +// revert(value2, value2) +// } +// { +// value0_60 := calldataload(add(headStart_58, value2)) +// } +// { +// value1_61 := calldataload(add(headStart_58, 32)) +// } +// { +// let offset_64 := calldataload(add(headStart_58, 64)) +// if gt(offset_64, 0xffffffffffffffff) // { -// abi_decode_i_9_1068 := add(abi_decode_i_9_1068, 1) +// revert(value2, value2) // } +// value2 := abi_decode_t_array$_t_uint256_$dyn_memory_ptr(add(headStart_58, offset_64), dataEnd_59) +// } +// { +// let offset_65 := calldataload(add(headStart_58, 96)) +// if gt(offset_65, 0xffffffffffffffff) // { -// if iszero(slt(add(abi_decode_src_8_1064, abi_decode__489_1056), _487)) -// { -// revert(_2, _2) -// } -// let abi_decode_abi_decode_length_14_1069 := 0x2 -// if _2 -// { -// revert(_2, _2) -// } -// let allocateMe_memPtr_315 := mload(abi_encode_pos_590) -// let allocateMe_newFreePtr := add(allocateMe_memPtr_315, abi_encode_pos_590) -// if or(gt(allocateMe_newFreePtr, _945), lt(allocateMe_newFreePtr, allocateMe_memPtr_315)) -// { -// revert(_2, _2) -// } -// mstore(abi_encode_pos_590, allocateMe_newFreePtr) -// let abi_decode_abi_decode_dst_15_1071 := allocateMe_memPtr_315 -// let abi_decode_abi_decode_src_16_1072 := abi_decode_src_8_1064 -// if gt(add(abi_decode_src_8_1064, abi_encode_pos_590), _487) -// { -// revert(_2, _2) -// } -// for { -// let abi_decode_abi_decode_i_17_1073 := _2 -// } -// lt(abi_decode_abi_decode_i_17_1073, abi_decode_abi_decode_length_14_1069) -// { -// abi_decode_abi_decode_i_17_1073 := add(abi_decode_abi_decode_i_17_1073, 1) -// } -// { -// mstore(abi_decode_abi_decode_dst_15_1071, calldataload(abi_decode_abi_decode_src_16_1072)) -// abi_decode_abi_decode_dst_15_1071 := add(abi_decode_abi_decode_dst_15_1071, _1) -// abi_decode_abi_decode_src_16_1072 := add(abi_decode_abi_decode_src_16_1072, _1) -// } -// mstore(abi_decode_dst_7_1062, allocateMe_memPtr_315) -// abi_decode_dst_7_1062 := add(abi_decode_dst_7_1062, _1) -// abi_decode_src_8_1064 := add(abi_decode_src_8_1064, _933) +// revert(value3, value3) // } -// abi_decode_value3 := abi_decode_array_5_254_1061 +// value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(headStart_58, offset_65), dataEnd_59) // } -// sstore(abi_decode_value0_60, abi_decode_value1_61) -// sstore(abi_decode_value2, abi_decode_value3) -// sstore(_2, abi_encode_pos) // } // function allocateMemory(size) -> memPtr // { @@ -651,4 +639,22 @@ // } // mstore(_199, newFreePtr) // } +// function array_allocation_size_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(length_92) -> size_93 +// { +// if gt(length_92, 0xffffffffffffffff) +// { +// revert(size_93, size_93) +// } +// let _217 := 0x20 +// size_93 := add(mul(length_92, _217), _217) +// } +// function array_allocation_size_t_array$_t_uint256_$dyn_memory_ptr(length_98) -> size_99 +// { +// if gt(length_98, 0xffffffffffffffff) +// { +// revert(size_99, size_99) +// } +// let _234 := 0x20 +// size_99 := add(mul(length_98, _234), _234) +// } // } diff --git a/test/libyul/yulOptimizerTests/fullSuite/medium.yul b/test/libyul/yulOptimizerTests/fullSuite/medium.yul index deb02068..fbe243d4 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/medium.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/medium.yul @@ -9,16 +9,23 @@ pop(allocate(0x20)) let x := allocate(0x40) mstore(array_index_access(x, 3), 2) + if 0 { + mstore(0x40, 0x20) + } + if sub(2,1) { + for { switch mul(1,2) case 2 { mstore(0x40, 0x20) } } sub(1,1) {} { mstore(0x80, 0x40) } + } } // ---- // fullSuite // { // { -// let _18 := 0x20 -// let allocate__7 := 0x40 -// mstore(allocate__7, add(mload(allocate__7), _18)) -// let allocate_p_12_31 := mload(allocate__7) -// mstore(allocate__7, add(allocate_p_12_31, allocate__7)) -// mstore(add(allocate_p_12_31, 96), 2) +// let _1 := 0x20 +// let allocate__19 := 0x40 +// mstore(allocate__19, add(mload(allocate__19), _1)) +// let allocate_p_24_41 := mload(allocate__19) +// mstore(allocate__19, add(allocate_p_24_41, allocate__19)) +// mstore(add(allocate_p_24_41, 96), 2) +// mstore(allocate__19, _1) // } // } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul new file mode 100644 index 00000000..ee1975e7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_movable_condition.yul @@ -0,0 +1,7 @@ +{ let a := mload(0) if a {} } +// ---- +// structuralSimplifier +// { +// let a := mload(0) +// pop(a) +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul new file mode 100644 index 00000000..5977297b --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/empty_if_non_movable_condition.yul @@ -0,0 +1,6 @@ +{ if mload(0) {} } +// ---- +// structuralSimplifier +// { +// pop(mload(0)) +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol b/test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol new file mode 100644 index 00000000..b881a0a3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/for_false_condition.sol @@ -0,0 +1,10 @@ +{ + for { let a := 42 } 0 { a := a } { + let b := a + } +} +// ---- +// structuralSimplifier +// { +// let a := 42 +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul new file mode 100644 index 00000000..0895b1bb --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_false_condition.yul @@ -0,0 +1,5 @@ +{ if 0 { mstore(0, 0) } } +// ---- +// structuralSimplifier +// { +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul new file mode 100644 index 00000000..0ece5dbd --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_multi_unassigned_condition.yul @@ -0,0 +1,10 @@ +{ + let x, y + if x { mstore(0, 0) } + if y { mstore(0, 0) } +} +// ---- +// structuralSimplifier +// { +// let x, y +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul new file mode 100644 index 00000000..ca9cba06 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_true_condition.yul @@ -0,0 +1,6 @@ +{ if 1 { mstore(0, 0) } } +// ---- +// structuralSimplifier +// { +// mstore(0, 0) +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul new file mode 100644 index 00000000..a327a882 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/if_unassigned_condition.yul @@ -0,0 +1,9 @@ +{ + let x + if x { mstore(0, 0) } +} +// ---- +// structuralSimplifier +// { +// let x +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul new file mode 100644 index 00000000..169a84d1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/nested.yul @@ -0,0 +1,6 @@ +{ if 1 { if 1 { for { mstore(0, 0) } 0 {} { mstore(2, 3) } if 0 { mstore(1, 2) } } } } +// ---- +// structuralSimplifier +// { +// mstore(0, 0) +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul new file mode 100644 index 00000000..7ca815a7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_only_default.yul @@ -0,0 +1,11 @@ +{ + switch mload(0) default { mstore(1, 2) } +} +// ---- +// structuralSimplifier +// { +// pop(mload(0)) +// { +// mstore(1, 2) +// } +// } diff --git a/test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul new file mode 100644 index 00000000..a741ac2f --- /dev/null +++ b/test/libyul/yulOptimizerTests/structuralSimplifier/switch_to_if.yul @@ -0,0 +1,11 @@ +{ + switch 1 case 2 { mstore(0, 0) } +} +// ---- +// structuralSimplifier +// { +// if eq(2, 1) +// { +// mstore(0, 0) +// } +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul new file mode 100644 index 00000000..5e2d60c2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/ambiguous.yul @@ -0,0 +1,29 @@ +{ + // This component does not need the disambiguator + function f() -> x, y { + let a, b + mstore(a, b) + let d + d := 2 + } + let a + a := 4 + let b := 2 + let x, y := f() +} +// ---- +// varDeclInitializer +// { +// function f() -> x, y +// { +// let a := 0 +// let b := 0 +// mstore(a, b) +// let d := 0 +// d := 2 +// } +// let a := 0 +// a := 4 +// let b := 2 +// let x, y := f() +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul new file mode 100644 index 00000000..16428d7e --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/inside_func.yul @@ -0,0 +1,24 @@ +{ + function f() -> x, y { + let a, b + mstore(a, b) + let d + d := 2 + } + let r + r := 4 +} +// ---- +// varDeclInitializer +// { +// function f() -> x, y +// { +// let a := 0 +// let b := 0 +// mstore(a, b) +// let d := 0 +// d := 2 +// } +// let r := 0 +// r := 4 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul new file mode 100644 index 00000000..02d731af --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/multi.yul @@ -0,0 +1,14 @@ +{ + let x, y, z + let a + let b +} +// ---- +// varDeclInitializer +// { +// let x := 0 +// let y := 0 +// let z := 0 +// let a := 0 +// let b := 0 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul new file mode 100644 index 00000000..2e14fe70 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/multi_assign.yul @@ -0,0 +1,21 @@ +{ + function f() -> x, y { + let a, b := f() + let u + } + let r + let s := 3 + let t +} +// ---- +// varDeclInitializer +// { +// function f() -> x, y +// { +// let a, b := f() +// let u := 0 +// } +// let r := 0 +// let s := 3 +// let t := 0 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul b/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul new file mode 100644 index 00000000..2a9bbe42 --- /dev/null +++ b/test/libyul/yulOptimizerTests/varDeclInitializer/simple.yul @@ -0,0 +1,8 @@ +{ + let a +} +// ---- +// varDeclInitializer +// { +// let a := 0 +// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul deleted file mode 100644 index 54fea2fb..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/init_assignment_inside_if.yul +++ /dev/null @@ -1,17 +0,0 @@ -{ - let a := 4 - let x - if a { - x := 2 - } -} -// ---- -// varDeclPropagator -// { -// let a := 4 -// let x -// if a -// { -// x := 2 -// } -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul deleted file mode 100644 index ed8d33b4..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/multi_assignment_vardecl.yul +++ /dev/null @@ -1,13 +0,0 @@ -{ - function f() -> a, b, c {} - let x, y, z - z, x, y := f() -} -// ---- -// varDeclPropagator -// { -// function f() -> a, b, c -// { -// } -// let z, x, y := f() -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul deleted file mode 100644 index ca921500..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/overwrite.yul +++ /dev/null @@ -1,11 +0,0 @@ -{ - let a - a := 4 - a := 5 -} -// ---- -// varDeclPropagator -// { -// let a := 4 -// a := 5 -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul deleted file mode 100644 index 3affcac6..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/rewrite_removes_unused_var.yul +++ /dev/null @@ -1,10 +0,0 @@ -{ - let a, b - a := mload(0) -} -// ---- -// varDeclPropagator -// { -// let b -// let a := mload(0) -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul deleted file mode 100644 index d8959040..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/simple1.yul +++ /dev/null @@ -1,9 +0,0 @@ -{ - let f - f := mload(0) -} -// ---- -// varDeclPropagator -// { -// let f := mload(0) -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul deleted file mode 100644 index e8c91e10..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/split_assign_splits_vardecl.yul +++ /dev/null @@ -1,11 +0,0 @@ -{ - let a, b - a := mload(0) - b := mload(1) -} -// ---- -// varDeclPropagator -// { -// let a := mload(0) -// let b := mload(1) -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul deleted file mode 100644 index 5312112a..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/use_before_init.yul +++ /dev/null @@ -1,12 +0,0 @@ -{ - let b - let a := b - b := 1 -} -// ---- -// varDeclPropagator -// { -// let b -// let a := b -// b := 1 -// } diff --git a/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul b/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul deleted file mode 100644 index e27785dd..00000000 --- a/test/libyul/yulOptimizerTests/varDeclPropagator/use_doesnt_rewrite.yul +++ /dev/null @@ -1,16 +0,0 @@ -{ - function f(x) {} - let a - f(a) - a := 4 -} -// ---- -// varDeclPropagator -// { -// function f(x) -// { -// } -// let a -// f(a) -// a := 4 -// } diff --git a/test/solcjsTests.sh b/test/solcjsTests.sh index e0bbc5df..b9224862 100755 --- a/test/solcjsTests.sh +++ b/test/solcjsTests.sh @@ -60,7 +60,7 @@ DIR=$(mktemp -d) # Update version (needed for some tests) echo "Updating package.json to version $VERSION" - npm version --no-git-tag-version $VERSION + npm version --allow-same-version --no-git-tag-version $VERSION echo "Running solc-js tests..." npm run test diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 736212fc..da8e0b39 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -4,7 +4,19 @@ target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_L add_executable(yulopti yulopti.cpp) target_link_libraries(yulopti PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_SYSTEM_LIBRARIES}) -add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../TestCase.cpp ../libsolidity/SyntaxTest.cpp - ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp - ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libsolidity/SMTCheckerJSONTest.cpp ../libyul/YulOptimizerTest.cpp) +add_executable(isoltest + isoltest.cpp + ../Options.cpp + ../Common.cpp + ../TestCase.cpp + ../libsolidity/SyntaxTest.cpp + ../libsolidity/AnalysisFramework.cpp + ../libsolidity/SolidityExecutionFramework.cpp + ../ExecutionFramework.cpp + ../RPCSession.cpp + ../libsolidity/ASTJSONTest.cpp + ../libsolidity/SMTCheckerJSONTest.cpp + ../libyul/ObjectCompilerTest.cpp + ../libyul/YulOptimizerTest.cpp +) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index f8e2dc58..e5578045 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -19,10 +19,7 @@ #include <test/Common.h> #include <test/libsolidity/AnalysisFramework.h> -#include <test/libsolidity/SyntaxTest.h> -#include <test/libsolidity/ASTJSONTest.h> -#include <test/libsolidity/SMTCheckerJSONTest.h> -#include <test/libyul/YulOptimizerTest.h> +#include <test/InteractiveTests.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/replace.hpp> @@ -379,48 +376,13 @@ Allowed options)", TestStats global_stats{0, 0}; // Actually run the tests. - // If you add new tests here, you also have to add them in boostTest.cpp - if (auto stats = runTestSuite("Syntax", testPath / "libsolidity", "syntaxTests", SyntaxTest::create, formatted)) - global_stats += *stats; - else - return 1; - - if (auto stats = runTestSuite("JSON AST", testPath / "libsolidity", "ASTJSON", ASTJSONTest::create, formatted)) - global_stats += *stats; - else - return 1; - - if (auto stats = runTestSuite( - "Yul Optimizer", - testPath / "libyul", - "yulOptimizerTests", - yul::test::YulOptimizerTest::create, - formatted - )) - global_stats += *stats; - else - return 1; - - if (!disableSMT) + // Interactive tests are added in InteractiveTests.h + for (auto const& ts: g_interactiveTestsuites) { - if (auto stats = runTestSuite( - "SMT Checker", - testPath / "libsolidity", - "smtCheckerTests", - SyntaxTest::create, - formatted - )) - global_stats += *stats; - else - return 1; + if (ts.smt && disableSMT) + continue; - if (auto stats = runTestSuite( - "SMT Checker JSON", - testPath / "libsolidity", - "smtCheckerTestsJSON", - SMTCheckerTest::create, - formatted - )) + if (auto stats = runTestSuite(ts.title, testPath / ts.path, ts.subpath, ts.testCaseCreator, formatted)) global_stats += *stats; else return 1; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 5273bbb9..fcbe308f 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -46,7 +46,10 @@ #include <libyul/optimiser/ExpressionJoiner.h> #include <libyul/optimiser/RedundantAssignEliminator.h> #include <libyul/optimiser/SSATransform.h> -#include <libyul/optimiser/VarDeclPropagator.h> +#include <libyul/optimiser/StructuralSimplifier.h> +#include <libyul/optimiser/VarDeclInitializer.h> + +#include <libyul/backends/evm/EVMDialect.h> #include <libdevcore/JSON.h> @@ -67,9 +70,9 @@ namespace po = boost::program_options; class YulOpti { public: - void printErrors(Scanner const& _scanner) + void printErrors() { - SourceReferenceFormatter formatter(cout, [&](string const&) -> Scanner const& { return _scanner; }); + SourceReferenceFormatter formatter(cout); for (auto const& error: m_errors) formatter.printExceptionInformation( @@ -82,11 +85,11 @@ public: { ErrorReporter errorReporter(m_errors); shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(_input, "")); - m_ast = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); + m_ast = yul::Parser(errorReporter, yul::EVMDialect::strictAssemblyForEVM()).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { cout << "Error parsing source." << endl; - printErrors(*scanner); + printErrors(); return false; } m_analysisInfo = make_shared<yul::AsmAnalysisInfo>(); @@ -94,13 +97,13 @@ public: *m_analysisInfo, errorReporter, EVMVersion::byzantium(), - boost::none, - AsmFlavour::Strict + langutil::Error::Type::SyntaxError, + EVMDialect::strictAssemblyForEVM() ); if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty()) { cout << "Error analyzing source." << endl; - printErrors(*scanner); + printErrors(); return false; } return true; @@ -122,9 +125,10 @@ public: m_nameDispenser = make_shared<NameDispenser>(*m_ast); disambiguated = true; } - cout << "(q)quit/(f)flatten/(c)se/propagate var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; + cout << "(q)quit/(f)flatten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; cout << " (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl; - cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter? "; + cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter/" << endl; + cout << " s(t)ructural simplifier? " << endl; cout.flush(); int option = readStandardInputChar(); cout << ' ' << char(option) << endl; @@ -142,7 +146,7 @@ public: (CommonSubexpressionEliminator{})(*m_ast); break; case 'd': - (VarDeclPropagator{})(*m_ast); + (VarDeclInitializer{})(*m_ast); break; case 'x': ExpressionSplitter{*m_nameDispenser}(*m_ast); @@ -165,6 +169,9 @@ public: case 's': ExpressionSimplifier::run(*m_ast); break; + case 't': + (StructuralSimplifier{})(*m_ast); + break; case 'u': UnusedPruner::runUntilStabilised(*m_ast); break; |