diff options
author | chriseth <chris@ethereum.org> | 2018-04-17 05:03:49 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-17 05:03:49 +0800 |
commit | 4cb486ee993cadde5564fb6c611d2bcf4fc44414 (patch) | |
tree | 6b971913021037cf28141c38af97c7ecda77719f /test | |
parent | dfe3193c7382c80f1814247a162663a97c3f5e67 (diff) | |
parent | b8431c5c4a6795db8c42a1a3389047658bb87301 (diff) | |
download | dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.tar dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.tar.gz dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.tar.bz2 dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.tar.lz dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.tar.xz dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.tar.zst dexon-solidity-4cb486ee993cadde5564fb6c611d2bcf4fc44414.zip |
Merge pull request #3892 from ethereum/develop
Merge develop into release for 0.4.22
Diffstat (limited to 'test')
225 files changed, 5664 insertions, 1493 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f36ad4c5..522856cc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,9 +1,27 @@ -file(GLOB_RECURSE sources "*.cpp") -list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/fuzzer.cpp") -file(GLOB_RECURSE headers "*.h") +file(GLOB sources "*.cpp") +file(GLOB headers "*.h") -add_executable(soltest ${sources} ${headers}) +file(GLOB contracts_sources "contracts/*.cpp") +file(GLOB contracts_headers "contracts/*.h") +file(GLOB libdevcore_sources "libdevcore/*.cpp") +file(GLOB libdevcore_headers "libdevcore/*.h") +file(GLOB libevmasm_sources "libevmasm/*.cpp") +file(GLOB libevmasm_headers "libevmasm/*.h") +file(GLOB libjulia_sources "libjulia/*.cpp") +file(GLOB libjulia_headers "libjulia/*.h") +file(GLOB liblll_sources "liblll/*.cpp") +file(GLOB liblll_headers "liblll/*.h") +file(GLOB libsolidity_sources "libsolidity/*.cpp") +file(GLOB libsolidity_headers "libsolidity/*.h") + +add_executable(soltest ${sources} ${headers} + ${contracts_sources} ${contracts_headers} + ${libdevcore_sources} ${libdevcore_headers} + ${libevmasm_sources} ${libevmasm_headers} + ${libjulia_sources} ${libjulia_headers} + ${liblll_sources} ${liblll_headers} + ${libsolidity_sources} ${libsolidity_headers} +) target_link_libraries(soltest PRIVATE libsolc solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) -add_executable(solfuzzer fuzzer.cpp) -target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES}) +add_subdirectory(tools) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index a7971b81..ee8da322 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -22,7 +22,7 @@ #pragma once -#include <test/TestHelper.h> +#include <test/Options.h> #include <test/RPCSession.h> #include <libsolidity/interface/EVMVersion.h> diff --git a/test/TestHelper.cpp b/test/Options.cpp index e0d4423d..ff4a7c98 100644 --- a/test/TestHelper.cpp +++ b/test/Options.cpp @@ -19,9 +19,10 @@ * @date 2014 */ -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/interface/EVMVersion.h> +#include <libsolidity/interface/Exceptions.h> #include <boost/test/framework.hpp> @@ -43,6 +44,11 @@ Options::Options() ipcPath = suite.argv[i + 1]; i++; } + else if (string(suite.argv[i]) == "--testpath" && i + 1 < suite.argc) + { + testPath = suite.argv[i + 1]; + i++; + } else if (string(suite.argv[i]) == "--optimize") optimize = true; else if (string(suite.argv[i]) == "--evm-version") @@ -60,6 +66,23 @@ Options::Options() if (!disableIPC && ipcPath.empty()) if (auto path = getenv("ETH_TEST_IPC")) ipcPath = path; + + if (testPath.empty()) + if (auto path = getenv("ETH_TEST_PATH")) + testPath = path; +} + +void Options::validate() const +{ + solAssert( + !dev::test::Options::get().testPath.empty(), + "No test path specified. The --testpath argument is required." + ); + if (!disableIPC) + solAssert( + !dev::test::Options::get().ipcPath.empty(), + "No ipc path specified. The --ipcpath argument is required, unless --no-ipc is used." + ); } dev::solidity::EVMVersion Options::evmVersion() const diff --git a/test/TestHelper.h b/test/Options.h index 8c2eec36..9bc69876 100644 --- a/test/TestHelper.h +++ b/test/Options.h @@ -35,11 +35,13 @@ namespace test struct Options: boost::noncopyable { std::string ipcPath; + boost::filesystem::path testPath; bool showMessages = false; bool optimize = false; bool disableIPC = false; bool disableSMT = false; + void validate() const; solidity::EVMVersion evmVersion() const; static Options const& get(); diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 54871057..f4eae865 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -21,7 +21,7 @@ #include <test/RPCSession.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/interface/EVMVersion.h> @@ -226,6 +226,8 @@ void RPCSession::test_setChainParams(vector<string> const& _accounts) forks += "\"EIP158ForkBlock\": \"0x00\",\n"; if (test::Options::get().evmVersion() >= solidity::EVMVersion::byzantium()) forks += "\"byzantiumForkBlock\": \"0x00\",\n"; + if (test::Options::get().evmVersion() >= solidity::EVMVersion::constantinople()) + forks += "\"constantinopleForkBlock\": \"0x00\",\n"; static string const c_configString = R"( { "sealEngine": "NoProof", @@ -337,7 +339,9 @@ Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const& BOOST_TEST_MESSAGE("Reply: " + reply); Json::Value result; - BOOST_REQUIRE(jsonParseStrict(reply, result)); + string errorMsg; + if (!jsonParseStrict(reply, result, &errorMsg)) + BOOST_REQUIRE_MESSAGE(false, errorMsg); if (result.isMember("error")) { diff --git a/test/boostTest.cpp b/test/boostTest.cpp index a3cc51c5..f16973b5 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -35,7 +35,8 @@ #pragma GCC diagnostic pop -#include <test/TestHelper.h> +#include <test/Options.h> +#include <test/libsolidity/SyntaxTest.h> using namespace boost::unit_test; @@ -54,6 +55,12 @@ 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(dev::solidity::test::SyntaxTest::registerTests( + master, + dev::test::Options::get().testPath / "libsolidity", + "syntaxTests" + ) > 0, "no syntax tests found"); if (dev::test::Options::get().disableIPC) { for (auto suite: { diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index e86e0ad4..1137c7b0 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -32,7 +32,7 @@ REPO_ROOT=$(cd $(dirname "$0")/.. && pwd) echo $REPO_ROOT SOLC="$REPO_ROOT/build/solc/solc" -FULLARGS="--optimize --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc" +FULLARGS="--optimize --ignore-missing --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc" echo "Checking that the bug list is up to date..." "$REPO_ROOT"/scripts/update_bugs_by_version.py @@ -170,14 +170,14 @@ TMPDIR=$(mktemp -d) for f in *.sol do set +e - "$REPO_ROOT"/build/test/solfuzzer --quiet < "$f" + "$REPO_ROOT"/build/test/tools/solfuzzer --quiet < "$f" if [ $? -ne 0 ]; then printError "Fuzzer failed on:" cat "$f" exit 1 fi - "$REPO_ROOT"/build/test/solfuzzer --without-optimizer --quiet < "$f" + "$REPO_ROOT"/build/test/tools/solfuzzer --without-optimizer --quiet < "$f" if [ $? -ne 0 ]; then printError "Fuzzer (without optimizer) failed on:" cat "$f" diff --git a/test/libdevcore/Checksum.cpp b/test/libdevcore/Checksum.cpp index 4eedbd99..95066b69 100644 --- a/test/libdevcore/Checksum.cpp +++ b/test/libdevcore/Checksum.cpp @@ -22,7 +22,7 @@ #include <libdevcore/Exceptions.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libdevcore/IndentedWriter.cpp b/test/libdevcore/IndentedWriter.cpp index a694aa1b..916c99d0 100644 --- a/test/libdevcore/IndentedWriter.cpp +++ b/test/libdevcore/IndentedWriter.cpp @@ -20,7 +20,7 @@ #include <libdevcore/IndentedWriter.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libdevcore/JSON.cpp b/test/libdevcore/JSON.cpp index 39d71b42..39d958f5 100644 --- a/test/libdevcore/JSON.cpp +++ b/test/libdevcore/JSON.cpp @@ -21,7 +21,7 @@ #include <libdevcore/JSON.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libdevcore/StringUtils.cpp b/test/libdevcore/StringUtils.cpp index 597457cc..9ee93d02 100644 --- a/test/libdevcore/StringUtils.cpp +++ b/test/libdevcore/StringUtils.cpp @@ -20,7 +20,7 @@ #include <libdevcore/StringUtils.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libdevcore/SwarmHash.cpp b/test/libdevcore/SwarmHash.cpp index 1ed1da18..913586f8 100644 --- a/test/libdevcore/SwarmHash.cpp +++ b/test/libdevcore/SwarmHash.cpp @@ -20,7 +20,7 @@ #include <libdevcore/SwarmHash.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libdevcore/UTF8.cpp b/test/libdevcore/UTF8.cpp index 719ada72..6de4570f 100644 --- a/test/libdevcore/UTF8.cpp +++ b/test/libdevcore/UTF8.cpp @@ -21,7 +21,7 @@ #include <libdevcore/CommonData.h> #include <libdevcore/UTF8.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libdevcore/Whiskers.cpp b/test/libdevcore/Whiskers.cpp index 84149173..b12acdd7 100644 --- a/test/libdevcore/Whiskers.cpp +++ b/test/libdevcore/Whiskers.cpp @@ -20,7 +20,7 @@ #include <libdevcore/Whiskers.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index e6abcb53..089be45d 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -20,7 +20,7 @@ * Tests for the Solidity optimizer. */ -#include <test/TestHelper.h> +#include <test/Options.h> #include <libevmasm/CommonSubexpressionEliminator.h> #include <libevmasm/PeepholeOptimiser.h> @@ -69,8 +69,9 @@ namespace { AssemblyItems input = addDummyLocations(_input); + bool usesMsize = (find(_input.begin(), _input.end(), AssemblyItem{Instruction::MSIZE}) != _input.end()); eth::CommonSubexpressionEliminator cse(_state); - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end(), usesMsize) == input.end()); AssemblyItems output = cse.getOptimizedItems(); for (AssemblyItem const& item: output) @@ -124,7 +125,7 @@ BOOST_AUTO_TEST_CASE(cse_intermediate_swap) Instruction::SLOAD, Instruction::SWAP1, u256(100), Instruction::EXP, Instruction::SWAP1, Instruction::DIV, u256(0xff), Instruction::AND }; - BOOST_REQUIRE(cse.feedItems(input.begin(), input.end()) == input.end()); + BOOST_REQUIRE(cse.feedItems(input.begin(), input.end(), false) == input.end()); AssemblyItems output = cse.getOptimizedItems(); BOOST_CHECK(!output.empty()); } @@ -857,6 +858,115 @@ BOOST_AUTO_TEST_CASE(peephole_pop_calldatasize) BOOST_CHECK(items.empty()); } +BOOST_AUTO_TEST_CASE(peephole_commutative_swap1) +{ + vector<Instruction> ops{ + Instruction::ADD, + Instruction::MUL, + Instruction::EQ, + Instruction::AND, + Instruction::OR, + Instruction::XOR + }; + for (Instruction const op: ops) + { + AssemblyItems items{ + u256(1), + u256(2), + Instruction::SWAP1, + op, + u256(4), + u256(5) + }; + AssemblyItems expectation{ + u256(1), + u256(2), + op, + u256(4), + u256(5) + }; + PeepholeOptimiser peepOpt(items); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); + } +} + +BOOST_AUTO_TEST_CASE(peephole_noncommutative_swap1) +{ + // NOTE: not comprehensive + vector<Instruction> ops{ + Instruction::SUB, + Instruction::DIV, + Instruction::SDIV, + Instruction::MOD, + Instruction::SMOD, + Instruction::EXP + }; + for (Instruction const op: ops) + { + AssemblyItems items{ + u256(1), + u256(2), + Instruction::SWAP1, + op, + u256(4), + u256(5) + }; + AssemblyItems expectation{ + u256(1), + u256(2), + Instruction::SWAP1, + op, + u256(4), + u256(5) + }; + PeepholeOptimiser peepOpt(items); + BOOST_REQUIRE(!peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); + } +} + +BOOST_AUTO_TEST_CASE(peephole_swap_comparison) +{ + map<Instruction, Instruction> swappableOps{ + { Instruction::LT, Instruction::GT }, + { Instruction::GT, Instruction::LT }, + { Instruction::SLT, Instruction::SGT }, + { Instruction::SGT, Instruction::SLT } + }; + + for (auto const& op: swappableOps) + { + AssemblyItems items{ + u256(1), + u256(2), + Instruction::SWAP1, + op.first, + u256(4), + u256(5) + }; + AssemblyItems expectation{ + u256(1), + u256(2), + op.second, + u256(4), + u256(5) + }; + PeepholeOptimiser peepOpt(items); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); + } +} + BOOST_AUTO_TEST_CASE(jumpdest_removal) { AssemblyItems items{ diff --git a/test/libevmasm/SourceLocation.cpp b/test/libevmasm/SourceLocation.cpp index 6889b3e6..764da3cd 100644 --- a/test/libevmasm/SourceLocation.cpp +++ b/test/libevmasm/SourceLocation.cpp @@ -22,7 +22,7 @@ #include <libevmasm/SourceLocation.h> -#include "../TestHelper.h" +#include <test/Options.h> namespace dev { diff --git a/test/libjulia/Common.cpp b/test/libjulia/Common.cpp index 41f5d320..24519b01 100644 --- a/test/libjulia/Common.cpp +++ b/test/libjulia/Common.cpp @@ -21,7 +21,7 @@ #include <test/libjulia/Common.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <libjulia/optimiser/Disambiguator.h> diff --git a/test/libjulia/CommonSubexpression.cpp b/test/libjulia/CommonSubexpression.cpp new file mode 100644 index 00000000..8a575c48 --- /dev/null +++ b/test/libjulia/CommonSubexpression.cpp @@ -0,0 +1,102 @@ +/* + 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 common subexpression eliminator optimizer stage. + */ + +#include <test/libjulia/Common.h> + +#include <libjulia/optimiser/CommonSubexpressionEliminator.h> + +#include <libsolidity/inlineasm/AsmPrinter.h> + +#include <boost/test/unit_test.hpp> + +#include <boost/range/adaptors.hpp> +#include <boost/algorithm/string/join.hpp> + +using namespace std; +using namespace dev; +using namespace dev::julia; +using namespace dev::julia::test; +using namespace dev::solidity; + + +#define CHECK(_original, _expectation)\ +do\ +{\ + assembly::AsmPrinter p;\ + Block b = disambiguate(_original, false);\ + (CommonSubexpressionEliminator{})(b);\ + string result = p(b);\ + BOOST_CHECK_EQUAL(result, format(_expectation, false));\ +}\ +while(false) + +BOOST_AUTO_TEST_SUITE(IuliaCSE) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + CHECK("{ }", "{ }"); +} + +BOOST_AUTO_TEST_CASE(trivial) +{ + CHECK( + "{ let a := mul(1, codesize()) let b := mul(1, codesize()) }", + "{ let a := mul(1, codesize()) let b := a }" + ); +} + +BOOST_AUTO_TEST_CASE(non_movable_instr) +{ + CHECK( + "{ let a := mload(1) let b := mload(1) }", + "{ let a := mload(1) let b := mload(1) }" + ); +} + +BOOST_AUTO_TEST_CASE(non_movable_instr2) +{ + CHECK( + "{ let a := gas() let b := gas() }", + "{ let a := gas() let b := gas() }" + ); +} + +BOOST_AUTO_TEST_CASE(branches_if) +{ + CHECK( + "{ let b := 1 if b { b := 1 } let c := 1 }", + "{ let b := 1 if b { b := b } let c := 1 }" + ); +} + +BOOST_AUTO_TEST_CASE(branches_for) +{ + CHECK( + "{ let a := 1 let b := codesize()" + "for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) }" + "{ mstore(1, codesize()) } mstore(1, codesize()) }", + + "{ let a := 1 let b := codesize()" + "for { } lt(1, b) { mstore(1, b) a := add(a, b) }" + "{ mstore(1, b) } mstore(1, b) }" + ); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp index df905dd6..9d66658e 100644 --- a/test/libjulia/Parser.cpp +++ b/test/libjulia/Parser.cpp @@ -19,7 +19,7 @@ * Unit tests for parsing Julia. */ -#include "../TestHelper.h" +#include <test/Options.h> #include <test/libsolidity/ErrorCheck.h> diff --git a/test/liblll/Compiler.cpp b/test/liblll/Compiler.cpp index 6c6eae3f..ebdea185 100644 --- a/test/liblll/Compiler.cpp +++ b/test/liblll/Compiler.cpp @@ -20,7 +20,7 @@ * Unit tests for the LLL compiler. */ -#include <test/TestHelper.h> +#include <test/Options.h> #include <libdevcore/FixedHash.h> diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index e5e70cf8..fd8099f2 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -21,7 +21,7 @@ */ #include <test/liblll/ExecutionFramework.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <boost/test/unit_test.hpp> diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index 15c04b37..beb7b5af 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -786,6 +786,89 @@ BOOST_AUTO_TEST_CASE(complex_struct) } +BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_simple) +{ + if (m_evmVersion == EVMVersion::homestead()) + return; + + string sourceCode = R"( + contract C { + function dyn() public returns (bytes) { + return "1234567890123456789012345678901234567890"; + } + function f() public returns (bytes) { + return this.dyn(); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x20, 40, string("1234567890123456789012345678901234567890"))); + ) +} + +BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_advanced) +{ + if (m_evmVersion == EVMVersion::homestead()) + return; + + string sourceCode = R"( + contract C { + function dyn() public returns (bytes a, uint b, bytes20[] c, uint d) { + a = "1234567890123456789012345678901234567890"; + b = uint(-1); + c = new bytes20[](4); + c[0] = bytes20(1234); + c[3] = bytes20(6789); + d = 0x1234; + } + function f() public returns (bytes, uint, bytes20[], uint) { + return this.dyn(); + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x80, u256(-1), 0xe0, 0x1234, + 40, string("1234567890123456789012345678901234567890"), + 4, u256(1234) << (8 * (32 - 20)), 0, 0, u256(6789) << (8 * (32 - 20)) + )); + ) +} + +BOOST_AUTO_TEST_CASE(return_dynamic_types_cross_call_out_of_range) +{ + string sourceCode = R"( + contract C { + function dyn(uint x) public returns (bytes a) { + assembly { + mstore(0, 0x20) + mstore(0x20, 0x21) + return(0, x) + } + } + function f(uint x) public returns (bool) { + this.dyn(x); + return true; + } + } + )"; + BOTH_ENCODERS( + compileAndRun(sourceCode, 0, "C"); + if (m_evmVersion == EVMVersion::homestead()) + { + ABI_CHECK(callContractFunction("f(uint256)", 0x60), encodeArgs(true)); + ABI_CHECK(callContractFunction("f(uint256)", 0x7f), encodeArgs(true)); + } + else + { + ABI_CHECK(callContractFunction("f(uint256)", 0x60), encodeArgs()); + ABI_CHECK(callContractFunction("f(uint256)", 0x61), encodeArgs(true)); + } + ABI_CHECK(callContractFunction("f(uint256)", 0x80), encodeArgs(true)); + ) +} BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp index 9bf60b64..5d5b14e8 100644 --- a/test/libsolidity/ASTJSON.cpp +++ b/test/libsolidity/ASTJSON.cpp @@ -20,7 +20,7 @@ * Tests for the json ast output. */ -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/CompilerStack.h> @@ -41,207 +41,62 @@ namespace test BOOST_AUTO_TEST_SUITE(SolidityASTJSON) -BOOST_AUTO_TEST_CASE(smoke_test) +BOOST_AUTO_TEST_CASE(short_type_name) { CompilerStack c; - c.addSource("a", "contract C {}"); + c.addSource("a", "contract c { function f() { uint[] memory x; } }"); c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); + Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); + Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["declarations"][0]; + BOOST_CHECK_EQUAL(varDecl["storageLocation"], "memory"); + BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeIdentifier"], "t_array$_t_uint256_$dyn_memory_ptr"); + BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeString"], "uint256[]"); } -BOOST_AUTO_TEST_CASE(source_location) +BOOST_AUTO_TEST_CASE(short_type_name_ref) { CompilerStack c; - c.addSource("a", "contract C { function f() { var x = 2; x++; } }"); + c.addSource("a", "contract c { function f() { uint[][] memory rows; } }"); c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); - BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition"); - BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition"); - BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["src"], "13:32:1"); + Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); + Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["declarations"][0]; + BOOST_CHECK_EQUAL(varDecl["storageLocation"], "memory"); + BOOST_CHECK_EQUAL(varDecl["typeName"]["typeDescriptions"]["typeIdentifier"], "t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr"); + BOOST_CHECK_EQUAL(varDecl["typeName"]["typeDescriptions"]["typeString"], "uint256[][]"); } -BOOST_AUTO_TEST_CASE(inheritance_specifier) +BOOST_AUTO_TEST_CASE(long_type_name_binary_operation) { CompilerStack c; - c.addSource("a", "contract C1 {} contract C2 is C1 {}"); + c.addSource("a", "contract c { function f() public { uint a = 2 + 3; } }"); c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["name"], "UserDefinedTypeName"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["attributes"]["name"], "C1"); + Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); + Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["initialValue"]["commonType"]; + BOOST_CHECK_EQUAL(varDecl["typeIdentifier"], "t_rational_5_by_1"); + BOOST_CHECK_EQUAL(varDecl["typeString"], "int_const 5"); } -BOOST_AUTO_TEST_CASE(using_for_directive) +BOOST_AUTO_TEST_CASE(long_type_name_identifier) { CompilerStack c; - c.addSource("a", "library L {} contract C { using L for uint; }"); + c.addSource("a", "contract c { uint[] a; function f() public { uint[] b = a; } }"); c.setEVMVersion(dev::test::Options::get().evmVersion()); c.parseAndAnalyze(); map<string, unsigned> sourceIndices; sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value usingFor = astJson["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective"); - BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1"); - BOOST_CHECK_EQUAL(usingFor["children"][0]["name"], "UserDefinedTypeName"); - BOOST_CHECK_EQUAL(usingFor["children"][0]["attributes"]["name"], "L"); - BOOST_CHECK_EQUAL(usingFor["children"][1]["name"], "ElementaryTypeName"); - BOOST_CHECK_EQUAL(usingFor["children"][1]["attributes"]["name"], "uint"); -} - -BOOST_AUTO_TEST_CASE(enum_value) -{ - CompilerStack c; - c.addSource("a", "contract C { enum E { A, B } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value enumDefinition = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue"); - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A"); - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["src"], "22:1:1"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["name"], "EnumValue"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["attributes"]["name"], "B"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["src"], "25:1:1"); -} - -BOOST_AUTO_TEST_CASE(modifier_definition) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value modifier = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition"); - BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M"); - BOOST_CHECK_EQUAL(modifier["src"], "13:25:1"); -} - -BOOST_AUTO_TEST_CASE(modifier_invocation) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value modifier = astJson["children"][0]["children"][1]["children"][2]; - BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation"); - BOOST_CHECK_EQUAL(modifier["src"], "52:4:1"); - BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["type"], "modifier (uint256)"); - BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["value"], "M"); - BOOST_CHECK_EQUAL(modifier["children"][1]["attributes"]["value"], "1"); -} - -BOOST_AUTO_TEST_CASE(event_definition) -{ - CompilerStack c; - c.addSource("a", "contract C { event E(); }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value event = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(event["name"], "EventDefinition"); - BOOST_CHECK_EQUAL(event["attributes"]["name"], "E"); - BOOST_CHECK_EQUAL(event["src"], "13:10:1"); -} - -BOOST_AUTO_TEST_CASE(array_type_name) -{ - CompilerStack c; - c.addSource("a", "contract C { uint[] i; }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value array = astJson["children"][0]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName"); - BOOST_CHECK_EQUAL(array["src"], "13:6:1"); -} - -BOOST_AUTO_TEST_CASE(placeholder_statement) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M { _; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement"); - BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1"); -} - -BOOST_AUTO_TEST_CASE(non_utf8) -{ - CompilerStack c; - c.addSource("a", "contract C { function f() { var x = hex\"ff\"; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1]; - BOOST_CHECK_EQUAL(literal["name"], "Literal"); - BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff"); - BOOST_CHECK_EQUAL(literal["attributes"]["token"], "string"); - BOOST_CHECK_EQUAL(literal["attributes"]["value"], Json::nullValue); - BOOST_CHECK(literal["attributes"]["type"].asString().find("invalid") != string::npos); -} - -BOOST_AUTO_TEST_CASE(function_type) -{ - CompilerStack c; - c.addSource("a", - "contract C { function f(function() external payable returns (uint) x) " - "returns (function() external constant returns (uint)) {} }" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value fun = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition"); - Json::Value argument = fun["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(argument["name"], "VariableDeclaration"); - BOOST_CHECK_EQUAL(argument["attributes"]["name"], "x"); - BOOST_CHECK_EQUAL(argument["attributes"]["type"], "function () payable external returns (uint256)"); - Json::Value funType = argument["children"][0]; - BOOST_CHECK_EQUAL(funType["attributes"]["constant"], false); - BOOST_CHECK_EQUAL(funType["attributes"]["payable"], true); - BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); - Json::Value retval = fun["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(retval["name"], "VariableDeclaration"); - BOOST_CHECK_EQUAL(retval["attributes"]["name"], ""); - BOOST_CHECK_EQUAL(retval["attributes"]["type"], "function () view external returns (uint256)"); - funType = retval["children"][0]; - BOOST_CHECK_EQUAL(funType["attributes"]["constant"], true); - BOOST_CHECK_EQUAL(funType["attributes"]["payable"], false); - BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); + Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); + Json::Value varDecl = astJson["nodes"][0]["nodes"][1]["body"]["statements"][0]["initialValue"]; + BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeIdentifier"], "t_array$_t_uint256_$dyn_storage"); + BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeString"], "uint256[] storage ref"); } BOOST_AUTO_TEST_CASE(documentation) @@ -266,30 +121,17 @@ BOOST_AUTO_TEST_CASE(documentation) sourceIndices["a"] = 0; sourceIndices["b"] = 1; sourceIndices["c"] = 2; - Json::Value astJsonA = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value documentationA = astJsonA["children"][0]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); - Json::Value astJsonB = ASTJsonConverter(true, sourceIndices).toJson(c.ast("b")); - Json::Value documentationB = astJsonB["children"][0]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); - Json::Value astJsonC = ASTJsonConverter(true, sourceIndices).toJson(c.ast("c")); - Json::Value documentationC0 = astJsonC["children"][0]["children"][0]["attributes"]["documentation"]; - Json::Value documentationC1 = astJsonC["children"][0]["children"][1]["attributes"]["documentation"]; - Json::Value documentationC2 = astJsonC["children"][0]["children"][2]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); - BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); - BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); //same tests for non-legacy mode - astJsonA = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - documentationA = astJsonA["nodes"][0]["documentation"]; + Json::Value astJsonA = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); + Json::Value documentationA = astJsonA["nodes"][0]["documentation"]; BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); - astJsonB = ASTJsonConverter(false, sourceIndices).toJson(c.ast("b")); - documentationB = astJsonB["nodes"][0]["documentation"]; + Json::Value astJsonB = ASTJsonConverter(false, sourceIndices).toJson(c.ast("b")); + Json::Value documentationB = astJsonB["nodes"][0]["documentation"]; BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); - astJsonC = ASTJsonConverter(false, sourceIndices).toJson(c.ast("c")); - documentationC0 = astJsonC["nodes"][0]["nodes"][0]["documentation"]; - documentationC1 = astJsonC["nodes"][0]["nodes"][1]["documentation"]; - documentationC2 = astJsonC["nodes"][0]["nodes"][2]["documentation"]; + Json::Value astJsonC = ASTJsonConverter(false, sourceIndices).toJson(c.ast("c")); + Json::Value documentationC0 = astJsonC["nodes"][0]["nodes"][0]["documentation"]; + Json::Value documentationC1 = astJsonC["nodes"][0]["nodes"][1]["documentation"]; + Json::Value documentationC2 = astJsonC["nodes"][0]["nodes"][2]["documentation"]; BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); diff --git a/test/libsolidity/ASTLegacyJSON.cpp b/test/libsolidity/ASTLegacyJSON.cpp new file mode 100644 index 00000000..13148682 --- /dev/null +++ b/test/libsolidity/ASTLegacyJSON.cpp @@ -0,0 +1,324 @@ +/* + 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/>. +*/ +/** + * @author Christian <c@ethdev.com> + * @date 2016 + * Tests for the json ast output. + */ + +#include <test/Options.h> + +#include <libsolidity/interface/Exceptions.h> +#include <libsolidity/interface/CompilerStack.h> +#include <libsolidity/ast/ASTJsonConverter.h> + +#include <boost/test/unit_test.hpp> + +#include <string> + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +BOOST_AUTO_TEST_SUITE(SolidityASTLegacyJSON) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + CompilerStack c; + c.addSource("a", "contract C {}"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); +} + +BOOST_AUTO_TEST_CASE(source_location) +{ + CompilerStack c; + c.addSource("a", "contract C { function f() { var x = 2; x++; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); + BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition"); + BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition"); + BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["src"], "13:32:1"); + +} + +BOOST_AUTO_TEST_CASE(inheritance_specifier) +{ + CompilerStack c; + c.addSource("a", "contract C1 {} contract C2 is C1 {}"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2"); + BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier"); + BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1"); + BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["name"], "UserDefinedTypeName"); + BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["attributes"]["name"], "C1"); +} + +BOOST_AUTO_TEST_CASE(using_for_directive) +{ + CompilerStack c; + c.addSource("a", "library L {} contract C { using L for uint; }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value usingFor = astJson["children"][1]["children"][0]; + BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective"); + BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1"); + BOOST_CHECK_EQUAL(usingFor["children"][0]["name"], "UserDefinedTypeName"); + BOOST_CHECK_EQUAL(usingFor["children"][0]["attributes"]["name"], "L"); + BOOST_CHECK_EQUAL(usingFor["children"][1]["name"], "ElementaryTypeName"); + BOOST_CHECK_EQUAL(usingFor["children"][1]["attributes"]["name"], "uint"); +} + +BOOST_AUTO_TEST_CASE(enum_value) +{ + CompilerStack c; + c.addSource("a", "contract C { enum E { A, B } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value enumDefinition = astJson["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue"); + BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A"); + BOOST_CHECK_EQUAL(enumDefinition["children"][0]["src"], "22:1:1"); + BOOST_CHECK_EQUAL(enumDefinition["children"][1]["name"], "EnumValue"); + BOOST_CHECK_EQUAL(enumDefinition["children"][1]["attributes"]["name"], "B"); + BOOST_CHECK_EQUAL(enumDefinition["children"][1]["src"], "25:1:1"); +} + +BOOST_AUTO_TEST_CASE(modifier_definition) +{ + CompilerStack c; + c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value modifier = astJson["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition"); + BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M"); + BOOST_CHECK_EQUAL(modifier["src"], "13:25:1"); +} + +BOOST_AUTO_TEST_CASE(modifier_invocation) +{ + CompilerStack c; + c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) {} }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value modifier = astJson["children"][0]["children"][1]["children"][2]; + BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation"); + BOOST_CHECK_EQUAL(modifier["src"], "52:4:1"); + BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["type"], "modifier (uint256)"); + BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["value"], "M"); + BOOST_CHECK_EQUAL(modifier["children"][1]["attributes"]["value"], "1"); +} + +BOOST_AUTO_TEST_CASE(event_definition) +{ + CompilerStack c; + c.addSource("a", "contract C { event E(); }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value event = astJson["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(event["name"], "EventDefinition"); + BOOST_CHECK_EQUAL(event["attributes"]["name"], "E"); + BOOST_CHECK_EQUAL(event["src"], "13:10:1"); +} + +BOOST_AUTO_TEST_CASE(array_type_name) +{ + CompilerStack c; + c.addSource("a", "contract C { uint[] i; }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value arrayDecl = astJson["children"][0]["children"][0]["attributes"]; + BOOST_CHECK_EQUAL(arrayDecl["storageLocation"], "default"); + BOOST_CHECK_EQUAL(arrayDecl["type"], "uint256[]"); + Json::Value array = astJson["children"][0]["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName"); + BOOST_CHECK_EQUAL(array["src"], "13:6:1"); +} + +BOOST_AUTO_TEST_CASE(short_type_name) +{ + CompilerStack c; + c.addSource("a", "contract c { function f() { uint[] memory x; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value arrayDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(arrayDecl["attributes"]["storageLocation"], "memory"); + BOOST_CHECK_EQUAL(arrayDecl["attributes"]["type"], "uint256[]"); +} + +BOOST_AUTO_TEST_CASE(short_type_name_ref) +{ + CompilerStack c; + c.addSource("a", "contract c { function f() { uint[][] memory rows; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value arrayDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(arrayDecl["attributes"]["storageLocation"], "memory"); + BOOST_CHECK_EQUAL(arrayDecl["attributes"]["type"], "uint256[][]"); +} + +BOOST_AUTO_TEST_CASE(placeholder_statement) +{ + CompilerStack c; + c.addSource("a", "contract C { modifier M { _; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0]; + BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement"); + BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1"); +} + +BOOST_AUTO_TEST_CASE(non_utf8) +{ + CompilerStack c; + c.addSource("a", "contract C { function f() { var x = hex\"ff\"; } }"); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value varDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(varDecl["attributes"]["type"], "string"); + BOOST_CHECK_EQUAL(varDecl["attributes"]["typeName"], Json::nullValue); + Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1]; + BOOST_CHECK_EQUAL(literal["name"], "Literal"); + BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff"); + BOOST_CHECK_EQUAL(literal["attributes"]["token"], "string"); + BOOST_CHECK_EQUAL(literal["attributes"]["value"], Json::nullValue); + BOOST_CHECK(literal["attributes"]["type"].asString().find("invalid") != string::npos); +} + +BOOST_AUTO_TEST_CASE(function_type) +{ + CompilerStack c; + c.addSource("a", + "contract C { function f(function() external payable returns (uint) x) " + "returns (function() external constant returns (uint)) {} }" + ); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 1; + Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value fun = astJson["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition"); + Json::Value argument = fun["children"][0]["children"][0]; + BOOST_CHECK_EQUAL(argument["name"], "VariableDeclaration"); + BOOST_CHECK_EQUAL(argument["attributes"]["name"], "x"); + BOOST_CHECK_EQUAL(argument["attributes"]["type"], "function () payable external returns (uint256)"); + Json::Value funType = argument["children"][0]; + BOOST_CHECK_EQUAL(funType["attributes"]["constant"], false); + BOOST_CHECK_EQUAL(funType["attributes"]["payable"], true); + BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); + Json::Value retval = fun["children"][1]["children"][0]; + BOOST_CHECK_EQUAL(retval["name"], "VariableDeclaration"); + BOOST_CHECK_EQUAL(retval["attributes"]["name"], ""); + BOOST_CHECK_EQUAL(retval["attributes"]["type"], "function () view external returns (uint256)"); + funType = retval["children"][0]; + BOOST_CHECK_EQUAL(funType["attributes"]["constant"], true); + BOOST_CHECK_EQUAL(funType["attributes"]["payable"], false); + BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); +} + +BOOST_AUTO_TEST_CASE(documentation) +{ + CompilerStack c; + c.addSource("a", "/**This contract is empty*/ contract C {}"); + c.addSource("b", + "/**This contract is empty" + " and has a line-breaking comment.*/" + "contract C {}" + ); + c.addSource("c", + "contract C {" + " /** Some comment on Evt.*/ event Evt();" + " /** Some comment on mod.*/ modifier mod() { _; }" + " /** Some comment on fn.*/ function fn() public {}" + "}" + ); + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + map<string, unsigned> sourceIndices; + sourceIndices["a"] = 0; + sourceIndices["b"] = 1; + sourceIndices["c"] = 2; + Json::Value astJsonA = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); + Json::Value documentationA = astJsonA["children"][0]["attributes"]["documentation"]; + BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); + Json::Value astJsonB = ASTJsonConverter(true, sourceIndices).toJson(c.ast("b")); + Json::Value documentationB = astJsonB["children"][0]["attributes"]["documentation"]; + BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); + Json::Value astJsonC = ASTJsonConverter(true, sourceIndices).toJson(c.ast("c")); + Json::Value documentationC0 = astJsonC["children"][0]["children"][0]["attributes"]["documentation"]; + Json::Value documentationC1 = astJsonC["children"][0]["children"][1]["attributes"]["documentation"]; + Json::Value documentationC2 = astJsonC["children"][0]["children"][2]["attributes"]["documentation"]; + BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); + BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); + BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); +} + + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 7c335a48..72b86767 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -20,7 +20,7 @@ #include <test/libsolidity/AnalysisFramework.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/SourceReferenceFormatter.h> @@ -56,12 +56,23 @@ AnalysisFramework::parseAnalyseAndReturnError( m_compiler.analyze(); + ErrorList errors = filterErrors(m_compiler.errors(), _reportWarnings); + if (errors.size() > 1 && !_allowMultipleErrors) + BOOST_FAIL("Multiple errors found: " + formatErrors()); + + return make_pair(&m_compiler.ast(""), std::move(errors)); +} + +ErrorList AnalysisFramework::filterErrors(ErrorList const& _errorList, bool _includeWarnings) const +{ ErrorList errors; - for (auto const& currentError: m_compiler.errors()) + for (auto const& currentError: _errorList) { solAssert(currentError->comment(), ""); if (currentError->type() == Error::Type::Warning) { + if (!_includeWarnings) + continue; bool ignoreWarning = false; for (auto const& filter: m_warningsToFilter) if (currentError->comment()->find(filter) == 0) @@ -73,17 +84,10 @@ AnalysisFramework::parseAnalyseAndReturnError( continue; } - if (_reportWarnings || (currentError->type() != Error::Type::Warning)) - { - if (!_allowMultipleErrors && !errors.empty()) - { - BOOST_FAIL("Multiple errors found: " + formatErrors()); - } - errors.emplace_back(std::move(currentError)); - } + errors.emplace_back(currentError); } - return make_pair(&m_compiler.ast(""), errors); + return errors; } SourceUnit const* AnalysisFramework::parseAndAnalyse(string const& _source) @@ -110,7 +114,7 @@ ErrorList AnalysisFramework::expectError(std::string const& _source, bool _warni return sourceAndErrors.second; } -string AnalysisFramework::formatErrors() +string AnalysisFramework::formatErrors() const { string message; for (auto const& error: m_compiler.errors()) @@ -118,7 +122,7 @@ string AnalysisFramework::formatErrors() return message; } -string AnalysisFramework::formatError(Error const& _error) +string AnalysisFramework::formatError(Error const& _error) const { return SourceReferenceFormatter::formatExceptionInformation( _error, diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index 6ecf4a5a..05490a42 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -57,8 +57,8 @@ protected: bool success(std::string const& _source); ErrorList expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false); - std::string formatErrors(); - std::string formatError(Error const& _error); + std::string formatErrors() const; + std::string formatError(Error const& _error) const; static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name); static FunctionTypePointer retrieveFunctionBySignature( @@ -66,6 +66,9 @@ protected: std::string const& _signature ); + // filter out the warnings in m_warningsToFilter or all warnings if _includeWarnings is false + ErrorList filterErrors(ErrorList const& _errorList, bool _includeWarnings) const; + std::vector<std::string> m_warningsToFilter = {"This is a pre-release compiler version"}; dev::solidity::CompilerStack m_compiler; }; diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index aff610a4..77ca363a 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -20,7 +20,7 @@ * Unit tests for Assembly Items from evmasm/Assembly.h */ -#include <test/TestHelper.h> +#include <test/Options.h> #include <libevmasm/SourceLocation.h> #include <libevmasm/Assembly.h> @@ -157,14 +157,23 @@ BOOST_AUTO_TEST_CASE(location_test) } } )"; - shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(24, SourceLocation(2, 75, n)) + - vector<SourceLocation>(32, SourceLocation(20, 72, n)) + - vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + - vector<SourceLocation>(2, SourceLocation(58, 67, n)) + - vector<SourceLocation>(2, SourceLocation(20, 72, n)); + vector<SourceLocation>(24, SourceLocation(2, 75, make_shared<string>(""))) + + vector<SourceLocation>(2, SourceLocation(20, 72, make_shared<string>(""))) + + vector<SourceLocation>(1, SourceLocation(8, 17, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(3, SourceLocation(5, 7, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(30, 31, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(27, 28, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(20, 32, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(5, 7, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(24, SourceLocation(20, 72, make_shared<string>(""))) + + vector<SourceLocation>(1, SourceLocation(42, 51, make_shared<string>(""))) + + vector<SourceLocation>(1, SourceLocation(65, 67, make_shared<string>(""))) + + vector<SourceLocation>(2, SourceLocation(58, 67, make_shared<string>(""))) + + vector<SourceLocation>(2, SourceLocation(20, 72, make_shared<string>(""))); + + checkAssemblyLocations(items, locations); } diff --git a/test/libsolidity/FormattedScope.h b/test/libsolidity/FormattedScope.h new file mode 100644 index 00000000..923404f0 --- /dev/null +++ b/test/libsolidity/FormattedScope.h @@ -0,0 +1,68 @@ +/* + 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 <boost/noncopyable.hpp> + +#include <ostream> +#include <vector> + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +namespace formatting +{ + +static constexpr char const* RESET = "\033[0m"; +static constexpr char const* RED = "\033[1;31m"; +static constexpr char const* GREEN = "\033[1;32m"; +static constexpr char const* YELLOW = "\033[1;33m"; +static constexpr char const* CYAN = "\033[1;36m"; +static constexpr char const* BOLD = "\033[1m"; +static constexpr char const* RED_BACKGROUND = "\033[48;5;160m"; +static constexpr char const* ORANGE_BACKGROUND = "\033[48;5;166m"; +static constexpr char const* INVERSE = "\033[7m"; + +} + +class FormattedScope: boost::noncopyable +{ +public: + /// @arg _formatting List of formatting strings (e.g. colors) defined in the formatting namespace. + FormattedScope(std::ostream& _stream, bool const _enabled, std::vector<char const*> const& _formatting): + m_stream(_stream), m_enabled(_enabled) + { + if (m_enabled) + for (auto const& format: _formatting) + m_stream << format; + } + ~FormattedScope() { if (m_enabled) m_stream << formatting::RESET; } + template<typename T> + std::ostream& operator<<(T&& _t) { return m_stream << std::forward<T>(_t); } +private: + std::ostream& m_stream; + bool m_enabled; +}; + +} +} +} diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index fd2017f9..0d66456c 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -294,6 +294,19 @@ BOOST_AUTO_TEST_CASE(extcodesize_gas) testRunTimeGas("f()", vector<bytes>{encodeArgs()}); } +BOOST_AUTO_TEST_CASE(regular_functions_exclude_fallback) +{ + // A bug in the estimator caused the costs for a specific function + // to always include the costs for the fallback. + char const* sourceCode = R"( + contract A { + uint public x; + function() { x = 2; } + } + )"; + testCreationTimeGas(sourceCode); + testRunTimeGas("x()", vector<bytes>{encodeArgs()}); +} BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index bc81b3b1..1b5dd4a5 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -21,7 +21,7 @@ */ #include <test/libsolidity/ErrorCheck.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/CompilerStack.h> diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index a4dcc4d5..0ced1792 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -20,7 +20,7 @@ * Unit tests for inline assembly. */ -#include "../TestHelper.h" +#include <test/Options.h> #include <libsolidity/interface/AssemblyStack.h> #include <libsolidity/parsing/Scanner.h> @@ -783,6 +783,8 @@ BOOST_AUTO_TEST_CASE(shift) BOOST_AUTO_TEST_CASE(shift_constantinople_warning) { + if (dev::test::Options::get().evmVersion().hasBitwiseShifting()) + return; CHECK_PARSE_WARNING("{ pop(shl(10, 32)) }", Warning, "The \"shl\" instruction is only available for Constantinople-compatible VMs."); CHECK_PARSE_WARNING("{ pop(shr(10, 32)) }", Warning, "The \"shr\" instruction is only available for Constantinople-compatible VMs."); CHECK_PARSE_WARNING("{ pop(sar(10, 32)) }", Warning, "The \"sar\" instruction is only available for Constantinople-compatible VMs."); diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp index 285c5604..2b3df3a7 100644 --- a/test/libsolidity/JSONCompiler.cpp +++ b/test/libsolidity/JSONCompiler.cpp @@ -25,8 +25,8 @@ #include <libsolidity/interface/Version.h> #include <libsolc/libsolc.h> -#include "../Metadata.h" -#include "../TestHelper.h" +#include <test/Metadata.h> +#include <test/Options.h> using namespace std; @@ -111,18 +111,18 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["bytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" ); BOOST_CHECK(contract["runtimeBytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), - "6060604052600080fd00" + "6080604052600080fd00" ); BOOST_CHECK(contract["functionHashes"].isObject()); BOOST_CHECK(contract["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[61,10600],\"external\":{},\"internal\":{}}" + "{\"creation\":[66,10600],\"external\":{},\"internal\":{}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); @@ -153,18 +153,18 @@ BOOST_AUTO_TEST_CASE(single_compilation) BOOST_CHECK(contract["bytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" ); BOOST_CHECK(contract["runtimeBytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["runtimeBytecode"].asString()), - "6060604052600080fd00" + "6080604052600080fd00" ); BOOST_CHECK(contract["functionHashes"].isObject()); BOOST_CHECK(contract["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[61,10600],\"external\":{},\"internal\":{}}" + "{\"creation\":[66,10600],\"external\":{},\"internal\":{}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp index f1edeeb7..808bd1e1 100644 --- a/test/libsolidity/Metadata.cpp +++ b/test/libsolidity/Metadata.cpp @@ -19,8 +19,8 @@ * Unit tests for the metadata output. */ -#include "../Metadata.h" -#include "../TestHelper.h" +#include <test/Metadata.h> +#include <test/Options.h> #include <libsolidity/interface/CompilerStack.h> #include <libdevcore/SwarmHash.h> #include <libdevcore/JSON.h> diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 12b5f439..beb933a4 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -329,6 +329,144 @@ BOOST_AUTO_TEST_CASE(ways_to_merge_variables) CHECK_WARNING(text, "Assertion violation happens here"); } +BOOST_AUTO_TEST_CASE(bool_simple) +{ + string text = R"( + contract C { + function f(bool x) public pure { + assert(x); + } + } + )"; + CHECK_WARNING(text, "Assertion violation happens here"); + text = R"( + contract C { + function f(bool x, bool y) public pure { + assert(x == y); + } + } + )"; + CHECK_WARNING(text, "Assertion violation happens here"); + text = R"( + contract C { + function f(bool x, bool y) public pure { + bool z = x || y; + assert(!(x && y) || z); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x) public pure { + if(x) { + assert(x); + } else { + assert(!x); + } + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x) public pure { + bool y = x; + assert(x == y); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x) public pure { + require(x); + bool y; + y = false; + assert(x || y); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x) public pure { + bool y; + assert(x <= y); + } + } + )"; + CHECK_WARNING(text, "Assertion violation happens here"); + text = R"( + contract C { + function f(bool x) public pure { + bool y; + assert(x >= y); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x) public pure { + require(x); + bool y; + assert(x > y); + assert(y < x); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(bool_int_mixed) +{ + string text = R"( + contract C { + function f(bool x) public pure { + uint a; + if(x) + a = 1; + assert(!x || a > 0); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x, uint a) public pure { + require(!x || a > 0); + uint b = a; + assert(!x || b > 0); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); + text = R"( + contract C { + function f(bool x, bool y) public pure { + uint a; + if (x) { + if (y) { + a = 0; + } else { + a = 1; + } + } else { + if (y) { + a = 1; + } else { + a = 0; + } + } + bool xor_x_y = (x && !y) || (!x && y); + assert(!xor_x_y || a > 0); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(while_loop_simple) { // Check that variables are cleared diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 08ef5277..07f8fba6 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -25,7 +25,7 @@ #include <tuple> #include <libsolidity/parsing/Scanner.h> #include <libsolidity/analysis/SemVerHandler.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 0d471b32..107abc26 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -20,7 +20,7 @@ * Unit tests for the solidity compiler JSON Interface output. */ -#include "../TestHelper.h" +#include <test/Options.h> #include <libsolidity/interface/CompilerStack.h> #include <libdevcore/Exceptions.h> diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp new file mode 100644 index 00000000..90540f3e --- /dev/null +++ b/test/libsolidity/SolidityCompiler.cpp @@ -0,0 +1,60 @@ +/* + 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 compiler itself. + */ + +#include <test/libsolidity/AnalysisFramework.h> + +#include <test/Options.h> + +using namespace std; + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +BOOST_FIXTURE_TEST_SUITE(Compiler, AnalysisFramework) + +BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions) +{ + char const* sourceCode = R"( + contract C { + uint x; + function C() { f(); } + function f() internal { for (uint i = 0; i < 10; ++i) x += 3 + i; } + } + )"; + BOOST_REQUIRE(success(sourceCode)); + m_compiler.setOptimiserSettings(dev::test::Options::get().optimize); + BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); + bytes const& creationBytecode = m_compiler.object("C").bytecode; + bytes const& runtimeBytecode = m_compiler.runtimeObject("C").bytecode; + BOOST_CHECK(creationBytecode.size() >= 130); + BOOST_CHECK(creationBytecode.size() <= 160); + BOOST_CHECK(runtimeBytecode.size() >= 50); + BOOST_CHECK(runtimeBytecode.size() <= 70); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 33cd1419..789b89d1 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -23,7 +23,7 @@ #include <test/libsolidity/SolidityExecutionFramework.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/interface/EVMVersion.h> @@ -102,6 +102,29 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(-8))); } +BOOST_AUTO_TEST_CASE(exp_zero) +{ + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a ** 0; } + } + )"; + compileAndRun(sourceCode); + testContractAgainstCppOnRange("f(uint256)", [](u256 const&) -> u256 { return u256(1); }, 0, 16); +} + +BOOST_AUTO_TEST_CASE(exp_zero_literal) +{ + char const* sourceCode = R"( + contract test { + function f() returns(uint d) { return 0 ** 0; } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()", bytes()), toBigEndian(u256(1))); +} + + BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) { char const* sourceCode = R"( @@ -1788,6 +1811,35 @@ BOOST_AUTO_TEST_CASE(transfer_ether) ABI_CHECK(callContractFunction("b(address,uint256)", oogRecipient, 10), encodeArgs()); } +BOOST_AUTO_TEST_CASE(uncalled_blockhash) +{ + char const* code = R"( + contract C { + function f() public view returns (bytes32) + { + var x = block.blockhash; + return x(block.number - 1); + } + } + )"; + compileAndRun(code, 0, "C"); + bytes result = callContractFunction("f()"); + BOOST_REQUIRE_EQUAL(result.size(), 32); + BOOST_CHECK(result[0] != 0 || result[1] != 0 || result[2] != 0); +} + +BOOST_AUTO_TEST_CASE(blockhash_shadow_resolution) +{ + char const* code = R"( + contract C { + function blockhash(uint256 blockNumber) public returns(bytes32) { bytes32 x; return x; } + function f() public returns(bytes32) { return blockhash(3); } + } + )"; + compileAndRun(code, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0)); +} + BOOST_AUTO_TEST_CASE(log0) { char const* sourceCode = R"( @@ -2048,6 +2100,31 @@ BOOST_AUTO_TEST_CASE(packed_keccak256) testContractAgainstCpp("a(bytes32)", f, u256(-1)); } +BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types) +{ + char const* sourceCode = R"( + contract test { + uint120[3] x; + function f() view returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) { + uint120[] memory y = new uint120[](3); + x[0] = y[0] = uint120(-2); + x[1] = y[1] = uint120(-3); + x[2] = y[2] = uint120(-4); + hash1 = keccak256(x); + hash2 = keccak256(y); + hash3 = keccak256(this.f); + } + } + )"; + compileAndRun(sourceCode); + // Strangely, arrays are encoded with intra-element padding. + ABI_CHECK(callContractFunction("f()"), encodeArgs( + dev::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))), + dev::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))), + dev::keccak256(fromHex(m_contractAddress.hex() + "26121ff0")) + )); +} + BOOST_AUTO_TEST_CASE(packed_sha256) { char const* sourceCode = R"( @@ -2879,6 +2956,58 @@ BOOST_AUTO_TEST_CASE(function_modifier_multiple_times_local_vars) ABI_CHECK(callContractFunction("a()"), encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(function_modifier_library) +{ + char const* sourceCode = R"( + library L { + struct S { uint v; } + modifier mod(S storage s) { s.v++; _; } + function libFun(S storage s) mod(s) internal { s.v += 0x100; } + } + + contract Test { + using L for *; + L.S s; + + function f() public returns (uint) { + s.libFun(); + L.libFun(s); + return s.v; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x202)); +} + +BOOST_AUTO_TEST_CASE(function_modifier_library_inheritance) +{ + // Tests that virtual lookup for modifiers in libraries does not consider + // the current inheritance hierarchy. + + char const* sourceCode = R"( + library L { + struct S { uint v; } + modifier mod(S storage s) { s.v++; _; } + function libFun(S storage s) mod(s) internal { s.v += 0x100; } + } + + contract Test { + using L for *; + L.S s; + modifier mod(L.S storage) { revert(); _; } + + function f() public returns (uint) { + s.libFun(); + L.libFun(s); + return s.v; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(0x202)); +} + BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack) { char const* sourceCode = R"( @@ -3451,6 +3580,45 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) ABI_CHECK(callContractFunction("f(uint256)", 9), encodeArgs(9)); } +BOOST_AUTO_TEST_CASE(sha256_empty) +{ + char const* sourceCode = R"( + contract C { + function f() returns (bytes32) { + return sha256(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), fromHex("0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); +} + +BOOST_AUTO_TEST_CASE(ripemd160_empty) +{ + char const* sourceCode = R"( + contract C { + function f() returns (bytes20) { + return ripemd160(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), fromHex("0x9c1185a5c5e9fc54612808977ee8f548b2258d31000000000000000000000000")); +} + +BOOST_AUTO_TEST_CASE(keccak256_empty) +{ + char const* sourceCode = R"( + contract C { + function f() returns (bytes32) { + return keccak256(); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); +} + BOOST_AUTO_TEST_CASE(keccak256_multiple_arguments) { char const* sourceCode = R"( @@ -4778,6 +4946,48 @@ BOOST_AUTO_TEST_CASE(array_push) ABI_CHECK(callContractFunction("test()"), encodeArgs(5, 4, 3, 3)); } +BOOST_AUTO_TEST_CASE(array_push_struct) +{ + char const* sourceCode = R"( + contract c { + struct S { uint16 a; uint16 b; uint16[3] c; uint16[] d; } + S[] data; + function test() returns (uint16, uint16, uint16, uint16) { + S memory s; + s.a = 2; + s.b = 3; + s.c[2] = 4; + s.d = new uint16[](4); + s.d[2] = 5; + data.push(s); + return (data[0].a, data[0].b, data[0].c[2], data[0].d[2]); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(2, 3, 4, 5)); +} + +BOOST_AUTO_TEST_CASE(array_push_packed_array) +{ + char const* sourceCode = R"( + contract c { + uint80[] x; + function test() returns (uint80, uint80, uint80, uint80) { + x.push(1); + x.push(2); + x.push(3); + x.push(4); + x.push(5); + x.length = 4; + return (x[0], x[1], x[2], x[3]); + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(1, 2, 3, 4)); +} + BOOST_AUTO_TEST_CASE(byte_array_push) { char const* sourceCode = R"( @@ -4798,6 +5008,29 @@ BOOST_AUTO_TEST_CASE(byte_array_push) ABI_CHECK(callContractFunction("test()"), encodeArgs(false)); } +BOOST_AUTO_TEST_CASE(byte_array_push_transition) +{ + // Tests transition between short and long encoding + char const* sourceCode = R"( + contract c { + bytes data; + function test() returns (uint) { + for (uint i = 1; i < 40; i++) + { + data.push(byte(i)); + if (data.length != i) return 0x1000 + i; + if (data[data.length - 1] != byte(i)) return i; + } + for (i = 1; i < 40; i++) + if (data[i - 1] != byte(i)) return 0x1000000 + i; + return 0; + } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("test()"), encodeArgs(0)); +} + BOOST_AUTO_TEST_CASE(external_array_args) { char const* sourceCode = R"( @@ -5020,7 +5253,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base) } uint public m_i; } - contract Derived is Base(2) { + contract Derived is Base { function Derived(uint i) Base(i) {} } @@ -5040,10 +5273,10 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base) } uint public m_i; } - contract Base1 is Base(3) { + contract Base1 is Base { function Base1(uint k) Base(k*k) {} } - contract Derived is Base(3), Base1(2) { + contract Derived is Base, Base1 { function Derived(uint i) Base(i) Base1(i) {} } @@ -5064,7 +5297,7 @@ BOOST_AUTO_TEST_CASE(pass_dynamic_arguments_to_the_base_base_with_gap) uint public m_i; } contract Base1 is Base(3) {} - contract Derived is Base(2), Base1 { + contract Derived is Base, Base1 { function Derived(uint i) Base(i) {} } contract Final is Derived(4) { @@ -6955,6 +7188,21 @@ BOOST_AUTO_TEST_CASE(library_call) ABI_CHECK(callContractFunction("f(uint256)", u256(33)), encodeArgs(u256(33) * 9)); } +BOOST_AUTO_TEST_CASE(library_function_external) +{ + char const* sourceCode = R"( + library Lib { function m(bytes b) external pure returns (byte) { return b[2]; } } + contract Test { + function f(bytes b) public pure returns (byte) { + return Lib.m(b); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f(bytes)", u256(0x20), u256(5), "abcde"), encodeArgs("c")); +} + BOOST_AUTO_TEST_CASE(library_stray_values) { char const* sourceCode = R"( @@ -7566,7 +7814,6 @@ BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size) ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256)); } - BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) { // Computes binomial coefficients the chinese way @@ -7589,6 +7836,41 @@ BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes) ABI_CHECK(callContractFunction("f(uint256,uint256)", encodeArgs(u256(9), u256(5))), encodeArgs(u256(70))); } +BOOST_AUTO_TEST_CASE(create_multiple_dynamic_arrays) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint) { + uint[][] memory x = new uint[][](42); + assert(x[0].length == 0); + x[0] = new uint[](1); + x[0][0] = 1; + assert(x[4].length == 0); + x[4] = new uint[](1); + x[4][0] = 2; + assert(x[10].length == 0); + x[10] = new uint[](1); + x[10][0] = 44; + uint[][] memory y = new uint[][](24); + assert(y[0].length == 0); + y[0] = new uint[](1); + y[0][0] = 1; + assert(y[4].length == 0); + y[4] = new uint[](1); + y[4][0] = 2; + assert(y[10].length == 0); + y[10] = new uint[](1); + y[10][0] = 88; + if ((x[0][0] == y[0][0]) && (x[4][0] == y[4][0]) && (x[10][0] == 44) && (y[10][0] == 88)) + return 7; + return 0; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); +} + BOOST_AUTO_TEST_CASE(memory_overwrite) { char const* sourceCode = R"( @@ -7627,12 +7909,12 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod_zero) { char const* sourceCode = R"( contract C { - function f() pure returns (uint) { - addmod(1, 2, 0); + function f(uint d) pure returns (uint) { + addmod(1, 2, d); return 2; } - function g() pure returns (uint) { - mulmod(1, 2, 0); + function g(uint d) pure returns (uint) { + mulmod(1, 2, d); return 2; } function h() pure returns (uint) { @@ -7645,8 +7927,8 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod_zero) } )"; compileAndRun(sourceCode); - ABI_CHECK(callContractFunction("f()"), encodeArgs()); - ABI_CHECK(callContractFunction("g()"), encodeArgs()); + ABI_CHECK(callContractFunction("f(uint)", 0), encodeArgs()); + ABI_CHECK(callContractFunction("g(uint)", 0), encodeArgs()); ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); } @@ -8548,6 +8830,24 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) ABI_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)), encodeArgs(0)); } +BOOST_AUTO_TEST_CASE(cleanup_bytes_types_shortening) +{ + char const* sourceCode = R"( + contract C { + function f() pure returns (bytes32 r) { + bytes4 x = 0xffffffff; + bytes2 y = bytes2(x); + assembly { r := y } + // At this point, r and y both store four bytes, but + // y is properly cleaned before the equality check + require(y == bytes2(0xffff)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs("\xff\xff\xff\xff")); +} + BOOST_AUTO_TEST_CASE(skip_dynamic_types) { // The EVM cannot provide access to dynamically-sized return values, so we have to skip them. @@ -8635,6 +8935,32 @@ BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); } +BOOST_AUTO_TEST_CASE(correctly_initialize_memory_array_in_constructor) +{ + // Memory arrays are initialized using codecopy past the size of the code. + // This test checks that it also works in the constructor context. + char const* sourceCode = R"( + contract C { + bool public success; + function C() public { + // Make memory dirty. + assembly { + for { let i := 0 } lt(i, 64) { i := add(i, 1) } { + mstore(msize, not(0)) + } + } + uint16[3] memory c; + require(c[0] == 0 && c[1] == 0 && c[2] == 0); + uint16[] memory x = new uint16[](3); + require(x[0] == 0 && x[1] == 0 && x[2] == 0); + success = true; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("success()"), encodeArgs(u256(1))); +} + BOOST_AUTO_TEST_CASE(return_does_not_skip_modifier) { char const* sourceCode = R"( @@ -8998,7 +9324,7 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) int mutex; function t() returns (uint) { if (mutex > 0) - return 7; + { assembly { mstore(0, 7) return(0, 0x20) } } mutex = 1; // Avoid re-executing this function if we jump somewhere. x(); @@ -9011,6 +9337,27 @@ BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail) ABI_CHECK(callContractFunction("t()"), encodeArgs()); } +BOOST_AUTO_TEST_CASE(calling_uninitialized_function_through_array) +{ + char const* sourceCode = R"( + contract C { + int mutex; + function t() returns (uint) { + if (mutex > 0) + { assembly { mstore(0, 7) return(0, 0x20) } } + mutex = 1; + // Avoid re-executing this function if we jump somewhere. + function() internal returns (uint)[200] x; + x[0](); + return 2; + } + } + )"; + + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("t()"), encodeArgs()); +} + BOOST_AUTO_TEST_CASE(pass_function_types_internally) { char const* sourceCode = R"( @@ -10152,6 +10499,214 @@ BOOST_AUTO_TEST_CASE(revert) ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(42))); } +BOOST_AUTO_TEST_CASE(revert_with_cause) +{ + char const* sourceCode = R"( + contract D { + function f() public { + revert("test123"); + } + function g() public { + revert("test1234567890123456789012345678901234567890"); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function g() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "test123") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(0, 0x40, 0x84) + errorSignature + encodeArgs(0x20, 44, "test1234567890123456789012345678901234567890") + bytes(28, 0): bytes()); +} + +BOOST_AUTO_TEST_CASE(require_with_message) +{ + char const* sourceCode = R"( + contract D { + bool flag = false; + string storageError = "abc"; + function f(uint x) public { + require(x > 7, "failed"); + } + function g() public { + // As a side-effect of internalFun, the flag will be set to true + // (even if the condition is true), + // but it will only throw in the next evaluation. + bool flagCopy = flag; + require(flagCopy == false, internalFun()); + } + function internalFun() returns (string) { + flag = true; + return "only on second run"; + } + function h() public { + require(false, storageError); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f(uint x) public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function g() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function h() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f(uint256)", 8), haveReturndata ? encodeArgs(1, 0x40, 0) : bytes()); + ABI_CHECK(callContractFunction("f(uint256)", 5), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 6, "failed") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(1, 0x40, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 18, "only on second run") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("h()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 3, "abc") + bytes(28, 0): bytes()); +} + +BOOST_AUTO_TEST_CASE(bubble_up_error_messages) +{ + char const* sourceCode = R"( + contract D { + function f() public { + revert("message"); + } + function g() public { + this.f(); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function g() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); +} + +BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer) +{ + char const* sourceCode = R"( + contract D { + function() public payable { + revert("message"); + } + function f() public { + this.transfer(0); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); +} + +BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_create) +{ + char const* sourceCode = R"( + contract E { + function E() { + revert("message"); + } + } + contract D { + function f() public { + var x = new E(); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); +} + BOOST_AUTO_TEST_CASE(negative_stack_height) { // This code was causing negative stack height during code generation @@ -10785,6 +11340,329 @@ BOOST_AUTO_TEST_CASE(snark) BOOST_CHECK(callContractFunction("verifyTx()") == encodeArgs(true)); } +BOOST_AUTO_TEST_CASE(abi_encode) +{ + char const* sourceCode = R"( + contract C { + function f0() returns (bytes) { + return abi.encode(); + } + function f1() returns (bytes) { + return abi.encode(1, 2); + } + function f2() returns (bytes) { + string memory x = "abc"; + return abi.encode(1, x, 2); + } + function f3() returns (bytes r) { + // test that memory is properly allocated + string memory x = "abc"; + r = abi.encode(1, x, 2); + bytes memory y = "def"; + require(y[0] == "d"); + y[0] = "e"; + require(y[0] == "e"); + } + function f4() returns (bytes) { + bytes4 x = "abcd"; + return abi.encode(bytes2(x)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 0)); + ABI_CHECK(callContractFunction("f1()"), encodeArgs(0x20, 0x40, 1, 2)); + ABI_CHECK(callContractFunction("f2()"), encodeArgs(0x20, 0xa0, 1, 0x60, 2, 3, "abc")); + ABI_CHECK(callContractFunction("f3()"), encodeArgs(0x20, 0xa0, 1, 0x60, 2, 3, "abc")); + ABI_CHECK(callContractFunction("f4()"), encodeArgs(0x20, 0x20, "ab")); +} + +BOOST_AUTO_TEST_CASE(abi_encode_v2) +{ + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract C { + struct S { uint a; uint[] b; } + function f0() public pure returns (bytes) { + return abi.encode(); + } + function f1() public pure returns (bytes) { + return abi.encode(1, 2); + } + function f2() public pure returns (bytes) { + string memory x = "abc"; + return abi.encode(1, x, 2); + } + function f3() public pure returns (bytes r) { + // test that memory is properly allocated + string memory x = "abc"; + r = abi.encode(1, x, 2); + bytes memory y = "def"; + require(y[0] == "d"); + y[0] = "e"; + require(y[0] == "e"); + } + S s; + function f4() public view returns (bytes r) { + string memory x = "abc"; + s.a = 7; + s.b.push(2); + s.b.push(3); + r = abi.encode(1, x, s, 2); + bytes memory y = "def"; + require(y[0] == "d"); + y[0] = "e"; + require(y[0] == "e"); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 0)); + ABI_CHECK(callContractFunction("f1()"), encodeArgs(0x20, 0x40, 1, 2)); + ABI_CHECK(callContractFunction("f2()"), encodeArgs(0x20, 0xa0, 1, 0x60, 2, 3, "abc")); + ABI_CHECK(callContractFunction("f3()"), encodeArgs(0x20, 0xa0, 1, 0x60, 2, 3, "abc")); + ABI_CHECK(callContractFunction("f4()"), encodeArgs(0x20, 0x160, 1, 0x80, 0xc0, 2, 3, "abc", 7, 0x40, 2, 2, 3)); +} + + +BOOST_AUTO_TEST_CASE(abi_encodePacked) +{ + char const* sourceCode = R"( + contract C { + function f0() public pure returns (bytes) { + return abi.encodePacked(); + } + function f1() public pure returns (bytes) { + return abi.encodePacked(uint8(1), uint8(2)); + } + function f2() public pure returns (bytes) { + string memory x = "abc"; + return abi.encodePacked(uint8(1), x, uint8(2)); + } + function f3() public pure returns (bytes r) { + // test that memory is properly allocated + string memory x = "abc"; + r = abi.encodePacked(uint8(1), x, uint8(2)); + bytes memory y = "def"; + require(y[0] == "d"); + y[0] = "e"; + require(y[0] == "e"); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 0)); + ABI_CHECK(callContractFunction("f1()"), encodeArgs(0x20, 2, "\x01\x02")); + ABI_CHECK(callContractFunction("f2()"), encodeArgs(0x20, 5, "\x01" "abc" "\x02")); + ABI_CHECK(callContractFunction("f3()"), encodeArgs(0x20, 5, "\x01" "abc" "\x02")); +} + +BOOST_AUTO_TEST_CASE(abi_encode_with_selector) +{ + char const* sourceCode = R"( + contract C { + function f0() public pure returns (bytes) { + return abi.encodeWithSelector(0x12345678); + } + function f1() public pure returns (bytes) { + return abi.encodeWithSelector(0x12345678, "abc"); + } + function f2() public pure returns (bytes) { + bytes4 x = 0x12345678; + return abi.encodeWithSelector(x, "abc"); + } + function f3() public pure returns (bytes) { + bytes4 x = 0x12345678; + return abi.encodeWithSelector(x, uint(-1)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 4, "\x12\x34\x56\x78")); + bytes expectation; + expectation = encodeArgs(0x20, 4 + 0x60) + bytes{0x12, 0x34, 0x56, 0x78} + encodeArgs(0x20, 3, "abc") + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f1()"), expectation); + expectation = encodeArgs(0x20, 4 + 0x60) + bytes{0x12, 0x34, 0x56, 0x78} + encodeArgs(0x20, 3, "abc") + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f2()"), expectation); + expectation = encodeArgs(0x20, 4 + 0x20) + bytes{0x12, 0x34, 0x56, 0x78} + encodeArgs(u256(-1)) + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f3()"), expectation); +} + +BOOST_AUTO_TEST_CASE(abi_encode_with_selectorv2) +{ + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + contract C { + function f0() public pure returns (bytes) { + return abi.encodeWithSelector(0x12345678); + } + function f1() public pure returns (bytes) { + return abi.encodeWithSelector(0x12345678, "abc"); + } + function f2() public pure returns (bytes) { + bytes4 x = 0x12345678; + return abi.encodeWithSelector(x, "abc"); + } + function f3() public pure returns (bytes) { + bytes4 x = 0x12345678; + return abi.encodeWithSelector(x, uint(-1)); + } + struct S { uint a; string b; uint16 c; } + function f4() public pure returns (bytes) { + bytes4 x = 0x12345678; + S memory s; + s.a = 0x1234567; + s.b = "Lorem ipsum dolor sit ethereum........"; + s.c = 0x1234; + return abi.encodeWithSelector(x, uint(-1), s, uint(3)); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 4, "\x12\x34\x56\x78")); + bytes expectation; + expectation = encodeArgs(0x20, 4 + 0x60) + bytes{0x12, 0x34, 0x56, 0x78} + encodeArgs(0x20, 3, "abc") + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f1()"), expectation); + expectation = encodeArgs(0x20, 4 + 0x60) + bytes{0x12, 0x34, 0x56, 0x78} + encodeArgs(0x20, 3, "abc") + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f2()"), expectation); + expectation = encodeArgs(0x20, 4 + 0x20) + bytes{0x12, 0x34, 0x56, 0x78} + encodeArgs(u256(-1)) + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f3()"), expectation); + expectation = + encodeArgs(0x20, 4 + 0x120) + + bytes{0x12, 0x34, 0x56, 0x78} + + encodeArgs(u256(-1), 0x60, u256(3), 0x1234567, 0x60, 0x1234, 38, "Lorem ipsum dolor sit ethereum........") + + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f4()"), expectation); +} + +BOOST_AUTO_TEST_CASE(abi_encode_with_signature) +{ + char const* sourceCode = R"T( + contract C { + function f0() public pure returns (bytes) { + return abi.encodeWithSignature("f(uint256)"); + } + function f1() public pure returns (bytes) { + string memory x = "f(uint256)"; + return abi.encodeWithSignature(x, "abc"); + } + string xstor; + function f1s() public returns (bytes) { + xstor = "f(uint256)"; + return abi.encodeWithSignature(xstor, "abc"); + } + function f2() public pure returns (bytes r, uint[] ar) { + string memory x = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + uint[] memory y = new uint[](4); + y[0] = uint(-1); + y[1] = uint(-2); + y[2] = uint(-3); + y[3] = uint(-4); + r = abi.encodeWithSignature(x, y); + // The hash uses temporary memory. This allocation re-uses the memory + // and should initialize it properly. + ar = new uint[](2); + } + } + )T"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 4, "\xb3\xde\x64\x8b")); + bytes expectation; + expectation = encodeArgs(0x20, 4 + 0x60) + bytes{0xb3, 0xde, 0x64, 0x8b} + encodeArgs(0x20, 3, "abc") + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f1()"), expectation); + ABI_CHECK(callContractFunction("f1s()"), expectation); + expectation = + encodeArgs(0x40, 0x140, 4 + 0xc0) + + (bytes{0xe9, 0xc9, 0x21, 0xcd} + encodeArgs(0x20, 4, u256(-1), u256(-2), u256(-3), u256(-4)) + bytes(0x20 - 4)) + + encodeArgs(2, 0, 0); + ABI_CHECK(callContractFunction("f2()"), expectation); +} + +BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2) +{ + char const* sourceCode = R"T( + pragma experimental ABIEncoderV2; + contract C { + function f0() public pure returns (bytes) { + return abi.encodeWithSignature("f(uint256)"); + } + function f1() public pure returns (bytes) { + string memory x = "f(uint256)"; + return abi.encodeWithSignature(x, "abc"); + } + string xstor; + function f1s() public returns (bytes) { + xstor = "f(uint256)"; + return abi.encodeWithSignature(xstor, "abc"); + } + function f2() public pure returns (bytes r, uint[] ar) { + string memory x = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + uint[] memory y = new uint[](4); + y[0] = uint(-1); + y[1] = uint(-2); + y[2] = uint(-3); + y[3] = uint(-4); + r = abi.encodeWithSignature(x, y); + // The hash uses temporary memory. This allocation re-uses the memory + // and should initialize it properly. + ar = new uint[](2); + } + struct S { uint a; string b; uint16 c; } + function f4() public pure returns (bytes) { + bytes4 x = 0x12345678; + S memory s; + s.a = 0x1234567; + s.b = "Lorem ipsum dolor sit ethereum........"; + s.c = 0x1234; + return abi.encodeWithSignature(s.b, uint(-1), s, uint(3)); + } + } + )T"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f0()"), encodeArgs(0x20, 4, "\xb3\xde\x64\x8b")); + bytes expectation; + expectation = encodeArgs(0x20, 4 + 0x60) + bytes{0xb3, 0xde, 0x64, 0x8b} + encodeArgs(0x20, 3, "abc") + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f1()"), expectation); + ABI_CHECK(callContractFunction("f1s()"), expectation); + expectation = + encodeArgs(0x40, 0x140, 4 + 0xc0) + + (bytes{0xe9, 0xc9, 0x21, 0xcd} + encodeArgs(0x20, 4, u256(-1), u256(-2), u256(-3), u256(-4)) + bytes(0x20 - 4)) + + encodeArgs(2, 0, 0); + ABI_CHECK(callContractFunction("f2()"), expectation); + expectation = + encodeArgs(0x20, 4 + 0x120) + + bytes{0x7c, 0x79, 0x30, 0x02} + + encodeArgs(u256(-1), 0x60, u256(3), 0x1234567, 0x60, 0x1234, 38, "Lorem ipsum dolor sit ethereum........") + + bytes(0x20 - 4); + ABI_CHECK(callContractFunction("f4()"), expectation); +} + +BOOST_AUTO_TEST_CASE(abi_encode_call) +{ + char const* sourceCode = R"T( + contract C { + bool x; + function c(uint a, uint[] b) public { + require(a == 5); + require(b.length == 2); + require(b[0] == 6); + require(b[1] == 7); + x = true; + } + function f() public returns (bool) { + uint a = 5; + uint[] memory b = new uint[](2); + b[0] = 6; + b[1] = 7; + require(this.call(abi.encodeWithSignature("c(uint256,uint256[])", a, b))); + return x; + } + } + )T"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); +} + BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) { char const* sourceCode = R"( @@ -10830,6 +11708,179 @@ BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) } } +BOOST_AUTO_TEST_CASE(swap_peephole_optimisation) +{ + char const* sourceCode = R"( + contract C { + function lt(uint a, uint b) returns (bool c) { + assembly { + a + b + swap1 + lt + =: c + } + } + function add(uint a, uint b) returns (uint c) { + assembly { + a + b + swap1 + add + =: c + } + } + function div(uint a, uint b) returns (uint c) { + assembly { + a + b + swap1 + div + =: c + } + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(3))); + BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(100), u256(200)) == encodeArgs(u256(300))); + BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(2))); + BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(200), u256(10)) == encodeArgs(u256(20))); + BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(1), u256(0)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(0), u256(1)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(bitwise_shifting_constantinople) +{ + if (!dev::test::Options::get().evmVersion().hasBitwiseShifting()) + return; + char const* sourceCode = R"( + contract C { + function shl(uint a, uint b) returns (uint c) { + assembly { + a + b + shl + =: c + } + } + function shr(uint a, uint b) returns (uint c) { + assembly { + a + b + shr + =: c + } + } + function sar(uint a, uint b) returns (uint c) { + assembly { + a + b + sar + =: c + } + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("shl(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(4))); + BOOST_CHECK(callContractFunction("shl(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(1)) == encodeArgs(u256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"))); + BOOST_CHECK(callContractFunction("shl(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(256)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("shr(uint256,uint256)", u256(3), u256(1)) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shr(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(1)) == encodeArgs(u256("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))); + BOOST_CHECK(callContractFunction("shr(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(255)) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shr(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(256)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("sar(uint256,uint256)", u256(3), u256(1)) == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("sar(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(1)) == encodeArgs(u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))); + BOOST_CHECK(callContractFunction("sar(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(255)) == encodeArgs(u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))); + BOOST_CHECK(callContractFunction("sar(uint256,uint256)", u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), u256(256)) == encodeArgs(u256("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))); +} + +BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) +{ + if (!dev::test::Options::get().evmVersion().hasBitwiseShifting()) + return; + char const* sourceCode = R"( + contract C { + function shl_1() returns (bool) { + uint c; + assembly { + 1 + 2 + shl + =: c + } + assert(c == 4); + return true; + } + function shl_2() returns (bool) { + uint c; + assembly { + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 1 + shl + =: c + } + assert(c == 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe); + return true; + } + function shl_3() returns (bool) { + uint c; + assembly { + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 256 + shl + =: c + } + assert(c == 0); + return true; + } + function shr_1() returns (bool) { + uint c; + assembly { + 3 + 1 + shr + =: c + } + assert(c == 1); + return true; + } + function shr_2() returns (bool) { + uint c; + assembly { + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 1 + shr + =: c + } + assert(c == 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + return true; + } + function shr_3() returns (bool) { + uint c; + assembly { + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + 256 + shr + =: c + } + assert(c == 0); + return true; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("shl_1()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shl_2()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shl_3()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shr_1()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shr_2()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("shr_3()") == encodeArgs(u256(1))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 5f044b44..90d8265c 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -30,7 +30,7 @@ #include <libsolidity/ast/AST.h> #include <libsolidity/analysis/TypeChecker.h> #include <libsolidity/interface/ErrorReporter.h> -#include "../TestHelper.h" +#include <test/Options.h> using namespace std; @@ -503,12 +503,15 @@ BOOST_AUTO_TEST_CASE(blockhash) char const* sourceCode = R"( contract test { function f() { - block.blockhash(3); + blockhash(3); } } )"; - bytes code = compileFirstExpression(sourceCode, {}, {}, - {make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block))}); + + auto blockhashFun = make_shared<FunctionType>(strings{"uint256"}, strings{"bytes32"}, + FunctionType::Kind::BlockHash, false, StateMutability::View); + + bytes code = compileFirstExpression(sourceCode, {}, {}, {make_shared<MagicVariableDeclaration>("blockhash", blockhashFun)}); bytes expectation({byte(Instruction::PUSH1), 0x03, byte(Instruction::BLOCKHASH)}); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 997b610e..d438a9dc 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -22,7 +22,7 @@ #include <test/libsolidity/AnalysisFramework.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <libsolidity/ast/AST.h> @@ -43,281 +43,6 @@ namespace test BOOST_FIXTURE_TEST_SUITE(SolidityNameAndTypeResolution, AnalysisFramework) -BOOST_AUTO_TEST_CASE(smoke_test) -{ - char const* text = R"( - contract test { - uint256 stateVariable1; - function fun(uint256 arg1) public { uint256 y; y = arg1; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) -{ - char const* text = R"( - contract test { - uint256 variable; - uint128 variable; - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared."); -} - -BOOST_AUTO_TEST_CASE(double_function_declaration) -{ - char const* text = R"( - contract test { - function fun() public { } - function fun() public { } - } - )"; - CHECK_ERROR(text, DeclarationError, "Function with same name and arguments defined twice."); -} - -BOOST_AUTO_TEST_CASE(double_variable_declaration) -{ - string text = R"( - contract test { - function f() pure public { - uint256 x; - if (true) { uint256 x; } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared"); -} - -BOOST_AUTO_TEST_CASE(double_variable_declaration_050) -{ - string text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - uint256 x; - if (true) { uint256 x; } - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "This declaration shadows an existing declaration.", - "Unused local variable", - "Unused local variable" - })); -} - -BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope) -{ - string text = R"( - contract test { - function f() pure public { - { uint x; } - { uint x; } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared"); -} - -BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_050) -{ - string text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - { uint x; } - { uint x; } - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Unused local variable", - "Unused local variable" - })); -} - -BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation) -{ - string text = R"( - contract test { - function f() pure public { - { uint x; } - uint x; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Identifier already declared"); -} - -BOOST_AUTO_TEST_CASE(double_variable_declaration_disjoint_scope_activation_050) -{ - string text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - { uint x; } - uint x; - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Unused local variable", - "Unused local variable" - })); -} -BOOST_AUTO_TEST_CASE(scoping_old) -{ - char const* text = R"( - contract test { - function f() pure public { - x = 4; - uint256 x = 2; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(scoping) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() public { - { - uint256 x; - } - x = 2; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier"); -} - -BOOST_AUTO_TEST_CASE(scoping_activation_old) -{ - char const* text = R"( - contract test { - function f() pure public { - x = 3; - uint x; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(scoping_activation) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - x = 3; - uint x; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier"); -} - -BOOST_AUTO_TEST_CASE(scoping_self_use) -{ - char const* text = R"( - contract test { - function f() pure public { - uint a = a; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(scoping_self_use_050) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - uint a = a; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier"); -} - -BOOST_AUTO_TEST_CASE(scoping_for) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - for (uint x = 0; x < 10; x ++){ - x = 2; - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(scoping_for2) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - for (uint x = 0; x < 10; x ++) - x = 2; - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(scoping_for3) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - for (uint x = 0; x < 10; x ++){ - x = 2; - } - x = 4; - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier"); -} - -BOOST_AUTO_TEST_CASE(scoping_for_decl_in_body) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract test { - function f() pure public { - for (;; y++){ - uint y = 3; - } - } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier"); -} - -BOOST_AUTO_TEST_CASE(name_shadowing) -{ - char const* text = R"( - contract test { - uint256 variable; - function f() public { uint32 variable; variable = 2; } - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(name_references) { char const* text = R"( @@ -367,61 +92,6 @@ BOOST_AUTO_TEST_CASE(reference_to_later_declaration) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) -{ - char const* text = R"( - contract test { - struct MyStructName { - address addr; - MyStructName x; - } - } - )"; - CHECK_ERROR(text, TypeError, "Recursive struct definition."); -} - -BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) -{ - char const* text = R"( - contract test { - struct MyStructName1 { - address addr; - uint256 count; - MyStructName2 x; - } - struct MyStructName2 { - MyStructName1 x; - } - } - )"; - CHECK_ERROR(text, TypeError, "Recursive struct definition."); -} - -BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) -{ - char const* text = R"( - contract test { - struct s1 { uint a; } - struct s2 { s1 x; s1 y; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) -{ - char const* text = R"( - contract test { - struct MyStructName1 { - address addr; - uint256 count; - mapping(uint => MyStructName1) x; - } - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(type_inference_smoke_test) { char const* text = R"( @@ -1237,6 +907,35 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments_override) CHECK_SUCCESS(text); } +BOOST_AUTO_TEST_CASE(new_constructor_syntax) +{ + char const* text = R"( + contract A { constructor() public {} } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(old_constructor_syntax) +{ + char const* text = R"( + contract A { function A() public {} } + )"; + CHECK_WARNING( + text, + "Defining constructors as functions with the same name as the contract is deprecated." + ); + + text = R"( + pragma experimental "v0.5.0"; + contract A { function A() public {} } + )"; + CHECK_ERROR( + text, + SyntaxError, + "Functions are not allowed to have the same name as the contract." + ); +} + BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion) { char const* text = R"( @@ -1276,139 +975,6 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract) CHECK_ERROR(text, TypeError, "Member \"f\" not found or not visible after argument-dependent lookup in contract super B"); } -BOOST_AUTO_TEST_CASE(function_modifier_invocation) -{ - char const* text = R"( - contract B { - function f() mod1(2, true) mod2("0123456") pure public { } - modifier mod1(uint a, bool b) { if (b) _; } - modifier mod2(bytes7 a) { while (a == "1234567") _; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(invalid_function_modifier_type) -{ - char const* text = R"( - contract B { - function f() mod1(true) public { } - modifier mod1(uint a) { if (a > 0) _; } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid type for argument in modifier invocation. Invalid implicit conversion from bool to uint256 requested."); -} - -BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) -{ - char const* text = R"( - contract B { - function f(uint8 a) mod1(a, true) mod2(r) public returns (bytes7 r) { } - modifier mod1(uint a, bool b) { if (b) _; } - modifier mod2(bytes7 a) { while (a == "1234567") _; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables) -{ - char const* text = R"( - contract B { - function f() mod(x) pure public { uint x = 7; } - modifier mod(uint a) { if (a > 0) _; } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables050) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - contract B { - function f() mod(x) pure public { uint x = 7; } - modifier mod(uint a) { if (a > 0) _; } - } - )"; - CHECK_ERROR(text, DeclarationError, "Undeclared identifier."); -} - -BOOST_AUTO_TEST_CASE(function_modifier_double_invocation) -{ - char const* text = R"( - contract B { - function f(uint x) mod(x) mod(2) public { } - modifier mod(uint a) { if (a > 0) _; } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(base_constructor_double_invocation) -{ - char const* text = R"( - contract C { function C(uint a) public {} } - contract B is C { - function B() C(2) C(2) public {} - } - )"; - CHECK_ERROR(text, DeclarationError, "Base constructor already provided"); -} - -BOOST_AUTO_TEST_CASE(legal_modifier_override) -{ - char const* text = R"( - contract A { modifier mod(uint a) { _; } } - contract B is A { modifier mod(uint a) { _; } } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(illegal_modifier_override) -{ - char const* text = R"( - contract A { modifier mod(uint a) { _; } } - contract B is A { modifier mod(uint8 a) { _; } } - )"; - CHECK_ERROR(text, TypeError, "Override changes modifier signature."); -} - -BOOST_AUTO_TEST_CASE(modifier_overrides_function) -{ - char const* text = R"( - contract A { modifier mod(uint a) { _; } } - contract B is A { function mod(uint a) public { } } - )"; - CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, string>>{ - {Error::Type::DeclarationError, "Identifier already declared"}, - {Error::Type::TypeError, "Override changes modifier to function"} - })); -} - -BOOST_AUTO_TEST_CASE(function_overrides_modifier) -{ - char const* text = R"( - contract A { function mod(uint a) public { } } - contract B is A { modifier mod(uint a) { _; } } - )"; - CHECK_ALLOW_MULTI(text, (vector<pair<Error::Type, string>>{ - {Error::Type::DeclarationError, "Identifier already declared"}, - {Error::Type::TypeError, "Override changes function to modifier"} - })); -} - -BOOST_AUTO_TEST_CASE(modifier_returns_value) -{ - char const* text = R"( - contract A { - function f(uint a) mod(2) public returns (uint r) { } - modifier mod(uint a) { _; return 7; } - } - )"; - CHECK_ERROR(text, TypeError, "Return arguments not allowed."); -} - BOOST_AUTO_TEST_CASE(state_variable_accessors) { char const* text = R"( @@ -2727,8 +2293,8 @@ BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 31, 0)) == *make_shared<FixedBytesType>(31)); BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 32, 0)) == *make_shared<FixedBytesType>(32)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Fixed, 0, 0)) == *make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Signed)); - BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixed, 0, 0)) == *make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Unsigned)); + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Fixed, 0, 0)) == *make_shared<FixedPointType>(128, 18, FixedPointType::Modifier::Signed)); + BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixed, 0, 0)) == *make_shared<FixedPointType>(128, 18, FixedPointType::Modifier::Unsigned)); } BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1) @@ -3424,7 +2990,10 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) } } )"; - CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed from \"inaccessible dynamic type\" to \"bytes storage pointer\"."); + if (dev::test::Options::get().evmVersion() == EVMVersion::homestead()) + CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed from \"inaccessible dynamic type\" to \"bytes storage pointer\"."); + else + CHECK_WARNING(sourceCode, "Use of the \"var\" keyword is deprecated"); } BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) @@ -4474,21 +4043,6 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count) -{ - // This caused a segfault in an earlier version - char const* text = R"( - contract C { - function C(){} - } - contract D is C { - function D() C(5){} - } - )"; - - CHECK_ERROR(text, TypeError, "Wrong argument count for modifier invocation: 1 arguments given but expected 0."); -} - BOOST_AUTO_TEST_CASE(index_access_for_bytes) { char const* text = R"( @@ -4743,7 +4297,7 @@ BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed) } } )"; - CHECK_ERROR(text, TypeError, "Type fixed128x19 is not implicitly convertible to expected type int256"); + CHECK_ERROR(text, TypeError, "Type fixed128x18 is not implicitly convertible to expected type int256"); } BOOST_AUTO_TEST_CASE(rational_unary_operation) @@ -4861,7 +4415,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size) } } )"; - CHECK_ERROR(text, TypeError, "Type ufixed128x19 is not implicitly convertible to expected type ufixed248x8"); + CHECK_ERROR(text, TypeError, "Type ufixed128x18 is not implicitly convertible to expected type ufixed248x8"); } BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_lost_data) @@ -4948,7 +4502,7 @@ BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion) } } )"; - CHECK_ERROR(text, TypeError, "fixed128x19 is not implicitly convertible to expected type bytes32"); + CHECK_ERROR(text, TypeError, "fixed128x18 is not implicitly convertible to expected type bytes32"); } BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal) @@ -5218,20 +4772,6 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(signed_rational_modulus) -{ - char const* text = R"( - contract test { - function f() public { - fixed a = 0.42578125 % -0.4271087646484375; - fixed b = .5 % a; - fixed c = a % b; - } - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(one_divided_by_three_integer_conversion) { char const* text = R"( @@ -5353,16 +4893,6 @@ BOOST_AUTO_TEST_CASE(no_warn_about_callcode_as_function) CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(modifier_without_underscore) -{ - char const* text = R"( - contract test { - modifier m() {} - } - )"; - CHECK_ERROR(text, SyntaxError, "Modifier body does not contain '_'."); -} - BOOST_AUTO_TEST_CASE(payable_in_library) { char const* text = R"( @@ -5562,319 +5092,6 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) CHECK_ERROR(text, TypeError, "Member \"b\" not found or not visible after argument-dependent lookup in bytes memory"); } -BOOST_AUTO_TEST_CASE(function_type) -{ - char const* text = R"( - contract C { - function f() public { - function(uint) returns (uint) x; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(function_type_parameter) -{ - char const* text = R"( - contract C { - function f(function(uint) external returns (uint) g) public returns (function(uint) external returns (uint)) { - return g; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(function_type_returned) -{ - char const* text = R"( - contract C { - function f() public returns (function(uint) external returns (uint) g) { - return g; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(private_function_type) -{ - char const* text = R"( - contract C { - function f() public { - function(uint) private returns (uint) x; - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid visibility, can only be \"external\" or \"internal\"."); -} - -BOOST_AUTO_TEST_CASE(public_function_type) -{ - char const* text = R"( - contract C { - function f() public { - function(uint) public returns (uint) x; - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid visibility, can only be \"external\" or \"internal\"."); -} - -BOOST_AUTO_TEST_CASE(payable_internal_function_type) -{ - char const* text = R"( - contract C { - function (uint) internal payable returns (uint) x; - } - )"; - CHECK_ERROR(text, TypeError, "Only external function types can be payable."); -} - -BOOST_AUTO_TEST_CASE(payable_internal_function_type_is_not_fatal) -{ - char const* text = R"( - contract C { - function (uint) internal payable returns (uint) x; - - function g() { - x = g; - } - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector<std::string>{"Only external function types can be payable."})); -} - -BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) -{ - char const* text = R"( - contract C { - function (uint) external returns (uint) x; - function f() public { - x.value(2)(); - } - } - )"; - CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup in function (uint256) external returns (uint256) - did you forget the \"payable\" modifier?"); -} - -BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) -{ - char const* text = R"( - contract C { - function() external returns (function () internal) x; - } - )"; - CHECK_ERROR(text, TypeError, "Internal type cannot be used for external function type."); -} - -BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) -{ - char const* text = R"( - contract C { - function(function () internal) external x; - } - )"; - CHECK_ERROR(text, TypeError, "Internal type cannot be used for external function type."); -} - -BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) -{ - char const* text = R"( - contract C { - function (uint) external payable returns (uint) x; - function f() public { - x.value(2)(1); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) -{ - // It should not be possible to give internal functions - // as parameters to external functions. - char const* text = R"( - contract C { - function f(function(uint) internal returns (uint) x) public { - } - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) -{ - // It should not be possible to return internal functions from external functions. - char const* text = R"( - contract C { - function f() public returns (function(uint) internal returns (uint) x) { - } - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal) -{ - char const* text = R"( - library L { - function f(function(uint) internal returns (uint) x) internal { - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external) -{ - char const* text = R"( - library L { - function f(function(uint) internal returns (uint) x) public { - } - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(function_type_arrays) -{ - char const* text = R"( - contract C { - function(uint) external returns (uint)[] public x; - function(uint) internal returns (uint)[10] y; - function f() public { - function(uint) returns (uint)[10] memory a; - function(uint) returns (uint)[10] storage b = y; - function(uint) external returns (uint)[] memory c; - c = new function(uint) external returns (uint)[](200); - a; b; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(delete_function_type) -{ - char const* text = R"( - contract C { - function(uint) external returns (uint) x; - function(uint) internal returns (uint) y; - function f() public { - delete x; - var a = y; - delete a; - delete y; - var c = f; - delete c; - function(uint) internal returns (uint) g; - delete g; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(delete_function_type_invalid) -{ - char const* text = R"( - contract C { - function f() public { - delete f; - } - } - )"; - CHECK_ERROR(text, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) -{ - char const* text = R"( - contract C { - function f() public { - delete this.f; - } - } - )"; - CHECK_ERROR(text, TypeError, "Expression has to be an lvalue."); -} - -BOOST_AUTO_TEST_CASE(external_function_to_function_type_calldata_parameter) -{ - // This is a test that checks that the type of the `bytes` parameter is - // correctly changed from its own type `bytes calldata` to `bytes memory` - // when converting to a function type. - char const* text = R"( - contract C { - function f(function(bytes memory) external g) public { } - function callback(bytes) external {} - function g() public { - f(this.callback); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(external_function_type_to_address) -{ - char const* text = R"( - contract C { - function f() public returns (address) { - return address(this.f); - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(internal_function_type_to_address) -{ - char const* text = R"( - contract C { - function f() public returns (address) { - return address(f); - } - } - )"; - CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed"); -} - -BOOST_AUTO_TEST_CASE(external_function_type_to_uint) -{ - char const* text = R"( - contract C { - function f() public returns (uint) { - return uint(this.f); - } - } - )"; - CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed"); -} - -BOOST_AUTO_TEST_CASE(warn_function_type_parameters_with_names) -{ - char const* text = R"( - contract C { - function(uint a) f; - } - )"; - CHECK_WARNING(text, "Naming function type parameters is deprecated."); -} - -BOOST_AUTO_TEST_CASE(warn_function_type_return_parameters_with_names) -{ - char const* text = R"( - contract C { - function(uint) returns (bool ret) f; - } - )"; - CHECK_WARNING(text, "Naming function type return parameters is deprecated."); -} - BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) { char const* text = R"( @@ -5915,6 +5132,16 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and int_const 4294967296"); } +BOOST_AUTO_TEST_CASE(shift_constant_right_fractional) +{ + char const* text = R"( + contract C { + uint public a = 0x42 >> (1 / 2); + } + )"; + CHECK_ERROR(text, TypeError, "Operator >> not compatible with types int_const 66 and rational_const 1 / 2"); +} + BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) { char const* text = R"( @@ -6439,43 +5666,22 @@ BOOST_AUTO_TEST_CASE(return_structs) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(return_recursive_structs) -{ - char const* text = R"( - contract C { - struct S { uint a; S[] sub; } - function f() returns (uint, S) { - } - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(return_recursive_structs2) +BOOST_AUTO_TEST_CASE(read_returned_struct) { char const* text = R"( - contract C { - struct S { uint a; S[2][] sub; } - function f() returns (uint, S) { + pragma experimental ABIEncoderV2; + contract A { + struct T { + int x; + int y; } - } - )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); -} - -BOOST_AUTO_TEST_CASE(return_recursive_structs3) -{ - char const* text = R"( - contract C { - struct S { uint a; S[][][] sub; } - struct T { S s; } - function f() returns (uint x, T t) { + function g() public returns (T) { + return this.g(); } } )"; - CHECK_ERROR(text, TypeError, "Internal or recursive type is not allowed for public or external functions."); + CHECK_WARNING(text, "Experimental features"); } - BOOST_AUTO_TEST_CASE(address_checksum_type_deduction) { char const* text = R"( @@ -6598,38 +5804,6 @@ BOOST_AUTO_TEST_CASE(address_methods) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(cyclic_dependency_for_constants) -{ - char const* text = R"( - contract C { - uint constant a = a; - } - )"; - CHECK_ERROR(text, TypeError, "cyclic dependency via a"); - text = R"( - contract C { - uint constant a = b * c; - uint constant b = 7; - uint constant c = b + uint(keccak256(d)); - uint constant d = 2 + a; - } - )"; - CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector<std::string>{ - "a has a cyclic dependency via c", - "c has a cyclic dependency via d", - "d has a cyclic dependency via a" - })); - text = R"( - contract C { - uint constant a = b * c; - uint constant b = 7; - uint constant c = 4 + uint(keccak256(d)); - uint constant d = 2 + b; - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(interface) { char const* text = R"( @@ -6674,54 +5848,6 @@ BOOST_AUTO_TEST_CASE(interface_function_bodies) CHECK_ERROR(text, TypeError, "Functions in interfaces cannot have an implementation"); } -BOOST_AUTO_TEST_CASE(interface_function_external) -{ - char const* text = R"( - pragma experimental "v0.5.0"; - interface I { - function f() external; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(interface_function_public) -{ - char const* text = R"( - interface I { - function f() public; - } - )"; - CHECK_WARNING(text, "Functions in interfaces should be declared external."); - text = R"( - pragma experimental "v0.5.0"; - interface I { - function f() public; - } - )"; - CHECK_ERROR(text, TypeError, "Functions in interfaces must be declared external."); -} - -BOOST_AUTO_TEST_CASE(interface_function_internal) -{ - char const* text = R"( - interface I { - function f() internal; - } - )"; - CHECK_ERROR(text, TypeError, "Functions in interfaces cannot be internal or private."); -} - -BOOST_AUTO_TEST_CASE(interface_function_private) -{ - char const* text = R"( - interface I { - function f() private; - } - )"; - CHECK_ERROR(text, TypeError, "Functions in interfaces cannot be internal or private."); -} - BOOST_AUTO_TEST_CASE(interface_events) { char const* text = R"( @@ -6816,6 +5942,20 @@ BOOST_AUTO_TEST_CASE(using_interface_complex) CHECK_SUCCESS(text); } +BOOST_AUTO_TEST_CASE(interface_implement_public_contract) +{ + char const* text = R"( + interface I { + function f() external; + } + contract C is I { + function f() public { + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_CASE(warn_about_throw) { char const* text = R"( @@ -6847,14 +5987,30 @@ BOOST_AUTO_TEST_CASE(bare_revert) } } )"; - CHECK_WARNING(text, "Statement has no effect."); + CHECK_ERROR(text, TypeError, "No matching declaration found"); +} + +BOOST_AUTO_TEST_CASE(revert_with_reason) +{ + char const* text = R"( + contract C { + function f(uint x) pure public { + if (x > 7) + revert("abc"); + else + revert(); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(bare_others) { CHECK_WARNING("contract C { function f() pure public { selfdestruct; } }", "Statement has no effect."); CHECK_WARNING("contract C { function f() pure public { assert; } }", "Statement has no effect."); - CHECK_WARNING("contract C { function f() pure public { require; } }", "Statement has no effect."); + // This is different because it does have overloads. + CHECK_ERROR("contract C { function f() pure public { require; } }", TypeError, "No matching declaration found after variable lookup."); CHECK_WARNING("contract C { function f() pure public { suicide; } }", "Statement has no effect."); } @@ -7195,7 +6351,7 @@ BOOST_AUTO_TEST_CASE(shadowing_builtins_ignores_constructor) { char const* text = R"( contract C { - function C() public {} + constructor() public {} } )"; CHECK_SUCCESS_NO_WARNINGS(text); @@ -7353,7 +6509,7 @@ BOOST_AUTO_TEST_CASE(does_not_error_transfer_regular_function) CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(returndatacopy_as_variable) +BOOST_AUTO_TEST_CASE(returndatasize_as_variable) { char const* text = R"( contract c { function f() public { uint returndatasize; assembly { returndatasize }}} @@ -7520,7 +6676,7 @@ BOOST_AUTO_TEST_CASE(modifiers_access_storage_pointer) { char const* text = R"( contract C { - struct S { } + struct S { uint a; } modifier m(S storage x) { x; _; @@ -7607,7 +6763,7 @@ BOOST_AUTO_TEST_CASE(using_this_in_constructor) { char const* text = R"( contract C { - function C() public { + constructor() public { this.f(); } function f() pure public { @@ -7921,53 +7077,6 @@ BOOST_AUTO_TEST_CASE(reject_interface_constructors) CHECK_ERROR(text, TypeError, "Wrong argument count for constructor call: 1 arguments given but expected 0."); } -BOOST_AUTO_TEST_CASE(tight_packing_literals) -{ - char const* text = R"( - contract C { - function f() pure public returns (bytes32) { - return keccak256(1); - } - } - )"; - CHECK_WARNING(text, "The type of \"int_const 1\" was inferred as uint8."); - text = R"( - contract C { - function f() pure public returns (bytes32) { - return keccak256(uint8(1)); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f() pure public returns (bytes32) { - return sha3(1); - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (std::vector<std::string>{ - "The type of \"int_const 1\" was inferred as uint8.", - "\"sha3\" has been deprecated in favour of \"keccak256\"" - })); - text = R"( - contract C { - function f() pure public returns (bytes32) { - return sha256(1); - } - } - )"; - CHECK_WARNING(text, "The type of \"int_const 1\" was inferred as uint8."); - text = R"( - contract C { - function f() pure public returns (bytes32) { - return ripemd160(1); - } - } - )"; - CHECK_WARNING(text, "The type of \"int_const 1\" was inferred as uint8."); -} - BOOST_AUTO_TEST_CASE(non_external_fallback) { char const* text = R"( @@ -8095,171 +7204,6 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(array_length_too_large) -{ - char const* text = R"( - contract C { - uint[8**90] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_length_not_convertible_to_integer) -{ - char const* text = R"( - contract C { - uint[true] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_length_constant_var) -{ - char const* text = R"( - contract C { - uint constant LEN = 10; - uint[LEN] ids; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_length_non_integer_constant_var) -{ - char const* text = R"( - contract C { - bool constant LEN = true; - uint[LEN] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_length_cannot_be_function) -{ - char const* text = R"( - contract C { - function f() {} - uint[f] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_length_can_be_recursive_constant) -{ - char const* text = R"( - contract C { - uint constant L = 5; - uint constant LEN = L + 4 * L; - uint[LEN] ids; - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_length_cannot_be_function_call) -{ - char const* text = R"( - contract C { - function f(uint x) {} - uint constant LEN = f(); - uint[LEN] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_length_const_cannot_be_fractional) -{ - char const* text = R"( - contract C { - fixed constant L = 10.5; - uint[L] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Array with fractional length specified"); -} - -BOOST_AUTO_TEST_CASE(array_length_can_be_constant_in_struct) -{ - char const* text = R"( - contract C { - uint constant LEN = 10; - struct Test { - uint[LEN] ids; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_length_can_be_constant_in_function) -{ - char const* text = R"( - contract C { - uint constant LEN = 10; - function f() { - uint[LEN] a; - } - } - )"; - CHECK_SUCCESS(text); -} - -BOOST_AUTO_TEST_CASE(array_length_cannot_be_constant_function_parameter) -{ - char const* text = R"( - contract C { - function f(uint constant LEN) { - uint[LEN] a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - -BOOST_AUTO_TEST_CASE(array_length_with_cyclic_constant) -{ - char const* text = R"( - contract C { - uint constant LEN = LEN; - function f() { - uint[LEN] a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Cyclic constant definition (or maximum recursion depth exhausted)."); -} - -BOOST_AUTO_TEST_CASE(array_length_with_complex_cyclic_constant) -{ - char const* text = R"( - contract C { - uint constant L2 = LEN - 10; - uint constant L1 = L2 / 10; - uint constant LEN = 10 + L1 * 5; - function f() { - uint[LEN] a; - } - } - )"; - CHECK_ERROR(text, TypeError, "Cyclic constant definition (or maximum recursion depth exhausted)."); -} - -BOOST_AUTO_TEST_CASE(array_length_with_pure_functions) -{ - char const* text = R"( - contract C { - uint constant LEN = keccak256(ripemd160(33)); - uint[LEN] ids; - } - )"; - CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal or constant expression."); -} - BOOST_AUTO_TEST_CASE(array_length_invalid_expression) { char const* text = R"( @@ -8587,6 +7531,33 @@ BOOST_AUTO_TEST_CASE(require_visibility_specifiers) CHECK_ERROR(text, SyntaxError, "No visibility specified."); } +BOOST_AUTO_TEST_CASE(blockhash) +{ + char const* code = R"( + contract C { + function f() public view returns (bytes32) { + return block.blockhash(3); + } + } + )"; + CHECK_WARNING(code, "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""); + + code = R"( + contract C { + function f() public view returns (bytes32) { return blockhash(3); } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(code); + + code = R"( + pragma experimental "v0.5.0"; + contract C { + function f() public returns (bytes32) { return block.blockhash(3); } + } + )"; + CHECK_ERROR(code, TypeError, "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 49a725e0..eeebeb74 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -20,7 +20,7 @@ * Unit tests for the solidity compiler JSON Interface output. */ -#include "../TestHelper.h" +#include <test/Options.h> #include <string> #include <libdevcore/JSON.h> #include <libsolidity/interface/CompilerStack.h> diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 33039ca9..5326feaf 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -74,11 +74,11 @@ public: unsigned const _optimizeRuns = 200 ) { - bytes nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false, _optimizeRuns); + m_nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false, _optimizeRuns); m_nonOptimizedContract = m_contractAddress; - bytes optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true, _optimizeRuns); - size_t nonOptimizedSize = numInstructions(nonOptimizedBytecode); - size_t optimizedSize = numInstructions(optimizedBytecode); + m_optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true, _optimizeRuns); + size_t nonOptimizedSize = numInstructions(m_nonOptimizedBytecode); + size_t optimizedSize = numInstructions(m_optimizedBytecode); BOOST_CHECK_MESSAGE( _optimizeRuns < 50 || optimizedSize < nonOptimizedSize, string("Optimizer did not reduce bytecode size. Non-optimized size: ") + @@ -93,8 +93,10 @@ public: { m_contractAddress = m_nonOptimizedContract; bytes nonOptimizedOutput = callContractFunction(_sig, _arguments...); + m_gasUsedNonOptimized = m_gasUsed; m_contractAddress = m_optimizedContract; bytes optimizedOutput = callContractFunction(_sig, _arguments...); + m_gasUsedOptimized = m_gasUsed; BOOST_CHECK_MESSAGE(!optimizedOutput.empty(), "No optimized output for " + _sig); BOOST_CHECK_MESSAGE(!nonOptimizedOutput.empty(), "No un-optimized output for " + _sig); BOOST_CHECK_MESSAGE(nonOptimizedOutput == optimizedOutput, "Computed values do not match." @@ -104,7 +106,7 @@ public: /// @returns the number of intructions in the given bytecode, not taking the metadata hash /// into account. - size_t numInstructions(bytes const& _bytecode) + size_t numInstructions(bytes const& _bytecode, boost::optional<Instruction> _which = boost::optional<Instruction>{}) { BOOST_REQUIRE(_bytecode.size() > 5); size_t metadataSize = (_bytecode[_bytecode.size() - 2] << 8) + _bytecode[_bytecode.size() - 1]; @@ -112,13 +114,18 @@ public: BOOST_REQUIRE(_bytecode.size() >= metadataSize + 2); bytes realCode = bytes(_bytecode.begin(), _bytecode.end() - metadataSize - 2); size_t instructions = 0; - solidity::eachInstruction(realCode, [&](Instruction, u256 const&) { - instructions++; + solidity::eachInstruction(realCode, [&](Instruction _instr, u256 const&) { + if (!_which || *_which == _instr) + instructions++; }); return instructions; } protected: + u256 m_gasUsedOptimized; + u256 m_gasUsedNonOptimized; + bytes m_nonOptimizedBytecode; + bytes m_optimizedBytecode; Address m_optimizedContract; Address m_nonOptimizedContract; }; @@ -581,6 +588,49 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join) compareVersions("test()"); } +BOOST_AUTO_TEST_CASE(init_empty_dynamic_arrays) +{ + // This is not so much an optimizer test, but rather a test + // that allocating empty arrays is implemented efficiently. + // In particular, initializing a dynamic memory array does + // not use any memory. + char const* sourceCode = R"( + contract Test { + function f() pure returns (uint r) { + uint[][] memory x = new uint[][](20000); + return x.length; + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f()"); + BOOST_CHECK_LE(m_gasUsedNonOptimized, 1900000); + BOOST_CHECK_LE(1600000, m_gasUsedNonOptimized); +} + +BOOST_AUTO_TEST_CASE(optimise_multi_stores) +{ + char const* sourceCode = R"( + contract Test { + struct S { uint16 a; uint16 b; uint16[3] c; uint[] dyn; } + uint padding; + S[] s; + function f() public returns (uint16, uint16, uint16[3], uint) { + uint16[3] memory c; + c[0] = 7; + c[1] = 8; + c[2] = 9; + s.push(S(1, 2, c, new uint[](4))); + return (s[0].a, s[0].b, s[0].c, s[0].dyn[2]); + } + } + )"; + compileBothVersions(sourceCode); + compareVersions("f()"); + BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 9); + BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 8); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index f03b30e1..100b3662 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -25,8 +25,8 @@ #include <libsolidity/parsing/Scanner.h> #include <libsolidity/parsing/Parser.h> #include <libsolidity/interface/ErrorReporter.h> -#include "../TestHelper.h" -#include "ErrorCheck.h" +#include <test/Options.h> +#include <test/libsolidity/ErrorCheck.h> using namespace std; @@ -112,26 +112,6 @@ while(0) BOOST_AUTO_TEST_SUITE(SolidityParser) -BOOST_AUTO_TEST_CASE(smoke_test) -{ - char const* text = R"( - contract test { - uint256 stateVariable1; - } - )"; - BOOST_CHECK(successParse(text)); -} - -BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) -{ - char const* text = R"( - contract test { - uint256 ; - } - )"; - CHECK_PARSE_ERROR(text, "Expected identifier"); -} - BOOST_AUTO_TEST_CASE(empty_function) { char const* text = R"( @@ -577,16 +557,6 @@ BOOST_AUTO_TEST_CASE(variable_definition_with_initialization) BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(variable_definition_in_function_parameter) -{ - char const* text = R"( - contract test { - function fun(var a) {} - } - )"; - CHECK_PARSE_ERROR(text, "Expected explicit type name"); -} - BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) { char const* text = R"( @@ -599,18 +569,6 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) CHECK_PARSE_ERROR(text, "Expected elementary type name for mapping key type"); } -BOOST_AUTO_TEST_CASE(variable_definition_in_function_return) -{ - char const* text = R"( - contract test { - function fun() returns(var d) { - return 1; - } - } - )"; - CHECK_PARSE_ERROR(text, "Expected explicit type name"); -} - BOOST_AUTO_TEST_CASE(operator_expression) { char const* text = R"( diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index bc9f2fe1..738b24bc 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -123,6 +123,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers) BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes32")->identifier(), "t_bytes32"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bool")->identifier(), "t_bool"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes")->identifier(), "t_bytes_storage_ptr"); + BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("bytes memory")->identifier(), "t_bytes_memory_ptr"); BOOST_CHECK_EQUAL(Type::fromElementaryTypeName("string")->identifier(), "t_string_storage_ptr"); ArrayType largeintArray(DataLocation::Memory, Type::fromElementaryTypeName("int128"), u256("2535301200456458802993406410752")); BOOST_CHECK_EQUAL(largeintArray.identifier(), "t_array$_t_int128_$2535301200456458802993406410752_memory_ptr"); diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 4c8918be..74bf01b2 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -261,19 +261,24 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), - "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" ); BOOST_CHECK(contract["evm"]["assembly"].isString()); BOOST_CHECK(contract["evm"]["assembly"].asString().find( - " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x60)\n jumpi(tag_1, iszero(callvalue))\n" - " 0x0\n dup1\n revert\ntag_1:\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, 0x60)\n 0x0\n dup1\n revert\n\n" - " auxdata: 0xa165627a7a7230582") == 0); + " /* \"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 " + "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 " + "dup1\n revert\n\n auxdata: 0xa165627a7a72305820" + ) == 0); BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["evm"]["gasEstimates"]), - "{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"61\",\"totalCost\":\"10661\"}}" + "{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"66\",\"totalCost\":\"10666\"}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); @@ -752,6 +757,8 @@ BOOST_AUTO_TEST_CASE(evm_version) BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"spuriousDragon\"") != string::npos); result = compile(inputForVersion("\"evmVersion\": \"byzantium\",")); BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"byzantium\"") != string::npos); + result = compile(inputForVersion("\"evmVersion\": \"constantinople\",")); + BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"constantinople\"") != string::npos); // test default result = compile(inputForVersion("")); BOOST_CHECK(result["contracts"]["fileA"]["A"]["metadata"].asString().find("\"evmVersion\":\"byzantium\"") != string::npos); diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp new file mode 100644 index 00000000..1c2355d5 --- /dev/null +++ b/test/libsolidity/SyntaxTest.cpp @@ -0,0 +1,283 @@ +/* + 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/libsolidity/SyntaxTest.h> +#include <test/Options.h> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/throw_exception.hpp> +#include <cctype> +#include <fstream> +#include <memory> +#include <stdexcept> + +using namespace dev; +using namespace solidity; +using namespace dev::solidity::test; +using namespace dev::solidity::test::formatting; +using namespace std; +namespace fs = boost::filesystem; +using namespace boost::unit_test; + +template<typename IteratorType> +void skipWhitespace(IteratorType& _it, IteratorType _end) +{ + while (_it != _end && isspace(*_it)) + ++_it; +} + +template<typename IteratorType> +void skipSlashes(IteratorType& _it, IteratorType _end) +{ + while (_it != _end && *_it == '/') + ++_it; +} + +void expect(string::iterator& _it, string::iterator _end, string::value_type _c) +{ + if (_it == _end || *_it != _c) + throw runtime_error(string("Invalid test expectation. Expected: \"") + _c + "\"."); + ++_it; +} + +int parseUnsignedInteger(string::iterator &_it, string::iterator _end) +{ + if (_it == _end || !isdigit(*_it)) + throw runtime_error("Invalid test expectation. Source location expected."); + int result = 0; + while (_it != _end && isdigit(*_it)) + { + result *= 10; + result += *_it - '0'; + ++_it; + } + return result; +} + +SyntaxTest::SyntaxTest(string const& _filename) +{ + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test contract: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + m_source = parseSource(file); + m_expectations = parseExpectations(file); +} + +bool SyntaxTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + string const versionPragma = "pragma solidity >=0.0;\n"; + m_compiler.reset(); + m_compiler.addSource("", versionPragma + m_source); + m_compiler.setEVMVersion(dev::test::Options::get().evmVersion()); + + if (m_compiler.parse()) + m_compiler.analyze(); + + for (auto const& currentError: filterErrors(m_compiler.errors(), true)) + { + int locationStart = -1, locationEnd = -1; + if (auto location = boost::get_error_info<errinfo_sourceLocation>(*currentError)) + { + // ignore the version pragma inserted by the testing tool when calculating locations. + if (location->start >= static_cast<int>(versionPragma.size())) + locationStart = location->start - versionPragma.size(); + if (location->end >= static_cast<int>(versionPragma.size())) + locationEnd = location->end - versionPragma.size(); + } + m_errorList.emplace_back(SyntaxTestError{ + currentError->typeName(), + errorMessage(*currentError), + locationStart, + locationEnd + }); + } + + if (m_expectations != m_errorList) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; + printErrorList(_stream, m_expectations, nextIndentLevel, _formatted); + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; + printErrorList(_stream, m_errorList, nextIndentLevel, _formatted); + return false; + } + return true; +} + +void SyntaxTest::printErrorList( + ostream& _stream, + vector<SyntaxTestError> const& _errorList, + string const& _linePrefix, + bool const _formatted +) +{ + if (_errorList.empty()) + FormattedScope(_stream, _formatted, {BOLD, GREEN}) << _linePrefix << "Success" << endl; + else + for (auto const& error: _errorList) + { + { + FormattedScope scope(_stream, _formatted, {BOLD, (error.type == "Warning") ? YELLOW : RED}); + _stream << _linePrefix; + _stream << error.type << ": "; + } + if (error.locationStart >= 0 || error.locationEnd >= 0) + { + _stream << "("; + if (error.locationStart >= 0) + _stream << error.locationStart; + _stream << "-"; + if (error.locationEnd >= 0) + _stream << error.locationEnd; + _stream << "): "; + } + _stream << error.message << endl; + } +} + +string SyntaxTest::errorMessage(Exception const& _e) +{ + if (_e.comment() && !_e.comment()->empty()) + return boost::replace_all_copy(*_e.comment(), "\n", "\\n"); + else + return "NONE"; +} + +string SyntaxTest::parseSource(istream& _stream) +{ + string source; + string line; + string const delimiter("// ----"); + while (getline(_stream, line)) + if (boost::algorithm::starts_with(line, delimiter)) + break; + else + source += line + "\n"; + return source; +} + +vector<SyntaxTestError> SyntaxTest::parseExpectations(istream& _stream) +{ + vector<SyntaxTestError> expectations; + string line; + while (getline(_stream, line)) + { + auto it = line.begin(); + + skipSlashes(it, line.end()); + skipWhitespace(it, line.end()); + + if (it == line.end()) continue; + + auto typeBegin = it; + while (it != line.end() && *it != ':') + ++it; + string errorType(typeBegin, it); + + // skip colon + if (it != line.end()) it++; + + skipWhitespace(it, line.end()); + + int locationStart = -1; + int locationEnd = -1; + + if (it != line.end() && *it == '(') + { + ++it; + locationStart = parseUnsignedInteger(it, line.end()); + expect(it, line.end(), '-'); + locationEnd = parseUnsignedInteger(it, line.end()); + expect(it, line.end(), ')'); + expect(it, line.end(), ':'); + } + + skipWhitespace(it, line.end()); + + string errorMessage(it, line.end()); + expectations.emplace_back(SyntaxTestError{ + move(errorType), + move(errorMessage), + locationStart, + locationEnd + }); + } + return expectations; +} + +#if BOOST_VERSION < 105900 +test_case *make_test_case( + function<void()> const& _fn, + string const& _name, + string const& /* _filename */, + size_t /* _line */ +) +{ + return make_test_case(_fn, _name); +} +#endif + +bool SyntaxTest::isTestFilename(boost::filesystem::path const& _filename) +{ + return _filename.extension().string() == ".sol" && + !boost::starts_with(_filename.string(), "~") && + !boost::starts_with(_filename.string(), "."); +} + +int SyntaxTest::registerTests( + boost::unit_test::test_suite& _suite, + boost::filesystem::path const& _basepath, + boost::filesystem::path const& _path +) +{ + int numTestsAdded = 0; + fs::path fullpath = _basepath / _path; + if (fs::is_directory(fullpath)) + { + test_suite* sub_suite = BOOST_TEST_SUITE(_path.filename().string()); + for (auto const& entry: boost::iterator_range<fs::directory_iterator>( + fs::directory_iterator(fullpath), + fs::directory_iterator() + )) + if (fs::is_directory(entry.path()) || isTestFilename(entry.path().filename())) + numTestsAdded += registerTests(*sub_suite, _basepath, _path / entry.path().filename()); + _suite.add(sub_suite); + } + else + { + static vector<unique_ptr<string>> filenames; + + filenames.emplace_back(new string(_path.string())); + _suite.add(make_test_case( + [fullpath] + { + BOOST_REQUIRE_NO_THROW({ + stringstream errorStream; + if (!SyntaxTest(fullpath.string()).run(errorStream)) + BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); + }); + }, + _path.stem().string(), + *filenames.back(), + 0 + )); + numTestsAdded = 1; + } + return numTestsAdded; +} diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h new file mode 100644 index 00000000..6159e789 --- /dev/null +++ b/test/libsolidity/SyntaxTest.h @@ -0,0 +1,91 @@ +/* + 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/libsolidity/AnalysisFramework.h> +#include <test/libsolidity/FormattedScope.h> +#include <libsolidity/interface/Exceptions.h> + +#include <boost/noncopyable.hpp> +#include <boost/test/unit_test.hpp> + +#include <iosfwd> +#include <string> +#include <vector> +#include <utility> + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +struct SyntaxTestError +{ + std::string type; + std::string message; + int locationStart; + int locationEnd; + bool operator==(SyntaxTestError const& _rhs) const + { + return type == _rhs.type && + message == _rhs.message && + locationStart == _rhs.locationStart && + locationEnd == _rhs.locationEnd; + } +}; + + +class SyntaxTest: AnalysisFramework +{ +public: + SyntaxTest(std::string const& _filename); + + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false); + + std::vector<SyntaxTestError> const& expectations() const { return m_expectations; } + std::string const& source() const { return m_source; } + std::vector<SyntaxTestError> const& errorList() const { return m_errorList; } + + static void printErrorList( + std::ostream& _stream, + std::vector<SyntaxTestError> const& _errors, + std::string const& _linePrefix, + bool const _formatted = false + ); + + static int registerTests( + boost::unit_test::test_suite& _suite, + boost::filesystem::path const& _basepath, + boost::filesystem::path const& _path + ); + static bool isTestFilename(boost::filesystem::path const& _filename); + static std::string errorMessage(Exception const& _e); +private: + static std::string parseSource(std::istream& _stream); + static std::vector<SyntaxTestError> parseExpectations(std::istream& _stream); + + std::string m_source; + std::vector<SyntaxTestError> m_expectations; + std::vector<SyntaxTestError> m_errorList; +}; + +} +} +} diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index 26ff461c..cd0a0b01 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -20,11 +20,12 @@ #include <test/libsolidity/AnalysisFramework.h> -#include <test/TestHelper.h> +#include <test/Options.h> #include <boost/test/unit_test.hpp> #include <string> +#include <tuple> using namespace std; @@ -111,6 +112,7 @@ BOOST_AUTO_TEST_CASE(environment_access) "block.difficulty", "block.number", "block.gaslimit", + "blockhash(7)", "gasleft()", "msg.gas", "msg.value", @@ -120,11 +122,12 @@ BOOST_AUTO_TEST_CASE(environment_access) "this", "address(1).balance" }; + // ``block.blockhash`` and ``blockhash`` are tested seperately below because their usage will + // produce warnings that can't be handled in a generic way. vector<string> pure{ "msg.data", "msg.data[0]", "msg.sig", - "block.blockhash", // Not evaluating the function "msg", "block", "tx" @@ -132,20 +135,32 @@ BOOST_AUTO_TEST_CASE(environment_access) for (string const& x: view) { CHECK_ERROR( - "contract C { function f() pure public { var x = " + x + "; x; } }", + "contract C { function f() pure public { " + x + "; } }", TypeError, "Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires \"view\"" ); } for (string const& x: pure) { - CHECK_WARNING_ALLOW_MULTI( - "contract C { function f() view public { var x = " + x + "; x; } }", - (std::vector<std::string>{ - "Function state mutability can be restricted to pure", - "Use of the \"var\" keyword is deprecated." - })); + CHECK_WARNING( + "contract C { function f() view public { " + x + "; } }", + "Function state mutability can be restricted to pure" + ); } + + CHECK_WARNING_ALLOW_MULTI( + "contract C { function f() view public { blockhash; } }", + (std::vector<std::string>{ + "Function state mutability can be restricted to pure", + "Statement has no effect." + })); + + CHECK_WARNING_ALLOW_MULTI( + "contract C { function f() view public { block.blockhash; } }", + (std::vector<std::string>{ + "Function state mutability can be restricted to pure", + "\"block.blockhash()\" has been deprecated in favor of \"blockhash()\"" + })); } BOOST_AUTO_TEST_CASE(view_error_for_050) diff --git a/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol b/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol new file mode 100644 index 00000000..11d40f26 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/array_length_cannot_be_constant_function_parameter.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint constant LEN) { + uint[LEN] a; + } +} +// ---- +// TypeError: (62-65): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol new file mode 100644 index 00000000..92536dd5 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_function.sol @@ -0,0 +1,8 @@ +contract C { + uint constant LEN = 10; + function f() public pure { + uint[LEN] memory a; + a; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol new file mode 100644 index 00000000..89e174f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/can_be_constant_in_struct.sol @@ -0,0 +1,7 @@ +contract C { + uint constant LEN = 10; + struct Test { + uint[LEN] ids; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol b/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol new file mode 100644 index 00000000..6810a9d6 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/can_be_recursive_constant.sol @@ -0,0 +1,6 @@ +contract C { + uint constant L = 5; + uint constant LEN = L + 4 * L; + uint[LEN] ids; +} +// ---- diff --git a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol new file mode 100644 index 00000000..ac3abc4c --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function.sol @@ -0,0 +1,6 @@ +contract C { + function f() {} + uint[f] ids; +} +// ---- +// TypeError: (42-43): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol new file mode 100644 index 00000000..a6863955 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/cannot_be_function_call.sol @@ -0,0 +1,7 @@ +contract C { + function f(uint x) {} + uint constant LEN = f(); + uint[LEN] ids; +} +// ---- +// TypeError: (77-80): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol b/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol new file mode 100644 index 00000000..254f9f02 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/complex_cyclic_constant.sol @@ -0,0 +1,10 @@ +contract C { + uint constant L2 = LEN - 10; + uint constant L1 = L2 / 10; + uint constant LEN = 10 + L1 * 5; + function f() { + uint[LEN] a; + } +} +// ---- +// TypeError: (36-39): Cyclic constant definition (or maximum recursion depth exhausted). diff --git a/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol b/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol new file mode 100644 index 00000000..397bbbcd --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/const_cannot_be_fractional.sol @@ -0,0 +1,6 @@ +contract C { + fixed constant L = 10.5; + uint[L] ids; +} +// ---- +// TypeError: (51-52): Array with fractional length specified. diff --git a/test/libsolidity/syntaxTests/arrayLength/constant_var.sol b/test/libsolidity/syntaxTests/arrayLength/constant_var.sol new file mode 100644 index 00000000..41750250 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/constant_var.sol @@ -0,0 +1,5 @@ +contract C { + uint constant LEN = 10; + uint[LEN] ids; +} +// ----
\ No newline at end of file diff --git a/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol b/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol new file mode 100644 index 00000000..91ba9045 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/cyclic_constant.sol @@ -0,0 +1,8 @@ +contract C { + uint constant LEN = LEN; + function f() { + uint[LEN] a; + } +} +// ---- +// TypeError: (37-40): Cyclic constant definition (or maximum recursion depth exhausted). diff --git a/test/libsolidity/syntaxTests/arrayLength/inline_array.sol b/test/libsolidity/syntaxTests/arrayLength/inline_array.sol new file mode 100644 index 00000000..a30745d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/inline_array.sol @@ -0,0 +1,5 @@ +contract C { + uint[[2]] a15; +} +// ---- +// TypeError: (22-25): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol new file mode 100644 index 00000000..c92861eb --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_1.sol @@ -0,0 +1,5 @@ +contract C { + uint[-true] ids; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol new file mode 100644 index 00000000..92e3c3cf --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_2.sol @@ -0,0 +1,5 @@ +contract C { + uint[true/1] ids; +} +// ---- +// TypeError: (22-28): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol new file mode 100644 index 00000000..26add45c --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_3.sol @@ -0,0 +1,5 @@ +contract C { + uint[1/true] ids; +} +// ---- +// TypeError: (22-28): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol new file mode 100644 index 00000000..a0d58f4a --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_4.sol @@ -0,0 +1,5 @@ +contract C { + uint[1.111111E1111111111111] ids; +} +// ---- +// TypeError: (22-44): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol new file mode 100644 index 00000000..38a80867 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/invalid_expression_5.sol @@ -0,0 +1,5 @@ +contract C { + uint[3/0] ids; +} +// ---- +// TypeError: (22-25): Operator / not compatible with types int_const 3 and int_const 0 diff --git a/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol b/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol new file mode 100644 index 00000000..7a853a34 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/non_integer_constant_var.sol @@ -0,0 +1,6 @@ +contract C { + bool constant LEN = true; + uint[LEN] ids; +} +// ---- +// TypeError: (52-55): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol b/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol new file mode 100644 index 00000000..b44ccfe9 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/not_convertible_to_integer.sol @@ -0,0 +1,5 @@ +contract C { + uint[true] ids; +} +// ---- +// TypeError: (22-26): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/parentheses.sol b/test/libsolidity/syntaxTests/arrayLength/parentheses.sol new file mode 100644 index 00000000..40f55ad6 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/parentheses.sol @@ -0,0 +1,25 @@ +contract C { + uint constant L1 = (2); + uint constant L2 = ((2)); + uint constant L3 = ((((2)))); + uint constant L4 = (2 + 1); + uint constant L5 = ((2 + 1)); + uint constant L6 = (((2) + ((1)))); + uint constant L7 = (2 + 1) / 1; + uint constant L8 = (2 + ((1))) / (1); + uint[L1] a1; + uint[L2] a2; + uint[L3] a3; + uint[L4] a4; + uint[L5] a5; + uint[L6] a6; + uint[L7] a7; + uint[L8] a8; + uint[(2)] a9; + uint[(2 + 1)] a10; + uint[(2 + 1) + 1] a11; + uint[((2) + 1) + 1] a12; + uint[(2 + 1) + ((1))] a13; + uint[(((2) + 1)) + (((1)))] a14; + uint[((((2) + 1)) + (((1))))%1] a15; +} diff --git a/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol b/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol new file mode 100644 index 00000000..b620db76 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/pure_functions.sol @@ -0,0 +1,6 @@ +contract C { + uint constant LEN = keccak256(ripemd160(33)); + uint[LEN] ids; +} +// ---- +// TypeError: (72-75): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/too_large.sol b/test/libsolidity/syntaxTests/arrayLength/too_large.sol new file mode 100644 index 00000000..c90a7494 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/too_large.sol @@ -0,0 +1,5 @@ +contract C { + uint[8**90] ids; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/arrayLength/tuples.sol b/test/libsolidity/syntaxTests/arrayLength/tuples.sol new file mode 100644 index 00000000..bc10b3b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/arrayLength/tuples.sol @@ -0,0 +1,5 @@ +contract C { + uint[(1,2)] a15; +} +// ---- +// TypeError: (22-27): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol b/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol new file mode 100644 index 00000000..26712735 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/addmod_mulmod_rational.sol @@ -0,0 +1,7 @@ +contract C { + uint constant a = addmod(3, 4, 0.1); + uint constant b = mulmod(3, 4, 0.1); +} +// ---- +// TypeError: (48-51): Invalid type for argument in function call. Invalid implicit conversion from rational_const 1 / 10 to uint256 requested. +// TypeError: (89-92): Invalid type for argument in function call. Invalid implicit conversion from rational_const 1 / 10 to uint256 requested. diff --git a/test/libsolidity/syntaxTests/constants/addmod_zero.sol b/test/libsolidity/syntaxTests/constants/addmod_zero.sol new file mode 100644 index 00000000..18f7d64a --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/addmod_zero.sol @@ -0,0 +1,11 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = addmod(3, 4, 0); + uint constant b2 = addmod(3, 4, a1); + uint constant b3 = addmod(3, 4, a2 - 1); +} +// ---- +// TypeError: (88-103): Arithmetic modulo zero. +// TypeError: (128-144): Arithmetic modulo zero. +// TypeError: (169-189): Arithmetic modulo zero. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol new file mode 100644 index 00000000..cb553fbe --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_1.sol @@ -0,0 +1,5 @@ +contract C { + uint constant a = a; +} +// ---- +// TypeError: (17-36): The value of the constant a has a cyclic dependency via a. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol new file mode 100644 index 00000000..00f9bb0f --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_2.sol @@ -0,0 +1,10 @@ +contract C { + uint constant a = b * c; + uint constant b = 7; + uint constant c = b + uint(keccak256(d)); + uint constant d = 2 + a; +} +// ---- +// TypeError: (17-40): The value of the constant a has a cyclic dependency via c. +// TypeError: (71-111): The value of the constant c has a cyclic dependency via d. +// TypeError: (117-140): The value of the constant d has a cyclic dependency via a. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol new file mode 100644 index 00000000..969ed50d --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_3.sol @@ -0,0 +1,11 @@ +contract C { + uint constant x = a; + uint constant a = b * c; + uint constant b = c; + uint constant c = b; +} +// ---- +// TypeError: (17-36): The value of the constant x has a cyclic dependency via a. +// TypeError: (42-65): The value of the constant a has a cyclic dependency via b. +// TypeError: (71-90): The value of the constant b has a cyclic dependency via c. +// TypeError: (96-115): The value of the constant c has a cyclic dependency via b. diff --git a/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol new file mode 100644 index 00000000..f01cb98e --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/cyclic_dependency_4.sol @@ -0,0 +1,6 @@ +contract C { + uint constant a = b * c; + uint constant b = 7; + uint constant c = 4 + uint(keccak256(d)); + uint constant d = 2 + b; +}
\ No newline at end of file diff --git a/test/libsolidity/syntaxTests/constants/division_by_zero.sol b/test/libsolidity/syntaxTests/constants/division_by_zero.sol new file mode 100644 index 00000000..bf6000ec --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/division_by_zero.sol @@ -0,0 +1,9 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = 7 / a1; + uint constant b2 = 7 / (a2 - 1); +} +// ---- +// TypeError: (88-94): Division by zero. +// TypeError: (119-131): Division by zero. diff --git a/test/libsolidity/syntaxTests/constants/mod_div_rational.sol b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol new file mode 100644 index 00000000..f8b6ce31 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/mod_div_rational.sol @@ -0,0 +1,6 @@ +contract C { + fixed a1 = 0.1 % -0.4271087646484375; + fixed a2 = 0.1 % 0.4271087646484375; + fixed a3 = 0 / 0.123; + fixed a4 = 0 / -0.123; +} diff --git a/test/libsolidity/syntaxTests/constants/mod_zero.sol b/test/libsolidity/syntaxTests/constants/mod_zero.sol new file mode 100644 index 00000000..f5e4a23a --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/mod_zero.sol @@ -0,0 +1,9 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = 3 % a1; + uint constant b2 = 3 % (a2 - 1); +} +// ---- +// TypeError: (88-94): Modulo zero. +// TypeError: (119-131): Modulo zero. diff --git a/test/libsolidity/syntaxTests/constants/mulmod_zero.sol b/test/libsolidity/syntaxTests/constants/mulmod_zero.sol new file mode 100644 index 00000000..856d01eb --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/mulmod_zero.sol @@ -0,0 +1,11 @@ +contract c { + uint constant a1 = 0; + uint constant a2 = 1; + uint constant b1 = mulmod(3, 4, 0); + uint constant b2 = mulmod(3, 4, a1); + uint constant b3 = mulmod(3, 4, a2 - 1); +} +// ---- +// TypeError: (88-103): Arithmetic modulo zero. +// TypeError: (128-144): Arithmetic modulo zero. +// TypeError: (169-189): Arithmetic modulo zero. diff --git a/test/libsolidity/syntaxTests/constants/pure_non_rational.sol b/test/libsolidity/syntaxTests/constants/pure_non_rational.sol new file mode 100644 index 00000000..4b96f1c7 --- /dev/null +++ b/test/libsolidity/syntaxTests/constants/pure_non_rational.sol @@ -0,0 +1,11 @@ +// Tests that the ConstantEvaluator does not crash for pure non-rational functions. +// Currently it does not evaluate such functions, but this may change in the future +// causing a division by zero error for a. +contract C { + uint constant a = 1 / (uint(keccak256([0])[0]) - uint(keccak256([0])[0])); + uint constant b = 1 / uint(keccak256([0])); + uint constant c = uint(keccak256([0])); + uint[c] mem; +} +// ---- +// TypeError: (392-393): Invalid array length, expected integer literal or constant expression. diff --git a/test/libsolidity/syntaxTests/constructor_this.sol b/test/libsolidity/syntaxTests/constructor_this.sol new file mode 100644 index 00000000..9d22a161 --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor_this.sol @@ -0,0 +1,12 @@ +contract C { + function f() public pure {} + constructor() public { + C c = this; + c.f(); // this does not warn now, but should warn in the future + this.f(); + (this).f(); + } +} +// ---- +// Warning: (172-176): "this" used in constructor. Note that external functions of a contract cannot be called while it is being constructed. +// Warning: (191-195): "this" used in constructor. Note that external functions of a contract cannot be called while it is being constructed. diff --git a/test/libsolidity/syntaxTests/docstring_empty_description.sol b/test/libsolidity/syntaxTests/docstring_empty_description.sol new file mode 100644 index 00000000..0caa1b23 --- /dev/null +++ b/test/libsolidity/syntaxTests/docstring_empty_description.sol @@ -0,0 +1,6 @@ +contract C { + /// @param id + function vote(uint id) public; +} +// ---- +// DocstringParsingError: No description given for param id diff --git a/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol b/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol new file mode 100644 index 00000000..fda4a17a --- /dev/null +++ b/test/libsolidity/syntaxTests/double_stateVariable_declaration.sol @@ -0,0 +1,6 @@ +contract test { + uint256 variable; + uint128 variable; +} +// ---- +// DeclarationError: (36-52): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/double_variable_declaration.sol b/test/libsolidity/syntaxTests/double_variable_declaration.sol new file mode 100644 index 00000000..9ab87959 --- /dev/null +++ b/test/libsolidity/syntaxTests/double_variable_declaration.sol @@ -0,0 +1,8 @@ +contract test { + function f() pure public { + uint256 x; + if (true) { uint256 x; } + } +} +// ---- +// DeclarationError: (71-80): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/double_variable_declaration_050.sol b/test/libsolidity/syntaxTests/double_variable_declaration_050.sol new file mode 100644 index 00000000..2f47e6dc --- /dev/null +++ b/test/libsolidity/syntaxTests/double_variable_declaration_050.sol @@ -0,0 +1,11 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + uint256 x; + if (true) { uint256 x; } + } +} +// ---- +// Warning: (101-110): This declaration shadows an existing declaration. +// Warning: (76-85): Unused local variable. +// Warning: (101-110): Unused local variable. diff --git a/test/libsolidity/syntaxTests/empty_struct.sol b/test/libsolidity/syntaxTests/empty_struct.sol new file mode 100644 index 00000000..12655309 --- /dev/null +++ b/test/libsolidity/syntaxTests/empty_struct.sol @@ -0,0 +1,5 @@ +contract test { + struct A {} +} +// ---- +// Warning: (17-28): Defining empty structs is deprecated. diff --git a/test/libsolidity/syntaxTests/empty_struct_050.sol b/test/libsolidity/syntaxTests/empty_struct_050.sol new file mode 100644 index 00000000..886f1f83 --- /dev/null +++ b/test/libsolidity/syntaxTests/empty_struct_050.sol @@ -0,0 +1,6 @@ +pragma experimental "v0.5.0"; +contract test { + struct A {} +} +// ---- +// SyntaxError: (47-58): Defining empty structs is disallowed. diff --git a/test/libsolidity/syntaxTests/functionCalls/arbitrary_parameters_but_restricted_first_type.sol b/test/libsolidity/syntaxTests/functionCalls/arbitrary_parameters_but_restricted_first_type.sol new file mode 100644 index 00000000..94da5881 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionCalls/arbitrary_parameters_but_restricted_first_type.sol @@ -0,0 +1,13 @@ +contract C { + function f() pure public { + abi.encodeWithSelector(); + abi.encodeWithSignature(); + abi.encodeWithSelector(uint(2), 2); + abi.encodeWithSignature(uint(2), 2); + } +} +// ---- +// TypeError: (52-76): Need at least 1 arguments for function call, but provided only 0. +// TypeError: (86-111): Need at least 1 arguments for function call, but provided only 0. +// TypeError: (144-151): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes4 requested. +// TypeError: (189-196): Invalid type for argument in function call. Invalid implicit conversion from uint256 to string memory requested. diff --git a/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol new file mode 100644 index 00000000..87c3b05b --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/call_value_on_non_payable_function_type.sol @@ -0,0 +1,8 @@ +contract C { + function (uint) external returns (uint) x; + function f() public { + x.value(2)(); + } +} +// ---- +// TypeError: (94-101): Member "value" not found or not visible after argument-dependent lookup in function (uint256) external returns (uint256) - did you forget the "payable" modifier? diff --git a/test/libsolidity/syntaxTests/functionTypes/call_value_on_payable_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/call_value_on_payable_function_type.sol new file mode 100644 index 00000000..ca2a0196 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/call_value_on_payable_function_type.sol @@ -0,0 +1,6 @@ +contract C { + function (uint) external payable returns (uint) x; + function f() public { + x.value(2)(1); + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/delete_external_function_type_invalid.sol b/test/libsolidity/syntaxTests/functionTypes/delete_external_function_type_invalid.sol new file mode 100644 index 00000000..2711dae8 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/delete_external_function_type_invalid.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + delete this.f; + } +} +// ---- +// TypeError: (54-60): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol new file mode 100644 index 00000000..a6fe6c22 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/delete_function_type.sol @@ -0,0 +1,17 @@ +contract C { + function(uint) external returns (uint) x; + function(uint) internal returns (uint) y; + function f() public { + delete x; + var a = y; + delete a; + delete y; + var c = f; + delete c; + function(uint) internal returns (uint) g; + delete g; + } +} +// ---- +// Warning: (157-162): Use of the "var" keyword is deprecated. +// Warning: (212-217): Use of the "var" keyword is deprecated. diff --git a/test/libsolidity/syntaxTests/functionTypes/delete_function_type_invalid.sol b/test/libsolidity/syntaxTests/functionTypes/delete_function_type_invalid.sol new file mode 100644 index 00000000..60da19e4 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/delete_function_type_invalid.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + delete f; + } +} +// ---- +// TypeError: (54-55): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol new file mode 100644 index 00000000..eb4f0693 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_to_function_type_calldata_parameter.sol @@ -0,0 +1,10 @@ +// This is a test that checks that the type of the `bytes` parameter is +// correctly changed from its own type `bytes calldata` to `bytes memory` +// when converting to a function type. +contract C { + function f(function(bytes memory) pure external /*g*/) pure public { } + function callback(bytes) pure external {} + function g() view public { + f(this.callback); + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_public_variable.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_public_variable.sol new file mode 100644 index 00000000..0a6d1e53 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_public_variable.sol @@ -0,0 +1,11 @@ +contract C { + function (uint) external public x; + + function g(uint) public { + x = this.g; + } + function f() public view returns (function(uint) external) { + return this.x(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_returning_internal.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_returning_internal.sol new file mode 100644 index 00000000..8b14d3dc --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_returning_internal.sol @@ -0,0 +1,5 @@ +contract C { + function() external returns (function () internal) x; +} +// ---- +// TypeError: (46-67): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_taking_internal.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_taking_internal.sol new file mode 100644 index 00000000..3e264c8c --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_taking_internal.sol @@ -0,0 +1,5 @@ +contract C { + function(function () internal) external x; +} +// ---- +// TypeError: (26-47): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address.sol new file mode 100644 index 00000000..b86425db --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_address.sol @@ -0,0 +1,5 @@ +contract C { + function f() public view returns (address) { + return address(this.f); + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_uint.sol b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_uint.sol new file mode 100644 index 00000000..f4287223 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/external_function_type_to_uint.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (uint) { + return uint(this.f); + } +} +// ---- +// TypeError: (69-81): Explicit type conversion not allowed from "function () external returns (uint256)" to "uint256". diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type.sol b/test/libsolidity/syntaxTests/functionTypes/function_type.sol new file mode 100644 index 00000000..23d50136 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type.sol @@ -0,0 +1,6 @@ +contract C { + function f() pure public { + function(uint) returns (uint) x; + x; + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_arrays.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_arrays.sol new file mode 100644 index 00000000..ec23d637 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_arrays.sol @@ -0,0 +1,11 @@ +contract C { + function(uint) external returns (uint)[] public x; + function(uint) internal returns (uint)[10] y; + function f() view public { + function(uint) returns (uint)[10] memory a; + function(uint) returns (uint)[10] storage b = y; + function(uint) external returns (uint)[] memory c; + c = new function(uint) external returns (uint)[](200); + a; b; + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol new file mode 100644 index 00000000..95ebc179 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor.sol @@ -0,0 +1,7 @@ +contract C { + // Fool parser into parsing a constructor as a function type. + constructor() x; +} +// ---- +// Warning: (83-99): Modifiers of functions without implementation are ignored. +// DeclarationError: (97-98): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol new file mode 100644 index 00000000..b7763d28 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_constructor_local.sol @@ -0,0 +1,8 @@ +contract C { + // Fool parser into parsing a constructor as a function type. + function f() { + constructor() x; + } +} +// ---- +// ParserError: (118-118): Expected token Semicolon got 'Identifier' diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_internal_public_variable.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_internal_public_variable.sol new file mode 100644 index 00000000..4eb53227 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_internal_public_variable.sol @@ -0,0 +1,5 @@ +contract C { + function(bytes memory) internal public a; +} +// ---- +// TypeError: (17-57): Internal or recursive type is not allowed for public state variables. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_parameter.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_parameter.sol new file mode 100644 index 00000000..da66ec8a --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_parameter.sol @@ -0,0 +1,7 @@ +contract C { + uint x; + function f(function(uint) external returns (uint) g) public returns (function(uint) external returns (uint)) { + x = 2; + return g; + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_returned.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_returned.sol new file mode 100644 index 00000000..9cd313c8 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_returned.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (function(uint) pure external returns (uint) g) { + return g; + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol new file mode 100644 index 00000000..f0240472 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_variable_external_internal.sol @@ -0,0 +1,6 @@ +contract test { + function fa(bytes memory) public { } + function(bytes memory) external internal a = fa; +} +// ---- +// TypeError: (106-108): Type function (bytes memory) is not implicitly convertible to expected type function (bytes memory) external. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_types_internal_visibility_error.sol b/test/libsolidity/syntaxTests/functionTypes/function_types_internal_visibility_error.sol new file mode 100644 index 00000000..36206d63 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_types_internal_visibility_error.sol @@ -0,0 +1,7 @@ +contract C { + // This is an error, you should explicitly use + // `external public` to fix it - `internal public` does not exist. + function(bytes memory) public a; +} +// ---- +// TypeError: (139-170): Invalid visibility, can only be "external" or "internal". diff --git a/test/libsolidity/syntaxTests/functionTypes/function_types_variable_visibility.sol b/test/libsolidity/syntaxTests/functionTypes/function_types_variable_visibility.sol new file mode 100644 index 00000000..91c2420a --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_types_variable_visibility.sol @@ -0,0 +1,9 @@ +contract C { + function(bytes memory) a1; + function(bytes memory) internal b1; + function(bytes memory) internal internal b2; + function(bytes memory) external c1; + function(bytes memory) external internal c2; + function(bytes memory) external public c3; +} +// ---- diff --git a/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter.sol b/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter.sol new file mode 100644 index 00000000..fa92d559 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter.sol @@ -0,0 +1,8 @@ +// It should not be possible to give internal functions +// as parameters to external functions. +contract C { + function f(function(uint) internal returns (uint) x) public { + } +} +// ---- +// TypeError: (124-164): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter_in_library_external.sol b/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter_in_library_external.sol new file mode 100644 index 00000000..b37fb285 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter_in_library_external.sol @@ -0,0 +1,6 @@ +library L { + function f(function(uint) internal returns (uint) x) public { + } +} +// ---- +// TypeError: (27-67): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter_in_library_internal.sol b/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter_in_library_internal.sol new file mode 100644 index 00000000..7ffa447e --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/internal_function_as_external_parameter_in_library_internal.sol @@ -0,0 +1,4 @@ +library L { + function f(function(uint) internal returns (uint) /*x*/) pure internal { + } +} diff --git a/test/libsolidity/syntaxTests/functionTypes/internal_function_returned_from_public_function.sol b/test/libsolidity/syntaxTests/functionTypes/internal_function_returned_from_public_function.sol new file mode 100644 index 00000000..41fcd0a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/internal_function_returned_from_public_function.sol @@ -0,0 +1,7 @@ +// It should not be possible to return internal functions from external functions. +contract C { + function f() public returns (function(uint) internal returns (uint) x) { + } +} +// ---- +// TypeError: (129-169): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/functionTypes/internal_function_type_to_address.sol b/test/libsolidity/syntaxTests/functionTypes/internal_function_type_to_address.sol new file mode 100644 index 00000000..b75a0d43 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/internal_function_type_to_address.sol @@ -0,0 +1,7 @@ +contract C { + function f() public returns (address) { + return address(f); + } +} +// ---- +// TypeError: (72-82): Explicit type conversion not allowed from "function () returns (address)" to "address". diff --git a/test/libsolidity/syntaxTests/functionTypes/payable_internal_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/payable_internal_function_type.sol new file mode 100644 index 00000000..a7cb9d92 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/payable_internal_function_type.sol @@ -0,0 +1,5 @@ +contract C { + function (uint) internal payable returns (uint) x; +} +// ---- +// TypeError: (17-66): Only external function types can be payable. diff --git a/test/libsolidity/syntaxTests/functionTypes/payable_internal_function_type_is_not_fatal.sol b/test/libsolidity/syntaxTests/functionTypes/payable_internal_function_type_is_not_fatal.sol new file mode 100644 index 00000000..5c6dc056 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/payable_internal_function_type_is_not_fatal.sol @@ -0,0 +1,9 @@ +contract C { + function (uint) internal payable returns (uint) x; + + function g() public { + x = g; + } +} +// ---- +// TypeError: (17-66): Only external function types can be payable. diff --git a/test/libsolidity/syntaxTests/functionTypes/private_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/private_function_type.sol new file mode 100644 index 00000000..9d4f0a09 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/private_function_type.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + function(uint) private returns (uint) x; + } +} +// ---- +// TypeError: (47-86): Invalid visibility, can only be "external" or "internal". diff --git a/test/libsolidity/syntaxTests/functionTypes/public_function_type.sol b/test/libsolidity/syntaxTests/functionTypes/public_function_type.sol new file mode 100644 index 00000000..756766d3 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/public_function_type.sol @@ -0,0 +1,7 @@ +contract C { + function f() public { + function(uint) public returns (uint) x; + } +} +// ---- +// TypeError: (47-85): Invalid visibility, can only be "external" or "internal". diff --git a/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol b/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol new file mode 100644 index 00000000..10c6767c --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/valid_function_type_variables.sol @@ -0,0 +1,23 @@ +contract test { + function fa(uint) {} + function fb(uint) internal {} + function fc(uint) internal {} + function fd(uint) external {} + function fe(uint) external {} + function ff(uint) internal {} + function fg(uint) internal pure {} + function fh(uint) pure internal {} + + function(uint) a = fa; + function(uint) internal b = fb; // (explicit internal applies to the function type) + function(uint) internal internal c = fc; + function(uint) external d = this.fd; + function(uint) external internal e = this.fe; + function(uint) internal public f = ff; + function(uint) internal pure public g = fg; + function(uint) pure internal public h = fh; +} +// ---- +// TypeError: (545-582): Internal or recursive type is not allowed for public state variables. +// TypeError: (588-630): Internal or recursive type is not allowed for public state variables. +// TypeError: (636-678): Internal or recursive type is not allowed for public state variables. diff --git a/test/libsolidity/syntaxTests/functionTypes/warn_function_type_parameters_with_names.sol b/test/libsolidity/syntaxTests/functionTypes/warn_function_type_parameters_with_names.sol new file mode 100644 index 00000000..072c7eb7 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/warn_function_type_parameters_with_names.sol @@ -0,0 +1,5 @@ +contract C { + function(uint a) f; +} +// ---- +// Warning: (26-32): Naming function type parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol b/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol new file mode 100644 index 00000000..67a74e54 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol @@ -0,0 +1,5 @@ +contract C { + function(uint) returns (bool ret) f; +} +// ---- +// Warning: (41-49): Naming function type return parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/inheritance/allow_empty_duplicated_super_constructor_call.sol b/test/libsolidity/syntaxTests/inheritance/allow_empty_duplicated_super_constructor_call.sol new file mode 100644 index 00000000..ce9d5f5f --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/allow_empty_duplicated_super_constructor_call.sol @@ -0,0 +1,2 @@ +contract A { constructor() public { } } +contract B is A { constructor() A() public { } } diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol new file mode 100644 index 00000000..0b18b995 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses.sol @@ -0,0 +1,7 @@ +contract Base { + constructor(uint) public {} +} +contract Derived is Base(2) { } +contract Derived2 is Base(), Derived() { } +// ---- +// Warning: (101-107): Wrong argument count for constructor call: 0 arguments given but expected 1. diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol new file mode 100644 index 00000000..db04ab8c --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_empty_parentheses_V050.sol @@ -0,0 +1,9 @@ +pragma experimental "v0.5.0"; + +contract Base { + constructor(uint) public {} +} +contract Derived is Base(2) { } +contract Derived2 is Base(), Derived() { } +// ---- +// TypeError: (132-138): Wrong argument count for constructor call: 0 arguments given but expected 1. diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol new file mode 100644 index 00000000..015b33e5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_multiple_inheritance.sol @@ -0,0 +1,9 @@ +contract Base { + constructor(uint) public { } +} +contract Base1 is Base(3) {} +contract Derived is Base, Base1 { + constructor(uint i) Base(i) public {} +} +// ---- +// Warning: (138-145): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol new file mode 100644 index 00000000..24cca8f0 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/base_arguments_no_parentheses.sol @@ -0,0 +1,5 @@ +contract Base { + constructor(uint) public {} +} +contract Derived is Base(2) { } +contract Derived2 is Base, Derived {} diff --git a/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol b/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol new file mode 100644 index 00000000..6cf68d2a --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/disallow_modifier_style_without_parentheses.sol @@ -0,0 +1,4 @@ +contract A { constructor() public { } } +contract B is A { constructor() A public { } } +// ---- +// Warning: (72-73): Modifier-style base constructor call without arguments. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol new file mode 100644 index 00000000..24cff54d --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor.sol @@ -0,0 +1,5 @@ +contract A { constructor(uint) public { } } +contract B is A(2) { constructor() public { } } +contract C is B { constructor() A(3) public { } } +// ---- +// Warning: (125-129): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol new file mode 100644 index 00000000..8d5df5bf --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol @@ -0,0 +1,7 @@ +pragma experimental "v0.5.0"; + +contract A { constructor(uint) public { } } +contract B is A(2) { constructor() public { } } +contract C is B { constructor() A(3) public { } } +// ---- +// DeclarationError: (156-160): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol new file mode 100644 index 00000000..9ceaea5e --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base.sol @@ -0,0 +1,4 @@ +contract A { constructor(uint) public { } } +contract B is A(2) { constructor() A(3) public { } } +// ---- +// Warning: (79-83): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol new file mode 100644 index 00000000..f9325f99 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol @@ -0,0 +1,6 @@ +pragma experimental "v0.5.0"; + +contract A { constructor(uint) public { } } +contract B is A(2) { constructor() A(3) public { } } +// ---- +// DeclarationError: (110-114): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol new file mode 100644 index 00000000..e5c2aa36 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi.sol @@ -0,0 +1,7 @@ +contract C { constructor(uint) public {} } +contract A is C(2) {} +contract B is C(2) {} +contract D is A, B { constructor() C(3) public {} } +// ---- +// Warning: (122-126): Base constructor arguments given twice. +// Warning: (122-126): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol new file mode 100644 index 00000000..1abf2992 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor.sol @@ -0,0 +1,6 @@ +contract C { constructor(uint) public {} } +contract A is C(2) {} +contract B is C(2) {} +contract D is A, B {} +// ---- +// Warning: (87-108): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol new file mode 100644 index 00000000..e15242db --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_multi_no_constructor_modifier_style.sol @@ -0,0 +1,6 @@ +contract C { constructor(uint) public {} } +contract A is C { constructor() C(2) public {} } +contract B is C { constructor() C(2) public {} } +contract D is A, B { } +// ---- +// Warning: (141-163): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol b/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol new file mode 100644 index 00000000..c55c41f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/too_few_base_arguments.sol @@ -0,0 +1,10 @@ +contract Base { + constructor(uint, uint) public {} +} +contract Derived is Base(2) { } +contract Derived2 is Base { + constructor() Base(2) public { } +} +// ---- +// TypeError: (74-81): Wrong argument count for constructor call: 1 arguments given but expected 2. +// TypeError: (130-137): Wrong argument count for modifier invocation: 1 arguments given but expected 2. diff --git a/test/libsolidity/syntaxTests/literalOperations/division_by_zero.sol b/test/libsolidity/syntaxTests/literalOperations/division_by_zero.sol new file mode 100644 index 00000000..b52b4c51 --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/division_by_zero.sol @@ -0,0 +1,5 @@ +contract C { + uint constant a = 1 / 0; +} +// ---- +// TypeError: (35-40): Operator / not compatible with types int_const 1 and int_const 0 diff --git a/test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex.sol b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex.sol new file mode 100644 index 00000000..8cc3b6f2 --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/division_by_zero_complex.sol @@ -0,0 +1,5 @@ +contract C { + uint constant a = 1 / ((1+3)-4); +} +// ---- +// TypeError: (35-48): Operator / not compatible with types int_const 1 and int_const 0 diff --git a/test/libsolidity/syntaxTests/literalOperations/mod_zero.sol b/test/libsolidity/syntaxTests/literalOperations/mod_zero.sol new file mode 100644 index 00000000..1bbbc3fc --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/mod_zero.sol @@ -0,0 +1,5 @@ +contract C { + uint constant b3 = 1 % 0; +} +// ---- +// TypeError: (36-41): Operator % not compatible with types int_const 1 and int_const 0 diff --git a/test/libsolidity/syntaxTests/literalOperations/mod_zero_complex.sol b/test/libsolidity/syntaxTests/literalOperations/mod_zero_complex.sol new file mode 100644 index 00000000..4899cac3 --- /dev/null +++ b/test/libsolidity/syntaxTests/literalOperations/mod_zero_complex.sol @@ -0,0 +1,5 @@ +contract C { + uint constant b3 = 1 % (-4+((2)*2)); +} +// ---- +// TypeError: (36-52): Operator % not compatible with types int_const 1 and int_const 0 diff --git a/test/libsolidity/syntaxTests/literal_comparisons.sol b/test/libsolidity/syntaxTests/literal_comparisons.sol new file mode 100644 index 00000000..dd2afcaa --- /dev/null +++ b/test/libsolidity/syntaxTests/literal_comparisons.sol @@ -0,0 +1,7 @@ +contract test { + function f(int8 x) public pure { + if (x == 1) {} + if (1 == x) {} + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol b/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol new file mode 100644 index 00000000..bdbab5d8 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/base_constructor_double_invocation.sol @@ -0,0 +1,7 @@ +contract C { constructor(uint a) public {} } +contract B is C { + constructor() C(2) C(2) public {} +} +// ---- +// Warning: (81-85): Base constructor arguments given twice. +// DeclarationError: (86-90): Base constructor already provided. diff --git a/test/libsolidity/syntaxTests/modifiers/constructor_call_invalid_arg_count.sol b/test/libsolidity/syntaxTests/modifiers/constructor_call_invalid_arg_count.sol new file mode 100644 index 00000000..4a2b5c4a --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/constructor_call_invalid_arg_count.sol @@ -0,0 +1,9 @@ +// This caused a segfault in an earlier version +contract C { + constructor() public {} +} +contract D is C { + constructor() C(5) public {} +} +// ---- +// TypeError: (127-131): Wrong argument count for modifier invocation: 1 arguments given but expected 0. diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_double_invocation.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_double_invocation.sol new file mode 100644 index 00000000..75624192 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_double_invocation.sol @@ -0,0 +1,4 @@ +contract B { + function f(uint x) mod(x) mod(2) public pure { } + modifier mod(uint a) { if (a > 0) _; } +} diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation.sol new file mode 100644 index 00000000..e15fcf49 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation.sol @@ -0,0 +1,5 @@ +contract B { + function f() mod1(2, true) mod2("0123456") pure public { } + modifier mod1(uint a, bool b) { if (b) _; } + modifier mod2(bytes7 a) { while (a == "1234567") _; } +} diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol new file mode 100644 index 00000000..00031924 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol @@ -0,0 +1,4 @@ +contract B { + function f() mod(x) pure public { uint x = 7; } + modifier mod(uint a) { if (a > 0) _; } +} diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol new file mode 100644 index 00000000..c19ccf2c --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol @@ -0,0 +1,7 @@ +pragma experimental "v0.5.0"; +contract B { + function f() mod(x) pure public { uint x = 7; } + modifier mod(uint a) { if (a > 0) _; } +} +// ---- +// DeclarationError: (64-65): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_parameters.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_parameters.sol new file mode 100644 index 00000000..de2a8f48 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_parameters.sol @@ -0,0 +1,5 @@ +contract B { + function f(uint8 a) mod1(a, true) mod2(r) pure public returns (bytes7 r) { } + modifier mod1(uint a, bool b) { if (b) _; } + modifier mod2(bytes7 a) { while (a == "1234567") _; } +} diff --git a/test/libsolidity/syntaxTests/modifiers/function_overrides_modifier.sol b/test/libsolidity/syntaxTests/modifiers/function_overrides_modifier.sol new file mode 100644 index 00000000..a64c2790 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/function_overrides_modifier.sol @@ -0,0 +1,5 @@ +contract A { function mod(uint a) public { } } +contract B is A { modifier mod(uint a) { _; } } +// ---- +// DeclarationError: (65-92): Identifier already declared. +// TypeError: (65-92): Override changes function to modifier. diff --git a/test/libsolidity/syntaxTests/modifiers/illegal_modifier_override.sol b/test/libsolidity/syntaxTests/modifiers/illegal_modifier_override.sol new file mode 100644 index 00000000..958be686 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/illegal_modifier_override.sol @@ -0,0 +1,4 @@ +contract A { modifier mod(uint a) { _; } } +contract B is A { modifier mod(uint8 a) { _; } } +// ---- +// TypeError: (61-89): Override changes modifier signature. diff --git a/test/libsolidity/syntaxTests/modifiers/invalid_function_modifier_type.sol b/test/libsolidity/syntaxTests/modifiers/invalid_function_modifier_type.sol new file mode 100644 index 00000000..c1e3108b --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/invalid_function_modifier_type.sol @@ -0,0 +1,6 @@ +contract B { + function f() mod1(true) public { } + modifier mod1(uint a) { if (a > 0) _; } +} +// ---- +// TypeError: (35-39): Invalid type for argument in modifier invocation. Invalid implicit conversion from bool to uint256 requested. diff --git a/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol b/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol new file mode 100644 index 00000000..51c3fd80 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/legal_modifier_override.sol @@ -0,0 +1,2 @@ +contract A { modifier mod(uint a) { _; } } +contract B is A { modifier mod(uint a) { _; } } diff --git a/test/libsolidity/syntaxTests/modifiers/modifier_overrides_function.sol b/test/libsolidity/syntaxTests/modifiers/modifier_overrides_function.sol new file mode 100644 index 00000000..a43646c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/modifier_overrides_function.sol @@ -0,0 +1,5 @@ +contract A { modifier mod(uint a) { _; } } +contract B is A { function mod(uint a) public { } } +// ---- +// DeclarationError: (61-92): Identifier already declared. +// TypeError: (13-40): Override changes modifier to function. diff --git a/test/libsolidity/syntaxTests/modifiers/modifier_returns_value.sol b/test/libsolidity/syntaxTests/modifiers/modifier_returns_value.sol new file mode 100644 index 00000000..d22e836c --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/modifier_returns_value.sol @@ -0,0 +1,6 @@ +contract A { + function f(uint a) mod(2) public returns (uint r) { } + modifier mod(uint a) { _; return 7; } +} +// ---- +// TypeError: (101-109): Return arguments not allowed. diff --git a/test/libsolidity/syntaxTests/modifiers/modifier_without_underscore.sol b/test/libsolidity/syntaxTests/modifiers/modifier_without_underscore.sol new file mode 100644 index 00000000..6198d3c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/modifier_without_underscore.sol @@ -0,0 +1,5 @@ +contract test { + modifier m() {} +} +// ---- +// SyntaxError: (33-35): Modifier body does not contain '_'. diff --git a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol new file mode 100644 index 00000000..af1babbc --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol @@ -0,0 +1,10 @@ +pragma experimental "v0.5.0"; +contract C +{ + modifier only_owner() { _; } + function foo() only_owner public; + function bar() public only_owner; +} +// ---- +// SyntaxError: (80-113): Functions without implementation cannot have modifiers. +// SyntaxError: (118-151): Functions without implementation cannot have modifiers. diff --git a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol new file mode 100644 index 00000000..e18c5cf9 --- /dev/null +++ b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_no_parser_error.sol @@ -0,0 +1,13 @@ +// Previous versions of Solidity turned this +// into a parser error (they wrongly recognized +// these functions as state variables of +// function type). +contract C +{ + modifier only_owner() { _; } + function foo() only_owner public; + function bar() public only_owner; +} +// ---- +// Warning: (203-236): Modifiers of functions without implementation are ignored. +// Warning: (241-274): Modifiers of functions without implementation are ignored. diff --git a/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol b/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol new file mode 100644 index 00000000..2d75f29b --- /dev/null +++ b/test/libsolidity/syntaxTests/more_than_256_declarationerrors.sol @@ -0,0 +1,524 @@ +contract C { + function f() { + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + b = 5; + } +} +// ---- +// DeclarationError: (34-35): Undeclared identifier. +// DeclarationError: (45-46): Undeclared identifier. +// DeclarationError: (56-57): Undeclared identifier. +// DeclarationError: (67-68): Undeclared identifier. +// DeclarationError: (78-79): Undeclared identifier. +// DeclarationError: (89-90): Undeclared identifier. +// DeclarationError: (100-101): Undeclared identifier. +// DeclarationError: (111-112): Undeclared identifier. +// DeclarationError: (122-123): Undeclared identifier. +// DeclarationError: (133-134): Undeclared identifier. +// DeclarationError: (144-145): Undeclared identifier. +// DeclarationError: (155-156): Undeclared identifier. +// DeclarationError: (166-167): Undeclared identifier. +// DeclarationError: (177-178): Undeclared identifier. +// DeclarationError: (188-189): Undeclared identifier. +// DeclarationError: (199-200): Undeclared identifier. +// DeclarationError: (210-211): Undeclared identifier. +// DeclarationError: (221-222): Undeclared identifier. +// DeclarationError: (232-233): Undeclared identifier. +// DeclarationError: (243-244): Undeclared identifier. +// DeclarationError: (254-255): Undeclared identifier. +// DeclarationError: (265-266): Undeclared identifier. +// DeclarationError: (276-277): Undeclared identifier. +// DeclarationError: (287-288): Undeclared identifier. +// DeclarationError: (298-299): Undeclared identifier. +// DeclarationError: (309-310): Undeclared identifier. +// DeclarationError: (320-321): Undeclared identifier. +// DeclarationError: (331-332): Undeclared identifier. +// DeclarationError: (342-343): Undeclared identifier. +// DeclarationError: (353-354): Undeclared identifier. +// DeclarationError: (364-365): Undeclared identifier. +// DeclarationError: (375-376): Undeclared identifier. +// DeclarationError: (386-387): Undeclared identifier. +// DeclarationError: (397-398): Undeclared identifier. +// DeclarationError: (408-409): Undeclared identifier. +// DeclarationError: (419-420): Undeclared identifier. +// DeclarationError: (430-431): Undeclared identifier. +// DeclarationError: (441-442): Undeclared identifier. +// DeclarationError: (452-453): Undeclared identifier. +// DeclarationError: (463-464): Undeclared identifier. +// DeclarationError: (474-475): Undeclared identifier. +// DeclarationError: (485-486): Undeclared identifier. +// DeclarationError: (496-497): Undeclared identifier. +// DeclarationError: (507-508): Undeclared identifier. +// DeclarationError: (518-519): Undeclared identifier. +// DeclarationError: (529-530): Undeclared identifier. +// DeclarationError: (540-541): Undeclared identifier. +// DeclarationError: (551-552): Undeclared identifier. +// DeclarationError: (562-563): Undeclared identifier. +// DeclarationError: (573-574): Undeclared identifier. +// DeclarationError: (584-585): Undeclared identifier. +// DeclarationError: (595-596): Undeclared identifier. +// DeclarationError: (606-607): Undeclared identifier. +// DeclarationError: (617-618): Undeclared identifier. +// DeclarationError: (628-629): Undeclared identifier. +// DeclarationError: (639-640): Undeclared identifier. +// DeclarationError: (650-651): Undeclared identifier. +// DeclarationError: (661-662): Undeclared identifier. +// DeclarationError: (672-673): Undeclared identifier. +// DeclarationError: (683-684): Undeclared identifier. +// DeclarationError: (694-695): Undeclared identifier. +// DeclarationError: (705-706): Undeclared identifier. +// DeclarationError: (716-717): Undeclared identifier. +// DeclarationError: (727-728): Undeclared identifier. +// DeclarationError: (738-739): Undeclared identifier. +// DeclarationError: (749-750): Undeclared identifier. +// DeclarationError: (760-761): Undeclared identifier. +// DeclarationError: (771-772): Undeclared identifier. +// DeclarationError: (782-783): Undeclared identifier. +// DeclarationError: (793-794): Undeclared identifier. +// DeclarationError: (804-805): Undeclared identifier. +// DeclarationError: (815-816): Undeclared identifier. +// DeclarationError: (826-827): Undeclared identifier. +// DeclarationError: (837-838): Undeclared identifier. +// DeclarationError: (848-849): Undeclared identifier. +// DeclarationError: (859-860): Undeclared identifier. +// DeclarationError: (870-871): Undeclared identifier. +// DeclarationError: (881-882): Undeclared identifier. +// DeclarationError: (892-893): Undeclared identifier. +// DeclarationError: (903-904): Undeclared identifier. +// DeclarationError: (914-915): Undeclared identifier. +// DeclarationError: (925-926): Undeclared identifier. +// DeclarationError: (936-937): Undeclared identifier. +// DeclarationError: (947-948): Undeclared identifier. +// DeclarationError: (958-959): Undeclared identifier. +// DeclarationError: (969-970): Undeclared identifier. +// DeclarationError: (980-981): Undeclared identifier. +// DeclarationError: (991-992): Undeclared identifier. +// DeclarationError: (1002-1003): Undeclared identifier. +// DeclarationError: (1013-1014): Undeclared identifier. +// DeclarationError: (1024-1025): Undeclared identifier. +// DeclarationError: (1035-1036): Undeclared identifier. +// DeclarationError: (1046-1047): Undeclared identifier. +// DeclarationError: (1057-1058): Undeclared identifier. +// DeclarationError: (1068-1069): Undeclared identifier. +// DeclarationError: (1079-1080): Undeclared identifier. +// DeclarationError: (1090-1091): Undeclared identifier. +// DeclarationError: (1101-1102): Undeclared identifier. +// DeclarationError: (1112-1113): Undeclared identifier. +// DeclarationError: (1123-1124): Undeclared identifier. +// DeclarationError: (1134-1135): Undeclared identifier. +// DeclarationError: (1145-1146): Undeclared identifier. +// DeclarationError: (1156-1157): Undeclared identifier. +// DeclarationError: (1167-1168): Undeclared identifier. +// DeclarationError: (1178-1179): Undeclared identifier. +// DeclarationError: (1189-1190): Undeclared identifier. +// DeclarationError: (1200-1201): Undeclared identifier. +// DeclarationError: (1211-1212): Undeclared identifier. +// DeclarationError: (1222-1223): Undeclared identifier. +// DeclarationError: (1233-1234): Undeclared identifier. +// DeclarationError: (1244-1245): Undeclared identifier. +// DeclarationError: (1255-1256): Undeclared identifier. +// DeclarationError: (1266-1267): Undeclared identifier. +// DeclarationError: (1277-1278): Undeclared identifier. +// DeclarationError: (1288-1289): Undeclared identifier. +// DeclarationError: (1299-1300): Undeclared identifier. +// DeclarationError: (1310-1311): Undeclared identifier. +// DeclarationError: (1321-1322): Undeclared identifier. +// DeclarationError: (1332-1333): Undeclared identifier. +// DeclarationError: (1343-1344): Undeclared identifier. +// DeclarationError: (1354-1355): Undeclared identifier. +// DeclarationError: (1365-1366): Undeclared identifier. +// DeclarationError: (1376-1377): Undeclared identifier. +// DeclarationError: (1387-1388): Undeclared identifier. +// DeclarationError: (1398-1399): Undeclared identifier. +// DeclarationError: (1409-1410): Undeclared identifier. +// DeclarationError: (1420-1421): Undeclared identifier. +// DeclarationError: (1431-1432): Undeclared identifier. +// DeclarationError: (1442-1443): Undeclared identifier. +// DeclarationError: (1453-1454): Undeclared identifier. +// DeclarationError: (1464-1465): Undeclared identifier. +// DeclarationError: (1475-1476): Undeclared identifier. +// DeclarationError: (1486-1487): Undeclared identifier. +// DeclarationError: (1497-1498): Undeclared identifier. +// DeclarationError: (1508-1509): Undeclared identifier. +// DeclarationError: (1519-1520): Undeclared identifier. +// DeclarationError: (1530-1531): Undeclared identifier. +// DeclarationError: (1541-1542): Undeclared identifier. +// DeclarationError: (1552-1553): Undeclared identifier. +// DeclarationError: (1563-1564): Undeclared identifier. +// DeclarationError: (1574-1575): Undeclared identifier. +// DeclarationError: (1585-1586): Undeclared identifier. +// DeclarationError: (1596-1597): Undeclared identifier. +// DeclarationError: (1607-1608): Undeclared identifier. +// DeclarationError: (1618-1619): Undeclared identifier. +// DeclarationError: (1629-1630): Undeclared identifier. +// DeclarationError: (1640-1641): Undeclared identifier. +// DeclarationError: (1651-1652): Undeclared identifier. +// DeclarationError: (1662-1663): Undeclared identifier. +// DeclarationError: (1673-1674): Undeclared identifier. +// DeclarationError: (1684-1685): Undeclared identifier. +// DeclarationError: (1695-1696): Undeclared identifier. +// DeclarationError: (1706-1707): Undeclared identifier. +// DeclarationError: (1717-1718): Undeclared identifier. +// DeclarationError: (1728-1729): Undeclared identifier. +// DeclarationError: (1739-1740): Undeclared identifier. +// DeclarationError: (1750-1751): Undeclared identifier. +// DeclarationError: (1761-1762): Undeclared identifier. +// DeclarationError: (1772-1773): Undeclared identifier. +// DeclarationError: (1783-1784): Undeclared identifier. +// DeclarationError: (1794-1795): Undeclared identifier. +// DeclarationError: (1805-1806): Undeclared identifier. +// DeclarationError: (1816-1817): Undeclared identifier. +// DeclarationError: (1827-1828): Undeclared identifier. +// DeclarationError: (1838-1839): Undeclared identifier. +// DeclarationError: (1849-1850): Undeclared identifier. +// DeclarationError: (1860-1861): Undeclared identifier. +// DeclarationError: (1871-1872): Undeclared identifier. +// DeclarationError: (1882-1883): Undeclared identifier. +// DeclarationError: (1893-1894): Undeclared identifier. +// DeclarationError: (1904-1905): Undeclared identifier. +// DeclarationError: (1915-1916): Undeclared identifier. +// DeclarationError: (1926-1927): Undeclared identifier. +// DeclarationError: (1937-1938): Undeclared identifier. +// DeclarationError: (1948-1949): Undeclared identifier. +// DeclarationError: (1959-1960): Undeclared identifier. +// DeclarationError: (1970-1971): Undeclared identifier. +// DeclarationError: (1981-1982): Undeclared identifier. +// DeclarationError: (1992-1993): Undeclared identifier. +// DeclarationError: (2003-2004): Undeclared identifier. +// DeclarationError: (2014-2015): Undeclared identifier. +// DeclarationError: (2025-2026): Undeclared identifier. +// DeclarationError: (2036-2037): Undeclared identifier. +// DeclarationError: (2047-2048): Undeclared identifier. +// DeclarationError: (2058-2059): Undeclared identifier. +// DeclarationError: (2069-2070): Undeclared identifier. +// DeclarationError: (2080-2081): Undeclared identifier. +// DeclarationError: (2091-2092): Undeclared identifier. +// DeclarationError: (2102-2103): Undeclared identifier. +// DeclarationError: (2113-2114): Undeclared identifier. +// DeclarationError: (2124-2125): Undeclared identifier. +// DeclarationError: (2135-2136): Undeclared identifier. +// DeclarationError: (2146-2147): Undeclared identifier. +// DeclarationError: (2157-2158): Undeclared identifier. +// DeclarationError: (2168-2169): Undeclared identifier. +// DeclarationError: (2179-2180): Undeclared identifier. +// DeclarationError: (2190-2191): Undeclared identifier. +// DeclarationError: (2201-2202): Undeclared identifier. +// DeclarationError: (2212-2213): Undeclared identifier. +// DeclarationError: (2223-2224): Undeclared identifier. +// DeclarationError: (2234-2235): Undeclared identifier. +// DeclarationError: (2245-2246): Undeclared identifier. +// DeclarationError: (2256-2257): Undeclared identifier. +// DeclarationError: (2267-2268): Undeclared identifier. +// DeclarationError: (2278-2279): Undeclared identifier. +// DeclarationError: (2289-2290): Undeclared identifier. +// DeclarationError: (2300-2301): Undeclared identifier. +// DeclarationError: (2311-2312): Undeclared identifier. +// DeclarationError: (2322-2323): Undeclared identifier. +// DeclarationError: (2333-2334): Undeclared identifier. +// DeclarationError: (2344-2345): Undeclared identifier. +// DeclarationError: (2355-2356): Undeclared identifier. +// DeclarationError: (2366-2367): Undeclared identifier. +// DeclarationError: (2377-2378): Undeclared identifier. +// DeclarationError: (2388-2389): Undeclared identifier. +// DeclarationError: (2399-2400): Undeclared identifier. +// DeclarationError: (2410-2411): Undeclared identifier. +// DeclarationError: (2421-2422): Undeclared identifier. +// DeclarationError: (2432-2433): Undeclared identifier. +// DeclarationError: (2443-2444): Undeclared identifier. +// DeclarationError: (2454-2455): Undeclared identifier. +// DeclarationError: (2465-2466): Undeclared identifier. +// DeclarationError: (2476-2477): Undeclared identifier. +// DeclarationError: (2487-2488): Undeclared identifier. +// DeclarationError: (2498-2499): Undeclared identifier. +// DeclarationError: (2509-2510): Undeclared identifier. +// DeclarationError: (2520-2521): Undeclared identifier. +// DeclarationError: (2531-2532): Undeclared identifier. +// DeclarationError: (2542-2543): Undeclared identifier. +// DeclarationError: (2553-2554): Undeclared identifier. +// DeclarationError: (2564-2565): Undeclared identifier. +// DeclarationError: (2575-2576): Undeclared identifier. +// DeclarationError: (2586-2587): Undeclared identifier. +// DeclarationError: (2597-2598): Undeclared identifier. +// DeclarationError: (2608-2609): Undeclared identifier. +// DeclarationError: (2619-2620): Undeclared identifier. +// DeclarationError: (2630-2631): Undeclared identifier. +// DeclarationError: (2641-2642): Undeclared identifier. +// DeclarationError: (2652-2653): Undeclared identifier. +// DeclarationError: (2663-2664): Undeclared identifier. +// DeclarationError: (2674-2675): Undeclared identifier. +// DeclarationError: (2685-2686): Undeclared identifier. +// DeclarationError: (2696-2697): Undeclared identifier. +// DeclarationError: (2707-2708): Undeclared identifier. +// DeclarationError: (2718-2719): Undeclared identifier. +// DeclarationError: (2729-2730): Undeclared identifier. +// DeclarationError: (2740-2741): Undeclared identifier. +// DeclarationError: (2751-2752): Undeclared identifier. +// DeclarationError: (2762-2763): Undeclared identifier. +// DeclarationError: (2773-2774): Undeclared identifier. +// DeclarationError: (2784-2785): Undeclared identifier. +// DeclarationError: (2795-2796): Undeclared identifier. +// DeclarationError: (2806-2807): Undeclared identifier. +// DeclarationError: (2817-2818): Undeclared identifier. +// DeclarationError: (2828-2829): Undeclared identifier. +// DeclarationError: (2839-2840): Undeclared identifier. +// Warning: There are more than 256 errors. Aborting. diff --git a/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol b/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol new file mode 100644 index 00000000..2c9b8a42 --- /dev/null +++ b/test/libsolidity/syntaxTests/more_than_256_syntaxerrors.sol @@ -0,0 +1,524 @@ +contract C { + function f() { + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + continue; + } +} +// ---- +// SyntaxError: (34-42): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (48-56): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (62-70): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (76-84): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (90-98): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (104-112): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (118-126): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (132-140): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (146-154): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (160-168): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (174-182): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (188-196): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (202-210): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (216-224): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (230-238): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (244-252): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (258-266): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (272-280): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (286-294): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (300-308): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (314-322): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (328-336): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (342-350): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (356-364): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (370-378): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (384-392): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (398-406): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (412-420): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (426-434): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (440-448): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (454-462): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (468-476): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (482-490): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (496-504): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (510-518): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (524-532): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (538-546): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (552-560): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (566-574): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (580-588): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (594-602): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (608-616): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (622-630): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (636-644): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (650-658): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (664-672): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (678-686): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (692-700): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (706-714): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (720-728): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (734-742): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (748-756): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (762-770): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (776-784): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (790-798): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (804-812): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (818-826): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (832-840): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (846-854): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (860-868): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (874-882): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (888-896): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (902-910): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (916-924): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (930-938): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (944-952): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (958-966): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (972-980): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (986-994): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1000-1008): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1014-1022): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1028-1036): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1042-1050): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1056-1064): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1070-1078): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1084-1092): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1098-1106): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1112-1120): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1126-1134): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1140-1148): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1154-1162): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1168-1176): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1182-1190): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1196-1204): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1210-1218): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1224-1232): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1238-1246): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1252-1260): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1266-1274): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1280-1288): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1294-1302): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1308-1316): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1322-1330): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1336-1344): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1350-1358): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1364-1372): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1378-1386): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1392-1400): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1406-1414): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1420-1428): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1434-1442): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1448-1456): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1462-1470): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1476-1484): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1490-1498): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1504-1512): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1518-1526): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1532-1540): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1546-1554): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1560-1568): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1574-1582): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1588-1596): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1602-1610): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1616-1624): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1630-1638): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1644-1652): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1658-1666): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1672-1680): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1686-1694): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1700-1708): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1714-1722): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1728-1736): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1742-1750): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1756-1764): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1770-1778): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1784-1792): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1798-1806): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1812-1820): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1826-1834): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1840-1848): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1854-1862): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1868-1876): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1882-1890): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1896-1904): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1910-1918): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1924-1932): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1938-1946): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1952-1960): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1966-1974): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1980-1988): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (1994-2002): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2008-2016): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2022-2030): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2036-2044): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2050-2058): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2064-2072): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2078-2086): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2092-2100): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2106-2114): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2120-2128): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2134-2142): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2148-2156): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2162-2170): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2176-2184): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2190-2198): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2204-2212): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2218-2226): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2232-2240): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2246-2254): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2260-2268): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2274-2282): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2288-2296): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2302-2310): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2316-2324): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2330-2338): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2344-2352): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2358-2366): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2372-2380): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2386-2394): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2400-2408): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2414-2422): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2428-2436): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2442-2450): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2456-2464): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2470-2478): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2484-2492): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2498-2506): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2512-2520): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2526-2534): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2540-2548): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2554-2562): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2568-2576): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2582-2590): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2596-2604): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2610-2618): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2624-2632): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2638-2646): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2652-2660): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2666-2674): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2680-2688): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2694-2702): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2708-2716): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2722-2730): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2736-2744): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2750-2758): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2764-2772): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2778-2786): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2792-2800): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2806-2814): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2820-2828): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2834-2842): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2848-2856): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2862-2870): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2876-2884): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2890-2898): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2904-2912): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2918-2926): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2932-2940): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2946-2954): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2960-2968): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2974-2982): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (2988-2996): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3002-3010): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3016-3024): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3030-3038): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3044-3052): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3058-3066): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3072-3080): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3086-3094): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3100-3108): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3114-3122): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3128-3136): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3142-3150): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3156-3164): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3170-3178): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3184-3192): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3198-3206): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3212-3220): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3226-3234): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3240-3248): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3254-3262): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3268-3276): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3282-3290): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3296-3304): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3310-3318): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3324-3332): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3338-3346): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3352-3360): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3366-3374): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3380-3388): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3394-3402): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3408-3416): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3422-3430): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3436-3444): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3450-3458): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3464-3472): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3478-3486): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3492-3500): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3506-3514): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3520-3528): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3534-3542): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3548-3556): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3562-3570): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3576-3584): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3590-3598): "continue" has to be in a "for" or "while" loop. +// SyntaxError: (3604-3612): "continue" has to be in a "for" or "while" loop. +// Warning: There are more than 256 errors. Aborting. diff --git a/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol b/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol new file mode 100644 index 00000000..9f714aea --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/constructor_allowed_this.sol @@ -0,0 +1,28 @@ +contract A { + function a() public pure { + } +} +contract B { + constructor(address) public { + } + function b(address) public returns (A) { + return new A(); + } +} +contract C { + B m_b; + C m_c; + constructor(C other_c) public { + m_c = other_c; + m_b = new B(this); + m_b.b(this).a(); + g(this).f(); + other_c.f(); + m_c.f(); + } + function f() public pure { + } + function g(C) public view returns (C) { + return m_c; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/constructor_super.sol b/test/libsolidity/syntaxTests/parsing/constructor_super.sol new file mode 100644 index 00000000..fa1be187 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/constructor_super.sol @@ -0,0 +1,10 @@ +contract A { + function x() pure internal {} +} + +contract B is A { + constructor() public { + // used to trigger warning about using ``this`` in constructor + super.x(); + } +} diff --git a/test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol b/test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol new file mode 100644 index 00000000..fd3067e3 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/missing_variable_name_in_declaration.sol @@ -0,0 +1,5 @@ +contract test { + uint256 ; +} +// ---- +// ParserError: (28-28): Expected identifier, got 'Semicolon' diff --git a/test/libsolidity/syntaxTests/parsing/return_var.sol b/test/libsolidity/syntaxTests/parsing/return_var.sol new file mode 100644 index 00000000..47ac9ef0 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/return_var.sol @@ -0,0 +1,25 @@ +contract C { + function f() returns(var) {} + function f() returns(var x) {} + function f() returns(var x, uint y) {} + function f() returns(uint x, var y) {} + function f() returns(var x, var y) {} + function f() public pure returns (var storage) {} + function f() public pure returns (var storage x) {} + function f() public pure returns (var storage x, var storage y) {} +} +// ---- +// ParserError: (38-38): Expected explicit type name. +// ParserError: (71-71): Expected explicit type name. +// ParserError: (106-106): Expected explicit type name. +// ParserError: (157-157): Expected explicit type name. +// ParserError: (192-192): Expected explicit type name. +// ParserError: (199-199): Expected explicit type name. +// ParserError: (247-247): Expected explicit type name. +// ParserError: (251-251): Location specifier needs explicit type name. +// ParserError: (301-301): Expected explicit type name. +// ParserError: (305-305): Location specifier needs explicit type name. +// ParserError: (357-357): Expected explicit type name. +// ParserError: (361-361): Location specifier needs explicit type name. +// ParserError: (372-372): Expected explicit type name. +// ParserError: (376-376): Location specifier needs explicit type name. diff --git a/test/libsolidity/syntaxTests/parsing/smoke_test.sol b/test/libsolidity/syntaxTests/parsing/smoke_test.sol new file mode 100644 index 00000000..d328b167 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/smoke_test.sol @@ -0,0 +1,4 @@ +contract test { + uint256 stateVariable1; +} +// ---- diff --git a/test/libsolidity/syntaxTests/parsing/var_in_function_arguments.sol b/test/libsolidity/syntaxTests/parsing/var_in_function_arguments.sol new file mode 100644 index 00000000..e041247d --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/var_in_function_arguments.sol @@ -0,0 +1,25 @@ +contract C { + function f(var) public pure {} + function f(var x) public pure {} + function f(var x, var y) public pure {} + function f(uint x, var y) public pure {} + function f(var x, uint y) public pure {} + function f(var storage) public pure {} + function f(var storage x) public pure {} + function f(var storage x, var storage y) public pure {} +} +// ---- +// ParserError: (28-28): Expected explicit type name. +// ParserError: (63-63): Expected explicit type name. +// ParserError: (100-100): Expected explicit type name. +// ParserError: (107-107): Expected explicit type name. +// ParserError: (152-152): Expected explicit type name. +// ParserError: (189-189): Expected explicit type name. +// ParserError: (234-234): Expected explicit type name. +// ParserError: (238-238): Location specifier needs explicit type name. +// ParserError: (277-277): Expected explicit type name. +// ParserError: (281-281): Location specifier needs explicit type name. +// ParserError: (322-322): Expected explicit type name. +// ParserError: (326-326): Location specifier needs explicit type name. +// ParserError: (337-337): Expected explicit type name. +// ParserError: (341-341): Location specifier needs explicit type name. diff --git a/test/libsolidity/syntaxTests/parsing/var_storage_var.sol b/test/libsolidity/syntaxTests/parsing/var_storage_var.sol new file mode 100644 index 00000000..431d4ca5 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/var_storage_var.sol @@ -0,0 +1,5 @@ +contract C { + var a; +} +// ---- +// ParserError: (17-17): Function, variable, struct or modifier declaration expected. diff --git a/test/libsolidity/syntaxTests/scoping/double_function_declaration.sol b/test/libsolidity/syntaxTests/scoping/double_function_declaration.sol new file mode 100644 index 00000000..dfd67aaa --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_function_declaration.sol @@ -0,0 +1,6 @@ +contract test { + function fun() public { } + function fun() public { } +} +// ---- +// DeclarationError: (20-45): Function with same name and arguments defined twice. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol new file mode 100644 index 00000000..d90ec2d7 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol @@ -0,0 +1,8 @@ +contract test { + function f() pure public { + { uint x; } + { uint x; } + } +} +// ---- +// DeclarationError: (77-83): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol new file mode 100644 index 00000000..06bfe7be --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol @@ -0,0 +1,10 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + { uint x; } + { uint x; } + } +} +// ---- +// Warning: (87-93): Unused local variable. +// Warning: (107-113): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol new file mode 100644 index 00000000..1a5ff2f9 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol @@ -0,0 +1,8 @@ +contract test { + function f() pure public { + { uint x; } + uint x; + } +} +// ---- +// DeclarationError: (75-81): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol new file mode 100644 index 00000000..20ea0349 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol @@ -0,0 +1,10 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + { uint x; } + uint x; + } +} +// ---- +// Warning: (87-93): Unused local variable. +// Warning: (105-111): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/name_shadowing.sol b/test/libsolidity/syntaxTests/scoping/name_shadowing.sol new file mode 100644 index 00000000..67ada4a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/name_shadowing.sol @@ -0,0 +1,6 @@ +contract test { + uint256 variable; + function f() pure public { uint32 variable; variable = 2; } +} +// ---- +// Warning: (69-84): This declaration shadows an existing declaration. diff --git a/test/libsolidity/syntaxTests/scoping/scoping.sol b/test/libsolidity/syntaxTests/scoping/scoping.sol new file mode 100644 index 00000000..34b055d9 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping.sol @@ -0,0 +1,11 @@ +pragma experimental "v0.5.0"; +contract test { + function f() public { + { + uint256 x; + } + x = 2; + } +} +// ---- +// DeclarationError: (123-124): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_activation.sol b/test/libsolidity/syntaxTests/scoping/scoping_activation.sol new file mode 100644 index 00000000..7334bc49 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_activation.sol @@ -0,0 +1,9 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + x = 3; + uint x; + } +} +// ---- +// DeclarationError: (85-86): Undeclared identifier. Did you mean "x"? diff --git a/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol b/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol new file mode 100644 index 00000000..d893a889 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol @@ -0,0 +1,6 @@ +contract test { + function f() pure public { + x = 3; + uint x; + } +} diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for.sol b/test/libsolidity/syntaxTests/scoping/scoping_for.sol new file mode 100644 index 00000000..6e5b7095 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_for.sol @@ -0,0 +1,8 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + for (uint x = 0; x < 10; x ++){ + x = 2; + } + } +} diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for2.sol b/test/libsolidity/syntaxTests/scoping/scoping_for2.sol new file mode 100644 index 00000000..eb74b8ab --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_for2.sol @@ -0,0 +1,7 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + for (uint x = 0; x < 10; x ++) + x = 2; + } +} diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for3.sol b/test/libsolidity/syntaxTests/scoping/scoping_for3.sol new file mode 100644 index 00000000..1814cb47 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_for3.sol @@ -0,0 +1,11 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + for (uint x = 0; x < 10; x ++){ + x = 2; + } + x = 4; + } +} +// ---- +// DeclarationError: (154-155): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol b/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol new file mode 100644 index 00000000..3e80b385 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol @@ -0,0 +1,10 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + for (;; y++){ + uint y = 3; + } + } +} +// ---- +// DeclarationError: (93-94): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_old.sol b/test/libsolidity/syntaxTests/scoping/scoping_old.sol new file mode 100644 index 00000000..83f6b60b --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_old.sol @@ -0,0 +1,6 @@ +contract test { + function f() pure public { + x = 4; + uint256 x = 2; + } +} diff --git a/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol b/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol new file mode 100644 index 00000000..9e2c0171 --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol @@ -0,0 +1,5 @@ +contract test { + function f() pure public { + uint a = a; + } +} diff --git a/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol b/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol new file mode 100644 index 00000000..ab3dcefb --- /dev/null +++ b/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol @@ -0,0 +1,8 @@ +pragma experimental "v0.5.0"; +contract test { + function f() pure public { + uint a = a; + } +} +// ---- +// DeclarationError: (94-95): Undeclared identifier. Did you mean "a"? diff --git a/test/libsolidity/syntaxTests/signed_rational_modulus.sol b/test/libsolidity/syntaxTests/signed_rational_modulus.sol new file mode 100644 index 00000000..b37d33d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/signed_rational_modulus.sol @@ -0,0 +1,8 @@ +contract test { + function f() public pure { + fixed a = 0.42578125 % -0.4271087646484375; + fixed b = .5 % a; + fixed c = a % b; + a; b; c; + } +} diff --git a/test/libsolidity/syntaxTests/smoke_test.sol b/test/libsolidity/syntaxTests/smoke_test.sol new file mode 100644 index 00000000..6abaff18 --- /dev/null +++ b/test/libsolidity/syntaxTests/smoke_test.sol @@ -0,0 +1,6 @@ +contract test { + uint256 stateVariable1; + function fun(uint256 arg1) public { uint256 y; y = arg1; } +} +// ---- +// Warning: (42-100): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol new file mode 100644 index 00000000..d9eebee4 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs.sol @@ -0,0 +1,17 @@ +contract C { + struct S { uint x; } + S s; + struct T { uint y; } + T t; + function f() public view { + abi.encode(s, t); + } + function g() public view { + abi.encodePacked(s, t); + } +} +// ---- +// TypeError: (131-132): This type cannot be encoded. +// TypeError: (134-135): This type cannot be encoded. +// TypeError: (200-201): This type cannot be encoded. +// TypeError: (203-204): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs_abiv2.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs_abiv2.sol new file mode 100644 index 00000000..d6cf60e4 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_structs_abiv2.sol @@ -0,0 +1,18 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S { uint x; } + S s; + struct T { uint y; } + T t; + function f() public view { + abi.encode(s, t); + } + function g() public view { + abi.encodePacked(s, t); + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (235-236): This type cannot be encoded. +// TypeError: (238-239): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol new file mode 100644 index 00000000..c98d7a57 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol @@ -0,0 +1,11 @@ +contract C { + function f() public pure { + bytes32 h = keccak256(keccak256, f, this.f.gas, block.blockhash); + h; + } +} +// ---- +// TypeError: (74-83): This type cannot be encoded. +// TypeError: (85-86): This type cannot be encoded. +// TypeError: (88-98): This type cannot be encoded. +// TypeError: (100-115): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol new file mode 100644 index 00000000..f1b5606e --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol @@ -0,0 +1,13 @@ +contract C { + function f() public pure { + bool a = address(this).call(address(this).delegatecall, super); + bool b = address(this).delegatecall(log0, tx, mulmod); + a; b; + } +} +// ---- +// TypeError: (80-106): This type cannot be encoded. +// TypeError: (108-113): This type cannot be encoded. +// TypeError: (160-164): This type cannot be encoded. +// TypeError: (166-168): This type cannot be encoded. +// TypeError: (170-176): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol new file mode 100644 index 00000000..fa910260 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol @@ -0,0 +1,13 @@ +contract C { + struct S { uint x; } + S s; + struct T { uint y; } + T t; + function f() public view { + bytes32 a = sha256(s, t); + a; + } +} +// ---- +// TypeError: (139-140): This type cannot be encoded. +// TypeError: (142-143): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol new file mode 100644 index 00000000..1187ce4a --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs_abiv2.sol @@ -0,0 +1,16 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct S { uint x; } + S s; + struct T { uint y; } + T t; + function f() public view { + bytes32 a = sha256(s, t); + a; + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (174-175): This type cannot be encoded. +// TypeError: (177-178): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol new file mode 100644 index 00000000..d10c1718 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol @@ -0,0 +1,17 @@ +contract C { + struct S { uint x; } + S s; + struct T { } + T t; + enum A { X, Y } + function f() public pure { + bool a = address(this).delegatecall(S, A, A.X, T, uint, uint[]); + } +} +// ---- +// Warning: (51-63): Defining empty structs is deprecated. +// TypeError: (168-169): This type cannot be encoded. +// TypeError: (171-172): This type cannot be encoded. +// TypeError: (179-180): This type cannot be encoded. +// TypeError: (182-186): This type cannot be encoded. +// TypeError: (188-194): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol b/test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol new file mode 100644 index 00000000..c8364548 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol @@ -0,0 +1,9 @@ +contract C { + uint[3] sarr; + function f() view public { + uint[3] memory arr; + bytes32 h = keccak256(this.f, arr, sarr); + h; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol b/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol new file mode 100644 index 00000000..895bb6c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/multi_struct_composition.sol @@ -0,0 +1,15 @@ +pragma experimental ABIEncoderV2; + +contract C { + struct T { U u; V v; } + + struct U { W w; } + + struct V { W w; } + + struct W { uint x; } + + function f(T) public pure { } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol new file mode 100644 index 00000000..96362ef0 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/parallel_structs.sol @@ -0,0 +1,15 @@ +pragma experimental ABIEncoderV2; + +contract TestContract +{ + struct SubStruct { + uint256 id; + } + struct TestStruct { + SubStruct subStruct1; + SubStruct subStruct2; + } + function addTestStruct(TestStruct) public pure {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol new file mode 100644 index 00000000..4966a731 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol @@ -0,0 +1,7 @@ +contract C { + struct S { uint a; S[] sub; } + function f() public pure returns (uint, S) { + } +} +// ---- +// TypeError: (91-92): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol new file mode 100644 index 00000000..68113924 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol @@ -0,0 +1,7 @@ +contract C { + struct S { uint a; S[2][] sub; } + function f() public pure returns (uint, S) { + } +} +// ---- +// TypeError: (94-95): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol new file mode 100644 index 00000000..47690d9b --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs3.sol @@ -0,0 +1,8 @@ +contract C { + struct S { uint a; S[][][] sub; } + struct T { S s; } + function f() public pure returns (uint x, T t) { + } +} +// ---- +// TypeError: (119-122): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol new file mode 100644 index 00000000..bcffe383 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_directly_recursive.sol @@ -0,0 +1,8 @@ +contract Test { + struct MyStructName { + address addr; + MyStructName x; + } +} +// ---- +// TypeError: (20-93): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol new file mode 100644 index 00000000..64dab8d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_indirectly_recursive.sol @@ -0,0 +1,12 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2 x; + } + struct MyStructName2 { + MyStructName1 x; + } +} +// ---- +// TypeError: (20-118): Recursive struct definition. diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol new file mode 100644 index 00000000..6ec4ee01 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_not_really_recursive.sol @@ -0,0 +1,4 @@ +contract Test { + struct S1 { uint a; } + struct S2 { S1 x; S1 y; } +} diff --git a/test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol new file mode 100644 index 00000000..926981b3 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/struct_definition_recursion_via_mapping.sol @@ -0,0 +1,7 @@ +contract Test { + struct MyStructName1 { + address addr; + uint256 count; + mapping(uint => MyStructName1) x; + } +} diff --git a/test/libsolidity/syntaxTests/tight_packing_literals.sol b/test/libsolidity/syntaxTests/tight_packing_literals.sol new file mode 100644 index 00000000..8258a8a6 --- /dev/null +++ b/test/libsolidity/syntaxTests/tight_packing_literals.sol @@ -0,0 +1,25 @@ +contract C { + function f() pure public returns (bytes32) { + return keccak256(1); + } + function g() pure public returns (bytes32) { + return sha3(1); + } + function h() pure public returns (bytes32) { + return sha256(1); + } + function j() pure public returns (bytes32) { + return ripemd160(1); + } + function k() pure public returns (bytes) { + return abi.encodePacked(1); + } +} + +// ---- +// Warning: (87-88): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (161-168): "sha3" has been deprecated in favour of "keccak256" +// Warning: (166-167): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (247-248): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (331-332): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. +// Warning: (420-421): The type of "int_const 1" was inferred as uint8. This is probably not desired. Use an explicit type to silence this warning. diff --git a/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol new file mode 100644 index 00000000..46407f71 --- /dev/null +++ b/test/libsolidity/syntaxTests/tight_packing_literals_fine.sol @@ -0,0 +1,11 @@ +contract C { + function f() pure public returns (bytes32) { + return keccak256(uint8(1)); + } + function g() pure public returns (bytes) { + return abi.encode(1); + } + function h() pure public returns (bytes) { + return abi.encodePacked(uint8(1)); + } +} diff --git a/test/libsolidity/syntaxTests/types/rational_number_array_index_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_array_index_limit.sol new file mode 100644 index 00000000..45ede998 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_array_index_limit.sol @@ -0,0 +1,5 @@ +contract c { + uint[2**253] data; +} +// ---- +// Warning: (17-34): Variable covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/types/rational_number_bitshift_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_bitshift_limit.sol new file mode 100644 index 00000000..94981aa0 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_bitshift_limit.sol @@ -0,0 +1,13 @@ +contract c { + function f() public pure { + int a; + a = 1 << 4095; // shift is fine, but result too large + a = 1 << 4096; // too large + a = (1E1233) << 2; // too large + } +} +// ---- +// TypeError: (71-80): Type int_const 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. +// TypeError: (133-142): Operator << not compatible with types int_const 1 and int_const 4096 +// TypeError: (169-182): Operator << not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 +// TypeError: (169-182): 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_div_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol new file mode 100644 index 00000000..1b0b5f94 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_div_limit.sol @@ -0,0 +1,9 @@ +contract c { + function f() public pure { + int a; + a = 1/(2<<4094)/(2<<4094); + } +} +// ---- +// 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): 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.sol b/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol new file mode 100644 index 00000000..6785f580 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_exp_limit.sol @@ -0,0 +1,50 @@ +contract c { + function f() public pure { + int a; + a = 4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4; + a = -4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4 ** 4; + a = 4 ** (-(2 ** 4 ** 4 ** 4 ** 4 ** 4)); + a = 0 ** 1E1233; // fine + a = 1 ** 1E1233; // fine + a = -1 ** 1E1233; // fine + a = 2 ** 1E1233; + a = -2 ** 1E1233; + a = 2 ** -1E1233; + a = -2 ** -1E1233; + a = 1E1233 ** 2; + a = -1E1233 ** 2; + a = 1E1233 ** -2; + a = -1E1233 ** -2; + a = 1E1233 ** 1E1233; + a = 1E1233 ** -1E1233; + a = -1E1233 ** 1E1233; + a = -1E1233 ** -1E1233; + } +} +// ---- +// TypeError: (71-102): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4 +// 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-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: (317-328): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (342-354): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (368-380): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (394-407): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (421-432): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2 +// TypeError: (421-432): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (446-458): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2 +// TypeError: (446-458): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (472-484): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2 +// TypeError: (472-484): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (498-511): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2 +// TypeError: (498-511): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (525-541): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (525-541): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (555-572): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (555-572): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (586-603): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError: (586-603): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. +// TypeError: (617-635): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError: (617-635): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_limit_1.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_1.sol new file mode 100644 index 00000000..233857a3 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_1.sol @@ -0,0 +1,9 @@ +contract c { + function bignum() public { + uint256 a; + a = 1e1233 / 1e1233; // 1e1233 is still fine + a = 1e1234; // 1e1234 is too big + } +} +// ---- +// TypeError: (128-134): Invalid literal value. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_limit_2.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_2.sol new file mode 100644 index 00000000..16673924 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_2.sol @@ -0,0 +1,9 @@ +contract c { + function bignum() public { + uint a; + a = 134562324532464234452335168163516E1200 / 134562324532464234452335168163516E1200; // still fine + a = 1345623245324642344523351681635168E1200; // too large + } +} +// ---- +// TypeError: (179-218): Invalid literal value. diff --git a/test/libsolidity/syntaxTests/types/rational_number_literal_limit_3.sol b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_3.sol new file mode 100644 index 00000000..5a696171 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_literal_limit_3.sol @@ -0,0 +1,9 @@ +contract c { + function bignum() public { + uint a; + a = 134562324532464.234452335168163517E1200 / 134562324532464.234452335168163517E1200; // still fine + a = 134562324532464.2344523351681635177E1200; // too large + } +} +// ---- +// TypeError: (181-221): Invalid literal value. diff --git a/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol b/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol new file mode 100644 index 00000000..bbed94b5 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_mul_limit.sol @@ -0,0 +1,9 @@ +contract c { + function f() public pure { + int a; + a = (1<<4095)*(1<<4095); + } +} +// ---- +// 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): Type int_const 5221...(1225 digits omitted)...5168 is not implicitly convertible to expected type int256. diff --git a/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol new file mode 100644 index 00000000..ca7db42e --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode.sol @@ -0,0 +1,8 @@ +contract C { + function f() pure public returns (bytes r) { + r = abi.encode(1, 2); + r = abi.encodePacked(f()); + r = abi.encodeWithSelector(0x12345678, 1); + r = abi.encodeWithSignature("f(uint256)", 4); + } +} diff --git a/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol new file mode 100644 index 00000000..547362c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPure/view_pure_abi_encode_arguments.sol @@ -0,0 +1,36 @@ +contract C { + uint x; + function gView() public view returns (uint) { return x; } + function gNonPayable() public returns (uint) { x = 4; return 0; } + + function f1() view public returns (bytes) { + return abi.encode(gView()); + } + function f2() view public returns (bytes) { + return abi.encodePacked(gView()); + } + function f3() view public returns (bytes) { + return abi.encodeWithSelector(0x12345678, gView()); + } + function f4() view public returns (bytes) { + return abi.encodeWithSignature("f(uint256)", gView()); + } + function g1() public returns (bytes) { + return abi.encode(gNonPayable()); + } + function g2() public returns (bytes) { + return abi.encodePacked(gNonPayable()); + } + function g3() public returns (bytes) { + return abi.encodeWithSelector(0x12345678, gNonPayable()); + } + function g4() public returns (bytes) { + return abi.encodeWithSignature("f(uint256)", gNonPayable()); + } + // This will generate the only warning. + function check() public returns (bytes) { + return abi.encode(2); + } +} +// ---- +// Warning: (1044-1121): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol b/test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol new file mode 100644 index 00000000..b033fd0c --- /dev/null +++ b/test/libsolidity/syntaxTests/virtualLookup/modifiers_in_libraries.sol @@ -0,0 +1,14 @@ +library WithModifier { + modifier mod() { require(msg.value > 10 ether); _; } + function withMod(uint self) mod() internal view { require(self > 0); } +} + +contract Test { + using WithModifier for *; + + function f(uint _value) public payable { + _value.withMod(); + WithModifier.withMod(_value); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/visibility/external_library_function.sol b/test/libsolidity/syntaxTests/visibility/external_library_function.sol new file mode 100644 index 00000000..110e74db --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/external_library_function.sol @@ -0,0 +1,14 @@ +library L { + function f(uint) pure external {} +} + +contract C { + using L for *; + + function f() public pure { + L.f(2); + uint x; + x.f(); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_default.sol b/test/libsolidity/syntaxTests/visibility/interface/function_default.sol new file mode 100644 index 00000000..72ce3b40 --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_default.sol @@ -0,0 +1,6 @@ +interface I { + function f(); +} +// ---- +// Warning: (15-28): Functions in interfaces should be declared external. +// Warning: (15-28): No visibility specified. Defaulting to "public". In interfaces it defaults to external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_default050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_default050.sol new file mode 100644 index 00000000..513df26b --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_default050.sol @@ -0,0 +1,7 @@ +pragma experimental "v0.5.0"; +interface I { + function f(); +} +// ---- +// SyntaxError: (45-58): No visibility specified. +// TypeError: (45-58): Functions in interfaces must be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol new file mode 100644 index 00000000..3f0a9aca --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol @@ -0,0 +1,5 @@ +pragma experimental "v0.5.0"; +interface I { + function f() external; +} +// ---- diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol b/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol new file mode 100644 index 00000000..ac62e69b --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_internal.sol @@ -0,0 +1,5 @@ +interface I { + function f() internal; +} +// ---- +// TypeError: (15-37): Functions in interfaces cannot be internal or private. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_private.sol b/test/libsolidity/syntaxTests/visibility/interface/function_private.sol new file mode 100644 index 00000000..881e647e --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_private.sol @@ -0,0 +1,5 @@ +interface I { + function f() private; +} +// ---- +// TypeError: (15-36): Functions in interfaces cannot be internal or private. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_public.sol b/test/libsolidity/syntaxTests/visibility/interface/function_public.sol new file mode 100644 index 00000000..891d9fdf --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_public.sol @@ -0,0 +1,5 @@ +interface I { + function f() public; +} +// ---- +// Warning: (15-35): Functions in interfaces should be declared external. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol new file mode 100644 index 00000000..e0c04095 --- /dev/null +++ b/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol @@ -0,0 +1,6 @@ +pragma experimental "v0.5.0"; +interface I { + function f() public; +} +// ---- +// TypeError: (45-65): Functions in interfaces must be declared external. diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt new file mode 100644 index 00000000..febb0c26 --- /dev/null +++ b/test/tools/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(solfuzzer fuzzer.cpp) +target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES}) + +add_executable(isoltest isoltest.cpp ../Options.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp) +target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/fuzzer.cpp b/test/tools/fuzzer.cpp index 71f38b67..71f38b67 100644 --- a/test/fuzzer.cpp +++ b/test/tools/fuzzer.cpp diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp new file mode 100644 index 00000000..7a147bd0 --- /dev/null +++ b/test/tools/isoltest.cpp @@ -0,0 +1,396 @@ +/* + 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 <libdevcore/CommonIO.h> +#include <test/libsolidity/AnalysisFramework.h> +#include <test/libsolidity/SyntaxTest.h> + +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/replace.hpp> +#include <boost/filesystem.hpp> +#include <boost/program_options.hpp> + +#include <cstdlib> +#include <iostream> +#include <fstream> +#include <queue> + +using namespace dev; +using namespace dev::solidity; +using namespace dev::solidity::test; +using namespace dev::solidity::test::formatting; +using namespace std; +namespace po = boost::program_options; +namespace fs = boost::filesystem; + +struct SyntaxTestStats +{ + int successCount; + int runCount; + operator bool() const { return successCount == runCount; } +}; + +class SyntaxTestTool +{ +public: + SyntaxTestTool(string const& _name, fs::path const& _path, bool _formatted): + m_formatted(_formatted), m_name(_name), m_path(_path) + {} + + enum class Result + { + Success, + Failure, + Exception + }; + + Result process(); + + static SyntaxTestStats processPath( + fs::path const& _basepath, + fs::path const& _path, + bool const _formatted + ); + + static string editor; +private: + enum class Request + { + Skip, + Rerun, + Quit + }; + + Request handleResponse(bool const _exception); + + void printContract() const; + + bool const m_formatted; + string const m_name; + fs::path const m_path; + unique_ptr<SyntaxTest> m_test; +}; + +string SyntaxTestTool::editor; + +void SyntaxTestTool::printContract() const +{ + if (m_formatted) + { + string const& source = m_test->source(); + if (source.empty()) + return; + + std::vector<char const*> sourceFormatting(source.length(), formatting::RESET); + for (auto const& error: m_test->errorList()) + if (error.locationStart >= 0 && error.locationEnd >= 0) + { + assert(static_cast<size_t>(error.locationStart) < source.length()); + assert(static_cast<size_t>(error.locationEnd) < source.length()); + bool isWarning = error.type == "Warning"; + for (int i = error.locationStart; i < error.locationEnd; i++) + if (isWarning) + { + if (sourceFormatting[i] == formatting::RESET) + sourceFormatting[i] = formatting::ORANGE_BACKGROUND; + } + else + sourceFormatting[i] = formatting::RED_BACKGROUND; + } + + cout << " " << sourceFormatting.front() << source.front(); + for (size_t i = 1; i < source.length(); i++) + { + if (sourceFormatting[i] != sourceFormatting[i - 1]) + cout << sourceFormatting[i]; + if (source[i] != '\n') + cout << source[i]; + else + { + cout << formatting::RESET << endl; + if (i + 1 < source.length()) + cout << " " << sourceFormatting[i]; + } + } + cout << formatting::RESET << endl; + } + else + { + stringstream stream(m_test->source()); + string line; + while (getline(stream, line)) + cout << " " << line << endl; + cout << endl; + } +} + +SyntaxTestTool::Result SyntaxTestTool::process() +{ + bool success; + std::stringstream outputMessages; + + (FormattedScope(cout, m_formatted, {BOLD}) << m_name << ": ").flush(); + + try + { + m_test = unique_ptr<SyntaxTest>(new SyntaxTest(m_path.string())); + success = m_test->run(outputMessages, " ", m_formatted); + } + catch(CompilerError const& _e) + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "Exception: " << SyntaxTest::errorMessage(_e) << endl; + return Result::Exception; + } + catch(InternalCompilerError const& _e) + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "InternalCompilerError: " << SyntaxTest::errorMessage(_e) << endl; + return Result::Exception; + } + catch(FatalError const& _e) + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "FatalError: " << SyntaxTest::errorMessage(_e) << endl; + return Result::Exception; + } + catch(UnimplementedFeatureError const& _e) + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "UnimplementedFeatureError: " << SyntaxTest::errorMessage(_e) << endl; + return Result::Exception; + } + catch (std::exception const& _e) + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << "Exception: " << _e.what() << endl; + return Result::Exception; + } + catch(...) + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "Unknown Exception" << endl; + return Result::Exception; + } + + if (success) + { + FormattedScope(cout, m_formatted, {BOLD, GREEN}) << "OK" << endl; + return Result::Success; + } + else + { + FormattedScope(cout, m_formatted, {BOLD, RED}) << "FAIL" << endl; + + FormattedScope(cout, m_formatted, {BOLD, CYAN}) << " Contract:" << endl; + printContract(); + + cout << outputMessages.str() << endl; + return Result::Failure; + } +} + +SyntaxTestTool::Request SyntaxTestTool::handleResponse(bool const _exception) +{ + if (_exception) + cout << "(e)dit/(s)kip/(q)uit? "; + else + cout << "(e)dit/(u)pdate expectations/(s)kip/(q)uit? "; + cout.flush(); + + while (true) + { + switch(readStandardInputChar()) + { + case 's': + cout << endl; + return Request::Skip; + case 'u': + if (_exception) + break; + else + { + cout << endl; + ofstream file(m_path.string(), ios::trunc); + file << m_test->source(); + file << "// ----" << endl; + if (!m_test->errorList().empty()) + m_test->printErrorList(file, m_test->errorList(), "// ", false); + return Request::Rerun; + } + case 'e': + cout << endl << endl; + if (system((editor + " \"" + m_path.string() + "\"").c_str())) + cerr << "Error running editor command." << endl << endl; + return Request::Rerun; + case 'q': + cout << endl; + return Request::Quit; + default: + break; + } + } +} + + +SyntaxTestStats SyntaxTestTool::processPath( + fs::path const& _basepath, + fs::path const& _path, + bool const _formatted +) +{ + std::queue<fs::path> paths; + paths.push(_path); + int successCount = 0; + int runCount = 0; + + while (!paths.empty()) + { + auto currentPath = paths.front(); + + fs::path fullpath = _basepath / currentPath; + if (fs::is_directory(fullpath)) + { + paths.pop(); + for (auto const& entry: boost::iterator_range<fs::directory_iterator>( + fs::directory_iterator(fullpath), + fs::directory_iterator() + )) + if (fs::is_directory(entry.path()) || SyntaxTest::isTestFilename(entry.path().filename())) + paths.push(currentPath / entry.path().filename()); + } + else + { + SyntaxTestTool testTool(currentPath.string(), fullpath, _formatted); + ++runCount; + auto result = testTool.process(); + + switch(result) + { + case Result::Failure: + case Result::Exception: + switch(testTool.handleResponse(result == Result::Exception)) + { + case Request::Quit: + return { successCount, runCount }; + case Request::Rerun: + cout << "Re-running test case..." << endl; + --runCount; + break; + case Request::Skip: + paths.pop(); + break; + } + break; + case Result::Success: + paths.pop(); + ++successCount; + break; + } + } + } + + return { successCount, runCount }; + +} + +int main(int argc, char *argv[]) +{ + if (getenv("EDITOR")) + SyntaxTestTool::editor = getenv("EDITOR"); + else if (fs::exists("/usr/bin/editor")) + SyntaxTestTool::editor = "/usr/bin/editor"; + + fs::path testPath; + bool formatted = true; + po::options_description options( + R"(isoltest, tool for interactively managing test contracts. +Usage: isoltest [Options] --testpath path +Interactively validates test contracts. + +Allowed options)", + po::options_description::m_default_line_length, + po::options_description::m_default_line_length - 23); + options.add_options() + ("help", "Show this help screen.") + ("testpath", po::value<fs::path>(&testPath), "path to test files") + ("no-color", "don't use colors") + ("editor", po::value<string>(&SyntaxTestTool::editor), "editor for opening contracts"); + + po::variables_map arguments; + try + { + po::command_line_parser cmdLineParser(argc, argv); + cmdLineParser.options(options); + po::store(cmdLineParser.run(), arguments); + + if (arguments.count("help")) + { + cout << options << endl; + return 0; + } + + if (arguments.count("no-color")) + formatted = false; + + po::notify(arguments); + } + catch (po::error const& _exception) + { + cerr << _exception.what() << endl; + return 1; + } + + if (testPath.empty()) + { + auto const searchPath = + { + fs::current_path() / ".." / ".." / ".." / "test", + fs::current_path() / ".." / ".." / "test", + fs::current_path() / ".." / "test", + fs::current_path() / "test", + fs::current_path() + }; + for (auto const& basePath : searchPath) + { + fs::path syntaxTestPath = basePath / "libsolidity" / "syntaxTests"; + if (fs::exists(syntaxTestPath) && fs::is_directory(syntaxTestPath)) + { + testPath = basePath; + break; + } + } + } + + fs::path syntaxTestPath = testPath / "libsolidity" / "syntaxTests"; + + if (fs::exists(syntaxTestPath) && fs::is_directory(syntaxTestPath)) + { + auto stats = SyntaxTestTool::processPath(testPath / "libsolidity", "syntaxTests", formatted); + + cout << endl << "Summary: "; + FormattedScope(cout, formatted, {BOLD, stats ? GREEN : RED}) << + stats.successCount << "/" << stats.runCount; + cout << " tests successful." << endl; + + return stats ? 0 : 1; + } + else + { + cerr << "Test path not found. Use the --testpath argument." << endl; + return 1; + } +} |