diff options
Diffstat (limited to 'test')
174 files changed, 2104 insertions, 880 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 91c1b200..10b78bdc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,24 +5,34 @@ 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 liblangutil_sources "liblangutil/*.cpp") +file(GLOB liblangutil_headers "liblangutil/*.h") file(GLOB libevmasm_sources "libevmasm/*.cpp") file(GLOB libevmasm_headers "libevmasm/*.h") file(GLOB libyul_sources "libyul/*.cpp") file(GLOB libyul_headers "libyul/*.h") -file(GLOB liblll_sources "liblll/*.cpp") -file(GLOB liblll_headers "liblll/*.h") +if (LLL) + file(GLOB liblll_sources "liblll/*.cpp") + file(GLOB liblll_headers "liblll/*.h") +endif() 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} + ${liblangutil_sources} ${liblangutil_headers} ${libevmasm_sources} ${libevmasm_headers} ${libyul_sources} ${libyul_headers} ${liblll_sources} ${liblll_headers} ${libsolidity_sources} ${libsolidity_headers} ) -target_link_libraries(soltest PRIVATE libsolc solidity lll evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) +target_link_libraries(soltest PRIVATE libsolc yul solidity evmasm devcore ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) + +if (LLL) + target_link_libraries(soltest PRIVATE lll) + target_compile_definitions(soltest PRIVATE HAVE_LLL=1) +endif() if (NOT Boost_USE_STATIC_LIBS) target_compile_definitions(soltest PUBLIC -DBOOST_TEST_DYN_LINK) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index d6de95a3..86c1bcca 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -25,7 +25,7 @@ #include <test/Options.h> #include <test/RPCSession.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <libdevcore/FixedHash.h> #include <libdevcore/Keccak256.h> diff --git a/test/Options.cpp b/test/Options.cpp index da08eb37..9f0d6752 100644 --- a/test/Options.cpp +++ b/test/Options.cpp @@ -23,8 +23,8 @@ #include <test/Common.h> -#include <libsolidity/interface/EVMVersion.h> -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/EVMVersion.h> +#include <liblangutil/Exceptions.h> #include <boost/test/framework.hpp> #include <boost/filesystem.hpp> diff --git a/test/Options.h b/test/Options.h index 0e8a51da..af6f06ee 100644 --- a/test/Options.h +++ b/test/Options.h @@ -19,7 +19,7 @@ #pragma once -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <boost/test/unit_test.hpp> #include <boost/filesystem.hpp> diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 9ac24972..0aae21a7 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -23,7 +23,7 @@ #include <test/Options.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/EVMVersion.h> #include <libdevcore/CommonData.h> diff --git a/test/libsolidity/TestCase.cpp b/test/TestCase.cpp index 17972269..e9e2c9f2 100644 --- a/test/libsolidity/TestCase.cpp +++ b/test/TestCase.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see <http://www.gnu.org/licenses/>. */ -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/predicate.hpp> diff --git a/test/libsolidity/TestCase.h b/test/TestCase.h index 3c05ae4e..3c05ae4e 100644 --- a/test/libsolidity/TestCase.h +++ b/test/TestCase.h diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 34eeaec9..7cb0c143 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -38,6 +38,7 @@ #include <test/Options.h> #include <test/libsolidity/ASTJSONTest.h> #include <test/libsolidity/SyntaxTest.h> +#include <test/libsolidity/SMTCheckerJSONTest.h> #include <test/libyul/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> @@ -143,15 +144,24 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) master, dev::test::Options::get().testPath / "libyul", "yulOptimizerTests", - dev::yul::test::YulOptimizerTest::create + yul::test::YulOptimizerTest::create ) > 0, "no Yul Optimizer tests found"); if (!dev::test::Options::get().disableSMT) + { solAssert(registerTests( master, dev::test::Options::get().testPath / "libsolidity", "smtCheckerTests", SyntaxTest::create ) > 0, "no SMT checker tests found"); + + solAssert(registerTests( + master, + dev::test::Options::get().testPath / "libsolidity", + "smtCheckerTestsJSON", + SMTCheckerTest::create + ) > 0, "no SMT checker JSON tests found"); + } if (dev::test::Options::get().disableIPC) { for (auto suite: { @@ -160,9 +170,11 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "SolidityAuctionRegistrar", "SolidityFixedFeeRegistrar", "SolidityWallet", +#if HAVE_LLL "LLLERC20", "LLLENS", "LLLEndToEndTest", +#endif "GasMeterTests", "SolidityEndToEndTest", "SolidityOptimizer" diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index b0b545f3..fdc9fbe3 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -124,7 +124,7 @@ test_solc_file_input_failures() { set -e sed -i -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path" - sed -i -e 's/ \?Consider adding "pragma .*$//' "$stderr_path" + sed -i -e 's/ Consider adding "pragma .*$//' "$stderr_path" if [[ $exitCode -eq 0 ]]; then printError "Incorrect exit code. Expected failure (non-zero) but got success (0)." @@ -262,10 +262,45 @@ SOLTMPDIR=$(mktemp -d) ) rm -rf "$SOLTMPDIR" -printTask "Testing assemble, yul, strict-assembly..." -echo '{}' | "$SOLC" - --assemble &>/dev/null -echo '{}' | "$SOLC" - --yul &>/dev/null -echo '{}' | "$SOLC" - --strict-assembly &>/dev/null +test_solc_assembly_output() { + local input="${1}" + local expected="${2}" + local solc_args="${3}" + + local expected_object="object \"object\" { code "${expected}" }" + + output=$(echo "${input}" | "$SOLC" - ${solc_args} 2>/dev/null) + empty=$(echo $output | sed -ne '/'"${expected_object}"'/p') + if [ -z "$empty" ] + then + printError "Incorrect assembly output. Expected: " + echo -e ${expected} + printError "with arguments ${solc_args}, but got:" + echo "${output}" + exit 1 + fi +} + +printTask "Testing assemble, yul, strict-assembly and optimize..." +( + echo '{}' | "$SOLC" - --assemble &>/dev/null + echo '{}' | "$SOLC" - --yul &>/dev/null + echo '{}' | "$SOLC" - --strict-assembly &>/dev/null + + # Test options above in conjunction with --optimize. + # Using both, --assemble and --optimize should fail. + ! echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null + + # Test yul and strict assembly output + # Non-empty code results in non-empty binary representation with optimizations turned off, + # while it results in empty binary representation with optimizations turned on. + test_solc_assembly_output "{ let x:u256 := 0:u256 }" "{ let x:u256 := 0:u256 }" "--yul" + test_solc_assembly_output "{ let x:u256 := 0:u256 }" "{ }" "--yul --optimize" + + test_solc_assembly_output "{ let x := 0 }" "{ let x := 0 }" "--strict-assembly" + test_solc_assembly_output "{ let x := 0 }" "{ }" "--strict-assembly --optimize" +) + printTask "Testing standard input..." SOLTMPDIR=$(mktemp -d) diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index eb274c09..6ce61a6e 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -112,7 +112,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem { uint constant c_renewalInterval = 365 days; uint constant c_freeBytes = 12; - function Registrar() public { + constructor() public { // TODO: Populate with hall-of-fame. } diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 1c041596..bece2be4 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -30,6 +30,7 @@ #include <memory> using namespace std; +using namespace langutil; using namespace dev::eth; namespace dev @@ -54,10 +55,12 @@ BOOST_AUTO_TEST_SUITE(Assembler) BOOST_AUTO_TEST_CASE(all_assembly_items) { Assembly _assembly; - _assembly.setSourceLocation(SourceLocation(1, 3, make_shared<string>("root.asm"))); + auto root_asm = make_shared<CharStream>("", "root.asm"); + _assembly.setSourceLocation(SourceLocation(1, 3, root_asm)); Assembly _subAsm; - _subAsm.setSourceLocation(SourceLocation(6, 8, make_shared<string>("sub.asm"))); + auto sub_asm = make_shared<CharStream>("", "sub.asm"); + _subAsm.setSourceLocation(SourceLocation(6, 8, sub_asm)); _subAsm.append(Instruction::INVALID); shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index c01e8758..7d102948 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -36,6 +36,7 @@ #include <memory> using namespace std; +using namespace langutil; using namespace dev::eth; namespace dev @@ -52,7 +53,7 @@ namespace // add dummy locations to each item so that we can check that they are not deleted AssemblyItems input = _input; for (AssemblyItem& item: input) - item.setLocation(SourceLocation(1, 3, make_shared<string>(""))); + item.setLocation(SourceLocation(1, 3, nullptr)); return input; } diff --git a/test/libevmasm/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp index 764da3cd..ef4103da 100644 --- a/test/libevmasm/SourceLocation.cpp +++ b/test/liblangutil/SourceLocation.cpp @@ -20,13 +20,11 @@ * Unit tests for the SourceLocation class. */ -#include <libevmasm/SourceLocation.h> +#include <liblangutil/SourceLocation.h> #include <test/Options.h> -namespace dev -{ -namespace solidity +namespace langutil { namespace test { @@ -35,16 +33,19 @@ BOOST_AUTO_TEST_SUITE(SourceLocationTest) BOOST_AUTO_TEST_CASE(test_fail) { + auto const source = std::make_shared<CharStream>("", "source"); + auto const sourceA = std::make_shared<CharStream>("", "sourceA"); + auto const sourceB = std::make_shared<CharStream>("", "sourceB"); + BOOST_CHECK(SourceLocation() == SourceLocation()); - BOOST_CHECK(SourceLocation(0, 3, std::make_shared<std::string>("sourceA")) != SourceLocation(0, 3, std::make_shared<std::string>("sourceB"))); - BOOST_CHECK(SourceLocation(0, 3, std::make_shared<std::string>("source")) == SourceLocation(0, 3, std::make_shared<std::string>("source"))); - BOOST_CHECK(SourceLocation(3, 7, std::make_shared<std::string>("source")).contains(SourceLocation(4, 6, std::make_shared<std::string>("source")))); - BOOST_CHECK(!SourceLocation(3, 7, std::make_shared<std::string>("sourceA")).contains(SourceLocation(4, 6, std::make_shared<std::string>("sourceB")))); - BOOST_CHECK(SourceLocation(3, 7, std::make_shared<std::string>("sourceA")) < SourceLocation(4, 6, std::make_shared<std::string>("sourceB"))); + BOOST_CHECK(SourceLocation(0, 3, sourceA) != SourceLocation(0, 3, sourceB)); + BOOST_CHECK(SourceLocation(0, 3, source) == SourceLocation(0, 3, source)); + BOOST_CHECK(SourceLocation(3, 7, source).contains(SourceLocation(4, 6, source))); + BOOST_CHECK(!SourceLocation(3, 7, sourceA).contains(SourceLocation(4, 6, sourceB))); + BOOST_CHECK(SourceLocation(3, 7, sourceA) < SourceLocation(4, 6, sourceB)); } BOOST_AUTO_TEST_SUITE_END() } -} } // end namespaces diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 60aef7b0..aad89b91 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -109,6 +109,19 @@ BOOST_AUTO_TEST_CASE(variables) BOOST_CHECK(callFallback() == encodeArgs(u256(488))); } +BOOST_AUTO_TEST_CASE(with) +{ + char const* sourceCode = R"( + (returnlll + (seq + (set 'x 11) + (with 'y 22 { [0]:(+ (get 'x) (get 'y)) }) + (return 0 32))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == toBigEndian(u256(33))); +} + BOOST_AUTO_TEST_CASE(when) { char const* sourceCode = R"( diff --git a/test/contracts/LLL_ENS.cpp b/test/liblll/LLL_ENS.cpp index cfd6970c..cfd6970c 100644 --- a/test/contracts/LLL_ENS.cpp +++ b/test/liblll/LLL_ENS.cpp diff --git a/test/contracts/LLL_ERC20.cpp b/test/liblll/LLL_ERC20.cpp index 6c6762dd..6c6762dd 100644 --- a/test/contracts/LLL_ERC20.cpp +++ b/test/liblll/LLL_ERC20.cpp diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index 94319985..291ed15a 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -22,7 +22,7 @@ #include <string> #include <tuple> #include <boost/test/unit_test.hpp> -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/Exceptions.h> #include <test/libsolidity/SolidityExecutionFramework.h> #include <test/libsolidity/ABITestsCommon.h> diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index d2125cc7..b6e6cedd 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -22,7 +22,7 @@ #include <string> #include <tuple> #include <boost/test/unit_test.hpp> -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/Exceptions.h> #include <test/libsolidity/SolidityExecutionFramework.h> #include <test/libsolidity/ABITestsCommon.h> diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h index 6f24bb60..dcdaf221 100644 --- a/test/libsolidity/ASTJSONTest.h +++ b/test/libsolidity/ASTJSONTest.h @@ -18,7 +18,7 @@ #pragma once #include <test/libsolidity/FormattedScope.h> -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> #include <iosfwd> #include <string> @@ -39,10 +39,10 @@ public: { return std::unique_ptr<TestCase>(new ASTJSONTest(_filename)); } ASTJSONTest(std::string const& _filename); - virtual bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; - virtual void printSource(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) const override; - virtual void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; + void printSource(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) const override; + void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; private: std::vector<std::pair<std::string, std::string>> m_sources; std::string m_expectation; diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index ec98026c..bd24115c 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -23,11 +23,11 @@ #include <test/Options.h> #include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libsolidity/ast/AST.h> -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/Scanner.h> #include <libdevcore/Keccak256.h> @@ -35,6 +35,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; using namespace dev::solidity::test; @@ -127,7 +128,7 @@ string AnalysisFramework::formatError(Error const& _error) const return SourceReferenceFormatter::formatExceptionInformation( _error, (_error.type() == Error::Type::Warning) ? "Warning" : "Error", - [&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); } + [&](std::string const& _sourceName) -> Scanner const& { return m_compiler.scanner(_sourceName); } ); } diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index a904617d..391a21da 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -45,7 +45,7 @@ class AnalysisFramework { protected: - virtual std::pair<SourceUnit const*, ErrorList> + virtual std::pair<SourceUnit const*, langutil::ErrorList> parseAnalyseAndReturnError( std::string const& _source, bool _reportWarnings = false, @@ -56,10 +56,10 @@ protected: SourceUnit const* parseAndAnalyse(std::string const& _source); bool success(std::string const& _source); - ErrorList expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false); + langutil::ErrorList expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false); std::string formatErrors() const; - std::string formatError(Error const& _error) const; + std::string formatError(langutil::Error const& _error) const; static ContractDefinition const* retrieveContractByName(SourceUnit const& _source, std::string const& _name); static FunctionTypePointer retrieveFunctionBySignature( @@ -68,7 +68,7 @@ protected: ); // filter out the warnings in m_warningsToFilter or all warnings if _includeWarnings is false - ErrorList filterErrors(ErrorList const& _errorList, bool _includeWarnings) const; + langutil::ErrorList filterErrors(langutil::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 e815d7d5..aa10147c 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -22,16 +22,16 @@ #include <test/Options.h> -#include <libevmasm/SourceLocation.h> +#include <liblangutil/SourceLocation.h> #include <libevmasm/Assembly.h> -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/Scanner.h> #include <libsolidity/parsing/Parser.h> #include <libsolidity/analysis/NameAndTypeResolver.h> #include <libsolidity/codegen/Compiler.h> #include <libsolidity/ast/AST.h> #include <libsolidity/analysis/TypeChecker.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <liblangutil/ErrorReporter.h> #include <boost/test/unit_test.hpp> @@ -39,6 +39,7 @@ #include <iostream> using namespace std; +using namespace langutil; using namespace dev::eth; namespace dev @@ -51,13 +52,13 @@ namespace test namespace { -eth::AssemblyItems compileContract(string const& _sourceCode) +eth::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode) { ErrorList errors; ErrorReporter errorReporter(errors); Parser parser(errorReporter); ASTPointer<SourceUnit> sourceUnit; - BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)))); + BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared<Scanner>(_sourceCode))); BOOST_CHECK(!!sourceUnit); map<ASTNode const*, shared_ptr<DeclarationContainer>> scopes; @@ -103,7 +104,7 @@ void printAssemblyLocations(AssemblyItems const& _items) ", " << _loc.end << ", make_shared<string>(\"" << - *_loc.sourceName << + _loc.source->name() << "\"))) +" << endl; }; @@ -134,7 +135,8 @@ void checkAssemblyLocations(AssemblyItems const& _items, vector<SourceLocation> BOOST_CHECK_EQUAL(_items.size(), _locations.size()); for (size_t i = 0; i < min(_items.size(), _locations.size()); ++i) { - if (_items[i].location() != _locations[i]) + if (_items[i].location().start != _locations[i].start || + _items[i].location().end != _locations[i].end) { BOOST_CHECK_MESSAGE(false, "Location mismatch for item " + to_string(i) + ". Found the following locations:"); printAssemblyLocations(_items); @@ -150,29 +152,32 @@ BOOST_AUTO_TEST_SUITE(Assembly) BOOST_AUTO_TEST_CASE(location_test) { - char const* sourceCode = R"( + auto sourceCode = make_shared<CharStream>(R"( contract test { function f() public returns (uint256 a) { return 16; } } - )"; + )", ""); AssemblyItems items = compileContract(sourceCode); bool hasShifts = dev::test::Options::get().evmVersion().hasBitwiseShifting(); + + auto codegenCharStream = make_shared<CharStream>("", "--CODEGEN--"); + vector<SourceLocation> locations = - vector<SourceLocation>(hasShifts ? 23 : 24, SourceLocation(2, 82, make_shared<string>(""))) + - vector<SourceLocation>(2, SourceLocation(20, 79, 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, 79, make_shared<string>(""))) + - vector<SourceLocation>(1, SourceLocation(49, 58, make_shared<string>(""))) + - vector<SourceLocation>(1, SourceLocation(72, 74, make_shared<string>(""))) + - vector<SourceLocation>(2, SourceLocation(65, 74, make_shared<string>(""))) + - vector<SourceLocation>(2, SourceLocation(20, 79, make_shared<string>(""))); + vector<SourceLocation>(hasShifts ? 21 : 22, SourceLocation(2, 82, sourceCode)) + + vector<SourceLocation>(2, SourceLocation(20, 79, sourceCode)) + + vector<SourceLocation>(1, SourceLocation(8, 17, codegenCharStream)) + + vector<SourceLocation>(3, SourceLocation(5, 7, codegenCharStream)) + + vector<SourceLocation>(1, SourceLocation(30, 31, codegenCharStream)) + + vector<SourceLocation>(1, SourceLocation(27, 28, codegenCharStream)) + + vector<SourceLocation>(1, SourceLocation(20, 32, codegenCharStream)) + + vector<SourceLocation>(1, SourceLocation(5, 7, codegenCharStream)) + + vector<SourceLocation>(24, SourceLocation(20, 79, sourceCode)) + + vector<SourceLocation>(1, SourceLocation(49, 58, sourceCode)) + + vector<SourceLocation>(1, SourceLocation(72, 74, sourceCode)) + + vector<SourceLocation>(2, SourceLocation(65, 74, sourceCode)) + + vector<SourceLocation>(2, SourceLocation(20, 79, sourceCode)); checkAssemblyLocations(items, locations); } diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp index fba2c897..e1f48fb2 100644 --- a/test/libsolidity/ErrorCheck.cpp +++ b/test/libsolidity/ErrorCheck.cpp @@ -27,6 +27,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace diff --git a/test/libsolidity/ErrorCheck.h b/test/libsolidity/ErrorCheck.h index 8ad81f85..c3a2f522 100644 --- a/test/libsolidity/ErrorCheck.h +++ b/test/libsolidity/ErrorCheck.h @@ -21,7 +21,7 @@ #pragma once -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/Exceptions.h> #include <vector> #include <tuple> @@ -30,10 +30,10 @@ namespace dev { namespace solidity { -bool searchErrorMessage(Error const& _err, std::string const& _substr); +bool searchErrorMessage(langutil::Error const& _err, std::string const& _substr); /// Checks that all provided errors are of the given type and have a given substring in their /// description. /// If the expectations are not met, returns a nonempty description, otherwise an empty string. -std::string searchErrors(ErrorList const& _errors, std::vector<std::pair<Error::Type, std::string>> const& _expectations); +std::string searchErrors(langutil::ErrorList const& _errors, std::vector<std::pair<langutil::Error::Type, std::string>> const& _expectations); } } diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 4887dd5b..601948bc 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -26,9 +26,10 @@ #include <libevmasm/PathGasMeter.h> #include <libsolidity/ast/AST.h> #include <libsolidity/interface/GasEstimator.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/SourceReferenceFormatter.h> using namespace std; +using namespace langutil; using namespace dev::eth; using namespace dev::solidity; using namespace dev::test; diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index dc33d577..abd659b6 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -23,7 +23,7 @@ #include <test/libsolidity/ErrorCheck.h> #include <test/Options.h> -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/Exceptions.h> #include <libsolidity/interface/CompilerStack.h> #include <boost/test/unit_test.hpp> diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index a9ce6e49..11d4c59f 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -23,8 +23,8 @@ #include <test/Options.h> #include <libsolidity/interface/AssemblyStack.h> -#include <libsolidity/parsing/Scanner.h> -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/Scanner.h> +#include <liblangutil/Exceptions.h> #include <libsolidity/ast/AST.h> #include <test/libsolidity/ErrorCheck.h> #include <libevmasm/Assembly.h> @@ -36,6 +36,7 @@ #include <memory> using namespace std; +using namespace langutil; namespace dev { @@ -123,7 +124,8 @@ void parsePrintCompare(string const& _source, bool _canWarn = false) BOOST_REQUIRE(Error::containsOnlyWarnings(stack.errors())); else BOOST_REQUIRE(stack.errors().empty()); - BOOST_CHECK_EQUAL(stack.print(), _source); + string expectation = "object \"object\" {\n code " + boost::replace_all_copy(_source, "\n", "\n ") + "\n}\n"; + BOOST_CHECK_EQUAL(stack.print(), expectation); } } @@ -566,12 +568,14 @@ BOOST_AUTO_TEST_CASE(print_string_literals) BOOST_AUTO_TEST_CASE(print_string_literal_unicode) { string source = "{ let x := \"\\u1bac\" }"; - string parsed = "{\n let x := \"\\xe1\\xae\\xac\"\n}"; + string parsed = "object \"object\" {\n code {\n let x := \"\\xe1\\xae\\xac\"\n }\n}\n"; AssemblyStack stack(dev::test::Options::get().evmVersion()); BOOST_REQUIRE(stack.parseAndAnalyze("", source)); BOOST_REQUIRE(stack.errors().empty()); BOOST_CHECK_EQUAL(stack.print(), parsed); - parsePrintCompare(parsed); + + string parsedInner = "{\n let x := \"\\xe1\\xae\\xac\"\n}"; + parsePrintCompare(parsedInner); } BOOST_AUTO_TEST_CASE(print_if) diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 195004cb..a49618bd 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -25,6 +25,7 @@ #include <string> using namespace std; +using namespace langutil; namespace dev { @@ -55,599 +56,6 @@ protected: BOOST_FIXTURE_TEST_SUITE(SMTChecker, SMTCheckerFramework) -BOOST_AUTO_TEST_CASE(smoke_test) -{ - string text = R"( - contract C { } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(simple_overflow) -{ - string text = R"( - contract C { - function f(uint a, uint b) public pure returns (uint) { return a + b; } - } - )"; - CHECK_WARNING(text, "Overflow (resulting value larger than"); -} - -BOOST_AUTO_TEST_CASE(warn_on_typecast) -{ - string text = R"( - contract C { - function f() public pure returns (uint) { - return uint8(1); - } - } - )"; - CHECK_WARNING(text, "Assertion checker does not yet implement this expression."); -} - -BOOST_AUTO_TEST_CASE(warn_on_struct) -{ - string text = R"( - pragma experimental ABIEncoderV2; - contract C { - struct A { uint a; uint b; } - function f() public pure returns (A memory) { - return A({ a: 1, b: 2 }); - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Experimental feature", - "Assertion checker does not yet implement this expression.", - "Assertion checker does not yet support the type of this variable." - })); -} - -BOOST_AUTO_TEST_CASE(simple_assert) -{ - string text = R"( - contract C { - function f(uint a) public pure { assert(a == 2); } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); -} - -BOOST_AUTO_TEST_CASE(simple_assert_with_require) -{ - string text = R"( - contract C { - function f(uint a) public pure { require(a < 10); assert(a < 20); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(assignment_in_declaration) -{ - string text = R"( - contract C { - function f() public pure { uint a = 2; assert(a == 2); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(branches_merge_variables) -{ - // Branch does not touch variable a - string text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - } - assert(a == 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - // Positive branch touches variable a, but assertion should still hold. - text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - a = 3; - } - assert(a == 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - // Negative branch touches variable a, but assertion should still hold. - text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - } else { - a = 3; - } - assert(a == 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - // Variable is not merged, if it is only read. - text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - assert(a == 3); - } else { - assert(a == 3); - } - assert(a == 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - // Variable is reset in both branches - text = R"( - contract C { - function f(uint x) public pure { - uint a = 2; - if (x > 10) { - a = 3; - } else { - a = 3; - } - assert(a == 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - // Variable is reset in both branches - text = R"( - contract C { - function f(uint x) public pure { - uint a = 2; - if (x > 10) { - a = 3; - } else { - a = 4; - } - assert(a >= 3); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(branches_assert_condition) -{ - string text = R"( - contract C { - function f(uint x) public pure { - if (x > 10) { - assert(x > 9); - } - else - { - assert(x < 11); - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(uint x) public pure { - if (x > 10) { - assert(x > 9); - } - else if (x > 2) - { - assert(x <= 10 && x > 2); - } - else - { - assert(0 <= x && x <= 2); - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - -BOOST_AUTO_TEST_CASE(ways_to_merge_variables) -{ - string text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - a++; - } - assert(a == 3); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - ++a; - } - assert(a == 3); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - text = R"( - contract C { - function f(uint x) public pure { - uint a = 3; - if (x > 10) { - a = 5; - } - assert(a == 3); - } - } - )"; - 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); -} - -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(storage_value_vars) -{ - string text = R"( - contract C - { - address a; - bool b; - uint c; - function f(uint x) public { - if (x == 0) - { - a = 0x0000000000000000000000000000000000000100; - b = true; - } - else - { - a = 0x0000000000000000000000000000000000000200; - b = false; - } - assert(a > 0x0000000000000000000000000000000000000000 && b); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - text = R"( - contract C - { - address a; - bool b; - uint c; - function f() public view { - assert(c > 0); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - text = R"( - contract C - { - function f(uint x) public { - if (x == 0) - { - a = 0x0000000000000000000000000000000000000100; - b = true; - } - else - { - a = 0x0000000000000000000000000000000000000200; - b = false; - } - assert(b == (a < 0x0000000000000000000000000000000000000200)); - } - - function g() public view { - require(a < 0x0000000000000000000000000000000000000100); - assert(c >= 0); - } - address a; - bool b; - uint c; - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C - { - function f() public view { - assert(c > 0); - } - uint c; - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - -} - -BOOST_AUTO_TEST_CASE(while_loop_simple) -{ - // Check that variables are cleared - string text = R"( - contract C { - function f(uint x) public pure { - x = 2; - while (x > 1) { - x = 2; - } - assert(x == 2); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - // Check that condition is assumed. - text = R"( - contract C { - function f(uint x) public pure { - while (x == 2) { - assert(x == 2); - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - // Check that condition is not assumed after the body anymore - text = R"( - contract C { - function f(uint x) public pure { - while (x == 2) { - } - assert(x == 2); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - // Check that negation of condition is not assumed after the body anymore - text = R"( - contract C { - function f(uint x) public pure { - while (x == 2) { - } - assert(x != 2); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - // Check that side-effects of condition are taken into account - text = R"( - contract C { - function f(uint x, uint y) public pure { - x = 7; - while ((x = y) > 0) { - } - assert(x == 7); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); -} - -BOOST_AUTO_TEST_CASE(constant_condition) -{ - string text = R"( - contract C { - function f(uint x) public pure { - if (x >= 0) { revert(); } - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Condition is always true", - "Assertion checker does not yet implement this type of function call" - })); - text = R"( - contract C { - function f(uint x) public pure { - if (x >= 10) { if (x < 10) { revert(); } } - } - } - )"; - CHECK_WARNING_ALLOW_MULTI(text, (vector<string>{ - "Condition is always false", - "Assertion checker does not yet implement this type of function call" - })); - // a plain literal constant is fine - text = R"( - contract C { - function f(uint) public pure { - if (true) { revert(); } - } - } - )"; - CHECK_WARNING(text, "Assertion checker does not yet implement this type of function call"); -} - - -BOOST_AUTO_TEST_CASE(for_loop) -{ - string text = R"( - contract C { - function f(uint x) public pure { - require(x == 2); - for (;;) {} - assert(x == 2); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(uint x) public pure { - for (; x == 2; ) { - assert(x == 2); - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(uint x) public pure { - for (uint y = 2; x < 10; ) { - assert(y == 2); - } - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(uint x) public pure { - for (uint y = 2; x < 10; y = 3) { - assert(y == 2); - } - } - } - )"; - CHECK_WARNING(text, "Assertion violation"); - text = R"( - contract C { - function f(uint x) public pure { - uint y; - for (y = 2; x < 10; ) { - y = 3; - } - assert(y == 3); - } - } - )"; - CHECK_WARNING(text, "Assertion violation"); - text = R"( - contract C { - function f(uint x) public pure { - uint y; - for (y = 2; x < 10; ) { - y = 3; - } - assert(y == 2); - } - } - )"; - CHECK_WARNING(text, "Assertion violation"); -} - BOOST_AUTO_TEST_CASE(division) { string text = R"( diff --git a/test/libsolidity/SMTCheckerJSONTest.cpp b/test/libsolidity/SMTCheckerJSONTest.cpp new file mode 100644 index 00000000..e9204cc4 --- /dev/null +++ b/test/libsolidity/SMTCheckerJSONTest.cpp @@ -0,0 +1,153 @@ +/* + 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/SMTCheckerJSONTest.h> +#include <test/Options.h> +#include <libsolidity/interface/StandardCompiler.h> +#include <libdevcore/JSON.h> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/throw_exception.hpp> +#include <fstream> +#include <memory> +#include <stdexcept> +#include <sstream> + +using namespace dev; +using namespace solidity; +using namespace dev::solidity::test; +using namespace dev::solidity::test::formatting; +using namespace std; +using namespace boost::unit_test; + +SMTCheckerTest::SMTCheckerTest(string const& _filename) +: SyntaxTest(_filename) +{ + if (!boost::algorithm::ends_with(_filename, ".sol")) + BOOST_THROW_EXCEPTION(runtime_error("Invalid test contract file name: \"" + _filename + "\".")); + + string jsonFilename = _filename.substr(0, _filename.size() - 4) + ".json"; + if ( + !jsonParseFile(jsonFilename, m_smtResponses) || + !m_smtResponses.isObject() + ) + BOOST_THROW_EXCEPTION(runtime_error("Invalid JSON file.")); +} + +bool SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + StandardCompiler compiler; + + // Run the compiler and retrieve the smtlib2queries (1st run) + string versionPragma = "pragma solidity >=0.0;\n"; + Json::Value input = buildJson(versionPragma); + Json::Value result = compiler.compile(input); + + // This is the list of query hashes requested by the 1st run + vector<string> outHashes = hashesFromJson(result, "auxiliaryInputRequested", "smtlib2queries"); + + // This is the list of responses provided in the test + string auxInput("auxiliaryInput"); + if (!m_smtResponses.isMember(auxInput)) + BOOST_THROW_EXCEPTION(runtime_error("JSON file does not contain field \"auxiliaryInput\".")); + + vector<string> inHashes = hashesFromJson(m_smtResponses, auxInput, "smtlib2responses"); + + // Ensure that the provided list matches the requested one + if (outHashes != inHashes) + BOOST_THROW_EXCEPTION(runtime_error( + "SMT query hashes differ: " + + boost::algorithm::join(outHashes, ", ") + + " x " + + boost::algorithm::join(inHashes, ", ") + )); + + // Rerun the compiler with the provided hashed (2nd run) + input[auxInput] = m_smtResponses[auxInput]; + Json::Value endResult = compiler.compile(input); + + if (endResult.isMember("errors") && endResult["errors"].isArray()) + { + Json::Value const& errors = endResult["errors"]; + for (auto const& error: errors) + { + if ( + !error.isMember("type") || + !error["type"].isString() + ) + BOOST_THROW_EXCEPTION(runtime_error("Error must have a type.")); + if ( + !error.isMember("message") || + !error["message"].isString() + ) + BOOST_THROW_EXCEPTION(runtime_error("Error must have a message.")); + if (!error.isMember("sourceLocation")) + continue; + Json::Value const& location = error["sourceLocation"]; + if ( + !location.isMember("start") || + !location["start"].isInt() || + !location.isMember("end") || + !location["end"].isInt() + ) + BOOST_THROW_EXCEPTION(runtime_error("Error must have a SourceLocation with start and end.")); + int start = location["start"].asInt(); + int end = location["end"].asInt(); + if (start >= static_cast<int>(versionPragma.size())) + start -= versionPragma.size(); + if (end >= static_cast<int>(versionPragma.size())) + end -= versionPragma.size(); + m_errorList.emplace_back(SyntaxTestError{ + error["type"].asString(), + error["message"].asString(), + start, + end + }); + } + } + + return printExpectationAndError(_stream, _linePrefix, _formatted); +} + +vector<string> SMTCheckerTest::hashesFromJson(Json::Value const& _jsonObj, string const& _auxInput, string const& _smtlib) +{ + vector<string> hashes; + Json::Value const& auxInputs = _jsonObj[_auxInput]; + if (!!auxInputs) + { + Json::Value const& smtlib = auxInputs[_smtlib]; + if (!!smtlib) + for (auto const& hashString: smtlib.getMemberNames()) + hashes.push_back(hashString); + } + return hashes; +} + +Json::Value SMTCheckerTest::buildJson(string const& _extra) +{ + string language = "\"language\": \"Solidity\""; + string sourceName = "\"A\""; + string sourceContent = "\"" + _extra + m_source + "\""; + string sourceObj = "{ \"content\": " + sourceContent + "}"; + string sources = " \"sources\": { " + sourceName + ": " + sourceObj + "}"; + string input = "{" + language + ", " + sources + "}"; + Json::Value source; + if (!jsonParse(input, source)) + BOOST_THROW_EXCEPTION(runtime_error("Could not build JSON from string.")); + return source; +} diff --git a/test/libsolidity/SMTCheckerJSONTest.h b/test/libsolidity/SMTCheckerJSONTest.h new file mode 100644 index 00000000..cf41acac --- /dev/null +++ b/test/libsolidity/SMTCheckerJSONTest.h @@ -0,0 +1,53 @@ +/* + 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/SyntaxTest.h> + +#include <libdevcore/JSON.h> + +#include <string> + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class SMTCheckerTest: public SyntaxTest +{ +public: + static std::unique_ptr<TestCase> create(std::string const& _filename) + { + return std::unique_ptr<TestCase>(new SMTCheckerTest(_filename)); + } + SMTCheckerTest(std::string const& _filename); + + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + +private: + std::vector<std::string> hashesFromJson(Json::Value const& _jsonObj, std::string const& _auxInput, std::string const& _smtlib); + Json::Value buildJson(std::string const& _extra); + + Json::Value m_smtResponses; +}; + +} +} +} diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 43951f73..2980acd1 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -23,11 +23,12 @@ #include <string> #include <vector> #include <tuple> -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/Scanner.h> #include <libsolidity/analysis/SemVerHandler.h> #include <test/Options.h> using namespace std; +using namespace langutil; namespace dev { @@ -40,7 +41,7 @@ BOOST_AUTO_TEST_SUITE(SemVerMatcher) SemVerMatchExpression parseExpression(string const& _input) { - Scanner scanner{CharStream(_input)}; + Scanner scanner{CharStream(_input, "")}; vector<string> literals; vector<Token> tokens; while (scanner.currentToken() != Token::EOS) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 87646737..c6135a72 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -25,8 +25,8 @@ #include <test/Options.h> -#include <libsolidity/interface/Exceptions.h> -#include <libsolidity/interface/EVMVersion.h> +#include <liblangutil/Exceptions.h> +#include <liblangutil/EVMVersion.h> #include <libevmasm/Assembly.h> @@ -8207,6 +8207,58 @@ BOOST_AUTO_TEST_CASE(inherited_function) { ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(1))); } +BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory) { + char const* sourceCode = R"( + contract A { function f(uint[] calldata a) external returns (uint) { return a[0]; } } + contract B is A { + function f(uint[] memory a) public returns (uint) { return a[1]; } + function g() public returns (uint) { + uint[] memory m = new uint[](2); + m[0] = 42; + m[1] = 23; + return A(this).f(m); + } + } + )"; + + compileAndRun(sourceCode, 0, "B"); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(23))); +} + +BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory_interface) { + char const* sourceCode = R"( + interface I { function f(uint[] calldata a) external returns (uint); } + contract A is I { function f(uint[] memory a) public returns (uint) { return 42; } } + contract B { + function f(uint[] memory a) public returns (uint) { return a[1]; } + function g() public returns (uint) { + I i = I(new A()); + return i.f(new uint[](2)); + } + } + )"; + + compileAndRun(sourceCode, 0, "B"); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(42))); +} + +BOOST_AUTO_TEST_CASE(inherited_function_calldata_calldata_interface) { + char const* sourceCode = R"( + interface I { function f(uint[] calldata a) external returns (uint); } + contract A is I { function f(uint[] calldata a) external returns (uint) { return 42; } } + contract B { + function f(uint[] memory a) public returns (uint) { return a[1]; } + function g() public returns (uint) { + I i = I(new A()); + return i.f(new uint[](2)); + } + } + )"; + + compileAndRun(sourceCode, 0, "B"); + ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(42))); +} + BOOST_AUTO_TEST_CASE(inherited_function_from_a_library) { char const* sourceCode = R"( library A { function f() internal returns (uint) { return 1; } } @@ -8658,6 +8710,90 @@ BOOST_AUTO_TEST_CASE(mapping_returns_in_library_named) ABI_CHECK(callContractFunction("g()"), encodeArgs(u256(0), u256(42), u256(0), u256(0), u256(21), u256(17))); } +BOOST_AUTO_TEST_CASE(using_library_mappings_public) +{ + char const* sourceCode = R"( + library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) public + { + m[key] = value; + } + } + contract Test { + mapping(uint => uint) m1; + mapping(uint => uint) m2; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.set(m1, 0, 1); + Lib.set(m1, 2, 42); + Lib.set(m2, 0, 23); + Lib.set(m2, 2, 99); + return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99))); +} + +BOOST_AUTO_TEST_CASE(using_library_mappings_external) +{ + char const* libSourceCode = R"( + library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) external + { + m[key] = value * 2; + } + } + )"; + char const* sourceCode = R"( + library Lib { + function set(mapping(uint => uint) storage m, uint key, uint value) external; + } + contract Test { + mapping(uint => uint) m1; + mapping(uint => uint) m2; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.set(m1, 0, 1); + Lib.set(m1, 2, 42); + Lib.set(m2, 0, 23); + Lib.set(m2, 2, 99); + return (m1[0], m1[1], m1[2], m2[0], m2[1], m2[2]); + } + } + )"; + compileAndRun(libSourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2), u256(0), u256(84), u256(46), u256(0), u256(198))); +} + +BOOST_AUTO_TEST_CASE(using_library_mappings_return) +{ + char const* sourceCode = R"( + library Lib { + function choose(mapping(uint => mapping(uint => uint)) storage m, uint key) external returns (mapping(uint => uint) storage) { + return m[key]; + } + } + contract Test { + mapping(uint => mapping(uint => uint)) m; + function f() public returns (uint, uint, uint, uint, uint, uint) + { + Lib.choose(m, 0)[0] = 1; + Lib.choose(m, 0)[2] = 42; + Lib.choose(m, 1)[0] = 23; + Lib.choose(m, 1)[2] = 99; + return (m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2]); + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99))); +} + BOOST_AUTO_TEST_CASE(using_library_structs) { char const* sourceCode = R"( @@ -9388,6 +9524,25 @@ BOOST_AUTO_TEST_CASE(using_for_by_name) ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(6 * 7))); } +BOOST_AUTO_TEST_CASE(bound_function_in_function) +{ + char const* sourceCode = R"( + library L { + function g(function() internal returns (uint) _t) internal returns (uint) { return _t(); } + } + contract C { + using L for *; + function f() public returns (uint) { + return t.g(); + } + function t() public pure returns (uint) { return 7; } + } + )"; + compileAndRun(sourceCode, 0, "L"); + compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); +} + BOOST_AUTO_TEST_CASE(bound_function_in_var) { char const* sourceCode = R"( @@ -14043,6 +14198,41 @@ BOOST_AUTO_TEST_CASE(flipping_sign_tests) ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } +BOOST_AUTO_TEST_CASE(external_public_override) +{ + char const* sourceCode = R"( + contract A { + function f() external returns (uint) { return 1; } + } + contract B is A { + function f() public returns (uint) { return 2; } + function g() public returns (uint) { return f(); } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); +} + +BOOST_AUTO_TEST_CASE(base_access_to_function_type_variables) +{ + char const* sourceCode = R"( + contract C { + function () internal returns (uint) x; + function set() public { + C.x = g; + } + function g() public pure returns (uint) { return 2; } + function h() public returns (uint) { return C.x(); } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("h()"), encodeArgs()); + ABI_CHECK(callContractFunction("set()"), encodeArgs()); + ABI_CHECK(callContractFunction("h()"), encodeArgs(2)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 12687dd1..cedbf51a 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -27,8 +27,8 @@ #include <test/ExecutionFramework.h> #include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/interface/Exceptions.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> +#include <liblangutil/Exceptions.h> +#include <liblangutil/SourceReferenceFormatter.h> namespace dev { @@ -72,13 +72,13 @@ public: m_compiler.setOptimiserSettings(m_optimize, m_optimizeRuns); if (!m_compiler.compile()) { - auto scannerFromSourceName = [&](std::string const& _sourceName) -> solidity::Scanner const& { return m_compiler.scanner(_sourceName); }; - SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); + auto scannerFromSourceName = [&](std::string const& _sourceName) -> langutil::Scanner const& { return m_compiler.scanner(_sourceName); }; + langutil::SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); for (auto const& error: m_compiler.errors()) formatter.printExceptionInformation( *error, - (error->type() == Error::Type::Warning) ? "Warning" : "Error" + (error->type() == langutil::Error::Type::Warning) ? "Warning" : "Error" ); BOOST_ERROR("Compiling contract failed"); } diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 309cbf0b..8bce26c1 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -22,17 +22,18 @@ #include <string> -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/Scanner.h> #include <libsolidity/parsing/Parser.h> #include <libsolidity/analysis/NameAndTypeResolver.h> #include <libsolidity/codegen/CompilerContext.h> #include <libsolidity/codegen/ExpressionCompiler.h> #include <libsolidity/ast/AST.h> #include <libsolidity/analysis/TypeChecker.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <liblangutil/ErrorReporter.h> #include <test/Options.h> using namespace std; +using namespace langutil; namespace dev { @@ -100,7 +101,7 @@ bytes compileFirstExpression( { ErrorList errors; ErrorReporter errorReporter(errors); - sourceUnit = Parser(errorReporter).parse(make_shared<Scanner>(CharStream(_sourceCode))); + sourceUnit = Parser(errorReporter).parse(make_shared<Scanner>(CharStream(_sourceCode, ""))); if (!sourceUnit) return bytes(); } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 5ec010c7..75726027 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -33,6 +33,7 @@ #include <string> using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index d77050cb..d930f697 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -24,9 +24,11 @@ #include <string> #include <libdevcore/JSON.h> #include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/interface/Exceptions.h> +#include <liblangutil/Exceptions.h> #include <libdevcore/Exceptions.h> +using namespace langutil; + namespace dev { namespace solidity diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 5432e9b5..d86d3d39 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -22,13 +22,14 @@ #include <string> #include <memory> -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/Scanner.h> #include <libsolidity/parsing/Parser.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <liblangutil/ErrorReporter.h> #include <test/Options.h> #include <test/libsolidity/ErrorCheck.h> using namespace std; +using namespace langutil; namespace dev { @@ -42,7 +43,7 @@ namespace ASTPointer<ContractDefinition> parseText(std::string const& _source, ErrorList& _errors) { ErrorReporter errorReporter(_errors); - ASTPointer<SourceUnit> sourceUnit = Parser(errorReporter).parse(std::make_shared<Scanner>(CharStream(_source))); + ASTPointer<SourceUnit> sourceUnit = Parser(errorReporter).parse(std::make_shared<Scanner>(CharStream(_source, ""))); if (!sourceUnit) return ASTPointer<ContractDefinition>(); for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 6965d886..5ce4eda2 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -20,10 +20,11 @@ * Unit tests for the solidity scanner. */ -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/Scanner.h> #include <boost/test/unit_test.hpp> using namespace std; +using namespace langutil; namespace dev { @@ -36,13 +37,13 @@ BOOST_AUTO_TEST_SUITE(SolidityScanner) BOOST_AUTO_TEST_CASE(test_empty) { - Scanner scanner(CharStream("")); + Scanner scanner(CharStream{}); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); } BOOST_AUTO_TEST_CASE(smoke_test) { - Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1")); + Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Function); BOOST_CHECK_EQUAL(scanner.next(), Token::Break); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon); @@ -60,7 +61,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(string_escapes) { - Scanner scanner(CharStream(" { \"a\\x61\"")); + Scanner scanner(CharStream(" { \"a\\x61\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "aa"); @@ -68,7 +69,7 @@ BOOST_AUTO_TEST_CASE(string_escapes) BOOST_AUTO_TEST_CASE(string_escapes_all) { - Scanner scanner(CharStream(" { \"a\\x61\\b\\f\\n\\r\\t\\v\"")); + Scanner scanner(CharStream(" { \"a\\x61\\b\\f\\n\\r\\t\\v\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "aa\b\f\n\r\t\v"); @@ -76,7 +77,7 @@ BOOST_AUTO_TEST_CASE(string_escapes_all) BOOST_AUTO_TEST_CASE(string_escapes_with_zero) { - Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"")); + Scanner scanner(CharStream(" { \"a\\x61\\x00abc\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("aa\0abc", 6)); @@ -84,9 +85,10 @@ BOOST_AUTO_TEST_CASE(string_escapes_with_zero) BOOST_AUTO_TEST_CASE(string_escape_illegal) { - Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); + Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalEscapeSequence); BOOST_CHECK_EQUAL(scanner.currentLiteral(), ""); // TODO recovery from illegal tokens should be improved BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); @@ -97,7 +99,7 @@ BOOST_AUTO_TEST_CASE(string_escape_illegal) BOOST_AUTO_TEST_CASE(hex_numbers) { - Scanner scanner(CharStream("var x = 0x765432536763762734623472346;")); + Scanner scanner(CharStream("var x = 0x765432536763762734623472346;", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Var); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Assign); @@ -105,34 +107,34 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x765432536763762734623472346"); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream("0x1234"), ""); + scanner.reset(CharStream("0x1234", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x1234"); - scanner.reset(CharStream("0X1234"), ""); + scanner.reset(CharStream("0X1234", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); } BOOST_AUTO_TEST_CASE(octal_numbers) { - Scanner scanner(CharStream("07")); + Scanner scanner(CharStream("07", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); - scanner.reset(CharStream("007"), ""); + scanner.reset(CharStream("007", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); - scanner.reset(CharStream("-07"), ""); + scanner.reset(CharStream("-07", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Sub); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); - scanner.reset(CharStream("-.07"), ""); + scanner.reset(CharStream("-.07", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Sub); BOOST_CHECK_EQUAL(scanner.next(), Token::Number); - scanner.reset(CharStream("0"), ""); + scanner.reset(CharStream("0", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); - scanner.reset(CharStream("0.1"), ""); + scanner.reset(CharStream("0.1", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); } BOOST_AUTO_TEST_CASE(scientific_notation) { - Scanner scanner(CharStream("var x = 2e10;")); + Scanner scanner(CharStream("var x = 2e10;", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Var); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Assign); @@ -144,19 +146,19 @@ BOOST_AUTO_TEST_CASE(scientific_notation) BOOST_AUTO_TEST_CASE(trailing_dot) { - Scanner scanner(CharStream("2.5")); + Scanner scanner(CharStream("2.5", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream("2.5e10"), ""); + scanner.reset(CharStream("2.5e10", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream(".5"), ""); + scanner.reset(CharStream(".5", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream(".5e10"), ""); + scanner.reset(CharStream(".5e10", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream("2."), ""); + scanner.reset(CharStream("2.", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::Period); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); @@ -165,7 +167,7 @@ BOOST_AUTO_TEST_CASE(trailing_dot) BOOST_AUTO_TEST_CASE(leading_underscore_decimal_is_identifier) { // Actual error is cought by SyntaxChecker. - Scanner scanner(CharStream("_1.2")); + Scanner scanner(CharStream("_1.2", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); @@ -174,11 +176,11 @@ BOOST_AUTO_TEST_CASE(leading_underscore_decimal_is_identifier) BOOST_AUTO_TEST_CASE(leading_underscore_decimal_after_dot_illegal) { // Actual error is cought by SyntaxChecker. - Scanner scanner(CharStream("1._2")); + Scanner scanner(CharStream("1._2", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream("1._"), ""); + scanner.reset(CharStream("1._", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -186,7 +188,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_decimal_after_dot_illegal) BOOST_AUTO_TEST_CASE(leading_underscore_exp_are_identifier) { // Actual error is cought by SyntaxChecker. - Scanner scanner(CharStream("_1e2")); + Scanner scanner(CharStream("_1e2", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -194,7 +196,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_exp_are_identifier) BOOST_AUTO_TEST_CASE(leading_underscore_exp_after_e_illegal) { // Actual error is cought by SyntaxChecker. - Scanner scanner(CharStream("1e_2")); + Scanner scanner(CharStream("1e_2", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "1e_2"); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); @@ -202,7 +204,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_exp_after_e_illegal) BOOST_AUTO_TEST_CASE(leading_underscore_hex_illegal) { - Scanner scanner(CharStream("0x_abc")); + Scanner scanner(CharStream("0x_abc", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); @@ -211,7 +213,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_hex_illegal) BOOST_AUTO_TEST_CASE(fixed_number_invalid_underscore_front) { // Actual error is cought by SyntaxChecker. - Scanner scanner(CharStream("12._1234_1234")); + Scanner scanner(CharStream("12._1234_1234", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -219,22 +221,22 @@ BOOST_AUTO_TEST_CASE(fixed_number_invalid_underscore_front) BOOST_AUTO_TEST_CASE(number_literals_with_trailing_underscore_at_eos) { // Actual error is cought by SyntaxChecker. - Scanner scanner(CharStream("0x123_")); + Scanner scanner(CharStream("0x123_", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream("123_"), ""); + scanner.reset(CharStream("123_", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); - scanner.reset(CharStream("12.34_"), ""); + scanner.reset(CharStream("12.34_", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(negative_numbers) { - Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9 + 2e-2;")); + Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9 + 2e-2;", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Var); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Assign); @@ -261,7 +263,7 @@ BOOST_AUTO_TEST_CASE(negative_numbers) BOOST_AUTO_TEST_CASE(locations) { - Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); + Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLocation().start, 0); BOOST_CHECK_EQUAL(scanner.currentLocation().end, 19); @@ -284,7 +286,7 @@ BOOST_AUTO_TEST_CASE(locations) BOOST_AUTO_TEST_CASE(ambiguities) { // test scanning of some operators which need look-ahead - Scanner scanner(CharStream("<=" "<" "+ +=a++ =>" "<<" ">>" " >>=" ">>>" ">>>=" " >>>>>=><<=")); + Scanner scanner(CharStream("<=" "<" "+ +=a++ =>" "<<" ">>" " >>=" ">>>" ">>>=" " >>>>>=><<=", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LessThanOrEqual); BOOST_CHECK_EQUAL(scanner.next(), Token::LessThan); BOOST_CHECK_EQUAL(scanner.next(), Token::Add); @@ -306,21 +308,21 @@ BOOST_AUTO_TEST_CASE(ambiguities) BOOST_AUTO_TEST_CASE(documentation_comments_parsed_begin) { - Scanner scanner(CharStream("/// Send $(value / 1000) chocolates to the user")); + Scanner scanner(CharStream("/// Send $(value / 1000) chocolates to the user", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); } BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed_begin) { - Scanner scanner(CharStream("/** Send $(value / 1000) chocolates to the user*/")); + Scanner scanner(CharStream("/** Send $(value / 1000) chocolates to the user*/", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "Send $(value / 1000) chocolates to the user"); } BOOST_AUTO_TEST_CASE(documentation_comments_parsed) { - Scanner scanner(CharStream("some other tokens /// Send $(value / 1000) chocolates to the user")); + Scanner scanner(CharStream("some other tokens /// Send $(value / 1000) chocolates to the user", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); @@ -332,7 +334,7 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_comments_parsed) { Scanner scanner(CharStream("some other tokens /**\n" "* Send $(value / 1000) chocolates to the user\n" - "*/")); + "*/", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); @@ -344,7 +346,7 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_no_stars) { Scanner scanner(CharStream("some other tokens /**\n" " Send $(value / 1000) chocolates to the user\n" - "*/")); + "*/", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); @@ -356,7 +358,7 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_whitespace_hell) { Scanner scanner(CharStream("some other tokens /** \t \r \n" "\t \r * Send $(value / 1000) chocolates to the user\n" - "*/")); + "*/", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); @@ -366,28 +368,28 @@ BOOST_AUTO_TEST_CASE(multiline_documentation_whitespace_hell) BOOST_AUTO_TEST_CASE(comment_before_eos) { - Scanner scanner(CharStream("//")); + Scanner scanner(CharStream("//", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); } BOOST_AUTO_TEST_CASE(documentation_comment_before_eos) { - Scanner scanner(CharStream("///")); + Scanner scanner(CharStream("///", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); } BOOST_AUTO_TEST_CASE(empty_multiline_comment) { - Scanner scanner(CharStream("/**/")); + Scanner scanner(CharStream("/**/", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); } BOOST_AUTO_TEST_CASE(empty_multiline_documentation_comment_before_eos) { - Scanner scanner(CharStream("/***/")); + Scanner scanner(CharStream("/***/", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::EOS); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); } @@ -396,7 +398,7 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence) { Scanner scanner(CharStream("hello_world ///documentation comment \n" "//simple comment \n" - "<<")); + "<<", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::SHL); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "documentation comment "); @@ -404,7 +406,7 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence) BOOST_AUTO_TEST_CASE(ether_subdenominations) { - Scanner scanner(CharStream("wei szabo finney ether")); + Scanner scanner(CharStream("wei szabo finney ether", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::SubWei); BOOST_CHECK_EQUAL(scanner.next(), Token::SubSzabo); BOOST_CHECK_EQUAL(scanner.next(), Token::SubFinney); @@ -413,7 +415,7 @@ BOOST_AUTO_TEST_CASE(ether_subdenominations) BOOST_AUTO_TEST_CASE(time_subdenominations) { - Scanner scanner(CharStream("seconds minutes hours days weeks years")); + Scanner scanner(CharStream("seconds minutes hours days weeks years", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::SubSecond); BOOST_CHECK_EQUAL(scanner.next(), Token::SubMinute); BOOST_CHECK_EQUAL(scanner.next(), Token::SubHour); @@ -424,7 +426,7 @@ BOOST_AUTO_TEST_CASE(time_subdenominations) BOOST_AUTO_TEST_CASE(empty_comment) { - Scanner scanner(CharStream("//\ncontract{}")); + Scanner scanner(CharStream("//\ncontract{}", "")); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Contract); BOOST_CHECK_EQUAL(scanner.next(), Token::LBrace); @@ -434,7 +436,7 @@ BOOST_AUTO_TEST_CASE(empty_comment) BOOST_AUTO_TEST_CASE(valid_unicode_string_escape) { - Scanner scanner(CharStream("{ \"\\u00DAnicode\"")); + Scanner scanner(CharStream("{ \"\\u00DAnicode\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\xC3\x9Anicode", 8)); @@ -442,7 +444,7 @@ BOOST_AUTO_TEST_CASE(valid_unicode_string_escape) BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_7f) { - Scanner scanner(CharStream("{ \"\\u007Fnicode\"")); + Scanner scanner(CharStream("{ \"\\u007Fnicode\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\x7Fnicode", 7)); @@ -450,7 +452,7 @@ BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_7f) BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_7ff) { - Scanner scanner(CharStream("{ \"\\u07FFnicode\"")); + Scanner scanner(CharStream("{ \"\\u07FFnicode\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\xDF\xBFnicode", 8)); @@ -458,7 +460,7 @@ BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_7ff) BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_ffff) { - Scanner scanner(CharStream("{ \"\\uFFFFnicode\"")); + Scanner scanner(CharStream("{ \"\\uFFFFnicode\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\xEF\xBF\xBFnicode", 9)); @@ -466,7 +468,7 @@ BOOST_AUTO_TEST_CASE(valid_unicode_string_escape_ffff) BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape) { - Scanner scanner(CharStream("{ \"\\uFFnicode\"")); + Scanner scanner(CharStream("{ \"\\uFFnicode\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); } @@ -475,7 +477,7 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape) BOOST_AUTO_TEST_CASE(valid_hex_literal) { - Scanner scanner(CharStream("{ hex\"00112233FF\"")); + Scanner scanner(CharStream("{ hex\"00112233FF\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); BOOST_CHECK_EQUAL(scanner.next(), Token::StringLiteral); BOOST_CHECK_EQUAL(scanner.currentLiteral(), std::string("\x00\x11\x22\x33\xFF", 5)); @@ -483,30 +485,34 @@ BOOST_AUTO_TEST_CASE(valid_hex_literal) BOOST_AUTO_TEST_CASE(invalid_short_hex_literal) { - Scanner scanner(CharStream("{ hex\"00112233F\"")); + Scanner scanner(CharStream("{ hex\"00112233F\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space) { - Scanner scanner(CharStream("{ hex\"00112233FF \"")); + Scanner scanner(CharStream("{ hex\"00112233FF \"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes) { - Scanner scanner(CharStream("{ hex\"00112233FF'")); + Scanner scanner(CharStream("{ hex\"00112233FF'", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string) { - Scanner scanner(CharStream("{ hex\"hello\"")); + Scanner scanner(CharStream("{ hex\"hello\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); } // COMMENTS @@ -514,7 +520,7 @@ BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string) BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) { // This used to parse as "comment", "identifier" - Scanner scanner(CharStream("/** / x")); + Scanner scanner(CharStream("/** / x", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -522,14 +528,14 @@ BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) BOOST_AUTO_TEST_CASE(multiline_doc_comment_at_eos) { // This used to parse as "whitespace" - Scanner scanner(CharStream("/**")); + Scanner scanner(CharStream("/**", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(multiline_comment_at_eos) { - Scanner scanner(CharStream("/*")); + Scanner scanner(CharStream("/*", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -538,7 +544,7 @@ BOOST_AUTO_TEST_CASE(regular_line_break_in_single_line_comment) { for (auto const& nl: {"\r", "\n"}) { - Scanner scanner(CharStream("// abc " + string(nl) + " def ")); + Scanner scanner(CharStream("// abc " + string(nl) + " def ", "")); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); @@ -550,7 +556,7 @@ BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_comment) { for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"}) { - Scanner scanner(CharStream("// abc " + string(nl) + " def ")); + Scanner scanner(CharStream("// abc " + string(nl) + " def ", "")); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); for (size_t i = 0; i < string(nl).size() - 1; i++) @@ -565,7 +571,7 @@ BOOST_AUTO_TEST_CASE(regular_line_breaks_in_single_line_doc_comment) { for (auto const& nl: {"\r", "\n"}) { - Scanner scanner(CharStream("/// abc " + string(nl) + " def ")); + Scanner scanner(CharStream("/// abc " + string(nl) + " def ", "")); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "abc "); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); @@ -577,7 +583,7 @@ BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_single_line_doc_comment) { for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"}) { - Scanner scanner(CharStream("/// abc " + string(nl) + " def ")); + Scanner scanner(CharStream("/// abc " + string(nl) + " def ", "")); BOOST_CHECK_EQUAL(scanner.currentCommentLiteral(), "abc "); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); for (size_t i = 0; i < string(nl).size() - 1; i++) @@ -592,7 +598,7 @@ BOOST_AUTO_TEST_CASE(regular_line_breaks_in_strings) { for (auto const& nl: {"\n", "\r"}) { - Scanner scanner(CharStream("\"abc " + string(nl) + " def\"")); + Scanner scanner(CharStream("\"abc " + string(nl) + " def\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); @@ -605,7 +611,7 @@ BOOST_AUTO_TEST_CASE(irregular_line_breaks_in_strings) { for (auto const& nl: {"\v", "\f", "\xE2\x80\xA8", "\xE2\x80\xA9"}) { - Scanner scanner(CharStream("\"abc " + string(nl) + " def\"")); + Scanner scanner(CharStream("\"abc " + string(nl) + " def\"", "")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); for (size_t i = 0; i < string(nl).size(); i++) BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 6f9d4ce8..c839afd4 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -26,6 +26,7 @@ #include <boost/test/unit_test.hpp> using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 91d1681f..c47ea599 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -25,6 +25,7 @@ #include <stdexcept> using namespace dev; +using namespace langutil; using namespace solidity; using namespace dev::solidity::test; using namespace dev::solidity::test::formatting; @@ -91,6 +92,11 @@ bool SyntaxTest::run(ostream& _stream, string const& _linePrefix, bool const _fo }); } + return printExpectationAndError(_stream, _linePrefix, _formatted); +} + +bool SyntaxTest::printExpectationAndError(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ if (m_expectations != m_errorList) { string nextIndentLevel = _linePrefix + " "; diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index e9e36aa6..12c14087 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -19,8 +19,8 @@ #include <test/libsolidity/AnalysisFramework.h> #include <test/libsolidity/FormattedScope.h> -#include <test/libsolidity/TestCase.h> -#include <libsolidity/interface/Exceptions.h> +#include <test/TestCase.h> +#include <liblangutil/Exceptions.h> #include <iosfwd> #include <string> @@ -57,17 +57,17 @@ public: { return std::unique_ptr<TestCase>(new SyntaxTest(_filename)); } SyntaxTest(std::string const& _filename); - virtual bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; - virtual void printSource(std::ostream &_stream, std::string const &_linePrefix = "", bool const _formatted = false) const override; - virtual void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override + void printSource(std::ostream &_stream, std::string const &_linePrefix = "", bool const _formatted = false) const override; + void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override { if (!m_errorList.empty()) printErrorList(_stream, m_errorList, _linePrefix, false); } static std::string errorMessage(Exception const& _e); -private: +protected: static void printErrorList( std::ostream& _stream, std::vector<SyntaxTestError> const& _errors, @@ -75,6 +75,8 @@ private: bool const _formatted = false ); + virtual bool printExpectationAndError(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false); + static std::vector<SyntaxTestError> parseExpectations(std::istream& _stream); std::string m_source; diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index b7ea1efc..64e52604 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -28,6 +28,7 @@ #include <tuple> using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/smtCheckerTests/complex/warn_on_struct.sol b/test/libsolidity/smtCheckerTests/complex/warn_on_struct.sol new file mode 100644 index 00000000..6d9afe7c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/complex/warn_on_struct.sol @@ -0,0 +1,14 @@ +pragma experimental SMTChecker; + +contract C { + struct A { uint a; uint b; } + function f() public pure returns (uint) { + A memory a = A({ a: 1, b: 2 }); + } +} +// ---- +// Warning: (133-143): Unused local variable. +// Warning: (133-143): Assertion checker does not yet support the type of this variable. +// Warning: (146-163): Assertion checker does not yet implement this expression. +// Warning: (146-163): Internal error: Expression undefined for SMT solver. +// Warning: (146-163): Assertion checker does not yet implement this type. diff --git a/test/libsolidity/smtCheckerTests/complex/warn_on_typecast.sol b/test/libsolidity/smtCheckerTests/complex/warn_on_typecast.sol new file mode 100644 index 00000000..be785414 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/complex/warn_on_typecast.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f() public pure returns (uint) { + return uint8(1); + } +} +// ---- +// Warning: (106-114): Assertion checker does not yet implement this expression. diff --git a/test/libsolidity/smtCheckerTests/control_flow/assignment_in_declaration.sol b/test/libsolidity/smtCheckerTests/control_flow/assignment_in_declaration.sol new file mode 100644 index 00000000..0c701672 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/assignment_in_declaration.sol @@ -0,0 +1,4 @@ +pragma experimental SMTChecker; +contract C { + function f() public pure { uint a = 2; assert(a == 2); } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_1.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_1.sol new file mode 100644 index 00000000..64f6e012 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_1.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + if (x > 10) { + assert(x > 9); + } + else + { + assert(x < 11); + } + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_2.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_2.sol new file mode 100644 index 00000000..e39ab844 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_2.sol @@ -0,0 +1,16 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + if (x > 10) { + assert(x > 9); + } + else if (x > 2) + { + assert(x <= 10 && x > 2); + } + else + { + assert(0 <= x && x <= 2); + } + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_1.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_1.sol new file mode 100644 index 00000000..f93e32e4 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_1.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +// Branch does not touch variable a +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + } + assert(a == 3); + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_2.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_2.sol new file mode 100644 index 00000000..c00ef787 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_2.sol @@ -0,0 +1,11 @@ +pragma experimental SMTChecker; +// Positive branch touches variable a, but assertion should still hold. +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + a = 3; + } + assert(a == 3); + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_3.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_3.sol new file mode 100644 index 00000000..4e18aa88 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_3.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +// Negative branch touches variable a, but assertion should still hold. +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + } else { + a = 3; + } + assert(a == 3); + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_4.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_4.sol new file mode 100644 index 00000000..e3a02704 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_4.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +// Variable is not merged, if it is only read. +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + assert(a == 3); + } else { + assert(a == 3); + } + assert(a == 3); + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_5.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_5.sol new file mode 100644 index 00000000..0bd1cf3a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_5.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +// Variable is reset in both branches +contract C { + function f(uint x) public pure { + uint a = 2; + if (x > 10) { + a = 3; + } else { + a = 3; + } + assert(a == 3); + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_6.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_6.sol new file mode 100644 index 00000000..8e477179 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_6.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +// Variable is reset in both branches +contract C { + function f(uint x) public pure { + uint a = 2; + if (x > 10) { + a = 3; + } else { + a = 4; + } + assert(a >= 3); + } +} diff --git a/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_1.sol b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_1.sol new file mode 100644 index 00000000..16d6fdfe --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_1.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + a++; + } + assert(a == 3); + } +} +// ---- +// Warning: (159-173): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_2.sol b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_2.sol new file mode 100644 index 00000000..e25ab20f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_2.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + ++a; + } + assert(a == 3); + } +} +// ---- +// Warning: (159-173): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_3.sol b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_3.sol new file mode 100644 index 00000000..03ae7216 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_3.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + uint a = 3; + if (x > 10) { + a = 5; + } + assert(a == 3); + } +} +// ---- +// Warning: (161-175): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/function_call_does_not_clear_local_vars.sol b/test/libsolidity/smtCheckerTests/functions/function_call_does_not_clear_local_vars.sol new file mode 100644 index 00000000..b4260224 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/function_call_does_not_clear_local_vars.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +contract C { + function f() public { + uint a = 3; + this.f(); + assert(a == 3); + f(); + assert(a == 3); + } +} +// ---- +// Warning: (99-107): Assertion checker does not yet implement this type of function call. +// Warning: (141-144): Assertion checker does not support recursive function calls. diff --git a/test/libsolidity/smtCheckerTests/functions/functions_bound_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_bound_1.sol new file mode 100644 index 00000000..5e9722de --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_bound_1.sol @@ -0,0 +1,19 @@ +pragma experimental SMTChecker; + +library L +{ + function add(uint x, uint y) internal pure returns (uint) { + require(x < 1000); + require(y < 1000); + return x + y; + } +} + +contract C +{ + using L for uint; + function f(uint x) public pure { + uint y = x.add(999); + assert(y < 10000); + } +} diff --git a/test/libsolidity/smtCheckerTests/functions/functions_bound_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_bound_1_fail.sol new file mode 100644 index 00000000..99c785d0 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_bound_1_fail.sol @@ -0,0 +1,21 @@ +pragma experimental SMTChecker; + +library L +{ + function add(uint x, uint y) internal pure returns (uint) { + require(x < 1000); + require(y < 1000); + return x + y; + } +} + +contract C +{ + using L for uint; + function f(uint x) public pure { + uint y = x.add(999); + assert(y < 1000); + } +} +// ---- +// Warning: (261-277): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/functions/functions_library_1.sol b/test/libsolidity/smtCheckerTests/functions/functions_library_1.sol new file mode 100644 index 00000000..2ceb9e60 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_library_1.sol @@ -0,0 +1,18 @@ +pragma experimental SMTChecker; + +library L +{ + function add(uint x, uint y) internal pure returns (uint) { + require(x < 1000); + require(y < 1000); + return x + y; + } +} + +contract C +{ + function f(uint x) public pure { + uint y = L.add(x, 999); + assert(y < 10000); + } +} diff --git a/test/libsolidity/smtCheckerTests/functions/functions_library_1_fail.sol b/test/libsolidity/smtCheckerTests/functions/functions_library_1_fail.sol new file mode 100644 index 00000000..32419700 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/functions/functions_library_1_fail.sol @@ -0,0 +1,20 @@ +pragma experimental SMTChecker; + +library L +{ + function add(uint x, uint y) internal pure returns (uint) { + require(x < 1000); + require(y < 1000); + return x + y; + } +} + +contract C +{ + function f(uint x) public pure { + uint y = L.add(x, 999); + assert(y < 1000); + } +} +// ---- +// Warning: (245-261): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_1.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_1.sol new file mode 100644 index 00000000..8988efad --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_1.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + require(x == 2); + for (;;) {} + assert(x == 2); + } +} diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_2.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_2.sol new file mode 100644 index 00000000..58c9f3a7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_2.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + for (; x == 2; ) { + assert(x == 2); + } + } +} diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_3.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_3.sol new file mode 100644 index 00000000..8bf9bdc7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_3.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + for (uint y = 2; x < 10; ) { + assert(y == 2); + } + } +} diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_4.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_4.sol new file mode 100644 index 00000000..4d082026 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_4.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + for (uint y = 2; x < 10; y = 3) { + assert(y == 2); + } + } +} +// ---- +// Warning: (136-150): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol new file mode 100644 index 00000000..2c84960f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + uint y; + for (y = 2; x < 10; ) { + y = 3; + } + assert(y == 3); + } +} +// ---- +// Warning: (167-181): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). diff --git a/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol new file mode 100644 index 00000000..90c4c328 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + uint y; + for (y = 2; x < 10; ) { + y = 3; + } + assert(y == 2); + } +} +// ---- +// Warning: (167-181): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol new file mode 100644 index 00000000..074be86f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; +// Check that variables are cleared +contract C { + function f(uint x) public pure { + x = 2; + while (x > 1) { + x = 2; + } + assert(x == 2); + } +} +// ---- +// Warning: (194-208): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_2.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_2.sol new file mode 100644 index 00000000..92a3f0fe --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_2.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +// Check that condition is assumed. +contract C { + function f(uint x) public pure { + while (x == 2) { + assert(x == 2); + } + } +} diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol new file mode 100644 index 00000000..a37df888 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol @@ -0,0 +1,11 @@ +pragma experimental SMTChecker; +// Check that condition is not assumed after the body anymore +contract C { + function f(uint x) public pure { + while (x == 2) { + } + assert(x == 2); + } +} +// ---- +// Warning: (187-201): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol new file mode 100644 index 00000000..f71da865 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol @@ -0,0 +1,11 @@ +pragma experimental SMTChecker; +// Check that negation of condition is not assumed after the body anymore +contract C { + function f(uint x) public pure { + while (x == 2) { + } + assert(x != 2); + } +} +// ---- +// Warning: (199-213): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). diff --git a/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol new file mode 100644 index 00000000..41559c99 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +// Check that side-effects of condition are taken into account +contract C { + function f(uint x, uint y) public pure { + x = 7; + while ((x = y) > 0) { + } + assert(x == 7); + } +} +// ---- +// Warning: (216-230): Assertion violation happens here\nNote that some information is erased after the execution of loops.\nYou can re-introduce information using require(). diff --git a/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol b/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol new file mode 100644 index 00000000..894ff1a4 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol @@ -0,0 +1,6 @@ +pragma experimental SMTChecker; +contract C { + function f(uint a, uint b) public pure returns (uint) { return a + b; } +} +// ---- +// Warning: (112-117): Overflow (resulting value larger than 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) happens here diff --git a/test/libsolidity/smtCheckerTests/simple/smoke_test.sol b/test/libsolidity/smtCheckerTests/simple/smoke_test.sol new file mode 100644 index 00000000..8b7b77da --- /dev/null +++ b/test/libsolidity/smtCheckerTests/simple/smoke_test.sol @@ -0,0 +1,3 @@ +pragma experimental SMTChecker; +contract C { +} diff --git a/test/libsolidity/smtCheckerTests/special/blockhash.sol b/test/libsolidity/smtCheckerTests/special/blockhash.sol index 1c693914..59a52922 100644 --- a/test/libsolidity/smtCheckerTests/special/blockhash.sol +++ b/test/libsolidity/smtCheckerTests/special/blockhash.sol @@ -2,9 +2,13 @@ pragma experimental SMTChecker; contract C { - function f() public payable { + function f(uint x) public payable { + assert(blockhash(x) > 0); assert(blockhash(2) > 0); + uint y = x; + assert(blockhash(x) == blockhash(y)); } } // ---- -// Warning: (79-103): Assertion violation happens here +// Warning: (85-109): Assertion violation happens here +// Warning: (113-137): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/bool_int_mixed_1.sol b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_1.sol new file mode 100644 index 00000000..d611cc17 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_1.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x) public pure { + uint a; + if(x) + a = 1; + assert(!x || a > 0); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/bool_int_mixed_2.sol b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_2.sol new file mode 100644 index 00000000..24640c5a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_2.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x, uint a) public pure { + require(!x || a > 0); + uint b = a; + assert(!x || b > 0); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/bool_int_mixed_3.sol b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_3.sol new file mode 100644 index 00000000..f872e82f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_3.sol @@ -0,0 +1,21 @@ +pragma experimental SMTChecker; +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); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_1.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_1.sol new file mode 100644 index 00000000..76b4b08b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_1.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x) public pure { + assert(x); + } +} +// ---- +// Warning: (90-99): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol new file mode 100644 index 00000000..5c166c02 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x, bool y) public pure { + assert(x == y); + } +} +// ---- +// Warning: (98-112): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_3.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_3.sol new file mode 100644 index 00000000..1d2ab49f --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_3.sol @@ -0,0 +1,7 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x, bool y) public pure { + bool z = x || y; + assert(!(x && y) || z); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_4.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_4.sol new file mode 100644 index 00000000..c40404a4 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_4.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x) public pure { + if(x) { + assert(x); + } else { + assert(!x); + } + } +} diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_5.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_5.sol new file mode 100644 index 00000000..4cecebbc --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_5.sol @@ -0,0 +1,7 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x) public pure { + bool y = x; + assert(x == y); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/bool_simple_6.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_6.sol new file mode 100644 index 00000000..90350bb6 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/bool_simple_6.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +contract C { + function f(bool x) public pure { + require(x); + bool y; + y = false; + assert(x || y); + } +} diff --git a/test/libsolidity/smtCheckerTests/types/storage_value_vars_1.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_1.sol new file mode 100644 index 00000000..84f6c77e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/storage_value_vars_1.sol @@ -0,0 +1,22 @@ +pragma experimental SMTChecker; +contract C +{ + address a; + bool b; + uint c; + function f(uint x) public { + if (x == 0) + { + a = 0x0000000000000000000000000000000000000100; + b = true; + } + else + { + a = 0x0000000000000000000000000000000000000200; + b = false; + } + assert(a > 0x0000000000000000000000000000000000000000 && b); + } +} +// ---- +// Warning: (362-421): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/storage_value_vars_2.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_2.sol new file mode 100644 index 00000000..bceddb38 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/storage_value_vars_2.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C +{ + address a; + bool b; + uint c; + function f() public view { + assert(c > 0); + } +} +// ---- +// Warning: (123-136): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/types/storage_value_vars_3.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_3.sol new file mode 100644 index 00000000..39049b99 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/storage_value_vars_3.sol @@ -0,0 +1,25 @@ +pragma experimental SMTChecker; +contract C +{ + function f(uint x) public { + if (x == 0) + { + a = 0x0000000000000000000000000000000000000100; + b = true; + } + else + { + a = 0x0000000000000000000000000000000000000200; + b = false; + } + assert(b == (a < 0x0000000000000000000000000000000000000200)); + } + + function g() public view { + require(a < 0x0000000000000000000000000000000000000100); + assert(c >= 0); + } + address a; + bool b; + uint c; +} diff --git a/test/libsolidity/smtCheckerTests/types/storage_value_vars_4.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_4.sol new file mode 100644 index 00000000..88b6b0ae --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/storage_value_vars_4.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +contract C +{ + function f() public view { + assert(c > 0); + } + uint c; +} +// ---- +// Warning: (84-97): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/verification_target/constant_condition_1.sol b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_1.sol new file mode 100644 index 00000000..b9fae4ee --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_1.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + if (x >= 0) { revert(); } + } +} +// ---- +// Warning: (94-100): Condition is always true. +// Warning: (104-112): Assertion checker does not yet implement this type of function call. diff --git a/test/libsolidity/smtCheckerTests/verification_target/constant_condition_2.sol b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_2.sol new file mode 100644 index 00000000..aaa613ea --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_2.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +contract C { + function f(uint x) public pure { + if (x >= 10) { if (x < 10) { revert(); } } + } +} +// ---- +// Warning: (109-115): Condition is always false. +// Warning: (119-127): Assertion checker does not yet implement this type of function call. diff --git a/test/libsolidity/smtCheckerTests/verification_target/constant_condition_3.sol b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_3.sol new file mode 100644 index 00000000..f22cd65e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_3.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +// a plain literal constant is fine +contract C { + function f(uint) public pure { + if (true) { revert(); } + } +} +// ---- +// Warning: (136-144): Assertion checker does not yet implement this type of function call. diff --git a/test/libsolidity/smtCheckerTests/verification_target/simple_assert.sol b/test/libsolidity/smtCheckerTests/verification_target/simple_assert.sol new file mode 100644 index 00000000..8bd6e61a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/simple_assert.sol @@ -0,0 +1,6 @@ +pragma experimental SMTChecker; +contract C { + function f(uint a) public pure { assert(a == 2); } +} +// ---- +// Warning: (82-96): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/verification_target/simple_assert_with_require.sol b/test/libsolidity/smtCheckerTests/verification_target/simple_assert_with_require.sol new file mode 100644 index 00000000..b66ae245 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/verification_target/simple_assert_with_require.sol @@ -0,0 +1,4 @@ +pragma experimental SMTChecker; +contract C { + function f(uint a) public pure { require(a < 10); assert(a < 20); } +} diff --git a/test/libsolidity/smtCheckerTestsJSON/multi.json b/test/libsolidity/smtCheckerTestsJSON/multi.json new file mode 100644 index 00000000..2ed5150d --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/multi.json @@ -0,0 +1,11 @@ +{ + "auxiliaryInput": + { + "smtlib2responses": + { + "0x0426cd198d1e7123a28ffac2b759a666b86508ad046babf5166500dd6d8ed308": "unsat\n(error \"line 31 column 26: model is not available\")", + "0xa51ca41ae407f5a727f27101cbc079834743cc8955f9f585582034ca634953f6": "sat\n((|EVALEXPR_0| 1))", + "0xe9477f683ff20aa57fcb08682150f86c5917e1d4c0686b278ab9b73446d0682c": "sat\n((|EVALEXPR_0| 0))" + } + } +} diff --git a/test/libsolidity/smtCheckerTestsJSON/multi.sol b/test/libsolidity/smtCheckerTestsJSON/multi.sol new file mode 100644 index 00000000..e0d69b1d --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/multi.sol @@ -0,0 +1,13 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + assert(x > 0); + assert(x > 100); + assert(x >= 0); + } +} +// ---- +// Warning: (82-95): Assertion violation happens here +// Warning: (99-114): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTestsJSON/simple.json b/test/libsolidity/smtCheckerTestsJSON/simple.json new file mode 100644 index 00000000..fd976b63 --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/simple.json @@ -0,0 +1,9 @@ +{ + "auxiliaryInput": + { + "smtlib2responses": + { + "0xe9477f683ff20aa57fcb08682150f86c5917e1d4c0686b278ab9b73446d0682c": "sat\n((|EVALEXPR_0| 0))" + } + } +} diff --git a/test/libsolidity/smtCheckerTestsJSON/simple.sol b/test/libsolidity/smtCheckerTestsJSON/simple.sol new file mode 100644 index 00000000..6bc7193d --- /dev/null +++ b/test/libsolidity/smtCheckerTestsJSON/simple.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; + +contract C +{ + function f(uint x) public pure { + assert(x > 0); + } +} +// ---- +// Warning: (82-95): Assertion violation happens here diff --git a/test/libsolidity/syntaxTests/bound/bound_all.sol b/test/libsolidity/syntaxTests/bound/bound_all.sol new file mode 100644 index 00000000..29f55b88 --- /dev/null +++ b/test/libsolidity/syntaxTests/bound/bound_all.sol @@ -0,0 +1,10 @@ +library L { + function g(function() internal returns (uint) _t) internal returns (uint) { return _t(); } +} +contract C { + using L for *; + function f() public returns (uint) { + return t.g(); + } + function t() public pure returns (uint) { return 7; } +} diff --git a/test/libsolidity/syntaxTests/bound/bound_call.sol b/test/libsolidity/syntaxTests/bound/bound_call.sol new file mode 100644 index 00000000..281f19b4 --- /dev/null +++ b/test/libsolidity/syntaxTests/bound/bound_call.sol @@ -0,0 +1,7 @@ +library D { function double(uint self) internal pure returns (uint) { return 2*self; } } +contract C { + using D for uint; + function f(uint a) public pure { + a.double(); + } +} diff --git a/test/libsolidity/syntaxTests/bound/bound_no_call.sol b/test/libsolidity/syntaxTests/bound/bound_no_call.sol new file mode 100644 index 00000000..dcb3c3c5 --- /dev/null +++ b/test/libsolidity/syntaxTests/bound/bound_no_call.sol @@ -0,0 +1,7 @@ +library D { function double(uint self) public pure returns (uint) { return 2*self; } } +contract C { + using D for uint; + function f(uint a) public pure { + a.double; + } +} diff --git a/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol b/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol new file mode 100644 index 00000000..2e6aeaa5 --- /dev/null +++ b/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol @@ -0,0 +1,15 @@ +// This used to cause an internal error because of the visitation order. +contract Test { + function createChild() public { + Child asset = new Child(); + } +} + +contract Parent { + constructor(address _address) public {} +} + +contract Child is Parent { +} +// ---- +// TypeError: (146-155): Trying to create an instance of an abstract contract. diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/deprecated_functions.sol index 62dfcff9..c5764e96 100644 --- a/test/libsolidity/syntaxTests/deprecated_functions.sol +++ b/test/libsolidity/syntaxTests/deprecated_functions.sol @@ -8,5 +8,5 @@ contract test { } } // ---- -// TypeError: (58-66): "sha3" has been deprecated in favour of "keccak256" -// TypeError: (101-152): "suicide" has been deprecated in favour of "selfdestruct" +// TypeError: (58-62): "sha3" has been deprecated in favour of "keccak256" +// TypeError: (101-108): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_struct.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_struct.sol new file mode 100644 index 00000000..a367996e --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_struct.sol @@ -0,0 +1,8 @@ +library L +{ + struct Nested + { + uint y; + } + function f(function(Nested memory) external) external pure {} +} diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_struct_undefined_member.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_struct_undefined_member.sol new file mode 100644 index 00000000..ca08afe5 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_struct_undefined_member.sol @@ -0,0 +1,11 @@ +library L +{ + struct Nested + { + Non y; + } + function f(function(Nested memory) external) external pure {} +} +// ---- +// DeclarationError: (32-35): Identifier not found or not unique. +// TypeError: (63-76): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/getter/complex_struct.sol b/test/libsolidity/syntaxTests/getter/complex_struct.sol new file mode 100644 index 00000000..3fa8111c --- /dev/null +++ b/test/libsolidity/syntaxTests/getter/complex_struct.sol @@ -0,0 +1,7 @@ +contract C { + struct Y { + uint a; + uint b; + } + mapping(uint256 => Y) public m; +} diff --git a/test/libsolidity/syntaxTests/getter/nested_structs.sol b/test/libsolidity/syntaxTests/getter/nested_structs.sol new file mode 100644 index 00000000..1068f287 --- /dev/null +++ b/test/libsolidity/syntaxTests/getter/nested_structs.sol @@ -0,0 +1,11 @@ +contract C { + struct Y { + uint b; + } + struct X { + Y a; + } + mapping(uint256 => X) public m; +} +// ---- +// TypeError: (88-118): The following types are only supported for getters in the new experimental ABI encoder: struct C.Y memory. Either remove "public" or use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/getter/recursive_struct.sol b/test/libsolidity/syntaxTests/getter/recursive_struct.sol new file mode 100644 index 00000000..d81cac60 --- /dev/null +++ b/test/libsolidity/syntaxTests/getter/recursive_struct.sol @@ -0,0 +1,8 @@ +contract C { + struct Y { + Y[] x; + } + mapping(uint256 => Y) public m; +} +// ---- +// TypeError: (53-83): Internal or recursive type is not allowed for public state variables. diff --git a/test/libsolidity/syntaxTests/getter/simple_struct.sol b/test/libsolidity/syntaxTests/getter/simple_struct.sol new file mode 100644 index 00000000..c7a23ae9 --- /dev/null +++ b/test/libsolidity/syntaxTests/getter/simple_struct.sol @@ -0,0 +1,6 @@ +contract C { + struct Y { + uint b; + } + mapping(uint256 => Y) public m; +} diff --git a/test/libsolidity/syntaxTests/globalFunctions/sha3_no_call.sol b/test/libsolidity/syntaxTests/globalFunctions/sha3_no_call.sol new file mode 100644 index 00000000..37b60e5e --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/sha3_no_call.sol @@ -0,0 +1,8 @@ +contract C +{ + function f(bytes memory data) public pure { + sha3; + } +} +// ---- +// TypeError: (60-64): "sha3" has been deprecated in favour of "keccak256" diff --git a/test/libsolidity/syntaxTests/globalFunctions/sha3_override.sol b/test/libsolidity/syntaxTests/globalFunctions/sha3_override.sol new file mode 100644 index 00000000..909c2dc3 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/sha3_override.sol @@ -0,0 +1,11 @@ +contract C +{ + function sha3() public pure returns (bool) { + return true; + } + function f() public pure returns (bool) { + return sha3(); + } +} +// ---- +// Warning: (14-76): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/globalFunctions/sha3_var.sol b/test/libsolidity/syntaxTests/globalFunctions/sha3_var.sol new file mode 100644 index 00000000..19ee72d9 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/sha3_var.sol @@ -0,0 +1,9 @@ +contract C +{ + function f() public pure returns (bool) { + bool sha3 = true; + return sha3; + } +} +// ---- +// Warning: (58-67): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/globalFunctions/suicide_no_call.sol b/test/libsolidity/syntaxTests/globalFunctions/suicide_no_call.sol new file mode 100644 index 00000000..bf3f5ebc --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/suicide_no_call.sol @@ -0,0 +1,8 @@ +contract C +{ + function f(bytes memory data) public pure { + suicide; + } +} +// ---- +// TypeError: (60-67): "suicide" has been deprecated in favour of "selfdestruct" diff --git a/test/libsolidity/syntaxTests/globalFunctions/suicide_override.sol b/test/libsolidity/syntaxTests/globalFunctions/suicide_override.sol new file mode 100644 index 00000000..7350da39 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/suicide_override.sol @@ -0,0 +1,11 @@ +contract C +{ + function suicide() public pure returns (bool) { + return true; + } + function f() public pure returns (bool) { + return suicide(); + } +} +// ---- +// Warning: (14-79): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/globalFunctions/suicide_var.sol b/test/libsolidity/syntaxTests/globalFunctions/suicide_var.sol new file mode 100644 index 00000000..3549a563 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/suicide_var.sol @@ -0,0 +1,9 @@ +contract C +{ + function f() public pure returns (bool) { + bool suicide = true; + return suicide; + } +} +// ---- +// Warning: (58-70): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory.sol new file mode 100644 index 00000000..e683ef39 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory.sol @@ -0,0 +1,13 @@ +contract A { + uint dummy; + function f(uint[] calldata) external pure {} + function g(uint[] calldata) external view { dummy; } + function h(uint[] calldata) external { dummy = 42; } + function i(uint[] calldata) external payable {} +} +contract B is A { + function f(uint[] memory) public pure {} + function g(uint[] memory) public view { dummy; } + function h(uint[] memory) public { dummy = 42; } + function i(uint[] memory) public payable {} +} diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_conflict.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_conflict.sol new file mode 100644 index 00000000..dc734d36 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_conflict.sol @@ -0,0 +1,26 @@ +contract A { + uint dummy; + function f(uint[] calldata) external pure {} + function g(uint[] calldata) external view { dummy; } + function h(uint[] calldata) external { dummy = 42; } + function i(uint[] calldata) external payable {} +} +contract B is A { + function f(uint[] calldata) external pure {} + function g(uint[] calldata) external view { dummy; } + function h(uint[] calldata) external { dummy = 42; } + function i(uint[] calldata) external payable {} + function f(uint[] memory) public pure {} + function g(uint[] memory) public view { dummy; } + function h(uint[] memory) public { dummy = 42; } + function i(uint[] memory) public payable {} +} +// ---- +// DeclarationError: (268-312): Function with same name and arguments defined twice. +// DeclarationError: (317-369): Function with same name and arguments defined twice. +// DeclarationError: (374-426): Function with same name and arguments defined twice. +// DeclarationError: (431-478): Function with same name and arguments defined twice. +// TypeError: (268-312): Overriding function visibility differs. +// TypeError: (317-369): Overriding function visibility differs. +// TypeError: (374-426): Overriding function visibility differs. +// TypeError: (431-478): Overriding function visibility differs. diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol new file mode 100644 index 00000000..7eecc079 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol @@ -0,0 +1,13 @@ +interface I { + function f(uint[] calldata) external pure; + function g(uint[] calldata) external view; + function h(uint[] calldata) external; + function i(uint[] calldata) external payable; +} +contract C is I { + uint dummy; + function f(uint[] memory) public pure {} + function g(uint[] memory) public view { dummy; } + function h(uint[] memory) public { dummy = 42; } + function i(uint[] memory) public payable {} +} diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol new file mode 100644 index 00000000..4cdc3924 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol @@ -0,0 +1,12 @@ +interface I { + function f(uint[] calldata) external pure; +} +contract A is I { + function f(uint[] memory) public pure {} +} +contract C { + function f() public { + I i = I(new A()); + i.f(new uint[](1)); + } +}
\ No newline at end of file diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol new file mode 100644 index 00000000..49b27fd7 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol @@ -0,0 +1,17 @@ +pragma experimental ABIEncoderV2; +interface I { + struct S { int a; } + function f(S calldata) external pure; + function g(S calldata) external view; + function h(S calldata) external; + function i(S calldata) external payable; +} +contract C is I { + uint dummy; + function f(S memory) public pure {} + function g(S memory) public view { dummy; } + function h(S memory) public { dummy = 42; } + function i(S memory) public payable {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_struct.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_struct.sol new file mode 100644 index 00000000..42aebf30 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_struct.sol @@ -0,0 +1,17 @@ +pragma experimental ABIEncoderV2; +contract A { + uint dummy; + struct S { int a; } + function f(S calldata) external pure {} + function g(S calldata) external view { dummy; } + function h(S calldata) external { dummy = 42; } + function i(S calldata) external payable {} +} +contract B is A { + function f(S memory) public pure {} + function g(S memory) public view { dummy; } + function h(S memory) public { dummy = 42; } + function i(S memory) public payable {} +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. diff --git a/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol new file mode 100644 index 00000000..804a1810 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol @@ -0,0 +1,10 @@ +interface I { + function f() external pure returns (uint); +} +contract B is I { + // The compiler used to have a bug where changing + // the return type was fine in this situation. + function f() public pure returns (uint, uint) {} +} +// ---- +// TypeError: (182-230): Overriding function return types differ. diff --git a/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol b/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol new file mode 100644 index 00000000..3d0394f5 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol @@ -0,0 +1,7 @@ +contract A { + function f() external pure {} +} +contract B is A { + function f() public pure { + } +} diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol new file mode 100644 index 00000000..49f7c33b --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol @@ -0,0 +1,7 @@ +interface X { function test() external returns (uint256); } +contract Y is X { + uint256 public test = 42; +} +contract T { + constructor() public { new Y(); } +} diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol new file mode 100644 index 00000000..32fac25c --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol @@ -0,0 +1,9 @@ +contract X { function test() internal returns (uint256); } +contract Y is X { + uint256 public test = 42; +} +contract T { + constructor() public { new Y(); } +} +// ---- +// DeclarationError: (81-105): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol new file mode 100644 index 00000000..c58e24b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol @@ -0,0 +1,7 @@ +contract X { function test() private returns (uint256); } +contract Y is X { + uint256 public test = 42; +} +contract T { + constructor() public { new Y(); } +} diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol new file mode 100644 index 00000000..7a59c137 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol @@ -0,0 +1,9 @@ +contract X { function test() public returns (uint256); } +contract Y is X { + uint256 public test = 42; +} +contract T { + constructor() public { new Y(); } +} +// ---- +// DeclarationError: (79-103): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/inheritance/override/internal_external.sol b/test/libsolidity/syntaxTests/inheritance/override/internal_external.sol new file mode 100644 index 00000000..90973ee7 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/internal_external.sol @@ -0,0 +1,7 @@ +contract A { + function f(uint[] calldata) external pure {} + function f(uint[] memory) internal pure {} +} +// ---- +// DeclarationError: (17-61): Function with same name and arguments defined twice. +// TypeError: (17-61): Overriding function visibility differs. diff --git a/test/libsolidity/syntaxTests/inheritance/override/internal_external_inheritance.sol b/test/libsolidity/syntaxTests/inheritance/override/internal_external_inheritance.sol new file mode 100644 index 00000000..c09a8000 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/internal_external_inheritance.sol @@ -0,0 +1,9 @@ +contract A { + function f(uint[] calldata) external pure {} +} +contract B { + function f(uint[] memory) internal pure {} +} +contract C is A, B {} +// ---- +// TypeError: (81-123): Overriding function visibility differs. diff --git a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol index 0f05cc8e..fb7f3fbd 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol @@ -6,3 +6,4 @@ contract C is A { } // ---- // DeclarationError: (50-85): Identifier already declared. +// TypeError: (50-85): Redeclaring an already implemented function as abstract diff --git a/test/libsolidity/syntaxTests/inheritance/super_on_external.sol b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol new file mode 100644 index 00000000..21f3b1c2 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol @@ -0,0 +1,10 @@ +contract A { + function f() external pure {} +} +contract B is A { + function f() public pure { + super.f(); + } +} +// ---- +// TypeError: (106-113): Member "f" not found or not visible after argument-dependent lookup in contract super B. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol index 715913de..b44d09e3 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol @@ -7,4 +7,4 @@ contract C { } // ---- // ParserError: (72-73): Literal, identifier or instruction expected. -// ParserError: (72-73): Expected primary expression. +// ParserError: (72-73): Octal numbers not allowed. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol b/test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol index e613758b..e613758b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol index 023404f7..023404f7 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol index 025244d3..025244d3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_int_conversion.sol index e7036bdf..e7036bdf 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_int_conversion.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_string_conversion.sol index 4e92f6e1..4e92f6e1 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_const_string_conversion.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/273_inline_array_declaration_no_type.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type.sol index 4d3e6aed..4d3e6aed 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/273_inline_array_declaration_no_type.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type_strings.sol index 6d36942d..6d36942d 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_declaration_no_type_strings.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/325_inline_array_fixed_types.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol index c46297c3..c46297c3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/325_inline_array_fixed_types.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol diff --git a/test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol new file mode 100644 index 00000000..59a88130 --- /dev/null +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol @@ -0,0 +1,8 @@ +contract C { + mapping(int => int) a; + function f() public { + [a]; + } +} +// ---- +// TypeError: (66-69): Type mapping(int256 => int256) is only valid in storage. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol index bdc3c2c1..bdc3c2c1 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/276_invalid_types_in_inline_array.sol b/test/libsolidity/syntaxTests/inline_arrays/invalid_types_in_inline_array.sol index 03d7266a..03d7266a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/276_invalid_types_in_inline_array.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/invalid_types_in_inline_array.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/278_lvalues_as_inline_array.sol b/test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol index 5a39f550..5a39f550 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/278_lvalues_as_inline_array.sol +++ b/test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol diff --git a/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol b/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol new file mode 100644 index 00000000..560a6c2a --- /dev/null +++ b/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol @@ -0,0 +1,7 @@ +contract C { + function () internal returns (uint) x; + constructor() public { + C.x = g; + } + function g() public pure returns (uint) {} +} diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol index cb9eb3fa..86585518 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol @@ -4,4 +4,4 @@ contract C { } // ---- // DeclarationError: (17-66): Function with same name and arguments defined twice. -// TypeError: (17-66): Overriding function visibility differs. +// TypeError: (17-66): Overriding function return types differ. diff --git a/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol b/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol index fb267ba3..352b5f8f 100644 --- a/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol +++ b/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol @@ -4,4 +4,4 @@ contract test { } } // ---- -// ParserError: (44-47): Expected primary expression. +// ParserError: (44-47): Identifier-start is not allowed at end of a number. diff --git a/test/libsolidity/syntaxTests/string/string_new_line.sol b/test/libsolidity/syntaxTests/string/string_new_line.sol index da2240f7..4cbc71a5 100644 --- a/test/libsolidity/syntaxTests/string/string_new_line.sol +++ b/test/libsolidity/syntaxTests/string/string_new_line.sol @@ -6,4 +6,4 @@ contract test { } } // ---- -// ParserError: (100-112): Expected primary expression. +// ParserError: (100-112): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol b/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol index 3eaba6af..fba53a03 100644 --- a/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol +++ b/test/libsolidity/syntaxTests/string/string_terminated_by_backslash.sol @@ -5,4 +5,4 @@ contract test { } } // ---- -// ParserError: (100-109): Expected primary expression.
\ No newline at end of file +// ParserError: (100-109): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/string/string_unterminated.sol b/test/libsolidity/syntaxTests/string/string_unterminated.sol index 3291781e..e893f4b1 100644 --- a/test/libsolidity/syntaxTests/string/string_unterminated.sol +++ b/test/libsolidity/syntaxTests/string/string_unterminated.sol @@ -4,4 +4,4 @@ contract test { } } // ---- -// ParserError: (100-112): Expected primary expression.
\ No newline at end of file +// ParserError: (100-112): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol b/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol index e7be50d2..b100396b 100644 --- a/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol +++ b/test/libsolidity/syntaxTests/string/string_unterminated_no_new_line.sol @@ -1,4 +1,4 @@ contract test { function f() pure public { "abc\ // ---- -// ParserError: (47-53): Expected primary expression.
\ No newline at end of file +// ParserError: (47-53): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_forward_reference.sol b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_forward_reference.sol new file mode 100644 index 00000000..d2a411ec --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_forward_reference.sol @@ -0,0 +1,11 @@ +pragma experimental ABIEncoderV2; + +contract C { + function f(Data.S memory a) public {} +} +contract Data { + struct S { S x; } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. +// TypeError: (63-78): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol index 1098008d..ebd05d86 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol @@ -3,4 +3,3 @@ library L { } } // ---- -// TypeError: (27-56): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol index dedd4f68..36e833b7 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol @@ -3,4 +3,3 @@ library L { } } // ---- -// TypeError: (27-56): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol index 1e756819..6c145801 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol @@ -5,6 +5,3 @@ library L } } // ---- -// TypeError: (27-58): Type is required to live outside storage. -// TypeError: (60-91): Type is required to live outside storage. -// TypeError: (123-152): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol index 357751a0..a98458cd 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol @@ -5,6 +5,3 @@ library L } } // ---- -// TypeError: (27-58): Type is required to live outside storage. -// TypeError: (60-91): Type is required to live outside storage. -// TypeError: (121-150): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol index c050f8e9..fa3757fa 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol @@ -2,5 +2,5 @@ contract c { function f1(mapping(uint => uint) calldata) pure external returns (mapping(uint => uint) memory) {} } // ---- -// TypeError: (29-59): Type is required to live outside storage. -// TypeError: (29-59): Internal or recursive type is not allowed for public or external functions. +// TypeError: (29-59): Mapping types for parameters or return variables can only be used in internal or library functions. +// TypeError: (84-112): Mapping types for parameters or return variables can only be used in internal or library functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol index b63868b8..8c73b5ae 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol @@ -2,5 +2,4 @@ contract c { function f3(mapping(uint => uint) memory) view public {} } // ---- -// TypeError: (29-57): Type is required to live outside storage. -// TypeError: (29-57): Internal or recursive type is not allowed for public or external functions. +// TypeError: (29-57): Mapping types for parameters or return variables can only be used in internal or library functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol index 35c3abc9..7378324a 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public_memory.sol @@ -3,5 +3,4 @@ contract C { } } // ---- -// TypeError: (51-79): Type is required to live outside storage. -// TypeError: (51-79): Internal or recursive type is not allowed for public or external functions. +// TypeError: (51-79): Mapping types for parameters or return variables can only be used in internal or library functions. diff --git a/test/libsolidity/syntaxTests/unicode_escape_literals.sol b/test/libsolidity/syntaxTests/unicode_escape_literals.sol index a340487b..4415d493 100644 --- a/test/libsolidity/syntaxTests/unicode_escape_literals.sol +++ b/test/libsolidity/syntaxTests/unicode_escape_literals.sol @@ -28,4 +28,4 @@ contract test { } // ---- -// ParserError: (678-681): Expected primary expression. +// ParserError: (678-681): Invalid escape sequence. diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function.sol b/test/libsolidity/syntaxTests/unimplemented_super_function.sol new file mode 100644 index 00000000..356727ae --- /dev/null +++ b/test/libsolidity/syntaxTests/unimplemented_super_function.sol @@ -0,0 +1,8 @@ +contract a { + function f() public; +} +contract b is a { + function f() public { super.f(); } +} +// ---- +// TypeError: (84-91): Member "f" not found or not visible after argument-dependent lookup in contract super b. diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol b/test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol new file mode 100644 index 00000000..88acbdf0 --- /dev/null +++ b/test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol @@ -0,0 +1,12 @@ +contract a { + function f() public; +} +contract b is a { + function f() public { super.f(); } +} +contract c is a,b { + // No error here. + function f() public { super.f(); } +} +// ---- +// TypeError: (84-91): Member "f" not found or not visible after argument-dependent lookup in contract super b. diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d224bdcd..a247a169 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -23,24 +23,24 @@ #include <test/Options.h> -#include <libyul/optimiser/Disambiguator.h> - -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/SourceReferenceFormatter.h> -#include <libsolidity/inlineasm/AsmParser.h> -#include <libsolidity/inlineasm/AsmAnalysis.h> -#include <libsolidity/inlineasm/AsmPrinter.h> +#include <libyul/optimiser/Disambiguator.h> +#include <libyul/AsmParser.h> +#include <libyul/AsmAnalysis.h> +#include <libyul/AsmPrinter.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <liblangutil/Scanner.h> +#include <liblangutil/ErrorReporter.h> #include <boost/test/unit_test.hpp> using namespace std; -using namespace dev::yul; +using namespace langutil; +using namespace yul; using namespace dev::solidity; -void dev::yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) +void yul::test::printErrors(ErrorList const& _errors, Scanner const& _scanner) { SourceReferenceFormatter formatter(cout, [&](std::string const&) -> Scanner const& { return _scanner; }); @@ -52,18 +52,18 @@ void dev::yul::test::printErrors(ErrorList const& _errors, Scanner const& _scann } -pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::yul::test::parse(string const& _source, bool _yul) +pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul) { - auto flavour = _yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; + auto flavour = _yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared<Scanner>(CharStream(_source), ""); - auto parserResult = assembly::Parser(errorReporter, flavour).parse(scanner, false); + auto scanner = make_shared<Scanner>(CharStream(_source, "")); + auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false); if (parserResult) { BOOST_REQUIRE(errorReporter.errors().empty()); - auto analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); - assembly::AsmAnalyzer analyzer( + auto analysisInfo = make_shared<yul::AsmAnalysisInfo>(); + yul::AsmAnalyzer analyzer( *analysisInfo, errorReporter, dev::test::Options::get().evmVersion(), @@ -83,13 +83,13 @@ pair<shared_ptr<Block>, shared_ptr<assembly::AsmAnalysisInfo>> dev::yul::test::p return {}; } -assembly::Block dev::yul::test::disambiguate(string const& _source, bool _yul) +yul::Block yul::test::disambiguate(string const& _source, bool _yul) { auto result = parse(_source, _yul); return boost::get<Block>(Disambiguator(*result.second, {})(*result.first)); } -string dev::yul::test::format(string const& _source, bool _yul) +string yul::test::format(string const& _source, bool _yul) { - return assembly::AsmPrinter(_yul)(*parse(_source, _yul).first); + return yul::AsmPrinter(_yul)(*parse(_source, _yul).first); } diff --git a/test/libyul/Common.h b/test/libyul/Common.h index ee191494..a1c64ca5 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -21,35 +21,34 @@ #pragma once -#include <libsolidity/inlineasm/AsmData.h> +#include <libyul/AsmData.h> #include <string> #include <vector> #include <memory> -namespace dev -{ -namespace solidity +namespace langutil { class Scanner; class Error; using ErrorList = std::vector<std::shared_ptr<Error const>>; -namespace assembly +} + +namespace yul { struct AsmAnalysisInfo; } -} + namespace yul { namespace test { -void printErrors(solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); -std::pair<std::shared_ptr<solidity::assembly::Block>, std::shared_ptr<solidity::assembly::AsmAnalysisInfo>> +void printErrors(langutil::ErrorList const& _errors, langutil::Scanner const& _scanner); +std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>> parse(std::string const& _source, bool _yul = true); -solidity::assembly::Block disambiguate(std::string const& _source, bool _yul = true); +Block disambiguate(std::string const& _source, bool _yul = true); std::string format(std::string const& _source, bool _yul = true); } } -} diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index 66810298..631cda08 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -26,8 +26,7 @@ #include <libyul/optimiser/FullInliner.h> #include <libyul/optimiser/FunctionHoister.h> #include <libyul/optimiser/FunctionGrouper.h> - -#include <libsolidity/inlineasm/AsmPrinter.h> +#include <libyul/AsmPrinter.h> #include <boost/test/unit_test.hpp> @@ -36,8 +35,8 @@ using namespace std; using namespace dev; -using namespace dev::yul; -using namespace dev::yul::test; +using namespace yul; +using namespace yul::test; using namespace dev::solidity; namespace diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp new file mode 100644 index 00000000..bb88e4da --- /dev/null +++ b/test/libyul/ObjectParser.cpp @@ -0,0 +1,257 @@ +/* + 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/>. +*/ +/** + * @date 2018 + * Unit tests for the Yul object parser. + */ + +#include <test/Options.h> + +#include <test/libsolidity/ErrorCheck.h> + +#include <libsolidity/interface/AssemblyStack.h> + +#include <boost/optional.hpp> +#include <boost/algorithm/string/replace.hpp> + +#include <string> +#include <memory> + +using namespace std; +using namespace langutil; + +namespace dev +{ +namespace yul +{ +namespace test +{ + +namespace +{ + +std::pair<bool, ErrorList> parse(string const& _source) +{ + try + { + solidity::AssemblyStack asmStack( + dev::test::Options::get().evmVersion(), + solidity::AssemblyStack::Language::StrictAssembly + ); + bool success = asmStack.parseAndAnalyze("source", _source); + return {success, asmStack.errors()}; + } + catch (FatalError const&) + { + BOOST_FAIL("Fatal error leaked."); + } + return {false, {}}; +} + +boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _allowWarnings = true) +{ + bool success; + ErrorList errors; + tie(success, errors) = parse(_source); + if (!success) + { + BOOST_REQUIRE_EQUAL(errors.size(), 1); + return *errors.front(); + } + else + { + // If success is true, there might still be an error in the assembly stage. + if (_allowWarnings && Error::containsOnlyWarnings(errors)) + return {}; + else if (!errors.empty()) + { + if (!_allowWarnings) + BOOST_CHECK_EQUAL(errors.size(), 1); + return *errors.front(); + } + } + return {}; +} + +bool successParse(std::string const& _source, bool _allowWarnings = true) +{ + return !parseAndReturnFirstError(_source, _allowWarnings); +} + +Error expectError(std::string const& _source, bool _allowWarnings = false) +{ + + auto error = parseAndReturnFirstError(_source, _allowWarnings); + BOOST_REQUIRE(error); + return *error; +} + +} + +#define CHECK_ERROR(text, typ, substring) \ +do \ +{ \ + Error err = expectError((text), false); \ + BOOST_CHECK(err.type() == (Error::Type::typ)); \ + BOOST_CHECK(solidity::searchErrorMessage(err, (substring))); \ +} while(0) + +BOOST_AUTO_TEST_SUITE(YulObjectParser) + +BOOST_AUTO_TEST_CASE(empty_code) +{ + BOOST_CHECK(successParse("{ }")); +} + +BOOST_AUTO_TEST_CASE(object_with_empty_code) +{ + BOOST_CHECK(successParse("object \"a\" { code { } }")); +} + +BOOST_AUTO_TEST_CASE(non_object) +{ + CHECK_ERROR("code {}", ParserError, "Expected keyword \"object\""); +} + +BOOST_AUTO_TEST_CASE(empty_name) +{ + CHECK_ERROR("object \"\" { code {} }", ParserError, "Object name cannot be empty"); +} + +BOOST_AUTO_TEST_CASE(recursion_depth) +{ + string input; + for (size_t i = 0; i < 20000; i++) + input += "object \"a" + to_string(i) + "\" { code {} "; + for (size_t i = 0; i < 20000; i++) + input += "}"; + + CHECK_ERROR(input, ParserError, "recursion"); +} + +BOOST_AUTO_TEST_CASE(object_with_code) +{ + BOOST_CHECK(successParse("object \"a\" { code { let x := mload(0) sstore(0, x) } }")); +} + +BOOST_AUTO_TEST_CASE(object_with_code_and_data) +{ + BOOST_CHECK(successParse("object \"a\" { code { let x := mload(0) sstore(0, x) } data \"b\" hex\"01010202\" }")); +} + +BOOST_AUTO_TEST_CASE(object_with_non_code_at_start) +{ + CHECK_ERROR("object \"a\" { data \"d\" hex\"0102\" code { } }", ParserError, "Expected keyword \"code\""); +} + +BOOST_AUTO_TEST_CASE(nested_object) +{ + string code = R"( + object "outer" { + code { let x := mload(0) } + data "x" "stringdata" + object "inner" { + code { mstore(0, 1) } + object "inner inner" { code {} } + data "innerx" "abc" + data "innery" "def" + } + } + )"; + BOOST_CHECK(successParse(code)); +} + +BOOST_AUTO_TEST_CASE(incomplete) +{ + CHECK_ERROR("object \"abc\" { code {} } object", ParserError, "Expected end of source"); +} + +BOOST_AUTO_TEST_CASE(reuse_object_name) +{ + string code = R"( + object "outer" { + code { } + data "outer" "stringdata" + } + )"; + CHECK_ERROR(code, ParserError, "Object name cannot be the same as the name of the containing object"); +} + +BOOST_AUTO_TEST_CASE(reuse_object_in_subobject) +{ + string code = R"( + object "outer" { + code { } + object "outer" { code {} } + } + )"; + CHECK_ERROR(code, ParserError, "Object name cannot be the same as the name of the containing object"); +} + +BOOST_AUTO_TEST_CASE(reuse_object_of_sibling) +{ + string code = R"( + object "O" { + code { } + object "i" { code {} } + data "i" "abc" + } + )"; + CHECK_ERROR(code, ParserError, "already exists inside the"); +} + +BOOST_AUTO_TEST_CASE(to_string) +{ + string code = R"( + object "O" { + code { let x := mload(0) if x { sstore(0, 1) } } + object "i" { code {} data "j" "def" } + data "j" "abc" + data "k" hex"010203" + } + )"; + string expectation = R"(object "O" { + code { + let x := mload(0) + if x + { + sstore(0, 1) + } + } + object "i" { + code { + } + data "j" hex"646566" + } + data "j" hex"616263" + data "k" hex"010203" +} +)"; + expectation = boost::replace_all_copy(expectation, "\t", " "); + solidity::AssemblyStack asmStack( + dev::test::Options::get().evmVersion(), + solidity::AssemblyStack::Language::StrictAssembly + ); + BOOST_REQUIRE(asmStack.parseAndAnalyze("source", code)); + BOOST_CHECK_EQUAL(asmStack.print(), expectation); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 3f329d28..caaf2719 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -23,11 +23,11 @@ #include <test/libsolidity/ErrorCheck.h> -#include <libsolidity/inlineasm/AsmParser.h> -#include <libsolidity/inlineasm/AsmAnalysis.h> -#include <libsolidity/inlineasm/AsmAnalysisInfo.h> -#include <libsolidity/parsing/Scanner.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <libyul/AsmParser.h> +#include <libyul/AsmAnalysis.h> +#include <libyul/AsmAnalysisInfo.h> +#include <liblangutil/Scanner.h> +#include <liblangutil/ErrorReporter.h> #include <boost/optional.hpp> #include <boost/algorithm/string/replace.hpp> @@ -36,10 +36,10 @@ #include <memory> using namespace std; +using namespace dev; +using namespace langutil; -namespace dev -{ -namespace solidity +namespace yul { namespace test { @@ -51,17 +51,17 @@ bool parse(string const& _source, ErrorReporter& errorReporter) { try { - auto scanner = make_shared<Scanner>(CharStream(_source)); - auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Yul).parse(scanner, false); + auto scanner = make_shared<Scanner>(CharStream(_source, "")); + auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Yul).parse(scanner, false); if (parserResult) { - assembly::AsmAnalysisInfo analysisInfo; - return (assembly::AsmAnalyzer( + yul::AsmAnalysisInfo analysisInfo; + return (yul::AsmAnalyzer( analysisInfo, errorReporter, dev::test::Options::get().evmVersion(), boost::none, - assembly::AsmFlavour::Yul + yul::AsmFlavour::Yul )).analyze(*parserResult); } } @@ -116,7 +116,7 @@ do \ { \ Error err = expectError((text), false); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ - BOOST_CHECK(searchErrorMessage(err, (substring))); \ + BOOST_CHECK(dev::solidity::searchErrorMessage(err, (substring))); \ } while(0) BOOST_AUTO_TEST_SUITE(YulParser) @@ -302,5 +302,4 @@ BOOST_AUTO_TEST_CASE(if_statement_invalid) BOOST_AUTO_TEST_SUITE_END() } -} } // end namespaces diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 03cd6446..15d70faa 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -31,6 +31,7 @@ #include <libyul/optimiser/FunctionHoister.h> #include <libyul/optimiser/ExpressionInliner.h> #include <libyul/optimiser/FullInliner.h> +#include <libyul/optimiser/ForLoopInitRewriter.h> #include <libyul/optimiser/MainFunction.h> #include <libyul/optimiser/Rematerialiser.h> #include <libyul/optimiser/ExpressionSimplifier.h> @@ -39,13 +40,13 @@ #include <libyul/optimiser/SSATransform.h> #include <libyul/optimiser/RedundantAssignEliminator.h> #include <libyul/optimiser/Suite.h> +#include <libyul/AsmPrinter.h> +#include <libyul/AsmParser.h> +#include <libyul/AsmAnalysis.h> +#include <liblangutil/SourceReferenceFormatter.h> -#include <libsolidity/parsing/Scanner.h> -#include <libsolidity/inlineasm/AsmPrinter.h> -#include <libsolidity/inlineasm/AsmParser.h> -#include <libsolidity/inlineasm/AsmAnalysis.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <liblangutil/ErrorReporter.h> +#include <liblangutil/Scanner.h> #include <boost/test/unit_test.hpp> #include <boost/algorithm/string.hpp> @@ -53,8 +54,9 @@ #include <fstream> using namespace dev; -using namespace dev::yul; -using namespace dev::yul::test; +using namespace langutil; +using namespace yul; +using namespace yul::test; using namespace dev::solidity; using namespace dev::solidity::test; using namespace std; @@ -90,9 +92,9 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename) bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) { - assembly::AsmPrinter printer{m_yul}; + yul::AsmPrinter printer{m_yul}; shared_ptr<Block> ast; - shared_ptr<assembly::AsmAnalysisInfo> analysisInfo; + shared_ptr<yul::AsmAnalysisInfo> analysisInfo; if (!parse(_stream, _linePrefix, _formatted)) return false; @@ -108,6 +110,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); VarDeclPropagator{}(*m_ast); } + else if (m_optimizerStep == "forLoopInitRewriter") + { + disambiguate(); + ForLoopInitRewriter{}(*m_ast); + } else if (m_optimizerStep == "commonSubexpressionEliminator") { disambiguate(); @@ -249,19 +256,19 @@ void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, st bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted) { - assembly::AsmFlavour flavour = m_yul ? assembly::AsmFlavour::Yul : assembly::AsmFlavour::Strict; + yul::AsmFlavour flavour = m_yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); - shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source), ""); - m_ast = assembly::Parser(errorReporter, flavour).parse(scanner, false); + shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, "")); + m_ast = yul::Parser(errorReporter, flavour).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl; printErrors(_stream, errorReporter.errors(), *scanner); return false; } - m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); - assembly::AsmAnalyzer analyzer( + m_analysisInfo = make_shared<yul::AsmAnalysisInfo>(); + yul::AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, dev::test::Options::get().evmVersion(), diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 7db17ceb..90026e24 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -17,28 +17,27 @@ #pragma once -#include <test/libsolidity/TestCase.h> +#include <test/TestCase.h> - -namespace dev -{ -namespace solidity +namespace langutil { class Scanner; class Error; using ErrorList = std::vector<std::shared_ptr<Error const>>; -namespace assembly +} + +namespace yul { struct AsmAnalysisInfo; struct Block; } -} + namespace yul { namespace test { -class YulOptimizerTest: public solidity::test::TestCase +class YulOptimizerTest: public dev::solidity::test::TestCase { public: static std::unique_ptr<TestCase> create(std::string const& _filename) @@ -58,18 +57,17 @@ private: bool parse(std::ostream& _stream, std::string const& _linePrefix, bool const _formatted); void disambiguate(); - static void printErrors(std::ostream& _stream, solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); + static void printErrors(std::ostream& _stream, langutil::ErrorList const& _errors, langutil::Scanner const& _scanner); std::string m_source; bool m_yul = false; std::string m_optimizerStep; std::string m_expectation; - std::shared_ptr<solidity::assembly::Block> m_ast; - std::shared_ptr<solidity::assembly::AsmAnalysisInfo> m_analysisInfo; + std::shared_ptr<Block> m_ast; + std::shared_ptr<AsmAnalysisInfo> m_analysisInfo; std::string m_obtainedResult; }; } } -} diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul new file mode 100644 index 00000000..3ca00f55 --- /dev/null +++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul @@ -0,0 +1,23 @@ +{ + let random := 42 + for { let a := 1 + let b := 1 } iszero(eq(a, 10)) { a := add(a, b) } { + a := add(a, 1) + } +} +// ---- +// forLoopInitRewriter +// { +// let random := 42 +// let a := 1 +// let b := 1 +// for { +// } +// iszero(eq(a, 10)) +// { +// a := add(a, b) +// } +// { +// a := add(a, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul new file mode 100644 index 00000000..05aceb52 --- /dev/null +++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul @@ -0,0 +1,20 @@ +{ + let a := 1 + for {} iszero(eq(a, 10)) { a := add(a, 1) } { + a := add(a, 1) + } +} +// ---- +// forLoopInitRewriter +// { +// let a := 1 +// for { +// } +// iszero(eq(a, 10)) +// { +// a := add(a, 1) +// } +// { +// a := add(a, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul new file mode 100644 index 00000000..565b7725 --- /dev/null +++ b/test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul @@ -0,0 +1,21 @@ +{ + let random := 42 + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } { + a := add(a, 1) + } +} +// ---- +// forLoopInitRewriter +// { +// let random := 42 +// let a := 1 +// for { +// } +// iszero(eq(a, 10)) +// { +// a := add(a, 1) +// } +// { +// a := add(a, 1) +// } +// } diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 19a1d958..736212fc 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -4,7 +4,7 @@ target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_L add_executable(yulopti yulopti.cpp) target_link_libraries(yulopti PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_SYSTEM_LIBRARIES}) -add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../libsolidity/TestCase.cpp ../libsolidity/SyntaxTest.cpp +add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../TestCase.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp - ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libyul/YulOptimizerTest.cpp) + ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp ../libsolidity/SMTCheckerJSONTest.cpp ../libyul/YulOptimizerTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 1b6fd54a..f8e2dc58 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -21,6 +21,7 @@ #include <test/libsolidity/AnalysisFramework.h> #include <test/libsolidity/SyntaxTest.h> #include <test/libsolidity/ASTJSONTest.h> +#include <test/libsolidity/SMTCheckerJSONTest.h> #include <test/libyul/YulOptimizerTest.h> #include <boost/algorithm/string.hpp> @@ -412,6 +413,17 @@ Allowed options)", global_stats += *stats; else return 1; + + if (auto stats = runTestSuite( + "SMT Checker JSON", + testPath / "libsolidity", + "smtCheckerTestsJSON", + SMTCheckerTest::create, + formatted + )) + global_stats += *stats; + else + return 1; } cout << endl << "Summary: "; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 348c5f4a..5273bbb9 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -19,15 +19,15 @@ */ #include <libdevcore/CommonIO.h> -#include <libsolidity/inlineasm/AsmAnalysis.h> -#include <libsolidity/inlineasm/AsmAnalysisInfo.h> -#include <libsolidity/parsing/Scanner.h> +#include <liblangutil/ErrorReporter.h> +#include <liblangutil/Scanner.h> +#include <libyul/AsmAnalysis.h> +#include <libyul/AsmAnalysisInfo.h> #include <libsolidity/parsing/Parser.h> -#include <libsolidity/inlineasm/AsmData.h> -#include <libsolidity/inlineasm/AsmParser.h> -#include <libsolidity/inlineasm/AsmPrinter.h> -#include <libsolidity/interface/SourceReferenceFormatter.h> -#include <libsolidity/interface/ErrorReporter.h> +#include <libyul/AsmData.h> +#include <libyul/AsmParser.h> +#include <libyul/AsmPrinter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libyul/optimiser/BlockFlattener.h> #include <libyul/optimiser/Disambiguator.h> @@ -38,6 +38,7 @@ #include <libyul/optimiser/FunctionHoister.h> #include <libyul/optimiser/ExpressionInliner.h> #include <libyul/optimiser/FullInliner.h> +#include <libyul/optimiser/ForLoopInitRewriter.h> #include <libyul/optimiser/MainFunction.h> #include <libyul/optimiser/Rematerialiser.h> #include <libyul/optimiser/ExpressionSimplifier.h> @@ -57,9 +58,9 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; -using namespace dev::solidity::assembly; -using namespace dev::yul; +using namespace yul; namespace po = boost::program_options; @@ -80,15 +81,15 @@ public: bool parse(string const& _input) { ErrorReporter errorReporter(m_errors); - shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(_input), ""); - m_ast = assembly::Parser(errorReporter, assembly::AsmFlavour::Strict).parse(scanner, false); + shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(_input, "")); + m_ast = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { cout << "Error parsing source." << endl; printErrors(*scanner); return false; } - m_analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); + m_analysisInfo = make_shared<yul::AsmAnalysisInfo>(); AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, @@ -116,14 +117,14 @@ public: return; if (!disambiguated) { - *m_ast = boost::get<assembly::Block>(Disambiguator(*m_analysisInfo)(*m_ast)); + *m_ast = boost::get<yul::Block>(Disambiguator(*m_analysisInfo)(*m_ast)); m_analysisInfo.reset(); m_nameDispenser = make_shared<NameDispenser>(*m_ast); disambiguated = true; } cout << "(q)quit/(f)flatten/(c)se/propagate var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl; cout << " (e)xpr inline/(i)nline/(s)implify/(u)nusedprune/ss(a) transform/" << endl; - cout << " (r)edundant assign elim./re(m)aterializer? "; + cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-pre-rewriter? "; cout.flush(); int option = readStandardInputChar(); cout << ' ' << char(option) << endl; @@ -134,6 +135,9 @@ public: case 'f': BlockFlattener{}(*m_ast); break; + case 'o': + ForLoopInitRewriter{}(*m_ast); + break; case 'c': (CommonSubexpressionEliminator{})(*m_ast); break; @@ -182,7 +186,7 @@ public: private: ErrorList m_errors; - shared_ptr<assembly::Block> m_ast; + shared_ptr<yul::Block> m_ast; shared_ptr<AsmAnalysisInfo> m_analysisInfo; shared_ptr<NameDispenser> m_nameDispenser; }; |