From d33d4b02a915b1fea4d33b0c751ccc4b652687d7 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 8 Nov 2018 14:28:25 +0100 Subject: [PATCH 001/168] Add archlinux run on circleci. --- .circleci/config.yml | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2967e1fb5..890a102a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -139,6 +139,27 @@ jobs: paths: - "*" + build_x86_archlinux: + docker: + - image: archlinux/base + environment: + TERM: xterm + steps: + - run: + name: Install build dependencies + command: | + pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake z3 cvc4 git openssh tar + - checkout + - run: *setup_prerelease_commit_hash + - run: *run_build + - store_artifacts: *solc_artifact + - persist_to_workspace: + root: build + paths: + - solc/solc + - test/soltest + - test/tools/solfuzzer + build_x86_clang7: docker: - image: buildpack-deps:cosmic @@ -146,6 +167,7 @@ jobs: TERM: xterm CC: /usr/bin/clang-7 CXX: /usr/bin/clang++-7 + IPC_ENABLED: false steps: - checkout - run: @@ -260,6 +282,28 @@ jobs: path: test_results/ destination: test_results/ + test_x86_archlinux: + docker: + - image: archlinux/base + environment: + TERM: xterm + steps: + - run: + name: Install dependencies + command: | + pacman --noconfirm -Syu --noprogressbar --needed boost python2 wget perl z3 cvc4 leveldb git openssh tar + ln -sf /usr/bin/core_perl/shasum /usr/bin + - checkout + - attach_workspace: + at: build + - run: mkdir -p test_results + - run: *run_tests + - store_test_results: + path: test_results/ + - store_artifacts: + path: test_results/ + destination: test_results/ + test_x86_mac: macos: xcode: "10.0.0" @@ -330,3 +374,8 @@ workflows: requires: - build_x86_mac - docs: *build_on_tags + - build_x86_archlinux: *build_on_tags + - test_x86_archlinux: + <<: *build_on_tags + requires: + - build_x86_archlinux From 6f136479231337d023d32ac8ad8c57fbedf4fb29 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 8 Nov 2018 19:38:13 +0100 Subject: [PATCH 002/168] Only run soltest with --no-ipc. --- .circleci/config.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 890a102a1..4bb5e651d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -167,7 +167,6 @@ jobs: TERM: xterm CC: /usr/bin/clang-7 CXX: /usr/bin/clang++-7 - IPC_ENABLED: false steps: - checkout - run: @@ -291,13 +290,12 @@ jobs: - run: name: Install dependencies command: | - pacman --noconfirm -Syu --noprogressbar --needed boost python2 wget perl z3 cvc4 leveldb git openssh tar - ln -sf /usr/bin/core_perl/shasum /usr/bin + pacman --noconfirm -Syu --noprogressbar --needed boost z3 cvc4 git openssh tar - checkout - attach_workspace: at: build - run: mkdir -p test_results - - run: *run_tests + - run: build/test/soltest --logger=JUNIT,test_suite,test_results/result.xml -- --no-ipc --testpath test - store_test_results: path: test_results/ - store_artifacts: From 6c47b67319a9f86795ce8be2cd907af831aee8b6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Nov 2018 19:34:57 +0100 Subject: [PATCH 003/168] Set version to 0.5.1. --- CMakeLists.txt | 2 +- Changelog.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2c84d201..e8a0e56d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.5.0") +set(PROJECT_VERSION "0.5.1") project(solidity VERSION ${PROJECT_VERSION}) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) diff --git a/Changelog.md b/Changelog.md index 026e2bac5..bb97c35b4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,15 @@ +### 0.5.1 (unreleased) + +Language Features: + + +Compiler Features: + + +Bugfixes: + + + ### 0.5.0 (2018-11-13) How to update your code: From 80fcd1aeb612b621aed4e937d50f10655dd6b1e5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Nov 2018 00:19:20 +0100 Subject: [PATCH 004/168] Fix commandline tests. --- test/cmdlineTests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index b0b545f3c..4838d088b 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)." From b4fcce0bde81939c8401ff8ec011850299cd4662 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 13 Nov 2018 14:01:15 +0000 Subject: [PATCH 005/168] Do not build LLL unless requested via the LLL cmake option --- CMakeLists.txt | 9 ++++++--- Changelog.md | 1 + docs/lll.rst | 7 +++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8a0e56d1..867696724 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,10 @@ eth_policy() set(PROJECT_VERSION "0.5.1") project(solidity VERSION ${PROJECT_VERSION}) +option(LLL "Build LLL" OFF) option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) option(LLLC_LINK_STATIC "Link lllc executable statically on supported platforms" OFF) -option(INSTALL_LLLC "Include lllc executable in installation" OFF) +option(INSTALL_LLLC "Include lllc executable in installation" ${LLL}) # Setup cccache. include(EthCcache) @@ -50,8 +51,10 @@ add_subdirectory(libsolc) if (NOT EMSCRIPTEN) add_subdirectory(solc) - add_subdirectory(liblll) - add_subdirectory(lllc) + if (LLL) + add_subdirectory(liblll) + add_subdirectory(lllc) + endif() endif() if (TESTS AND NOT EMSCRIPTEN) diff --git a/Changelog.md b/Changelog.md index bb97c35b4..b5e7eed81 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. Bugfixes: diff --git a/docs/lll.rst b/docs/lll.rst index d9409bf84..16be829e6 100644 --- a/docs/lll.rst +++ b/docs/lll.rst @@ -9,6 +9,13 @@ LLL is a low-level language for the EVM with an s-expressions syntax. The Solidity repository contains an LLL compiler, which shares the assembler subsystem with Solidity. However, apart from maintaining that it still compiles, no other improvements are made to it. +It is not built unless specifically requested: + +.. code-block:: bash + + $ cmake -DLLL=ON .. + $ cmake --build . + .. warning:: The LLL codebase is deprecated and will be removed from the Solidity repository in the future. From 6961899cb2a0abd4d236a9a6f2657b4533720484 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 13 Nov 2018 14:34:19 +0000 Subject: [PATCH 006/168] Do not build tests for LLL if disabled --- test/CMakeLists.txt | 13 ++++++++++--- test/boostTest.cpp | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 91c1b200b..3b6745026 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,8 +9,10 @@ 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") @@ -22,7 +24,12 @@ add_executable(soltest ${sources} ${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 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/boostTest.cpp b/test/boostTest.cpp index 34eeaec9c..5352ef858 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -160,9 +160,11 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "SolidityAuctionRegistrar", "SolidityFixedFeeRegistrar", "SolidityWallet", +#if HAVE_LLL "LLLERC20", "LLLENS", "LLLEndToEndTest", +#endif "GasMeterTests", "SolidityEndToEndTest", "SolidityOptimizer" From 00cb5dbd43eb07b307258865dfa5abe72a3926a5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 13 Nov 2018 14:34:37 +0000 Subject: [PATCH 007/168] Move LLL tests into a single directory --- test/{contracts => liblll}/LLL_ENS.cpp | 0 test/{contracts => liblll}/LLL_ERC20.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename test/{contracts => liblll}/LLL_ENS.cpp (100%) rename test/{contracts => liblll}/LLL_ERC20.cpp (100%) diff --git a/test/contracts/LLL_ENS.cpp b/test/liblll/LLL_ENS.cpp similarity index 100% rename from test/contracts/LLL_ENS.cpp rename to test/liblll/LLL_ENS.cpp diff --git a/test/contracts/LLL_ERC20.cpp b/test/liblll/LLL_ERC20.cpp similarity index 100% rename from test/contracts/LLL_ERC20.cpp rename to test/liblll/LLL_ERC20.cpp From 74553efb69cedbd5b24e6594df0fbf525718659d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 13 Nov 2018 14:35:46 +0000 Subject: [PATCH 008/168] Build with LLL on CircleCI --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index cf9c92128..dd0011c14 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -146,6 +146,7 @@ jobs: TERM: xterm CC: /usr/bin/clang-7 CXX: /usr/bin/clang++-7 + CMAKE_OPTIONS: -DLLL=ON steps: - checkout - run: @@ -167,6 +168,7 @@ jobs: xcode: "10.0.0" environment: TERM: xterm + CMAKE_OPTIONS: -DLLL=ON steps: - checkout - run: From 79243eac08f5d8d3ccedbbedb929848a58ff26c4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 7 Nov 2018 23:37:40 +0100 Subject: [PATCH 009/168] Rename some builtin yul functions for signed types. --- docs/yul.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index 9e9fac8ec..ea0a298b2 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -369,10 +369,10 @@ The following functions must be available: +---------------------------------------------+-----------------------------------------------------------------+ | gtu256(x:u256, y:u256) -> z:bool | true if x > y, false otherwise | +---------------------------------------------+-----------------------------------------------------------------+ -| sltu256(x:s256, y:s256) -> z:bool | true if x < y, false otherwise | +| lts256(x:s256, y:s256) -> z:bool | true if x < y, false otherwise | | | (for signed numbers in two's complement) | +---------------------------------------------+-----------------------------------------------------------------+ -| sgtu256(x:s256, y:s256) -> z:bool | true if x > y, false otherwise | +| gts256(x:s256, y:s256) -> z:bool | true if x > y, false otherwise | | | (for signed numbers in two's complement) | +---------------------------------------------+-----------------------------------------------------------------+ | equ256(x:u256, y:u256) -> z:bool | true if x == y, false otherwise | @@ -391,7 +391,7 @@ The following functions must be available: +---------------------------------------------+-----------------------------------------------------------------+ | shru256(x:u256, y:u256) -> z:u256 | logical right shift of x by y | +---------------------------------------------+-----------------------------------------------------------------+ -| saru256(x:u256, y:u256) -> z:u256 | arithmetic right shift of x by y | +| sars256(x:s256, y:u256) -> z:u256 | arithmetic right shift of x by y | +---------------------------------------------+-----------------------------------------------------------------+ | byte(n:u256, x:u256) -> v:u256 | nth byte of x, where the most significant byte is the 0th byte | | | Cannot this be just replaced by and256(shr256(n, x), 0xff) and | From 5778af07a390f70692be927f3e9702f1725d78f4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 6 Aug 2018 12:56:28 +0100 Subject: [PATCH 010/168] Do not crash on filesystemFriendlyName if no contracts were compiled --- libsolidity/interface/CompilerStack.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 441c78971..889903f00 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -389,6 +389,9 @@ string const* CompilerStack::runtimeSourceMapping(string const& _contractName) c std::string const CompilerStack::filesystemFriendlyName(string const& _contractName) const { + if (m_contracts.empty()) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + // Look up the contract (by its fully-qualified name) Contract const& matchContract = m_contracts.at(_contractName); // Check to see if it could collide on name From be70703f82d7ac0822ce518ca11acb7c34514b00 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 6 Aug 2018 13:00:21 +0100 Subject: [PATCH 011/168] Move lastContractName closer to contractNames --- libsolidity/interface/CompilerStack.cpp | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 889903f00..082a0939f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -353,6 +353,19 @@ vector CompilerStack::contractNames() const return contractNames; } +string const CompilerStack::lastContractName() const +{ + if (m_contracts.empty()) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + // try to find some user-supplied contract + string contractName; + for (auto const& it: m_sources) + for (ASTPointer const& node: it.second.ast->nodes()) + if (auto contract = dynamic_cast(node.get())) + contractName = contract->fullyQualifiedName(); + return contractName; +} + eth::AssemblyItems const* CompilerStack::assemblyItems(string const& _contractName) const { Contract const& currentContract = contract(_contractName); @@ -760,19 +773,6 @@ void CompilerStack::compileContract( _compiledContracts[compiledContract.contract] = &compiler->assembly(); } -string const CompilerStack::lastContractName() const -{ - if (m_contracts.empty()) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); - // try to find some user-supplied contract - string contractName; - for (auto const& it: m_sources) - for (ASTPointer const& node: it.second.ast->nodes()) - if (auto contract = dynamic_cast(node.get())) - contractName = contract->fullyQualifiedName(); - return contractName; -} - CompilerStack::Contract const& CompilerStack::contract(string const& _contractName) const { if (m_contracts.empty()) From d60cab1983039b3fd7c3eef7ad02246d58a7d1ac Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 6 Aug 2018 13:09:19 +0100 Subject: [PATCH 012/168] Add CompilerStack state assertions in internal methods --- libsolidity/interface/CompilerStack.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 082a0939f..d6a63f1dd 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -329,13 +329,14 @@ bool CompilerStack::compile() if (auto contract = dynamic_cast(node.get())) if (isRequestedContract(*contract)) compileContract(*contract, compiledContracts); - this->link(); m_stackState = CompilationSuccessful; + this->link(); return true; } void CompilerStack::link() { + solAssert(m_stackState >= CompilationSuccessful, ""); for (auto& contract: m_contracts) { contract.second.object.link(m_libraries); @@ -355,8 +356,8 @@ vector CompilerStack::contractNames() const string const CompilerStack::lastContractName() const { - if (m_contracts.empty()) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + if (m_stackState < AnalysisSuccessful) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); // try to find some user-supplied contract string contractName; for (auto const& it: m_sources) @@ -402,7 +403,7 @@ string const* CompilerStack::runtimeSourceMapping(string const& _contractName) c std::string const CompilerStack::filesystemFriendlyName(string const& _contractName) const { - if (m_contracts.empty()) + if (m_stackState < AnalysisSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); // Look up the contract (by its fully-qualified name) @@ -600,6 +601,7 @@ tuple CompilerStack::positionFromSourceLocation(SourceLocati StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string const& _sourcePath) { + solAssert(m_stackState < ParsingSuccessful, ""); StringMap newSources; for (auto const& node: _ast.nodes()) if (ImportDirective const* import = dynamic_cast(node.get())) @@ -633,6 +635,7 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string string CompilerStack::applyRemapping(string const& _path, string const& _context) { + solAssert(m_stackState < ParsingSuccessful, ""); // Try to find the longest prefix match in all remappings that are active in the current context. auto isPrefixOf = [](string const& _a, string const& _b) { @@ -674,6 +677,8 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context void CompilerStack::resolveImports() { + solAssert(m_stackState == ParsingSuccessful, ""); + // topological sorting (depth first search) of the import graph, cutting potential cycles vector sourceOrder; set sourcesSeen; @@ -718,6 +723,8 @@ void CompilerStack::compileContract( map& _compiledContracts ) { + solAssert(m_stackState >= AnalysisSuccessful, ""); + if ( _compiledContracts.count(&_contract) || !_contract.annotation().unimplementedFunctions.empty() || @@ -775,8 +782,7 @@ void CompilerStack::compileContract( CompilerStack::Contract const& CompilerStack::contract(string const& _contractName) const { - if (m_contracts.empty()) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("No compiled contracts found.")); + solAssert(m_stackState >= AnalysisSuccessful, ""); auto it = m_contracts.find(_contractName); if (it != m_contracts.end()) From 3e5664841ca16db93b62b69c7586bd4fab10d47e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 14 Nov 2018 12:56:13 +0000 Subject: [PATCH 013/168] Revert "Disable covereage cmake option" This reverts commit 5effc0eeb9cd5158b906facde69a3c4d52d95314. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f1b49649c..0980fa5c8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -122,7 +122,7 @@ jobs: - image: buildpack-deps:artful environment: TERM: xterm - CMAKE_OPTIONS: -DCOVERAGE=OFF + CMAKE_OPTIONS: -DCOVERAGE=ON steps: - checkout - run: From fa1cb346ae3c79785bcf66fd0bb7bdb4ed130cdd Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Wed, 24 Oct 2018 13:23:15 +0200 Subject: [PATCH 014/168] Update syntax used for input and output parameters --- docs/layout-of-source-files.rst | 2 +- docs/types.rst | 2 +- docs/units-and-global-variables.rst | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 9a8bdc3e3..ad84b200c 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -276,7 +276,7 @@ functions, annotate conditions for formal verification, and provide a function. In the following example we document the title of the contract, the explanation -for the two input parameters and two returned values. +for the two function parameters and two return variables. :: diff --git a/docs/types.rst b/docs/types.rst index 34b94b88e..87e7011a2 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -253,7 +253,7 @@ Send is the low-level counterpart of ``transfer``. If the execution fails, the c In order to interface with contracts that do not adhere to the ABI, or to get more direct control over the encoding, the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. -They all take a single ``bytes memory`` argument as input and +They all take a single ``bytes memory`` parameter and return the success condition (as a ``bool``) and the returned data (``bytes memory``). The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 7f62e71e6..336aaf771 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -43,8 +43,8 @@ library has to be updated by an external oracle. .. note:: The suffix ``years`` has been removed in version 0.5.0 due to the reasons above. -These suffixes cannot be applied to variables. If you want to -interpret some input variable in e.g. days, you can do it in the following way:: +These suffixes cannot be applied to variables. For example, if you want to +interpret a function parameter in days, you can in the following way:: function f(uint start, uint daysAfter) public { if (now >= start + daysAfter * 1 days) { @@ -125,7 +125,7 @@ ABI Encoding and Decoding Functions These encoding functions can be used to craft data for external function calls without actually calling an external function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a way to compute the hash of structured data (although be aware that it is possible to - craft a "hash collision" using different inputs types). + craft a "hash collision" using different function parameter types). See the documentation about the :ref:`ABI ` and the :ref:`tightly packed encoding ` for details about the encoding. @@ -240,4 +240,3 @@ Furthermore, all functions of the current contract are callable directly includi .. note:: Prior to version 0.5.0, there was a function called ``suicide`` with the same semantics as ``selfdestruct``. - From eef6697355441273479c34358103e48d0275e39d Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Wed, 24 Oct 2018 13:18:26 +0200 Subject: [PATCH 015/168] Change terminology used for input output parameters Change from review Changes from review Changes fro review Changes from review --- docs/control-structures.rst | 80 +++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 5e3b722bb..889fbdb95 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -2,23 +2,22 @@ Expressions and Control Structures ################################## -.. index:: ! parameter, parameter;input, parameter;output, parameter;multiple +.. index:: ! parameter, parameter;input, parameter;output, function parameter, parameter;function, return variable, variable;return, return -Input Parameters and Output Parameters -====================================== +Function Parameters and Return Variables +======================================== -As in Javascript, functions may take parameters as input; -unlike in Javascript and C, they may also return arbitrary number of -parameters as output. +As in JavaScript, functions may take parameters as input. Unlike in JavaScript +and C, functions may also return an arbitrary number of values as output. -Input Parameters ----------------- +Function Parameters +------------------- -The input parameters are declared the same way as variables are. -The name of unused parameters can be omitted. -For example, suppose we want our contract to -accept one kind of external calls with two integers, we would write -something like:: +Function parameters are declared the same way as variables, and the name of +unused parameters can be omitted. + +For example, if you want your contract to accept one kind of external call +with two integers, you would use something like:: pragma solidity >=0.4.16 <0.6.0; @@ -29,18 +28,18 @@ something like:: } } -Input parameters can be used just as any other local variable -can be used, they can also be assigned to. +Function parameters can be used as any other local variable and they can also be assigned to. .. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct -Output Parameters ------------------ +Return Variables +---------------- -The output parameters can be declared with the same syntax after the -``returns`` keyword. For example, suppose we wished to return two results: -the sum and the product of the two given integers, then we would -write:: +Function return variables are declared with the same syntax after the +``returns`` keyword. + +For example, suppose you want to return two results: the sum and the product of +two integers passed as function parameters, then you use something like:: pragma solidity >=0.4.16 <0.6.0; @@ -55,12 +54,31 @@ write:: } } -The names of output parameters can be omitted. -The return values can be specified using ``return`` statements, -which are also capable of :ref:`returning multiple values`. -Return parameters can be used as any other local variable and they -are zero-initialized; if they are not explicitly -set, they stay zero. +The names of return variables can be omitted. +Return variables can be used as any other local variable and they +are zero-initialized. If they are not explicitly +set, they stay zero value. + +You can either explicitly assign to return variables and +then leave the function using ``return;``, +or you can provide return values +(either a single or :ref:`multiple ones`) directly with the ``return`` +statement:: + + pragma solidity >=0.4.16 <0.6.0; + + contract Simple { + function arithmetic(uint _a, uint _b) + public + pure + returns (uint o_sum, uint o_product) + { + return (_a + _b, _a * _b); + } + } + +This form is equivalent to first assigning values to the +return variables and then using ``return;`` to leave the function. .. note:: @@ -90,12 +108,12 @@ Solidity. .. _multi-return: -Returning Multiple Values -------------------------- +Returning Multiple Variables +---------------------------- -When a function has multiple output parameters, ``return (v0, v1, ..., +When a function has multiple return types, ``return (v0, v1, ..., vn)`` can return multiple values. The number of components must be -the same as the number of output parameters. +the same as the number of return types. .. index:: ! function;call, function;internal, function;external From 121d733b34ce71b28eb406c90e630b8d23d8b60d Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Tue, 10 Jul 2018 17:54:09 +0200 Subject: [PATCH 016/168] Begin review of micropayments example Language tidy, add correct method and package namespaces and make more consistent with each project docs First changes from review Further fixes after review Fix line breaks Revert code changes Update --- docs/solidity-by-example.rst | 189 ++++++++++++----------------------- 1 file changed, 65 insertions(+), 124 deletions(-) diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 752e86418..88ee79130 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -647,10 +647,10 @@ Safe Remote Purchase Micropayment Channel ******************** -In this section we will learn how to build a simple implementation -of a payment channel. It use cryptographics signatures to make +In this section we will learn how to build an example implementation +of a payment channel. It uses cryptographic signatures to make repeated transfers of Ether between the same parties secure, instantaneous, and -without transaction fees. To do it we need to understand how to +without transaction fees. For the example, we need to understand how to sign and verify signatures, and setup the payment channel. Creating and verifying signatures @@ -658,88 +658,69 @@ Creating and verifying signatures Imagine Alice wants to send a quantity of Ether to Bob, i.e. Alice is the sender and the Bob is the recipient. -Alice only needs to send cryptographically signed messages off-chain -(e.g. via email) to Bob and it will be very similar to writing checks. -Signatures are used to authorize transactions, -and they are a general tool that is available to -smart contracts. Alice will build a simple -smart contract that lets her transmit Ether, but -in a unusual way, instead of calling a function herself -to initiate a payment, she will let Bob -do that, and therefore pay the transaction fee. +Alice only needs to send cryptographically signed messages off-chain +(e.g. via email) to Bob and it is similar to writing checks. + +Alice and Bob use signatures to authorise transactions, which is possible with smart contracts on Ethereum. +Alice will build a simple smart contract that lets her transmit Ether, but instead of calling a function herself +to initiate a payment, she will let Bob do that, and therefore pay the transaction fee. + The contract will work as follows: 1. Alice deploys the ``ReceiverPays`` contract, attaching enough Ether to cover the payments that will be made. - 2. Alice authorizes a payment by signing a message with their private key. + 2. Alice authorises a payment by signing a message with their private key. 3. Alice sends the cryptographically signed message to Bob. The message does not need to be kept secret - (you will understand it later), and the mechanism for sending it does not matter. + (explained later), and the mechanism for sending it does not matter. 4. Bob claims their payment by presenting the signed message to the smart contract, it verifies the authenticity of the message and then releases the funds. Creating the signature ---------------------- -Alice does not need to interact with Ethereum network to -sign the transaction, the process is completely offline. -In this tutorial, we will sign messages in the browser -using ``web3.js`` and ``MetaMask``. -In particular, we will use the standard way described in `EIP-762 `_, +Alice does not need to interact with the Ethereum network to sign the transaction, the process is completely offline. +In this tutorial, we will sign messages in the browser using `web3.js `_ and `MetaMask `_, using the method described in `EIP-762 `_, as it provides a number of other security benefits. :: + /// Hashing first makes things easier + var hash = web3.utils.sha3("message to sign"); + web3.eth.personal.sign(hash, web3.eth.defaultAccount, function () { + console.log("Signed") + }); - /// Hashing first makes a few things easier - var hash = web3.sha3("message to sign"); - web3.personal.sign(hash, web3.eth.defaultAccount, function () {...}); - - -Note that the ``web3.personal.sign`` prepends the length of the message to the signed data. -Since we hash first, the message will always be exactly 32 bytes long, -and thus this length prefix is always the same, making everything easier. +.. note:: + The ``web3.eth.personal.sign`` prepends the length of the message to the signed data. Since we hash first, the message will always be exactly 32 bytes long, and thus this length prefix is always the same. What to Sign ------------ -For a contract that fulfills payments, the signed message must include: +For a contract that fulfils payments, the signed message must include: - 1. The recipient's address - 2. The amount to be transferred - 3. Protection against replay attacks + 1. The recipient's address. + 2. The amount to be transferred. + 3. Protection against replay attacks. A replay attack is when a signed message is reused to claim authorization for a second action. -To avoid replay attacks we will use the same as in Ethereum transactions +To avoid replay attacks we use the same as in Ethereum transactions themselves, a so-called nonce, which is the number of transactions sent by an account. -The smart contract will check if a nonce is used multiple times. +The smart contract checks if a nonce is used multiple times. -There is another type of replay attacks, it occurs when the -owner deploys a ``ReceiverPays`` smart contract, performs some payments, -and then destroy the contract. Later, she decides to deploy the -``RecipientPays`` smart contract again, but the new contract does not -know the nonces used in the previous deployment, so the attacker -can use the old messages again. +Another type of replay attack can occur when the owner deploys a ``ReceiverPays`` smart contract, makes some payments, and then destroys the contract. Later, they decide to deploy the ``RecipientPays`` smart contract again, but the new contract does not know the nonces used in the previous deployment, so the attacker can use the old messages again. -Alice can protect against it including -the contract's address in the message, and only -messages containing contract's address itself will be accepted. -This functionality can be found in the first two lines of the ``claimPayment()`` function in the full contract -at the end of this chapter. +Alice can protect against this attack by including the contract's address in the message, and only messages containing the contract's address itself will be accepted. You can find an example of this in the first two lines of the ``claimPayment()`` function of the full contract at the end of this section. Packing arguments ----------------- -Now that we have identified what information to include in the -signed message, we are ready to put the message together, hash it, -and sign it. For simplicity, we just concatenate the data. -The -`ethereumjs-abi `_ library provides -a function called ``soliditySHA3`` that mimics the behavior -of Solidity's ``keccak256`` function applied to arguments encoded -using ``abi.encodePacked``. -Putting it all together, here is a JavaScript function that -creates the proper signature for the ``ReceiverPays`` example: +Now that we have identified what information to include in the signed message, +we are ready to put the message together, hash it, and sign it. For simplicity, +we concatenate the data. The `ethereumjs-abi `_ +library provides a function called ``soliditySHA3`` that mimics the behaviour of +Solidity's ``keccak256`` function applied to arguments encoded using ``abi.encodePacked``. +Here is a JavaScript function that creates the proper signature for the ``ReceiverPays`` example: :: @@ -748,46 +729,30 @@ creates the proper signature for the ``ReceiverPays`` example: // nonce can be any unique number to prevent replay attacks // contractAddress is used to prevent cross-contract replay attacks function signPayment(recipient, amount, nonce, contractAddress, callback) { - var hash = "0x" + ethereumjs.ABI.soliditySHA3( + var hash = "0x" + abi.soliditySHA3( ["address", "uint256", "uint256", "address"], [recipient, amount, nonce, contractAddress] ).toString("hex"); - web3.personal.sign(hash, web3.eth.defaultAccount, callback); + web3.eth.personal.sign(hash, web3.eth.defaultAccount, callback); } Recovering the Message Signer in Solidity ----------------------------------------- -In general, ECDSA signatures consist of two parameters, ``r`` and ``s``. -Signatures in Ethereum include a third parameter called ``v``, that can be used -to recover which account's private key was used to sign in the message, -the transaction's sender. Solidity provides a built-in function -`ecrecover `_ -that accepts a message along with the ``r``, ``s`` and ``v`` parameters and -returns the address that was used to sign the message. +In general, ECDSA signatures consist of two parameters, ``r`` and ``s``. Signatures in Ethereum include a third parameter called ``v``, that you can use to verify which account's private key was used to sign the message, and the transaction's sender. Solidity provides a built-in function `ecrecover `_ that accepts a message along with the ``r``, ``s`` and ``v`` parameters and returns the address that was used to sign the message. Extracting the Signature Parameters ----------------------------------- -Signatures produced by web3.js are the concatenation of ``r``, ``s`` and ``v``, -so the first step is splitting those parameters back out. It can be done on the client, -but doing it inside the smart contract means only one signature parameter -needs to be sent rather than three. -Splitting apart a byte array into component parts is a little messy. -We will use `inline assembly `_ to do the job -in the ``splitSignature`` function (the third function in the full contract -at the end of this chapter). +Signatures produced by web3.js are the concatenation of ``r``, ``s`` and ``v``, so the first step is to split these parameters apart. You can do this on the client-side, but doing it inside the smart contract means you only need to send one signature parameter rather than three. Splitting apart a byte array into component parts is a messy, so we use `inline assembly `_ to do the job in the ``splitSignature`` function (the third function in the full contract at the end of this section). Computing the Message Hash -------------------------- -The smart contract needs to know exactly what parameters were signed, -and so it must recreate the message from the parameters and use that -for signature verification. The functions ``prefixed`` and -``recoverSigner`` do this and their use can be found in the -``claimPayment`` function. - +The smart contract needs to know exactly what parameters were signed, and so it +must recreate the message from the parameters and use that for signature verification. +The functions ``prefixed`` and ``recoverSigner`` do this in the ``claimPayment`` function. The full contract ----------------- @@ -861,41 +826,26 @@ The full contract Writing a Simple Payment Channel ================================ -Alice will now build a simple but complete implementation of a payment channel. -Payment channels use cryptographic signatures to make repeated transfers -of Ether securely, instantaneously, and without transaction fees. +Alice now builds a simple but complete implementation of a payment channel. Payment channels use cryptographic signatures to make repeated transfers of Ether securely, instantaneously, and without transaction fees. What is a Payment Channel? -------------------------- -Payment channels allow participants to make repeated transfers of Ether without -using transactions. This means that the delays and fees associated with transactions -can be avoided. We are going to explore a simple unidirectional payment channel between -two parties (Alice and Bob). Using it involves three steps: +Payment channels allow participants to make repeated transfers of Ether without using transactions. This means that you can avoid the delays and fees associated with transactions. We are going to explore a simple unidirectional payment channel between two parties (Alice and Bob). It involves three steps: 1. Alice funds a smart contract with Ether. This "opens" the payment channel. 2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment. 3. Bob "closes" the payment channel, withdrawing their portion of the Ether and sending the remainder back to the sender. -Note that only steps 1 and 3 require Ethereum transactions, step 2 means that -the sender transmits a cryptographically signed message to the recipient via off chain ways (e.g. email). -This means only two transactions are required to support any number of transfers. +.. note:: + Only steps 1 and 3 require Ethereum transactions, step 2 means that the sender transmits a cryptographically signed message to the recipient via off chain methods (e.g. email). This means only two transactions are required to support any number of transfers. -Bob is guaranteed to receive their funds because the smart contract escrows -the Ether and honors a valid signed message. The smart contract also enforces a timeout, -so Alice is guaranteed to eventually recover their funds even if the recipient refuses -to close the channel. -It is up to the participants in a payment channel to decide how long to keep it open. -For a short-lived transaction, such as paying an internet cafe for each minute of network access, -or for a longer relationship, such as paying an employee an hourly wage, a payment could last for months or years. +Bob is guaranteed to receive their funds because the smart contract escrows the Ether and honours a valid signed message. The smart contract also enforces a timeout, so Alice is guaranteed to eventually recover their funds even if the recipient refuses to close the channel. It is up to the participants in a payment channel to decide how long to keep it open. For a short-lived transaction, such as paying an internet café for each minute of network access, or for a longer relationship, such as paying an employee an hourly wage, a payment could last for months or years. Opening the Payment Channel --------------------------- -To open the payment channel, Alice deploys the smart contract, -attaching the Ether to be escrowed and specifying the intendend recipient -and a maximum duration for the channel to exist. It is the function -``SimplePaymentChannel`` in the contract, that is at the end of this chapter. +To open the payment channel, Alice deploys the smart contract, attaching the Ether to be escrowed and specifying the intended recipient and a maximum duration for the channel to exist. This is the function ``SimplePaymentChannel`` in the contract, at the end of this section. Making Payments --------------- @@ -910,27 +860,26 @@ Each message includes the following information: * The total amount of Ether that is owed the recipient so far. A payment channel is closed just once, at the end of a series of transfers. -Because of this, only one of the messages sent will be redeemed. This is why +Because of this, only one of the messages sent is redeemed. This is why each message specifies a cumulative total amount of Ether owed, rather than the amount of the individual micropayment. The recipient will naturally choose to redeem the most recent message because that is the one with the highest total. -The nonce per-message is not needed anymore, because the smart contract will -only honor a single message. The address of the smart contract is still used +The nonce per-message is not needed anymore, because the smart contract only honors a single message. The address of the smart contract is still used to prevent a message intended for one payment channel from being used for a different channel. -Here is the modified javascript code to cryptographically sign a message from the previous chapter: +Here is the modified JavaScript code to cryptographically sign a message from the previous section: :: function constructPaymentMessage(contractAddress, amount) { - return ethereumjs.ABI.soliditySHA3( + return abi.soliditySHA3( ["address", "uint256"], [contractAddress, amount] ); } function signMessage(message, callback) { - web3.personal.sign( + web3.eth.personal.sign( "0x" + message.toString("hex"), web3.eth.defaultAccount, callback @@ -951,18 +900,15 @@ Closing the Payment Channel When Bob is ready to receive their funds, it is time to close the payment channel by calling a ``close`` function on the smart contract. -Closing the channel pays the recipient the Ether they are owed and destroys the contract, -sending any remaining Ether back to Alice. -To close the channel, Bob needs to provide a message signed by Alice. +Closing the channel pays the recipient the Ether they are owed and destroys the contract, sending any remaining Ether back to Alice. To close the channel, Bob needs to provide a message signed by Alice. The smart contract must verify that the message contains a valid signature from the sender. The process for doing this verification is the same as the process the recipient uses. The Solidity functions ``isValidSignature`` and ``recoverSigner`` work just like their -JavaScript counterparts in the previous section. The latter is borrowed from the -``ReceiverPays`` contract in the previous chapter. +JavaScript counterparts in the previous section, with the latter function borrowed from the ``ReceiverPays`` contract. -The ``close`` function can only be called by the payment channel recipient, -who will naturally pass the most recent payment message because that message +Only the payment channel recipient can call the ``close`` function, +who naturally passes the most recent payment message because that message carries the highest total owed. If the sender were allowed to call this function, they could provide a message with a lower amount and cheat the recipient out of what they are owed. @@ -977,13 +923,11 @@ Channel Expiration Bob can close the payment channel at any time, but if they fail to do so, Alice needs a way to recover their escrowed funds. An *expiration* time was set at the time of contract deployment. Once that time is reached, Alice can call -``claimTimeout`` to recover their funds. You can see the ``claimTimeout`` function in the -full contract. +``claimTimeout`` to recover their funds. You can see the ``claimTimeout`` function in the full contract. After this function is called, Bob can no longer receive any Ether, so it is important that Bob closes the channel before the expiration is reached. - The full contract ----------------- @@ -1081,16 +1025,15 @@ The full contract } -Note: The function ``splitSignature`` is very simple and does not use all security checks. -A real implementation should use a more rigorously tested library, such as -openzepplin's `version `_ of this code. - - +.. note:: + The function ``splitSignature`` does not use all security + checks. A real implementation should use a more rigorously tested library, + such as openzepplin's `version `_ of this code. Verifying Payments ------------------ -Unlike in our previous chapter, messages in a payment channel aren't +Unlike in the previous section, messages in a payment channel aren't redeemed right away. The recipient keeps track of the latest message and redeems it when it's time to close the payment channel. This means it's critical that the recipient perform their own verification of each message. @@ -1105,10 +1048,8 @@ The recipient should verify each message using the following process: 4. Verify that the signature is valid and comes from the payment channel sender. We'll use the `ethereumjs-util `_ -library to write this verifications. The final step can be done a number of ways, -but if it's being done in **JavaScript**. -The following code borrows the `constructMessage` function from the signing **JavaScript code** -above: +library to write this verification. The final step can be done a number of ways, +and we use JavaScript. The following code borrows the `constructMessage` function from the signing **JavaScript code** above: :: From 5783ebb93d12b50321ac8a75b128db514ae64b62 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 14 Nov 2018 17:33:02 +0100 Subject: [PATCH 017/168] Small changes to yul object specification. --- docs/yul.rst | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index ea0a298b2..2784078c5 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -515,6 +515,16 @@ The following functions must be available: +---------------------------------------------+-----------------------------------------------------------------+ | keccak256(p:u256, s:u256) -> v:u256 | keccak(mem[p...(p+s))) | +---------------------------------------------+-----------------------------------------------------------------+ +| *Object access* | | ++---------------------------------------------+-----------------------------------------------------------------+ +| datasize(name:string) -> size:u256 | size of the data object in bytes, name has to be string literal | ++---------------------------------------------+-----------------------------------------------------------------+ +| dataoffset(name:string) -> offset:u256 | offset of the data object inside the data area in bytes, | +| | name has to be string literal | ++---------------------------------------------+-----------------------------------------------------------------+ +| datacopy(dst:u256, src:u256, len:u256) | copy len bytes from the data area starting at offset src bytes | +| | to memory at position dst | ++---------------------------------------------+-----------------------------------------------------------------+ Backends -------- @@ -540,12 +550,19 @@ TBD Specification of Yul Object =========================== +Yul objects are used to group named code and data sections. +The functions ``datasize``, ``dataoffset`` and ``datacopy`` +can be used to access these sections from within code. +Hex strings can be used to specify data in hex encoding, +regular strings in native encoding. For code, +``datacopy`` will access its assembled binary representation. + Grammar:: TopLevelObject = 'object' '{' Code? ( Object | Data )* '}' Object = 'object' StringLiteral '{' Code? ( Object | Data )* '}' Code = 'code' Block - Data = 'data' StringLiteral HexLiteral + Data = 'data' StringLiteral ( HexLiteral | StringLiteral ) HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' @@ -558,14 +575,28 @@ An example Yul Object is shown below: // Code consists of a single object. A single "code" node is the code of the object. // Every (other) named object or data section is serialized and // made accessible to the special built-in functions datacopy / dataoffset / datasize - object { + // Access to nested objects can be performed by joining the names using ``.``. + // The current object and sub-objects and data items inside the current object + // are in scope without nested access. + object "Contract1" { code { - let size = datasize("runtime") + // first create "runtime.Contract2" + let size = datasize("runtime.Contract2") let offset = allocate(size) // This will turn into a memory->memory copy for eWASM and // a codecopy for EVM - datacopy(dataoffset("runtime"), offset, size) - // this is a constructor and the runtime code is returned + datacopy(offset, dataoffset("runtime.Contract2"), size) + // constructor parameter is a single number 0x1234 + mstore(add(offset, size), 0x1234) + create(offset, add(size, 32)) + + // now return the runtime object (this is + // constructor code) + size := datasize("runtime") + offset := allocate(size) + // This will turn into a memory->memory copy for eWASM and + // a codecopy for EVM + datacopy(offset, dataoffset("runtime"), size) return(offset, size) } @@ -579,7 +610,7 @@ An example Yul Object is shown below: let offset = allocate(size) // This will turn into a memory->memory copy for eWASM and // a codecopy for EVM - datacopy(dataoffset("Contract2"), offset, size) + datacopy(offset, dataoffset("Contract2"), size) // constructor parameter is a single number 0x1234 mstore(add(offset, size), 0x1234) create(offset, add(size, 32)) From b6e2e4ad6b909500ed0f015d79927941f8a0de95 Mon Sep 17 00:00:00 2001 From: Yet another codejunkie <2772295+kn1g@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:31:22 +0100 Subject: [PATCH 018/168] Consistent use of address() First example is with address() and the following examples without. I suggest a consistent use here. --- docs/types.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 87e7011a2..04f8d808e 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -280,15 +280,15 @@ Example:: It is possible to adjust the supplied gas with the ``.gas()`` modifier:: - namReg.call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); + address(namReg).call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); Similarly, the supplied Ether value can be controlled too:: - nameReg.call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); Lastly, these modifiers can be combined. Their order does not matter:: - nameReg.call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. From 727e3f24bc57b9470b7972fe882d60117625afe5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 7 Nov 2018 23:52:13 +0100 Subject: [PATCH 019/168] Do not perform cleanup on unsigned integers when loading from calldata. --- Changelog.md | 1 + libsolidity/codegen/CompilerUtils.cpp | 9 ++++++++- test/libsolidity/Assembly.cpp | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index b5e7eed81..b2b03ae4a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. + * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. Bugfixes: diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 90eb74fea..a0d110175 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -1236,6 +1236,7 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda } solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested."); m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD); + bool cleanupNeeded = true; if (isExternalFunctionType) splitExternalFunctionType(true); else if (numBytes != 32) @@ -1245,10 +1246,16 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda int shiftFactor = (32 - numBytes) * 8; rightShiftNumberOnStack(shiftFactor); if (leftAligned) + { leftShiftNumberOnStack(shiftFactor); + cleanupNeeded = false; + } + else if (IntegerType const* intType = dynamic_cast(&_type)) + if (!intType->isSigned()) + cleanupNeeded = false; } if (_fromCalldata) - convertType(_type, _type, true, false, true); + convertType(_type, _type, cleanupNeeded, false, true); return numBytes; } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index e815d7d59..5e1576788 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -160,7 +160,7 @@ BOOST_AUTO_TEST_CASE(location_test) AssemblyItems items = compileContract(sourceCode); bool hasShifts = dev::test::Options::get().evmVersion().hasBitwiseShifting(); vector locations = - vector(hasShifts ? 23 : 24, SourceLocation(2, 82, make_shared(""))) + + vector(hasShifts ? 21 : 22, SourceLocation(2, 82, make_shared(""))) + vector(2, SourceLocation(20, 79, make_shared(""))) + vector(1, SourceLocation(8, 17, make_shared("--CODEGEN--"))) + vector(3, SourceLocation(5, 7, make_shared("--CODEGEN--"))) + From d66052554c434ab0f1423ff44b1e645c96a59b34 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 14 Nov 2018 21:00:33 +0000 Subject: [PATCH 020/168] Fix indentation in documentation --- docs/solidity-by-example.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 88ee79130..d07452c5b 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -685,9 +685,7 @@ as it provides a number of other security benefits. :: /// Hashing first makes things easier var hash = web3.utils.sha3("message to sign"); - web3.eth.personal.sign(hash, web3.eth.defaultAccount, function () { - console.log("Signed") - }); + web3.eth.personal.sign(hash, web3.eth.defaultAccount, function () { console.log("Signed"); }); .. note:: The ``web3.eth.personal.sign`` prepends the length of the message to the signed data. Since we hash first, the message will always be exactly 32 bytes long, and thus this length prefix is always the same. From bddbdebd91234361982ccb8c50c7a7b46f6ac884 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 14 Nov 2018 22:39:12 -0500 Subject: [PATCH 021/168] Qualify that storage slots are shared for contiguous data --- docs/miscellaneous.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 21978ded0..cc2ba8012 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -8,7 +8,7 @@ Miscellaneous Layout of State Variables in Storage ************************************ -Statically-sized variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position ``0``. Multiple items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules: +Statically-sized variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position ``0``. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules: - The first item in a storage slot is stored lower-order aligned. - Elementary types use only that many bytes that are necessary to store them. From 70bb0eaf95ab6a549f875b845395b31a5d49f99e Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Thu, 25 Oct 2018 16:00:09 +0200 Subject: [PATCH 022/168] [SMTChecker] Implement uninterpreted functions and use it for blockhash() --- Changelog.md | 2 ++ libsolidity/formal/CVC4Interface.cpp | 10 ++++++- libsolidity/formal/CVC4Interface.h | 3 ++- libsolidity/formal/SMTChecker.cpp | 22 ++++++++++++--- libsolidity/formal/SMTChecker.h | 6 +++++ libsolidity/formal/SMTLib2Interface.cpp | 20 ++++++++++++-- libsolidity/formal/SMTLib2Interface.h | 3 ++- libsolidity/formal/SMTPortfolio.cpp | 2 +- libsolidity/formal/SMTPortfolio.h | 2 +- libsolidity/formal/SolverInterface.h | 27 ++++++++++--------- libsolidity/formal/SymbolicTypes.cpp | 9 +++++++ libsolidity/formal/SymbolicTypes.h | 3 +++ libsolidity/formal/SymbolicVariables.cpp | 5 ++++ libsolidity/formal/SymbolicVariables.h | 2 ++ libsolidity/formal/Z3Interface.cpp | 10 ++++++- libsolidity/formal/Z3Interface.h | 3 ++- .../smtCheckerTests/special/blockhash.sol | 8 ++++-- 17 files changed, 110 insertions(+), 27 deletions(-) diff --git a/Changelog.md b/Changelog.md index b2b03ae4a..fae28bb78 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,8 @@ Language Features: Compiler Features: * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. + * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. + * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. Bugfixes: diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index 6cb914834..118229279 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -50,7 +50,7 @@ void CVC4Interface::pop() m_solver.pop(); } -void CVC4Interface::declareFunction(string _name, Sort _domain, Sort _codomain) +void CVC4Interface::declareFunction(string _name, vector const& _domain, Sort _codomain) { if (!m_functions.count(_name)) { @@ -201,3 +201,11 @@ CVC4::Type CVC4Interface::cvc4Sort(Sort _sort) // Cannot be reached. return m_context.integerType(); } + +vector CVC4Interface::cvc4Sort(vector const& _sorts) +{ + vector cvc4Sorts; + for (auto const& _sort: _sorts) + cvc4Sorts.push_back(cvc4Sort(_sort)); + return cvc4Sorts; +} diff --git a/libsolidity/formal/CVC4Interface.h b/libsolidity/formal/CVC4Interface.h index cd6d761dd..273dce235 100644 --- a/libsolidity/formal/CVC4Interface.h +++ b/libsolidity/formal/CVC4Interface.h @@ -51,7 +51,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, Sort _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; @@ -61,6 +61,7 @@ public: private: CVC4::Expr toCVC4Expr(Expression const& _expr); CVC4::Type cvc4Sort(smt::Sort _sort); + std::vector cvc4Sort(std::vector const& _sort); CVC4::ExprManager m_context; CVC4::SmtEngine m_solver; diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index cc580021e..9a2b9bbf9 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -78,6 +78,9 @@ bool SMTChecker::visit(FunctionDefinition const& _function) m_interface->reset(); m_pathConditions.clear(); m_expressions.clear(); + m_specialVariables.clear(); + m_uninterpretedFunctions.clear(); + m_uninterpretedTerms.clear(); resetStateVariables(); initializeLocalVariables(_function); } @@ -412,9 +415,12 @@ void SMTChecker::visitGasLeft(FunctionCall const& _funCall) void SMTChecker::visitBlockHash(FunctionCall const& _funCall) { - string blockHash = "blockhash()"; - // TODO Define blockhash as an uninterpreted function - defineSpecialVariable(blockHash, _funCall); + string blockHash = "blockhash"; + defineUninterpretedFunction(blockHash, {smt::Sort::Int}, smt::Sort::Int); + auto const& arguments = _funCall.arguments(); + solAssert(arguments.size() == 1, ""); + defineExpr(_funCall, m_uninterpretedFunctions.at(blockHash)({expr(*arguments[0])})); + m_uninterpretedTerms.push_back(&_funCall); } void SMTChecker::inlineFunctionCall(FunctionCall const& _funCall) @@ -587,6 +593,11 @@ void SMTChecker::defineSpecialVariable(string const& _name, Expression const& _e defineExpr(_expr, m_specialVariables.at(_name)->currentValue()); } +void SMTChecker::defineUninterpretedFunction(string const& _name, vector const& _domain, smt::Sort _codomain) +{ + if (!m_uninterpretedFunctions.count(_name)) + m_uninterpretedFunctions.emplace(_name, m_interface->newFunction(_name, _domain, _codomain)); +} void SMTChecker::arithmeticOperation(BinaryOperation const& _op) { @@ -770,6 +781,11 @@ void SMTChecker::checkCondition( expressionsToEvaluate.emplace_back(var.second->currentValue()); expressionNames.push_back(var.first); } + for (auto const& uf: m_uninterpretedTerms) + { + expressionsToEvaluate.emplace_back(expr(*uf)); + expressionNames.push_back(m_scanner->sourceAt(uf->location())); + } } smt::CheckResult result; vector values; diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index a7f955dd4..869c9c50a 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -83,6 +83,7 @@ private: void inlineFunctionCall(FunctionCall const&); void defineSpecialVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex = false); + void defineUninterpretedFunction(std::string const& _name, std::vector const& _domain, smt::Sort _codomain); /// Division expression in the given type. Requires special treatment because /// of rounding for signed division. @@ -193,6 +194,11 @@ private: std::unordered_map> m_expressions; std::unordered_map> m_variables; std::unordered_map> m_specialVariables; + /// Stores the declaration of an Uninterpreted Function. + std::unordered_map m_uninterpretedFunctions; + /// Stores the instances of an Uninterpreted Function applied to arguments. + /// Used to retrieve models. + std::vector m_uninterpretedTerms; std::vector m_pathConditions; ErrorReporter& m_errorReporter; std::shared_ptr m_scanner; diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index a6c1f87c7..545422338 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -64,9 +64,12 @@ void SMTLib2Interface::pop() m_accumulatedOutput.pop_back(); } -void SMTLib2Interface::declareFunction(string _name, Sort _domain, Sort _codomain) +void SMTLib2Interface::declareFunction(string _name, vector const& _domain, Sort _codomain) { // TODO Use domain and codomain as key as well + string domain(""); + for (auto const& sort: _domain) + domain += toSmtLibSort(sort) + ' '; if (!m_functions.count(_name)) { m_functions.insert(_name); @@ -74,7 +77,7 @@ void SMTLib2Interface::declareFunction(string _name, Sort _domain, Sort _codomai "(declare-fun |" + _name + "| (" + - (_domain == Sort::Int ? "Int" : "Bool") + + domain + ") " + (_codomain == Sort::Int ? "Int" : "Bool") + ")" @@ -140,6 +143,19 @@ string SMTLib2Interface::toSExpr(Expression const& _expr) return sexpr; } +string SMTLib2Interface::toSmtLibSort(Sort _sort) +{ + switch (_sort) + { + case Sort::Int: + return "Int"; + case Sort::Bool: + return "Bool"; + default: + solAssert(false, "Invalid SMT sort"); + } +} + void SMTLib2Interface::write(string _data) { solAssert(!m_accumulatedOutput.empty(), ""); diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index eb876a7f0..08ad74daf 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -49,7 +49,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, Sort _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; @@ -58,6 +58,7 @@ public: private: std::string toSExpr(Expression const& _expr); + std::string toSmtLibSort(Sort _sort); void write(std::string _data); diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index 8b9fe9ce1..e1cde04c6 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -64,7 +64,7 @@ void SMTPortfolio::pop() s->pop(); } -void SMTPortfolio::declareFunction(string _name, Sort _domain, Sort _codomain) +void SMTPortfolio::declareFunction(string _name, vector const& _domain, Sort _codomain) { for (auto s : m_solvers) s->declareFunction(_name, _domain, _codomain); diff --git a/libsolidity/formal/SMTPortfolio.h b/libsolidity/formal/SMTPortfolio.h index 96c7ff57b..50bd87d46 100644 --- a/libsolidity/formal/SMTPortfolio.h +++ b/libsolidity/formal/SMTPortfolio.h @@ -49,7 +49,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, Sort _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index af1cc8e40..a6618fb59 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -45,9 +45,7 @@ enum class CheckResult enum class Sort { Int, - Bool, - IntIntFun, // Function of one Int returning a single Int - IntBoolFun // Function of one Int returning a single Bool + Bool }; /// C++ representation of an SMTLIB2 expression. @@ -150,7 +148,7 @@ public: { return Expression("/", std::move(_a), std::move(_b), Sort::Int); } - Expression operator()(Expression _a) const + Expression operator()(std::vector _arguments) const { solAssert( arguments.empty(), @@ -158,10 +156,10 @@ public: ); switch (sort) { - case Sort::IntIntFun: - return Expression(name, _a, Sort::Int); - case Sort::IntBoolFun: - return Expression(name, _a, Sort::Bool); + case Sort::Int: + return Expression(name, std::move(_arguments), Sort::Int); + case Sort::Bool: + return Expression(name, std::move(_arguments), Sort::Bool); default: solAssert( false, @@ -199,18 +197,21 @@ public: virtual void push() = 0; virtual void pop() = 0; - virtual void declareFunction(std::string _name, Sort _domain, Sort _codomain) = 0; - Expression newFunction(std::string _name, Sort _domain, Sort _codomain) + virtual void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) = 0; + void declareFunction(std::string _name, Sort _domain, Sort _codomain) + { + declareFunction(std::move(_name), std::vector{std::move(_domain)}, std::move(_codomain)); + } + Expression newFunction(std::string _name, std::vector const& _domain, Sort _codomain) { declareFunction(_name, _domain, _codomain); - solAssert(_domain == Sort::Int, "Function sort not supported."); // Subclasses should do something here switch (_codomain) { case Sort::Int: - return Expression(std::move(_name), {}, Sort::IntIntFun); + return Expression(std::move(_name), {}, Sort::Int); case Sort::Bool: - return Expression(std::move(_name), {}, Sort::IntBoolFun); + return Expression(std::move(_name), {}, Sort::Bool); default: solAssert(false, "Function sort not supported."); break; diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 3eb1c1ce6..78bf861bf 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -24,6 +24,15 @@ using namespace std; using namespace dev::solidity; +smt::Sort dev::solidity::smtSort(Type::Category _category) +{ + if (isNumber(_category)) + return smt::Sort::Int; + else if (isBool(_category)) + return smt::Sort::Bool; + solAssert(false, "Invalid type"); +} + bool dev::solidity::isSupportedType(Type::Category _category) { return isNumber(_category) || diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index dcdd9ea42..2639fcb94 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -28,6 +28,9 @@ namespace dev namespace solidity { +/// Returns the SMT sort that models the Solidity type _type. +smt::Sort smtSort(Type::Category _type); + /// So far int, bool and address are supported. /// Returns true if type is supported. bool isSupportedType(Type::Category _category); diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 85818ba07..194c843ec 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -37,6 +37,11 @@ SymbolicVariable::SymbolicVariable( { } +string SymbolicVariable::currentName() const +{ + return uniqueSymbol(m_ssa->index()); +} + string SymbolicVariable::uniqueSymbol(unsigned _index) const { return m_uniqueName + "_" + to_string(_index); diff --git a/libsolidity/formal/SymbolicVariables.h b/libsolidity/formal/SymbolicVariables.h index 4fd9b2451..13b944a5a 100644 --- a/libsolidity/formal/SymbolicVariables.h +++ b/libsolidity/formal/SymbolicVariables.h @@ -51,6 +51,8 @@ public: return valueAtIndex(m_ssa->index()); } + std::string currentName() const; + virtual smt::Expression valueAtIndex(int _index) const = 0; smt::Expression increaseIndex() diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 9a0ccf48b..2519e41b7 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -51,7 +51,7 @@ void Z3Interface::pop() m_solver.pop(); } -void Z3Interface::declareFunction(string _name, Sort _domain, Sort _codomain) +void Z3Interface::declareFunction(string _name, vector const& _domain, Sort _codomain) { if (!m_functions.count(_name)) m_functions.insert({_name, m_context.function(_name.c_str(), z3Sort(_domain), z3Sort(_codomain))}); @@ -183,3 +183,11 @@ z3::sort Z3Interface::z3Sort(Sort _sort) // Cannot be reached. return m_context.int_sort(); } + +z3::sort_vector Z3Interface::z3Sort(vector const& _sorts) +{ + z3::sort_vector z3Sorts(m_context); + for (auto const& _sort: _sorts) + z3Sorts.push_back(z3Sort(_sort)); + return z3Sorts; +} diff --git a/libsolidity/formal/Z3Interface.h b/libsolidity/formal/Z3Interface.h index 84880ff32..5eae618e8 100644 --- a/libsolidity/formal/Z3Interface.h +++ b/libsolidity/formal/Z3Interface.h @@ -40,7 +40,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, Sort _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; @@ -50,6 +50,7 @@ public: private: z3::expr toZ3Expr(Expression const& _expr); z3::sort z3Sort(smt::Sort _sort); + z3::sort_vector z3Sort(std::vector const& _sort); z3::context m_context; z3::solver m_solver; diff --git a/test/libsolidity/smtCheckerTests/special/blockhash.sol b/test/libsolidity/smtCheckerTests/special/blockhash.sol index 1c6939142..59a529228 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 From caf44302e56208a5ee428d87b27fe647813886da Mon Sep 17 00:00:00 2001 From: Yet another codejunkie <2772295+kn1g@users.noreply.github.com> Date: Thu, 15 Nov 2018 10:10:28 +0100 Subject: [PATCH 023/168] Fixed consistent use of `nameReg` Fixed consistent use of `nameReg` instead of `namReg` --- docs/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index 04f8d808e..020cb1059 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -280,7 +280,7 @@ Example:: It is possible to adjust the supplied gas with the ``.gas()`` modifier:: - address(namReg).call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); Similarly, the supplied Ether value can be controlled too:: From 5f4eb96341ee59f214e3a87c4d9bd4bdb608eed5 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Thu, 15 Nov 2018 11:55:57 +0100 Subject: [PATCH 024/168] Remove Struct copy FAQ item --- docs/frequently-asked-questions.rst | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 8b655b0d3..a100bb15d 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -232,24 +232,6 @@ Note2: Optimizing storage access can pull the gas costs down considerably, becau currently do not work across loops and also have a problem with bounds checking. You might get much better results in the future, though. -What happens to a ``struct``'s mapping when copying over a ``struct``? -====================================================================== - -This is a very interesting question. Suppose that we have a contract field set up like such:: - - struct User { - mapping(string => string) comments; - } - - function somefunction public { - User user1; - user1.comments["Hello"] = "World"; - User user2 = user1; - } - -In this case, the mapping of the struct being copied over into ``user2`` is ignored as there is no "list of mapped keys". -Therefore it is not possible to find out which values should be copied over. - How do I initialize a contract with only a specific amount of wei? ================================================================== From f1d02432a69b44b6bcf784892c332c9f47a829b3 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Thu, 15 Nov 2018 12:02:38 +0100 Subject: [PATCH 025/168] Move undefined FAQ item --- docs/frequently-asked-questions.rst | 38 ----------------------------- docs/types.rst | 2 ++ 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 8b655b0d3..a569a8965 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -143,44 +143,6 @@ arguments for you. See `ping.sol `_ and `pong.sol `_. -When returning a value of say ``uint`` type, is it possible to return an ``undefined`` or "null"-like value? -============================================================================================================ - -This is not possible, because all types use up the full value range. - -You have the option to ``throw`` on error, which will also revert the whole -transaction, which might be a good idea if you ran into an unexpected -situation. - -If you do not want to throw, you can return a pair:: - - pragma solidity >0.4.23 <0.6.0; - - contract C { - uint[] counters; - - function getCounter(uint index) - public - view - returns (uint counter, bool error) { - if (index >= counters.length) - return (0, true); - else - return (counters[index], false); - } - - function checkCounter(uint index) public view { - (uint counter, bool error) = getCounter(index); - if (error) { - // Handle the error - } else { - // Do something with counter. - require(counter > 7, "Invalid counter value"); - } - } - } - - Are comments included with deployed contracts and do they increase deployment gas? ================================================================================== diff --git a/docs/types.rst b/docs/types.rst index 020cb1059..e01e2f775 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -13,6 +13,8 @@ Solidity provides several elementary types which can be combined to form complex In addition, types can interact with each other in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. +The concept of "undefined" or "null" values do not exist in Solidity. To handle any unexpected values, you should use the :ref:`revert function` to revert the whole transaction. + .. index:: ! value type, ! type;value Value Types From 9b657134ef33a5a01dd09d8fcd7a13922bb7aaa4 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Thu, 15 Nov 2018 12:11:25 +0100 Subject: [PATCH 026/168] Remove length related FAQ item --- docs/frequently-asked-questions.rst | 44 ----------------------------- docs/types.rst | 4 ++- 2 files changed, 3 insertions(+), 45 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 8b655b0d3..985d8d3ce 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -325,50 +325,6 @@ to create an independent copy of the storage value in memory. On the other hand, ``h(x)`` successfully modifies ``x`` because only a reference and not a copy is passed. -Sometimes, when I try to change the length of an array with ex: ``arrayname.length = 7;`` I get a compiler error ``Value must be an lvalue``. Why? -================================================================================================================================================== - -You can resize a dynamic array in storage (i.e. an array declared at the -contract level) with ``arrayname.length = ;``. If you get the -"lvalue" error, you are probably doing one of two things wrong. - -1. You might be trying to resize an array in "memory", or - -2. You might be trying to resize a non-dynamic array. - -:: - - pragma solidity >=0.4.18 <0.6.0; - - // This will not compile - contract C { - int8[] dynamicStorageArray; - int8[5] fixedStorageArray; - - function f() public { - int8[] memory memArr; // Case 1 - memArr.length++; // illegal - - int8[5] storage storageArr = fixedStorageArray; // Case 2 - storageArr.length++; // illegal - - int8[] storage storageArr2 = dynamicStorageArray; - storageArr2.length++; // legal - - - } - } - -**Important note:** In Solidity, array dimensions are declared backwards from the way you -might be used to declaring them in C or Java, but they are access as in -C or Java. - -For example, ``int8[][5] somearray;`` are 5 dynamic ``int8`` arrays. - -The reason for this is that ``T[5]`` is always an array of 5 ``T``'s, -no matter whether ``T`` itself is an array or not (this is not the -case in C or Java). - Is it possible to return an array of strings (``string[]``) from a Solidity function? ===================================================================================== diff --git a/docs/types.rst b/docs/types.rst index 020cb1059..b84d32226 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -913,7 +913,9 @@ Members For dynamically-sized arrays (only available for storage), this member can be assigned to resize the array. Accessing elements outside the current length does not automatically resize the array and instead causes a failing assertion. Increasing the length adds new zero-initialised elements to the array. - Reducing the length performs an implicit :ref:``delete`` on each of the removed elements. + Reducing the length performs an implicit :ref:``delete`` on each of the + removed elements. If you try to resize a non-dynamic array that isn't in + storage, you receive a ``Value must be an lvalue`` error. **push**: Dynamic storage arrays and ``bytes`` (not ``string``) have a member function called ``push`` that you can use to append an element at the end of the array. The element will be zero-initialised. The function returns the new length. **pop**: From 7debfa757004d65c5fb88c51a5dcd9c43c2c18c9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 15 Nov 2018 12:08:35 +0000 Subject: [PATCH 027/168] Ask for target EVM version in issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index c3caf86e3..dd4d0b410 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -21,6 +21,7 @@ about: Bug reports about the Solidity Compiler. ## Environment - Compiler version: +- Target EVM version (as per compiler settings): - Framework/IDE (e.g. Truffle or Remix): - EVM execution environment / backend / blockchain client: - Operating system: From f705a45d43d69ca4f29bd496d091f7237bdc31ff Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 7 Nov 2018 11:18:02 +0100 Subject: [PATCH 028/168] [Yul] Implements a pass to rewrite for-loop's pre block into the parent's Block. --- libyul/optimiser/ForLoopInitRewriter.cpp | 43 +++++++++++++++++++ libyul/optimiser/ForLoopInitRewriter.h | 39 +++++++++++++++++ libyul/optimiser/Suite.cpp | 2 + test/libyul/YulOptimizerTest.cpp | 6 +++ .../forLoopInitRewriter/complex_pre.yul | 23 ++++++++++ .../forLoopInitRewriter/empty_pre.yul | 20 +++++++++ .../forLoopInitRewriter/simple.yul | 21 +++++++++ test/tools/yulopti.cpp | 6 ++- 8 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 libyul/optimiser/ForLoopInitRewriter.cpp create mode 100644 libyul/optimiser/ForLoopInitRewriter.h create mode 100644 test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul create mode 100644 test/libyul/yulOptimizerTests/forLoopInitRewriter/empty_pre.yul create mode 100644 test/libyul/yulOptimizerTests/forLoopInitRewriter/simple.yul diff --git a/libyul/optimiser/ForLoopInitRewriter.cpp b/libyul/optimiser/ForLoopInitRewriter.cpp new file mode 100644 index 000000000..0decf5e22 --- /dev/null +++ b/libyul/optimiser/ForLoopInitRewriter.cpp @@ -0,0 +1,43 @@ +/* + 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 . +*/ +#include +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::yul; + +void ForLoopInitRewriter::operator()(Block& _block) +{ + iterateReplacing( + _block.statements, + [](Statement& _stmt) -> boost::optional> + { + if (_stmt.type() == typeid(ForLoop)) + { + auto& forLoop = boost::get(_stmt); + vector rewrite; + swap(rewrite, forLoop.pre.statements); + rewrite.emplace_back(move(forLoop)); + return rewrite; + } + return {}; + } + ); +} diff --git a/libyul/optimiser/ForLoopInitRewriter.h b/libyul/optimiser/ForLoopInitRewriter.h new file mode 100644 index 000000000..64f537111 --- /dev/null +++ b/libyul/optimiser/ForLoopInitRewriter.h @@ -0,0 +1,39 @@ +/* + 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 . +*/ +#pragma once + +#include + +namespace dev +{ +namespace yul +{ + +/** + * Rewrites ForLoop by moving the pre statement block in front of the ForLoop. + * Requirements: + * - The Disambiguator must be run upfront. + */ +class ForLoopInitRewriter: public ASTModifier +{ +public: + using ASTModifier::operator(); + void operator()(Block& _block) override; +}; + +} +} diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 7d52a5a8d..4d6dad45b 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ void OptimiserSuite::run( (FunctionHoister{})(ast); (FunctionGrouper{})(ast); + (ForLoopInitRewriter{})(ast); NameDispenser dispenser{ast}; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 03cd6446d..9e2577177 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,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(); diff --git a/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul b/test/libyul/yulOptimizerTests/forLoopInitRewriter/complex_pre.yul new file mode 100644 index 000000000..3ca00f557 --- /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 000000000..05aceb520 --- /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 000000000..565b77251 --- /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/yulopti.cpp b/test/tools/yulopti.cpp index 348c5f4a1..3e96ef356 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -123,7 +124,7 @@ public: } 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; From 06c3f0953ae9f9921683f80349c7b1bbddcb3a9f Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Thu, 25 Oct 2018 17:50:31 +0200 Subject: [PATCH 029/168] [SMTChecker] Support bound function calls --- Changelog.md | 1 + libsolidity/formal/SMTChecker.cpp | 12 +++++++++++ .../functions/functions_bound_1.sol | 19 +++++++++++++++++ .../functions/functions_bound_1_fail.sol | 21 +++++++++++++++++++ .../functions/functions_library_1.sol | 18 ++++++++++++++++ .../functions/functions_library_1_fail.sol | 20 ++++++++++++++++++ 6 files changed, 91 insertions(+) create mode 100644 test/libsolidity/smtCheckerTests/functions/functions_bound_1.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/functions_bound_1_fail.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/functions_library_1.sol create mode 100644 test/libsolidity/smtCheckerTests/functions/functions_library_1_fail.sol diff --git a/Changelog.md b/Changelog.md index fae28bb78..197419fae 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. + * SMTChecker: Support internal bound function calls. Bugfixes: diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 9a2b9bbf9..bbc78c0c7 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -457,6 +457,14 @@ void SMTChecker::inlineFunctionCall(FunctionCall const& _funCall) else if (_funDef && _funDef->isImplemented()) { vector funArgs; + auto const& funType = dynamic_cast(_calledExpr->annotation().type.get()); + solAssert(funType, ""); + if (funType->bound()) + { + auto const& boundFunction = dynamic_cast(_calledExpr); + solAssert(boundFunction, ""); + funArgs.push_back(expr(boundFunction->expression())); + } for (auto arg: _funCall.arguments()) funArgs.push_back(expr(*arg)); initializeFunctionCallParameters(*_funDef, funArgs); @@ -548,6 +556,10 @@ void SMTChecker::endVisit(Return const& _return) bool SMTChecker::visit(MemberAccess const& _memberAccess) { + auto const& accessType = _memberAccess.annotation().type; + if (accessType->category() == Type::Category::Function) + return true; + auto const& exprType = _memberAccess.expression().annotation().type; solAssert(exprType, ""); if (exprType->category() == Type::Category::Magic) 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 000000000..5e9722de7 --- /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 000000000..99c785d08 --- /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 000000000..2ceb9e607 --- /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 000000000..324197004 --- /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 From 119aa107da56a0d94d7c1c58cf4f21ae8039b791 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Wed, 11 Jul 2018 17:15:03 +0200 Subject: [PATCH 030/168] Use emscripten 1.37.21 and boost 1.67.0 on both travis and circle. --- .circleci/config.yml | 2 +- .travis.yml | 4 +-- scripts/build_emscripten.sh | 2 +- scripts/travis-emscripten/build_emscripten.sh | 27 +++++++------------ scripts/travis-emscripten/install_deps.sh | 18 +++++++++---- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0980fa5c8..975d1c7a3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,7 +53,7 @@ jobs: name: Save Boost build key: *boost-cache-key paths: - - boost_1_57_0 + - boost_1_67_0 - store_artifacts: path: build/libsolc/soljson.js destination: soljson.js diff --git a/.travis.yml b/.travis.yml index ef4f8b398..d68c79ba4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -90,7 +90,7 @@ matrix: before_install: - nvm install 8 - nvm use 8 - - docker pull trzeci/emscripten:sdk-tag-1.35.4-64bit + - docker pull trzeci/emscripten:sdk-tag-1.37.21-64bit env: - SOLC_EMSCRIPTEN=On - SOLC_INSTALL_DEPS_TRAVIS=Off @@ -153,7 +153,7 @@ git: cache: ccache: true directories: - - boost_1_57_0 + - boost_1_67_0 - $HOME/.local install: diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index cddcd4f86..14c497aea 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -30,5 +30,5 @@ set -e if [[ "$OSTYPE" != "darwin"* ]]; then ./scripts/travis-emscripten/install_deps.sh - docker run -v $(pwd):/root/project -w /root/project trzeci/emscripten:sdk-tag-1.35.4-64bit ./scripts/travis-emscripten/build_emscripten.sh + docker run -v $(pwd):/root/project -w /root/project trzeci/emscripten:sdk-tag-1.37.21-64bit ./scripts/travis-emscripten/build_emscripten.sh fi diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh index f49ff5b2f..328999037 100755 --- a/scripts/travis-emscripten/build_emscripten.sh +++ b/scripts/travis-emscripten/build_emscripten.sh @@ -56,18 +56,14 @@ else echo 'NODE_JS=["nodejs", "--stack_size=8192"]' > ~/.emscripten fi - # Boost echo -en 'travis_fold:start:compiling_boost\\r' -cd "$WORKSPACE"/boost_1_57_0 +cd "$WORKSPACE"/boost_1_67_0 # if b2 exists, it is a fresh checkout, otherwise it comes from the cache # and is already compiled test -e b2 && ( -sed -i 's|using gcc ;|using gcc : : em++ ;|g' ./project-config.jam -sed -i 's|$(archiver\[1\])|emar|g' ./tools/build/src/tools/gcc.jam -sed -i 's|$(ranlib\[1\])|emranlib|g' ./tools/build/src/tools/gcc.jam -./b2 link=static variant=release threading=single runtime-link=static \ - system regex filesystem unit_test_framework program_options +./b2 toolset=emscripten link=static variant=release threading=single runtime-link=static \ + system regex filesystem unit_test_framework program_options cxxflags="-Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" find . -name 'libboost*.a' -exec cp {} . \; rm -rf b2 libs doc tools more bin.v2 status ) @@ -89,17 +85,12 @@ cmake \ -DBoost_FOUND=1 \ -DBoost_USE_STATIC_LIBS=1 \ -DBoost_USE_STATIC_RUNTIME=1 \ - -DBoost_INCLUDE_DIR="$WORKSPACE"/boost_1_57_0/ \ - -DBoost_FILESYSTEM_LIBRARY="$WORKSPACE"/boost_1_57_0/libboost_filesystem.a \ - -DBoost_FILESYSTEM_LIBRARIES="$WORKSPACE"/boost_1_57_0/libboost_filesystem.a \ - -DBoost_PROGRAM_OPTIONS_LIBRARY="$WORKSPACE"/boost_1_57_0/libboost_program_options.a \ - -DBoost_PROGRAM_OPTIONS_LIBRARIES="$WORKSPACE"/boost_1_57_0/libboost_program_options.a \ - -DBoost_REGEX_LIBRARY="$WORKSPACE"/boost_1_57_0/libboost_regex.a \ - -DBoost_REGEX_LIBRARIES="$WORKSPACE"/boost_1_57_0/libboost_regex.a \ - -DBoost_SYSTEM_LIBRARY="$WORKSPACE"/boost_1_57_0/libboost_system.a \ - -DBoost_SYSTEM_LIBRARIES="$WORKSPACE"/boost_1_57_0/libboost_system.a \ - -DBoost_UNIT_TEST_FRAMEWORK_LIBRARY="$WORKSPACE"/boost_1_57_0/libboost_unit_test_framework.a \ - -DBoost_UNIT_TEST_FRAMEWORK_LIBRARIES="$WORKSPACE"/boost_1_57_0/libboost_unit_test_framework.a \ + -DBoost_INCLUDE_DIR="$WORKSPACE"/boost_1_67_0/ \ + -DBoost_FILESYSTEM_LIBRARY_RELEASE="$WORKSPACE"/boost_1_67_0/libboost_filesystem.a \ + -DBoost_PROGRAM_OPTIONS_LIBRARY_RELEASE="$WORKSPACE"/boost_1_67_0/libboost_program_options.a \ + -DBoost_REGEX_LIBRARY_RELEASE="$WORKSPACE"/boost_1_67_0/libboost_regex.a \ + -DBoost_SYSTEM_LIBRARY_RELEASE="$WORKSPACE"/boost_1_67_0/libboost_system.a \ + -DBoost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE="$WORKSPACE"/boost_1_67_0/libboost_unit_test_framework.a \ -DTESTS=0 \ .. make -j 4 diff --git a/scripts/travis-emscripten/install_deps.sh b/scripts/travis-emscripten/install_deps.sh index 45c16a9f8..155506e4f 100755 --- a/scripts/travis-emscripten/install_deps.sh +++ b/scripts/travis-emscripten/install_deps.sh @@ -30,11 +30,19 @@ set -ev echo -en 'travis_fold:start:installing_dependencies\\r' -test -e boost_1_57_0 -a -e boost_1_57_0/boost || ( -wget 'https://sourceforge.net/projects/boost/files/boost/1.57.0/boost_1_57_0.tar.gz/download'\ - -O - | tar xz -cd boost_1_57_0 -./bootstrap.sh --with-toolset=gcc --with-libraries=thread,system,regex,date_time,chrono,filesystem,program_options,random +test -e boost_1_67_0 -a -e boost_1_67_0/boost || ( +rm -rf boost_1_67_0 +rm -f boost.tar.xz +wget -q 'https://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.gz/download'\ + -O boost.tar.xz +test "$(shasum boost.tar.xz)" = "77e73c9fd7bf85b14067767b9e8fdc39b49ee0f2 boost.tar.xz" +tar -xzf boost.tar.xz +rm boost.tar.xz +cd boost_1_67_0 +./bootstrap.sh +wget -q 'https://raw.githubusercontent.com/tee3/boost-build-emscripten/master/emscripten.jam' +test "$(shasum emscripten.jam)" = "a7e13fc2c1e53b0e079ef440622f879aa6da3049 emscripten.jam" +echo "using emscripten : : em++ ;" >> project-config.jam ) cd .. echo -en 'travis_fold:end:installing_dependencies\\r' From ea8b7d803ebd151401be7479f48afb0ad19f5f74 Mon Sep 17 00:00:00 2001 From: mordax Date: Thu, 15 Nov 2018 20:09:04 -0500 Subject: [PATCH 031/168] Removing redundant virtual from override function declaration Remove trailing whitespace Remove changelog change --- libevmasm/ConstantOptimiser.h | 12 +- libsolidity/analysis/ControlFlowAnalyzer.h | 2 +- libsolidity/analysis/ControlFlowBuilder.h | 28 +- libsolidity/analysis/ControlFlowGraph.h | 4 +- libsolidity/analysis/DocStringAnalyser.h | 8 +- libsolidity/analysis/PostTypeChecker.h | 10 +- libsolidity/analysis/ReferencesResolver.h | 36 +- libsolidity/analysis/StaticAnalyzer.h | 24 +- libsolidity/analysis/SyntaxChecker.h | 42 +- libsolidity/analysis/TypeChecker.h | 58 +- libsolidity/analysis/ViewPureChecker.h | 22 +- libsolidity/ast/AST.h | 254 ++++----- libsolidity/ast/ASTVisitor.h | 4 +- libsolidity/ast/Types.h | 512 +++++++++--------- libsolidity/codegen/ContractCompiler.h | 32 +- libsolidity/codegen/ExpressionCompiler.h | 22 +- libsolidity/codegen/LValue.h | 22 +- libsolidity/formal/SMTChecker.h | 36 +- libyul/backends/evm/EVMAssembly.h | 32 +- libyul/optimiser/ASTCopier.h | 30 +- .../optimiser/CommonSubexpressionEliminator.h | 2 +- libyul/optimiser/DataFlowAnalyzer.h | 14 +- libyul/optimiser/Disambiguator.h | 10 +- libyul/optimiser/ExpressionInliner.h | 4 +- libyul/optimiser/ExpressionSplitter.h | 12 +- libyul/optimiser/FullInliner.h | 8 +- .../InlinableExpressionFunctionFinder.h | 6 +- libyul/optimiser/Metrics.h | 4 +- libyul/optimiser/NameCollector.h | 6 +- libyul/optimiser/Rematerialiser.h | 2 +- libyul/optimiser/SSAValueTracker.h | 4 +- libyul/optimiser/Semantics.h | 8 +- libyul/optimiser/Substitution.h | 2 +- libyul/optimiser/UnusedPruner.h | 2 +- test/libsolidity/ASTJSONTest.h | 6 +- test/libsolidity/SyntaxTest.h | 6 +- 36 files changed, 643 insertions(+), 643 deletions(-) diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 2c753fa8c..2c2b87a0d 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -109,8 +109,8 @@ class LiteralMethod: public ConstantOptimisationMethod public: explicit LiteralMethod(Params const& _params, u256 const& _value): ConstantOptimisationMethod(_params, _value) {} - virtual bigint gasNeeded() const override; - virtual AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; } + bigint gasNeeded() const override; + AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; } }; /** @@ -120,8 +120,8 @@ class CodeCopyMethod: public ConstantOptimisationMethod { public: explicit CodeCopyMethod(Params const& _params, u256 const& _value); - virtual bigint gasNeeded() const override; - virtual AssemblyItems execute(Assembly& _assembly) const override; + bigint gasNeeded() const override; + AssemblyItems execute(Assembly& _assembly) const override; protected: static AssemblyItems const& copyRoutine(); @@ -144,8 +144,8 @@ public: ); } - virtual bigint gasNeeded() const override { return gasNeeded(m_routine); } - virtual AssemblyItems execute(Assembly&) const override + bigint gasNeeded() const override { return gasNeeded(m_routine); } + AssemblyItems execute(Assembly&) const override { return m_routine; } diff --git a/libsolidity/analysis/ControlFlowAnalyzer.h b/libsolidity/analysis/ControlFlowAnalyzer.h index 43e13fb65..aaaf1bff6 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.h +++ b/libsolidity/analysis/ControlFlowAnalyzer.h @@ -34,7 +34,7 @@ public: bool analyze(ASTNode const& _astRoot); - virtual bool visit(FunctionDefinition const& _function) override; + bool visit(FunctionDefinition const& _function) override; private: static std::set variablesAssignedInNode(CFGNode const *node); diff --git a/libsolidity/analysis/ControlFlowBuilder.h b/libsolidity/analysis/ControlFlowBuilder.h index e9d96e5fc..40605e005 100644 --- a/libsolidity/analysis/ControlFlowBuilder.h +++ b/libsolidity/analysis/ControlFlowBuilder.h @@ -46,19 +46,19 @@ public: private: explicit ControlFlowBuilder(CFG::NodeContainer& _nodeContainer, FunctionFlow const& _functionFlow); - virtual bool visit(BinaryOperation const& _operation) override; - virtual bool visit(Conditional const& _conditional) override; - virtual bool visit(IfStatement const& _ifStatement) override; - virtual bool visit(ForStatement const& _forStatement) override; - virtual bool visit(WhileStatement const& _whileStatement) override; - virtual bool visit(Break const&) override; - virtual bool visit(Continue const&) override; - virtual bool visit(Throw const&) override; - virtual bool visit(Block const&) override; - virtual void endVisit(Block const&) override; - virtual bool visit(Return const& _return) override; - virtual bool visit(PlaceholderStatement const&) override; - virtual bool visit(FunctionCall const& _functionCall) override; + bool visit(BinaryOperation const& _operation) override; + bool visit(Conditional const& _conditional) override; + bool visit(IfStatement const& _ifStatement) override; + bool visit(ForStatement const& _forStatement) override; + bool visit(WhileStatement const& _whileStatement) override; + bool visit(Break const&) override; + bool visit(Continue const&) override; + bool visit(Throw const&) override; + bool visit(Block const&) override; + void endVisit(Block const&) override; + bool visit(Return const& _return) override; + bool visit(PlaceholderStatement const&) override; + bool visit(FunctionCall const& _functionCall) override; /// Appends the control flow of @a _node to the current control flow. @@ -74,7 +74,7 @@ private: protected: - virtual bool visitNode(ASTNode const& node) override; + bool visitNode(ASTNode const& node) override; private: diff --git a/libsolidity/analysis/ControlFlowGraph.h b/libsolidity/analysis/ControlFlowGraph.h index c646e4f18..3f4820b80 100644 --- a/libsolidity/analysis/ControlFlowGraph.h +++ b/libsolidity/analysis/ControlFlowGraph.h @@ -105,8 +105,8 @@ public: bool constructFlow(ASTNode const& _astRoot); - virtual bool visit(ModifierDefinition const& _modifier) override; - virtual bool visit(FunctionDefinition const& _function) override; + bool visit(ModifierDefinition const& _modifier) override; + bool visit(FunctionDefinition const& _function) override; FunctionFlow const& functionFlow(FunctionDefinition const& _function) const; diff --git a/libsolidity/analysis/DocStringAnalyser.h b/libsolidity/analysis/DocStringAnalyser.h index 5d339428d..827462071 100644 --- a/libsolidity/analysis/DocStringAnalyser.h +++ b/libsolidity/analysis/DocStringAnalyser.h @@ -43,10 +43,10 @@ public: bool analyseDocStrings(SourceUnit const& _sourceUnit); private: - virtual bool visit(ContractDefinition const& _contract) override; - virtual bool visit(FunctionDefinition const& _function) override; - virtual bool visit(ModifierDefinition const& _modifier) override; - virtual bool visit(EventDefinition const& _event) override; + bool visit(ContractDefinition const& _contract) override; + bool visit(FunctionDefinition const& _function) override; + bool visit(ModifierDefinition const& _modifier) override; + bool visit(EventDefinition const& _event) override; void checkParameters( CallableDeclaration const& _callable, diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h index 4f9dac6e7..8382948aa 100644 --- a/libsolidity/analysis/PostTypeChecker.h +++ b/libsolidity/analysis/PostTypeChecker.h @@ -47,13 +47,13 @@ private: /// Adds a new error to the list of errors. void typeError(SourceLocation const& _location, std::string const& _description); - virtual bool visit(ContractDefinition const& _contract) override; - virtual void endVisit(ContractDefinition const& _contract) override; + bool visit(ContractDefinition const& _contract) override; + void endVisit(ContractDefinition const& _contract) override; - virtual bool visit(VariableDeclaration const& _variable) override; - virtual void endVisit(VariableDeclaration const& _variable) override; + bool visit(VariableDeclaration const& _variable) override; + void endVisit(VariableDeclaration const& _variable) override; - virtual bool visit(Identifier const& _identifier) override; + bool visit(Identifier const& _identifier) override; VariableDeclaration const* findCycle(VariableDeclaration const& _startingFrom); diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 24ec46430..34dbca967 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -57,24 +57,24 @@ public: bool resolve(ASTNode const& _root); private: - virtual bool visit(Block const& _block) override; - virtual void endVisit(Block const& _block) override; - virtual bool visit(ForStatement const& _for) override; - virtual void endVisit(ForStatement const& _for) override; - virtual void endVisit(VariableDeclarationStatement const& _varDeclStatement) override; - virtual bool visit(Identifier const& _identifier) override; - virtual bool visit(ElementaryTypeName const& _typeName) override; - virtual bool visit(FunctionDefinition const& _functionDefinition) override; - virtual void endVisit(FunctionDefinition const& _functionDefinition) override; - virtual bool visit(ModifierDefinition const& _modifierDefinition) override; - virtual void endVisit(ModifierDefinition const& _modifierDefinition) override; - virtual void endVisit(UserDefinedTypeName const& _typeName) override; - virtual void endVisit(FunctionTypeName const& _typeName) override; - virtual void endVisit(Mapping const& _typeName) override; - virtual void endVisit(ArrayTypeName const& _typeName) override; - virtual bool visit(InlineAssembly const& _inlineAssembly) override; - virtual bool visit(Return const& _return) override; - virtual void endVisit(VariableDeclaration const& _variable) override; + bool visit(Block const& _block) override; + void endVisit(Block const& _block) override; + bool visit(ForStatement const& _for) override; + void endVisit(ForStatement const& _for) override; + void endVisit(VariableDeclarationStatement const& _varDeclStatement) override; + bool visit(Identifier const& _identifier) override; + bool visit(ElementaryTypeName const& _typeName) override; + bool visit(FunctionDefinition const& _functionDefinition) override; + void endVisit(FunctionDefinition const& _functionDefinition) override; + bool visit(ModifierDefinition const& _modifierDefinition) override; + void endVisit(ModifierDefinition const& _modifierDefinition) override; + void endVisit(UserDefinedTypeName const& _typeName) override; + void endVisit(FunctionTypeName const& _typeName) override; + void endVisit(Mapping const& _typeName) override; + void endVisit(ArrayTypeName const& _typeName) override; + bool visit(InlineAssembly const& _inlineAssembly) override; + bool visit(Return const& _return) override; + void endVisit(VariableDeclaration const& _variable) override; /// Adds a new error to the list of errors. void typeError(SourceLocation const& _location, std::string const& _description); diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h index 7f5c743a5..f5f3dbce5 100644 --- a/libsolidity/analysis/StaticAnalyzer.h +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -52,20 +52,20 @@ public: private: - virtual bool visit(ContractDefinition const& _contract) override; - virtual void endVisit(ContractDefinition const& _contract) override; + bool visit(ContractDefinition const& _contract) override; + void endVisit(ContractDefinition const& _contract) override; - virtual bool visit(FunctionDefinition const& _function) override; - virtual void endVisit(FunctionDefinition const& _function) override; + bool visit(FunctionDefinition const& _function) override; + void endVisit(FunctionDefinition const& _function) override; - virtual bool visit(ExpressionStatement const& _statement) override; - virtual bool visit(VariableDeclaration const& _variable) override; - virtual bool visit(Identifier const& _identifier) override; - virtual bool visit(Return const& _return) override; - virtual bool visit(MemberAccess const& _memberAccess) override; - virtual bool visit(InlineAssembly const& _inlineAssembly) override; - virtual bool visit(BinaryOperation const& _operation) override; - virtual bool visit(FunctionCall const& _functionCall) override; + bool visit(ExpressionStatement const& _statement) override; + bool visit(VariableDeclaration const& _variable) override; + bool visit(Identifier const& _identifier) override; + bool visit(Return const& _return) override; + bool visit(MemberAccess const& _memberAccess) override; + bool visit(InlineAssembly const& _inlineAssembly) override; + bool visit(BinaryOperation const& _operation) override; + bool visit(FunctionCall const& _functionCall) override; /// @returns the size of this type in storage, including all sub-types. static bigint structureSizeEstimate(Type const& _type, std::set& _structsSeen); diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index f5716bf93..9e3c46525 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -45,41 +45,41 @@ public: private: - virtual bool visit(SourceUnit const& _sourceUnit) override; - virtual void endVisit(SourceUnit const& _sourceUnit) override; - virtual bool visit(PragmaDirective const& _pragma) override; + bool visit(SourceUnit const& _sourceUnit) override; + void endVisit(SourceUnit const& _sourceUnit) override; + bool visit(PragmaDirective const& _pragma) override; - virtual bool visit(ModifierDefinition const& _modifier) override; - virtual void endVisit(ModifierDefinition const& _modifier) override; + bool visit(ModifierDefinition const& _modifier) override; + void endVisit(ModifierDefinition const& _modifier) override; /// Reports an error if _statement is a VariableDeclarationStatement. /// Used by if/while/for to check for single statement variable declarations /// without a block. void checkSingleStatementVariableDeclaration(ASTNode const& _statement); - virtual bool visit(IfStatement const& _ifStatement) override; - virtual bool visit(WhileStatement const& _whileStatement) override; - virtual void endVisit(WhileStatement const& _whileStatement) override; - virtual bool visit(ForStatement const& _forStatement) override; - virtual void endVisit(ForStatement const& _forStatement) override; + bool visit(IfStatement const& _ifStatement) override; + bool visit(WhileStatement const& _whileStatement) override; + void endVisit(WhileStatement const& _whileStatement) override; + bool visit(ForStatement const& _forStatement) override; + void endVisit(ForStatement const& _forStatement) override; - virtual bool visit(Continue const& _continueStatement) override; - virtual bool visit(Break const& _breakStatement) override; + bool visit(Continue const& _continueStatement) override; + bool visit(Break const& _breakStatement) override; - virtual bool visit(Throw const& _throwStatement) override; + bool visit(Throw const& _throwStatement) override; - virtual bool visit(UnaryOperation const& _operation) override; + bool visit(UnaryOperation const& _operation) override; - virtual bool visit(PlaceholderStatement const& _placeholderStatement) override; + bool visit(PlaceholderStatement const& _placeholderStatement) override; - virtual bool visit(ContractDefinition const& _contract) override; - virtual bool visit(FunctionDefinition const& _function) override; - virtual bool visit(FunctionTypeName const& _node) override; + bool visit(ContractDefinition const& _contract) override; + bool visit(FunctionDefinition const& _function) override; + bool visit(FunctionTypeName const& _node) override; - virtual bool visit(VariableDeclarationStatement const& _statement) override; + bool visit(VariableDeclarationStatement const& _statement) override; - virtual bool visit(StructDefinition const& _struct) override; - virtual bool visit(Literal const& _literal) override; + bool visit(StructDefinition const& _struct) override; + bool visit(Literal const& _literal) override; ErrorReporter& m_errorReporter; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index c76fa4667..ae3ebc523 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -62,7 +62,7 @@ public: private: - virtual bool visit(ContractDefinition const& _contract) override; + bool visit(ContractDefinition const& _contract) override; /// Checks that two functions defined in this contract with the same name have different /// arguments and that there is at most one constructor. void checkContractDuplicateFunctions(ContractDefinition const& _contract); @@ -122,37 +122,37 @@ private: FunctionTypePointer _functionType ); - virtual void endVisit(InheritanceSpecifier const& _inheritance) override; - virtual void endVisit(UsingForDirective const& _usingFor) override; - virtual bool visit(StructDefinition const& _struct) override; - virtual bool visit(FunctionDefinition const& _function) override; - virtual bool visit(VariableDeclaration const& _variable) override; + void endVisit(InheritanceSpecifier const& _inheritance) override; + void endVisit(UsingForDirective const& _usingFor) override; + bool visit(StructDefinition const& _struct) override; + bool visit(FunctionDefinition const& _function) override; + bool visit(VariableDeclaration const& _variable) override; /// We need to do this manually because we want to pass the bases of the current contract in /// case this is a base constructor call. void visitManually(ModifierInvocation const& _modifier, std::vector const& _bases); - virtual bool visit(EventDefinition const& _eventDef) override; - virtual void endVisit(FunctionTypeName const& _funType) override; - virtual bool visit(InlineAssembly const& _inlineAssembly) override; - virtual bool visit(IfStatement const& _ifStatement) override; - virtual bool visit(WhileStatement const& _whileStatement) override; - virtual bool visit(ForStatement const& _forStatement) override; - virtual void endVisit(Return const& _return) override; - virtual bool visit(EmitStatement const&) override { m_insideEmitStatement = true; return true; } - virtual void endVisit(EmitStatement const& _emit) override; - virtual bool visit(VariableDeclarationStatement const& _variable) override; - virtual void endVisit(ExpressionStatement const& _statement) override; - virtual bool visit(Conditional const& _conditional) override; - virtual bool visit(Assignment const& _assignment) override; - virtual bool visit(TupleExpression const& _tuple) override; - virtual void endVisit(BinaryOperation const& _operation) override; - virtual bool visit(UnaryOperation const& _operation) override; - virtual bool visit(FunctionCall const& _functionCall) override; - virtual void endVisit(NewExpression const& _newExpression) override; - virtual bool visit(MemberAccess const& _memberAccess) override; - virtual bool visit(IndexAccess const& _indexAccess) override; - virtual bool visit(Identifier const& _identifier) override; - virtual void endVisit(ElementaryTypeNameExpression const& _expr) override; - virtual void endVisit(Literal const& _literal) override; + bool visit(EventDefinition const& _eventDef) override; + void endVisit(FunctionTypeName const& _funType) override; + bool visit(InlineAssembly const& _inlineAssembly) override; + bool visit(IfStatement const& _ifStatement) override; + bool visit(WhileStatement const& _whileStatement) override; + bool visit(ForStatement const& _forStatement) override; + void endVisit(Return const& _return) override; + bool visit(EmitStatement const&) override { m_insideEmitStatement = true; return true; } + void endVisit(EmitStatement const& _emit) override; + bool visit(VariableDeclarationStatement const& _variable) override; + void endVisit(ExpressionStatement const& _statement) override; + bool visit(Conditional const& _conditional) override; + bool visit(Assignment const& _assignment) override; + bool visit(TupleExpression const& _tuple) override; + void endVisit(BinaryOperation const& _operation) override; + bool visit(UnaryOperation const& _operation) override; + bool visit(FunctionCall const& _functionCall) override; + void endVisit(NewExpression const& _newExpression) override; + bool visit(MemberAccess const& _memberAccess) override; + bool visit(IndexAccess const& _indexAccess) override; + bool visit(Identifier const& _identifier) override; + void endVisit(ElementaryTypeNameExpression const& _expr) override; + void endVisit(Literal const& _literal) override; template void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); diff --git a/libsolidity/analysis/ViewPureChecker.h b/libsolidity/analysis/ViewPureChecker.h index faa5b6982..1109ad766 100644 --- a/libsolidity/analysis/ViewPureChecker.h +++ b/libsolidity/analysis/ViewPureChecker.h @@ -46,17 +46,17 @@ private: SourceLocation location; }; - virtual bool visit(FunctionDefinition const& _funDef) override; - virtual void endVisit(FunctionDefinition const& _funDef) override; - virtual bool visit(ModifierDefinition const& _modifierDef) override; - virtual void endVisit(ModifierDefinition const& _modifierDef) override; - virtual void endVisit(Identifier const& _identifier) override; - virtual bool visit(MemberAccess const& _memberAccess) override; - virtual void endVisit(MemberAccess const& _memberAccess) override; - virtual void endVisit(IndexAccess const& _indexAccess) override; - virtual void endVisit(ModifierInvocation const& _modifier) override; - virtual void endVisit(FunctionCall const& _functionCall) override; - virtual void endVisit(InlineAssembly const& _inlineAssembly) override; + bool visit(FunctionDefinition const& _funDef) override; + void endVisit(FunctionDefinition const& _funDef) override; + bool visit(ModifierDefinition const& _modifierDef) override; + void endVisit(ModifierDefinition const& _modifierDef) override; + void endVisit(Identifier const& _identifier) override; + bool visit(MemberAccess const& _memberAccess) override; + void endVisit(MemberAccess const& _memberAccess) override; + void endVisit(IndexAccess const& _indexAccess) override; + void endVisit(ModifierInvocation const& _modifier) override; + void endVisit(FunctionCall const& _functionCall) override; + void endVisit(InlineAssembly const& _inlineAssembly) override; /// Called when an element of mutability @a _mutability is encountered. /// Creates appropriate warnings and errors and sets @a m_currentBestMutability. diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 4fd2bcb87..23a6078bd 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -126,9 +126,9 @@ public: SourceUnit(SourceLocation const& _location, std::vector> const& _nodes): ASTNode(_location), m_nodes(_nodes) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; - virtual SourceUnitAnnotation& annotation() const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; + SourceUnitAnnotation& annotation() const override; std::vector> nodes() const { return m_nodes; } @@ -242,8 +242,8 @@ public: ): ASTNode(_location), m_tokens(_tokens), m_literals(_literals) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector const& tokens() const { return m_tokens; } std::vector const& literals() const { return m_literals; } @@ -279,17 +279,17 @@ public: m_symbolAliases(_symbolAliases) { } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; ASTString const& path() const { return *m_path; } std::vector, ASTPointer>> const& symbolAliases() const { return m_symbolAliases; } - virtual ImportAnnotation& annotation() const override; + ImportAnnotation& annotation() const override; - virtual TypePointer type() const override; + TypePointer type() const override; private: ASTPointer m_path; @@ -375,8 +375,8 @@ public: m_contractKind(_contractKind) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& baseContracts() const { return m_baseContracts; } std::vector> const& subNodes() const { return m_subNodes; } @@ -407,9 +407,9 @@ public: std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); } - virtual TypePointer type() const override; + TypePointer type() const override; - virtual ContractDefinitionAnnotation& annotation() const override; + ContractDefinitionAnnotation& annotation() const override; ContractKind contractKind() const { return m_contractKind; } @@ -434,8 +434,8 @@ public: ): ASTNode(_location), m_baseName(_baseName), m_arguments(std::move(_arguments)) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; UserDefinedTypeName const& name() const { return *m_baseName; } // Returns nullptr if no argument list was given (``C``). @@ -463,8 +463,8 @@ public: ): ASTNode(_location), m_libraryName(_libraryName), m_typeName(_typeName) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; UserDefinedTypeName const& libraryName() const { return *m_libraryName; } /// @returns the type name the library is attached to, null for `*`. @@ -485,14 +485,14 @@ public: ): Declaration(_location, _name), m_members(_members) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& members() const { return m_members; } - virtual TypePointer type() const override; + TypePointer type() const override; - virtual TypeDeclarationAnnotation& annotation() const override; + TypeDeclarationAnnotation& annotation() const override; private: std::vector> m_members; @@ -507,14 +507,14 @@ public: std::vector> const& _members ): Declaration(_location, _name), m_members(_members) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& members() const { return m_members; } - virtual TypePointer type() const override; + TypePointer type() const override; - virtual TypeDeclarationAnnotation& annotation() const override; + TypeDeclarationAnnotation& annotation() const override; private: std::vector> m_members; @@ -529,10 +529,10 @@ public: EnumValue(SourceLocation const& _location, ASTPointer const& _name): Declaration(_location, _name) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; - virtual TypePointer type() const override; + TypePointer type() const override; }; /** @@ -548,8 +548,8 @@ public: std::vector> const& _parameters ): ASTNode(_location), m_parameters(_parameters) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& parameters() const { return m_parameters; } @@ -610,8 +610,8 @@ public: m_body(_body) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; StateMutability stateMutability() const { return m_stateMutability; } bool isConstructor() const { return m_isConstructor; } @@ -620,11 +620,11 @@ public: std::vector> const& modifiers() const { return m_functionModifiers; } std::vector> const& returnParameters() const { return m_returnParameters->parameters(); } Block const& body() const { solAssert(m_body, ""); return *m_body; } - virtual bool isVisibleInContract() const override + bool isVisibleInContract() const override { return Declaration::isVisibleInContract() && !isConstructor() && !isFallback(); } - virtual bool isPartOfExternalInterface() const override { return isPublic() && !isConstructor() && !isFallback(); } + bool isPartOfExternalInterface() const override { return isPublic() && !isConstructor() && !isFallback(); } /// @returns the external signature of the function /// That consists of the name of the function followed by the types of the @@ -633,13 +633,13 @@ public: ContractDefinition::ContractKind inContractKind() const; - virtual TypePointer type() const override; + TypePointer type() const override; /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. - virtual FunctionTypePointer functionType(bool /*_internal*/) const override; + FunctionTypePointer functionType(bool /*_internal*/) const override; - virtual FunctionDefinitionAnnotation& annotation() const override; + FunctionDefinitionAnnotation& annotation() const override; private: StateMutability m_stateMutability; @@ -676,14 +676,14 @@ public: m_isConstant(_isConstant), m_location(_referenceLocation) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; TypeName* typeName() const { return m_typeName.get(); } ASTPointer const& value() const { return m_value; } - virtual bool isLValue() const override; - virtual bool isPartOfExternalInterface() const override { return isPublic(); } + bool isLValue() const override; + bool isPartOfExternalInterface() const override { return isPublic(); } /// @returns true iff this variable is the parameter (or return parameter) of a function /// (or function type name or event) or declared inside a function body. @@ -717,13 +717,13 @@ public: /// @returns a set of allowed storage locations for the variable. std::set allowedDataLocations() const; - virtual TypePointer type() const override; + TypePointer type() const override; /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. - virtual FunctionTypePointer functionType(bool /*_internal*/) const override; + FunctionTypePointer functionType(bool /*_internal*/) const override; - virtual VariableDeclarationAnnotation& annotation() const override; + VariableDeclarationAnnotation& annotation() const override; protected: Visibility defaultVisibility() const override { return Visibility::Internal; } @@ -758,14 +758,14 @@ public: { } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Block const& body() const { return *m_body; } - virtual TypePointer type() const override; + TypePointer type() const override; - virtual ModifierDefinitionAnnotation& annotation() const override; + ModifierDefinitionAnnotation& annotation() const override; private: ASTPointer m_body; @@ -784,8 +784,8 @@ public: ): ASTNode(_location), m_modifierName(_name), m_arguments(std::move(_arguments)) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; ASTPointer const& name() const { return m_modifierName; } // Returns nullptr if no argument list was given (``mod``). @@ -817,15 +817,15 @@ public: { } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; bool isAnonymous() const { return m_anonymous; } - virtual TypePointer type() const override; - virtual FunctionTypePointer functionType(bool /*_internal*/) const override; + TypePointer type() const override; + FunctionTypePointer functionType(bool /*_internal*/) const override; - virtual EventDefinitionAnnotation& annotation() const override; + EventDefinitionAnnotation& annotation() const override; private: bool m_anonymous = false; @@ -840,21 +840,21 @@ class MagicVariableDeclaration: public Declaration public: MagicVariableDeclaration(ASTString const& _name, std::shared_ptr const& _type): Declaration(SourceLocation(), std::make_shared(_name)), m_type(_type) {} - virtual void accept(ASTVisitor&) override + void accept(ASTVisitor&) override { solAssert(false, "MagicVariableDeclaration used inside real AST."); } - virtual void accept(ASTConstVisitor&) const override + void accept(ASTConstVisitor&) const override { solAssert(false, "MagicVariableDeclaration used inside real AST."); } - virtual FunctionTypePointer functionType(bool) const override + FunctionTypePointer functionType(bool) const override { solAssert(m_type->category() == Type::Category::Function, ""); return std::dynamic_pointer_cast(m_type); } - virtual TypePointer type() const override { return m_type; } + TypePointer type() const override { return m_type; } private: std::shared_ptr m_type; @@ -872,7 +872,7 @@ protected: explicit TypeName(SourceLocation const& _location): ASTNode(_location) {} public: - virtual TypeNameAnnotation& annotation() const override; + TypeNameAnnotation& annotation() const override; }; /** @@ -891,8 +891,8 @@ public: solAssert(!_stateMutability.is_initialized() || _elem.token() == Token::Address, ""); } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; ElementaryTypeNameToken const& typeName() const { return m_type; } @@ -911,12 +911,12 @@ class UserDefinedTypeName: public TypeName public: UserDefinedTypeName(SourceLocation const& _location, std::vector const& _namePath): TypeName(_location), m_namePath(_namePath) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector const& namePath() const { return m_namePath; } - virtual UserDefinedTypeNameAnnotation& annotation() const override; + UserDefinedTypeNameAnnotation& annotation() const override; private: std::vector m_namePath; @@ -938,8 +938,8 @@ public: TypeName(_location), m_parameterTypes(_parameterTypes), m_returnTypes(_returnTypes), m_visibility(_visibility), m_stateMutability(_stateMutability) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& parameterTypes() const { return m_parameterTypes->parameters(); } std::vector> const& returnParameterTypes() const { return m_returnTypes->parameters(); } @@ -972,8 +972,8 @@ public: ASTPointer const& _valueType ): TypeName(_location), m_keyType(_keyType), m_valueType(_valueType) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; ElementaryTypeName const& keyType() const { return *m_keyType; } TypeName const& valueType() const { return *m_valueType; } @@ -995,8 +995,8 @@ public: ASTPointer const& _length ): TypeName(_location), m_baseType(_baseType), m_length(_length) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; TypeName const& baseType() const { return *m_baseType; } Expression const* length() const { return m_length.get(); } @@ -1023,7 +1023,7 @@ public: ASTPointer const& _docString ): ASTNode(_location), Documented(_docString) {} - virtual StatementAnnotation& annotation() const override; + StatementAnnotation& annotation() const override; }; namespace assembly @@ -1044,12 +1044,12 @@ public: std::shared_ptr const& _operations ): Statement(_location, _docString), m_operations(_operations) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; assembly::Block const& operations() const { return *m_operations; } - virtual InlineAssemblyAnnotation& annotation() const override; + InlineAssemblyAnnotation& annotation() const override; private: std::shared_ptr m_operations; @@ -1067,8 +1067,8 @@ public: std::vector> const& _statements ): Statement(_location, _docString), m_statements(_statements) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& statements() const { return m_statements; } @@ -1088,8 +1088,8 @@ public: ASTPointer const& _docString ): Statement(_location, _docString) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; }; /** @@ -1111,8 +1111,8 @@ public: m_trueBody(_trueBody), m_falseBody(_falseBody) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& condition() const { return *m_condition; } Statement const& trueStatement() const { return *m_trueBody; } @@ -1149,8 +1149,8 @@ public: ): BreakableStatement(_location, _docString), m_condition(_condition), m_body(_body), m_isDoWhile(_isDoWhile) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& condition() const { return *m_condition; } Statement const& body() const { return *m_body; } @@ -1182,8 +1182,8 @@ public: m_loopExpression(_loopExpression), m_body(_body) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Statement const* initializationExpression() const { return m_initExpression.get(); } Expression const* condition() const { return m_condExpression.get(); } @@ -1206,8 +1206,8 @@ class Continue: public Statement public: explicit Continue(SourceLocation const& _location, ASTPointer const& _docString): Statement(_location, _docString) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; }; class Break: public Statement @@ -1215,8 +1215,8 @@ class Break: public Statement public: explicit Break(SourceLocation const& _location, ASTPointer const& _docString): Statement(_location, _docString) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; }; class Return: public Statement @@ -1227,12 +1227,12 @@ public: ASTPointer const& _docString, ASTPointer _expression ): Statement(_location, _docString), m_expression(_expression) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const* expression() const { return m_expression.get(); } - virtual ReturnAnnotation& annotation() const override; + ReturnAnnotation& annotation() const override; private: ASTPointer m_expression; ///< value to return, optional @@ -1246,8 +1246,8 @@ class Throw: public Statement public: explicit Throw(SourceLocation const& _location, ASTPointer const& _docString): Statement(_location, _docString) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; }; /** @@ -1262,8 +1262,8 @@ public: ASTPointer const& _functionCall ): Statement(_location, _docString), m_eventCall(_functionCall) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; FunctionCall const& eventCall() const { return *m_eventCall; } @@ -1289,8 +1289,8 @@ public: ASTPointer const& _initialValue ): Statement(_location, _docString), m_variables(_variables), m_initialValue(_initialValue) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& declarations() const { return m_variables; } Expression const* initialValue() const { return m_initialValue.get(); } @@ -1317,8 +1317,8 @@ public: ASTPointer _expression ): Statement(_location, _docString), m_expression(_expression) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& expression() const { return *m_expression; } @@ -1358,8 +1358,8 @@ public: m_trueExpression(_trueExpression), m_falseExpression(_falseExpression) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& condition() const { return *m_condition; } Expression const& trueExpression() const { return *m_trueExpression; } @@ -1389,8 +1389,8 @@ public: { solAssert(TokenTraits::isAssignmentOp(_assignmentOperator), ""); } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& leftHandSide() const { return *m_leftHandSide; } Token assignmentOperator() const { return m_assigmentOperator; } @@ -1421,8 +1421,8 @@ public: Expression(_location), m_components(_components), m_isArray(_isArray) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; std::vector> const& components() const { return m_components; } bool isInlineArray() const { return m_isArray; } @@ -1452,8 +1452,8 @@ public: { solAssert(TokenTraits::isUnaryOp(_operator), ""); } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Token getOperator() const { return m_operator; } bool isPrefixOperation() const { return m_isPrefix; } @@ -1482,8 +1482,8 @@ public: { solAssert(TokenTraits::isBinaryOp(_operator) || TokenTraits::isCompareOp(_operator), ""); } - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& leftExpression() const { return *m_left; } Expression const& rightExpression() const { return *m_right; } @@ -1510,14 +1510,14 @@ public: std::vector> const& _names ): Expression(_location), m_expression(_expression), m_arguments(_arguments), m_names(_names) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& expression() const { return *m_expression; } std::vector> arguments() const { return {m_arguments.begin(), m_arguments.end()}; } std::vector> const& names() const { return m_names; } - virtual FunctionCallAnnotation& annotation() const override; + FunctionCallAnnotation& annotation() const override; private: ASTPointer m_expression; @@ -1537,8 +1537,8 @@ public: ASTPointer const& _typeName ): Expression(_location), m_typeName(_typeName) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; TypeName const& typeName() const { return *m_typeName; } @@ -1558,12 +1558,12 @@ public: ASTPointer const& _memberName ): Expression(_location), m_expression(_expression), m_memberName(_memberName) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& expression() const { return *m_expression; } ASTString const& memberName() const { return *m_memberName; } - virtual MemberAccessAnnotation& annotation() const override; + MemberAccessAnnotation& annotation() const override; private: ASTPointer m_expression; @@ -1582,8 +1582,8 @@ public: ASTPointer const& _index ): Expression(_location), m_base(_base), m_index(_index) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Expression const& baseExpression() const { return *m_base; } Expression const* indexExpression() const { return m_index.get(); } @@ -1614,12 +1614,12 @@ public: ASTPointer const& _name ): PrimaryExpression(_location), m_name(_name) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; ASTString const& name() const { return *m_name; } - virtual IdentifierAnnotation& annotation() const override; + IdentifierAnnotation& annotation() const override; private: ASTPointer m_name; @@ -1636,8 +1636,8 @@ public: ElementaryTypeNameExpression(SourceLocation const& _location, ElementaryTypeNameToken const& _type): PrimaryExpression(_location), m_typeToken(_type) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; ElementaryTypeNameToken const& typeName() const { return m_typeToken; } @@ -1672,8 +1672,8 @@ public: SubDenomination _sub = SubDenomination::None ): PrimaryExpression(_location), m_token(_token), m_value(_value), m_subDenomination(_sub) {} - virtual void accept(ASTVisitor& _visitor) override; - virtual void accept(ASTConstVisitor& _visitor) const override; + void accept(ASTVisitor& _visitor) override; + void accept(ASTConstVisitor& _visitor) const override; Token token() const { return m_token; } /// @returns the non-parsed value of the literal diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index 6c0ce6f81..1a7610328 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -262,8 +262,8 @@ public: ): m_onVisit(_onVisit), m_onEndVisit(_onEndVisit) {} protected: - virtual bool visitNode(ASTNode const& _n) override { return m_onVisit ? m_onVisit(_n) : true; } - virtual void endVisitNode(ASTNode const& _n) override { m_onEndVisit(_n); } + bool visitNode(ASTNode const& _n) override { return m_onVisit ? m_onVisit(_n) : true; } + void endVisitNode(ASTNode const& _n) override { m_onEndVisit(_n); } private: std::function m_onVisit; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 24ace4478..fbf11f491 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -331,31 +331,31 @@ public: static AddressType& address() { static std::shared_ptr addr(std::make_shared(StateMutability::NonPayable)); return *addr; } static AddressType& addressPayable() { static std::shared_ptr addr(std::make_shared(StateMutability::Payable)); return *addr; } - virtual Category category() const override { return Category::Address; } + Category category() const override { return Category::Address; } explicit AddressType(StateMutability _stateMutability); - virtual std::string richIdentifier() const override; - virtual bool isImplicitlyConvertibleTo(Type const& _other) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; + std::string richIdentifier() const override; + bool isImplicitlyConvertibleTo(Type const& _other) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; - virtual bool operator==(Type const& _other) const override; + bool operator==(Type const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : 160 / 8; } - virtual unsigned storageBytes() const override { return 160 / 8; } - virtual bool isValueType() const override { return true; } + unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : 160 / 8; } + unsigned storageBytes() const override { return 160 / 8; } + bool isValueType() const override { return true; } - virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; + MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; - virtual std::string toString(bool _short) const override; - virtual std::string canonicalName() const override; + std::string toString(bool _short) const override; + std::string canonicalName() const override; - virtual u256 literalValue(Literal const* _literal) const override; + u256 literalValue(Literal const* _literal) const override; - virtual TypePointer encodingType() const override { return shared_from_this(); } - virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } + TypePointer encodingType() const override { return shared_from_this(); } + TypePointer interfaceType(bool) const override { return shared_from_this(); } StateMutability stateMutability(void) const { return m_stateMutability; } @@ -374,26 +374,26 @@ public: Unsigned, Signed }; - virtual Category category() const override { return Category::Integer; } + Category category() const override { return Category::Integer; } explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned); - virtual std::string richIdentifier() const override; - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; + std::string richIdentifier() const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; - virtual bool operator==(Type const& _other) const override; + bool operator==(Type const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_bits / 8; } - virtual unsigned storageBytes() const override { return m_bits / 8; } - virtual bool isValueType() const override { return true; } + unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_bits / 8; } + unsigned storageBytes() const override { return m_bits / 8; } + bool isValueType() const override { return true; } - virtual std::string toString(bool _short) const override; + std::string toString(bool _short) const override; - virtual TypePointer encodingType() const override { return shared_from_this(); } - virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } + TypePointer encodingType() const override { return shared_from_this(); } + TypePointer interfaceType(bool) const override { return shared_from_this(); } unsigned numBits() const { return m_bits; } bool isSigned() const { return m_modifier == Modifier::Signed; } @@ -416,26 +416,26 @@ public: { Unsigned, Signed }; - virtual Category category() const override { return Category::FixedPoint; } + Category category() const override { return Category::FixedPoint; } explicit FixedPointType(unsigned _totalBits, unsigned _fractionalDigits, Modifier _modifier = Modifier::Unsigned); - virtual std::string richIdentifier() const override; - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; + std::string richIdentifier() const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; - virtual bool operator==(Type const& _other) const override; + bool operator==(Type const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_totalBits / 8; } - virtual unsigned storageBytes() const override { return m_totalBits / 8; } - virtual bool isValueType() const override { return true; } + unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_totalBits / 8; } + unsigned storageBytes() const override { return m_totalBits / 8; } + bool isValueType() const override { return true; } - virtual std::string toString(bool _short) const override; + std::string toString(bool _short) const override; - virtual TypePointer encodingType() const override { return shared_from_this(); } - virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } + TypePointer encodingType() const override { return shared_from_this(); } + TypePointer interfaceType(bool) const override { return shared_from_this(); } /// Number of bits used for this type in total. unsigned numBits() const { return m_totalBits; } @@ -467,7 +467,7 @@ class RationalNumberType: public Type { public: - virtual Category category() const override { return Category::RationalNumber; } + Category category() const override { return Category::RationalNumber; } static TypePointer forLiteral(Literal const& _literal); @@ -475,20 +475,20 @@ public: m_value(_value), m_compatibleBytesType(_compatibleBytesType) {} - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; - virtual bool canBeStored() const override { return false; } - virtual bool canLiveOutsideStorage() const override { return false; } + bool canBeStored() const override { return false; } + bool canLiveOutsideStorage() const override { return false; } - virtual std::string toString(bool _short) const override; - virtual u256 literalValue(Literal const* _literal) const override; - virtual TypePointer mobileType() const override; + std::string toString(bool _short) const override; + u256 literalValue(Literal const* _literal) const override; + TypePointer mobileType() const override; /// @returns the smallest integer type that can hold the value or an empty pointer if not possible. std::shared_ptr integerType() const; @@ -530,25 +530,25 @@ private: class StringLiteralType: public Type { public: - virtual Category category() const override { return Category::StringLiteral; } + Category category() const override { return Category::StringLiteral; } explicit StringLiteralType(Literal const& _literal); - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; - virtual bool canBeStored() const override { return false; } - virtual bool canLiveOutsideStorage() const override { return false; } - virtual unsigned sizeOnStack() const override { return 0; } + bool canBeStored() const override { return false; } + bool canLiveOutsideStorage() const override { return false; } + unsigned sizeOnStack() const override { return 0; } - virtual std::string toString(bool) const override; - virtual TypePointer mobileType() const override; + std::string toString(bool) const override; + TypePointer mobileType() const override; bool isValidUTF8() const; @@ -564,25 +564,25 @@ private: class FixedBytesType: public Type { public: - virtual Category category() const override { return Category::FixedBytes; } + Category category() const override { return Category::FixedBytes; } explicit FixedBytesType(unsigned _bytes); - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded) const override { return _padded && m_bytes > 0 ? 32 : m_bytes; } - virtual unsigned storageBytes() const override { return m_bytes; } - virtual bool isValueType() const override { return true; } + unsigned calldataEncodedSize(bool _padded) const override { return _padded && m_bytes > 0 ? 32 : m_bytes; } + unsigned storageBytes() const override { return m_bytes; } + bool isValueType() const override { return true; } - virtual std::string toString(bool) const override { return "bytes" + dev::toString(m_bytes); } - virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; - virtual TypePointer encodingType() const override { return shared_from_this(); } - virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } + std::string toString(bool) const override { return "bytes" + dev::toString(m_bytes); } + MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; + TypePointer encodingType() const override { return shared_from_this(); } + TypePointer interfaceType(bool) const override { return shared_from_this(); } unsigned numBytes() const { return m_bytes; } @@ -597,19 +597,19 @@ class BoolType: public Type { public: BoolType() {} - virtual Category category() const override { return Category::Bool; } - virtual std::string richIdentifier() const override { return "t_bool"; } - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; + Category category() const override { return Category::Bool; } + std::string richIdentifier() const override { return "t_bool"; } + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded) const override{ return _padded ? 32 : 1; } - virtual unsigned storageBytes() const override { return 1; } - virtual bool isValueType() const override { return true; } + unsigned calldataEncodedSize(bool _padded) const override{ return _padded ? 32 : 1; } + unsigned storageBytes() const override { return 1; } + bool isValueType() const override { return true; } - virtual std::string toString(bool) const override { return "bool"; } - virtual u256 literalValue(Literal const* _literal) const override; - virtual TypePointer encodingType() const override { return shared_from_this(); } - virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } + std::string toString(bool) const override { return "bool"; } + u256 literalValue(Literal const* _literal) const override; + TypePointer encodingType() const override { return shared_from_this(); } + TypePointer interfaceType(bool) const override { return shared_from_this(); } }; /** @@ -622,20 +622,20 @@ public: explicit ReferenceType(DataLocation _location): m_location(_location) {} DataLocation location() const { return m_location; } - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual unsigned memoryHeadSize() const override { return 32; } + unsigned memoryHeadSize() const override { return 32; } /// @returns a copy of this type with location (recursively) changed to @a _location, /// whereas isPointer is only shallowly changed - the deep copy is always a bound reference. virtual TypePointer copyForLocation(DataLocation _location, bool _isPointer) const = 0; - virtual TypePointer mobileType() const override { return copyForLocation(m_location, true); } - virtual bool dataStoredIn(DataLocation _location) const override { return m_location == _location; } - virtual bool hasSimpleZeroValueInMemory() const override { return false; } + TypePointer mobileType() const override { return copyForLocation(m_location, true); } + bool dataStoredIn(DataLocation _location) const override { return m_location == _location; } + bool hasSimpleZeroValueInMemory() const override { return false; } /// Storage references can be pointers or bound references. In general, local variables are of /// pointer type, state variables are bound references. Assignments to pointers or deleting @@ -677,7 +677,7 @@ public: static ArrayType& bytesMemory() { static std::shared_ptr addr(std::make_shared(DataLocation::Memory)); return *addr; } static ArrayType& stringMemory() { static std::shared_ptr addr(std::make_shared(DataLocation::Memory, true)); return *addr; } - virtual Category category() const override { return Category::Array; } + Category category() const override { return Category::Array; } /// Constructor for a byte array ("bytes") and string. explicit ArrayType(DataLocation _location, bool _isString = false): @@ -700,24 +700,24 @@ public: m_length(_length) {} - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(const Type& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded) const override; - virtual bool isDynamicallySized() const override { return m_hasDynamicLength; } - virtual bool isDynamicallyEncoded() const override; - virtual u256 storageSize() const override; - virtual bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); } - virtual unsigned sizeOnStack() const override; - virtual std::string toString(bool _short) const override; - virtual std::string canonicalName() const override; - virtual std::string signatureInExternalFunction(bool _structsByName) const override; - virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; - virtual TypePointer encodingType() const override; - virtual TypePointer decodingType() const override; - virtual TypePointer interfaceType(bool _inLibrary) const override; - virtual bool canBeUsedExternally(bool _inLibrary) const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + std::string richIdentifier() const override; + bool operator==(const Type& _other) const override; + unsigned calldataEncodedSize(bool _padded) const override; + bool isDynamicallySized() const override { return m_hasDynamicLength; } + bool isDynamicallyEncoded() const override; + u256 storageSize() const override; + bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); } + unsigned sizeOnStack() const override; + std::string toString(bool _short) const override; + std::string canonicalName() const override; + std::string signatureInExternalFunction(bool _structsByName) const override; + MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; + TypePointer encodingType() const override; + TypePointer decodingType() const override; + TypePointer interfaceType(bool _inLibrary) const override; + bool canBeUsedExternally(bool _inLibrary) const override; /// @returns true if this is valid to be stored in calldata bool validForCalldata() const; @@ -751,36 +751,36 @@ private: class ContractType: public Type { public: - virtual Category category() const override { return Category::Contract; } + Category category() const override { return Category::Contract; } explicit ContractType(ContractDefinition const& _contract, bool _super = false): m_contract(_contract), m_super(_super) {} /// Contracts can be implicitly converted only to base contracts. - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; /// Contracts can only be explicitly converted to address types and base contracts. - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded ) const override + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + unsigned calldataEncodedSize(bool _padded ) const override { solAssert(!isSuper(), ""); return encodingType()->calldataEncodedSize(_padded); } - virtual unsigned storageBytes() const override { solAssert(!isSuper(), ""); return 20; } - virtual bool canLiveOutsideStorage() const override { return !isSuper(); } - virtual unsigned sizeOnStack() const override { return m_super ? 0 : 1; } - virtual bool isValueType() const override { return !isSuper(); } - virtual std::string toString(bool _short) const override; - virtual std::string canonicalName() const override; + unsigned storageBytes() const override { solAssert(!isSuper(), ""); return 20; } + bool canLiveOutsideStorage() const override { return !isSuper(); } + unsigned sizeOnStack() const override { return m_super ? 0 : 1; } + bool isValueType() const override { return !isSuper(); } + std::string toString(bool _short) const override; + std::string canonicalName() const override; - virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; - virtual TypePointer encodingType() const override + MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; + TypePointer encodingType() const override { if (isSuper()) return TypePointer{}; return std::make_shared(isPayable() ? StateMutability::Payable : StateMutability::NonPayable); } - virtual TypePointer interfaceType(bool _inLibrary) const override + TypePointer interfaceType(bool _inLibrary) const override { if (isSuper()) return TypePointer{}; @@ -816,31 +816,31 @@ private: class StructType: public ReferenceType { public: - virtual Category category() const override { return Category::Struct; } + Category category() const override { return Category::Struct; } explicit StructType(StructDefinition const& _struct, DataLocation _location = DataLocation::Storage): ReferenceType(_location), m_struct(_struct) {} - virtual bool isImplicitlyConvertibleTo(const Type& _convertTo) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded) const override; - virtual bool isDynamicallyEncoded() const override; + bool isImplicitlyConvertibleTo(const Type& _convertTo) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + unsigned calldataEncodedSize(bool _padded) const override; + bool isDynamicallyEncoded() const override; u256 memorySize() const; - virtual u256 storageSize() const override; - virtual bool canLiveOutsideStorage() const override { return true; } - virtual std::string toString(bool _short) const override; + u256 storageSize() const override; + bool canLiveOutsideStorage() const override { return true; } + std::string toString(bool _short) const override; - virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; - virtual TypePointer encodingType() const override + MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; + TypePointer encodingType() const override { return location() == DataLocation::Storage ? std::make_shared(256) : shared_from_this(); } - virtual TypePointer interfaceType(bool _inLibrary) const override; - virtual bool canBeUsedExternally(bool _inLibrary) const override; + TypePointer interfaceType(bool _inLibrary) const override; + bool canBeUsedExternally(bool _inLibrary) const override; TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; - virtual std::string canonicalName() const override; - virtual std::string signatureInExternalFunction(bool _structsByName) const override; + std::string canonicalName() const override; + std::string signatureInExternalFunction(bool _structsByName) const override; /// @returns a function that performs the type conversion between a list of struct members /// and a memory struct of this type. @@ -872,27 +872,27 @@ private: class EnumType: public Type { public: - virtual Category category() const override { return Category::Enum; } + Category category() const override { return Category::Enum; } explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {} - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual unsigned calldataEncodedSize(bool _padded) const override + TypePointer unaryOperatorResult(Token _operator) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + unsigned calldataEncodedSize(bool _padded) const override { return encodingType()->calldataEncodedSize(_padded); } - virtual unsigned storageBytes() const override; - virtual bool canLiveOutsideStorage() const override { return true; } - virtual std::string toString(bool _short) const override; - virtual std::string canonicalName() const override; - virtual bool isValueType() const override { return true; } + unsigned storageBytes() const override; + bool canLiveOutsideStorage() const override { return true; } + std::string toString(bool _short) const override; + std::string canonicalName() const override; + bool isValueType() const override { return true; } - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer encodingType() const override + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer encodingType() const override { return std::make_shared(8 * int(storageBytes())); } - virtual TypePointer interfaceType(bool _inLibrary) const override + TypePointer interfaceType(bool _inLibrary) const override { return _inLibrary ? shared_from_this() : encodingType(); } @@ -913,21 +913,21 @@ private: class TupleType: public Type { public: - virtual Category category() const override { return Category::Tuple; } + Category category() const override { return Category::Tuple; } explicit TupleType(std::vector const& _types = std::vector()): m_components(_types) {} - virtual bool isImplicitlyConvertibleTo(Type const& _other) const override; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual std::string toString(bool) const override; - virtual bool canBeStored() const override { return false; } - virtual u256 storageSize() const override; - virtual bool canLiveOutsideStorage() const override { return false; } - virtual unsigned sizeOnStack() const override; - virtual bool hasSimpleZeroValueInMemory() const override { return false; } - virtual TypePointer mobileType() const override; + bool isImplicitlyConvertibleTo(Type const& _other) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } + std::string toString(bool) const override; + bool canBeStored() const override { return false; } + u256 storageSize() const override; + bool canLiveOutsideStorage() const override { return false; } + unsigned sizeOnStack() const override; + bool hasSimpleZeroValueInMemory() const override { return false; } + TypePointer mobileType() const override; /// Converts components to their temporary types and performs some wildcard matching. - virtual TypePointer closestTemporaryType(TypePointer const& _targetType) const override; + TypePointer closestTemporaryType(TypePointer const& _targetType) const override; std::vector const& components() const { return m_components; } @@ -987,7 +987,7 @@ public: GasLeft, ///< gasleft() }; - virtual Category category() const override { return Category::Function; } + Category category() const override { return Category::Function; } /// Creates the type of a function. explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); @@ -1061,25 +1061,25 @@ public: /// @returns the "self" parameter type for a bound function TypePointer const& selfType() const; - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; - virtual TypePointer unaryOperatorResult(Token _operator) const override; - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override; - virtual std::string canonicalName() const override; - virtual std::string toString(bool _short) const override; - virtual unsigned calldataEncodedSize(bool _padded) const override; - virtual bool canBeStored() const override { return m_kind == Kind::Internal || m_kind == Kind::External; } - virtual u256 storageSize() const override; - virtual unsigned storageBytes() const override; - virtual bool isValueType() const override { return true; } - virtual bool canLiveOutsideStorage() const override { return m_kind == Kind::Internal || m_kind == Kind::External; } - virtual unsigned sizeOnStack() const override; - virtual bool hasSimpleZeroValueInMemory() const override { return false; } - virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; - virtual TypePointer encodingType() const override; - virtual TypePointer interfaceType(bool _inLibrary) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; + bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; + TypePointer unaryOperatorResult(Token _operator) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override; + std::string canonicalName() const override; + std::string toString(bool _short) const override; + unsigned calldataEncodedSize(bool _padded) const override; + bool canBeStored() const override { return m_kind == Kind::Internal || m_kind == Kind::External; } + u256 storageSize() const override; + unsigned storageBytes() const override; + bool isValueType() const override { return true; } + bool canLiveOutsideStorage() const override { return m_kind == Kind::Internal || m_kind == Kind::External; } + unsigned sizeOnStack() const override; + bool hasSimpleZeroValueInMemory() const override { return false; } + MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; + TypePointer encodingType() const override; + TypePointer interfaceType(bool _inLibrary) const override; /// @returns TypePointer of a new FunctionType object. All input/return parameters are an /// appropriate external types (i.e. the interfaceType()s) of input/return parameters of @@ -1187,27 +1187,27 @@ private: class MappingType: public Type { public: - virtual Category category() const override { return Category::Mapping; } + Category category() const override { return Category::Mapping; } MappingType(TypePointer const& _keyType, TypePointer const& _valueType): m_keyType(_keyType), m_valueType(_valueType) {} - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual std::string toString(bool _short) const override; - virtual std::string canonicalName() const override; - virtual bool canLiveOutsideStorage() const override { return false; } - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual TypePointer encodingType() const override + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + std::string toString(bool _short) const override; + std::string canonicalName() const override; + bool canLiveOutsideStorage() const override { return false; } + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } + TypePointer encodingType() const override { return std::make_shared(256); } - virtual TypePointer interfaceType(bool _inLibrary) const override + TypePointer interfaceType(bool _inLibrary) const override { return _inLibrary ? shared_from_this() : TypePointer(); } - virtual bool dataStoredIn(DataLocation _location) const override { return _location == DataLocation::Storage; } + bool dataStoredIn(DataLocation _location) const override { return _location == DataLocation::Storage; } /// Cannot be stored in memory, but just in case. - virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } + bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } TypePointer const& keyType() const { return m_keyType; } TypePointer const& valueType() const { return m_valueType; } @@ -1225,20 +1225,20 @@ private: class TypeType: public Type { public: - virtual Category category() const override { return Category::TypeType; } + Category category() const override { return Category::TypeType; } explicit TypeType(TypePointer const& _actualType): m_actualType(_actualType) {} TypePointer const& actualType() const { return m_actualType; } - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual bool canBeStored() const override { return false; } - virtual u256 storageSize() const override; - virtual bool canLiveOutsideStorage() const override { return false; } - virtual unsigned sizeOnStack() const override; - virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } - virtual std::string toString(bool _short) const override { return "type(" + m_actualType->toString(_short) + ")"; } - virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + bool canBeStored() const override { return false; } + u256 storageSize() const override; + bool canLiveOutsideStorage() const override { return false; } + unsigned sizeOnStack() const override; + bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } + std::string toString(bool _short) const override { return "type(" + m_actualType->toString(_short) + ")"; } + MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; private: TypePointer m_actualType; @@ -1251,18 +1251,18 @@ private: class ModifierType: public Type { public: - virtual Category category() const override { return Category::Modifier; } + Category category() const override { return Category::Modifier; } explicit ModifierType(ModifierDefinition const& _modifier); - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual bool canBeStored() const override { return false; } - virtual u256 storageSize() const override; - virtual bool canLiveOutsideStorage() const override { return false; } - virtual unsigned sizeOnStack() const override { return 0; } - virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual std::string toString(bool _short) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } + bool canBeStored() const override { return false; } + u256 storageSize() const override; + bool canLiveOutsideStorage() const override { return false; } + unsigned sizeOnStack() const override { return 0; } + bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + std::string toString(bool _short) const override; private: TypePointers m_parameterTypes; @@ -1276,20 +1276,20 @@ private: class ModuleType: public Type { public: - virtual Category category() const override { return Category::Module; } + Category category() const override { return Category::Module; } explicit ModuleType(SourceUnit const& _source): m_sourceUnit(_source) {} - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual bool canBeStored() const override { return false; } - virtual bool canLiveOutsideStorage() const override { return true; } - virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } - virtual unsigned sizeOnStack() const override { return 0; } - virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + bool canBeStored() const override { return false; } + bool canLiveOutsideStorage() const override { return true; } + bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } + unsigned sizeOnStack() const override { return 0; } + MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; - virtual std::string toString(bool _short) const override; + std::string toString(bool _short) const override; private: SourceUnit const& m_sourceUnit; @@ -1303,24 +1303,24 @@ class MagicType: public Type { public: enum class Kind { Block, Message, Transaction, ABI }; - virtual Category category() const override { return Category::Magic; } + Category category() const override { return Category::Magic; } explicit MagicType(Kind _kind): m_kind(_kind) {} - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual std::string richIdentifier() const override; - virtual bool operator==(Type const& _other) const override; - virtual bool canBeStored() const override { return false; } - virtual bool canLiveOutsideStorage() const override { return true; } - virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } - virtual unsigned sizeOnStack() const override { return 0; } - virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; + std::string richIdentifier() const override; + bool operator==(Type const& _other) const override; + bool canBeStored() const override { return false; } + bool canLiveOutsideStorage() const override { return true; } + bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } + unsigned sizeOnStack() const override { return 0; } + MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; - virtual std::string toString(bool _short) const override; + std::string toString(bool _short) const override; Kind kind() const { return m_kind; } @@ -1335,20 +1335,20 @@ private: class InaccessibleDynamicType: public Type { public: - virtual Category category() const override { return Category::InaccessibleDynamic; } + Category category() const override { return Category::InaccessibleDynamic; } - virtual std::string richIdentifier() const override { return "t_inaccessible"; } - virtual bool isImplicitlyConvertibleTo(Type const&) const override { return false; } - virtual bool isExplicitlyConvertibleTo(Type const&) const override { return false; } - virtual TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } - virtual unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; } - virtual bool canBeStored() const override { return false; } - virtual bool canLiveOutsideStorage() const override { return false; } - virtual bool isValueType() const override { return true; } - virtual unsigned sizeOnStack() const override { return 1; } - virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } - virtual std::string toString(bool) const override { return "inaccessible dynamic type"; } - virtual TypePointer decodingType() const override { return std::make_shared(256); } + std::string richIdentifier() const override { return "t_inaccessible"; } + bool isImplicitlyConvertibleTo(Type const&) const override { return false; } + bool isExplicitlyConvertibleTo(Type const&) const override { return false; } + TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); } + unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; } + bool canBeStored() const override { return false; } + bool canLiveOutsideStorage() const override { return false; } + bool isValueType() const override { return true; } + unsigned sizeOnStack() const override { return 1; } + bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); } + std::string toString(bool) const override { return "inaccessible dynamic type"; } + TypePointer decodingType() const override { return std::make_shared(256); } }; } diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h index 5fa650b17..001aec7ca 100644 --- a/libsolidity/codegen/ContractCompiler.h +++ b/libsolidity/codegen/ContractCompiler.h @@ -88,22 +88,22 @@ private: void registerStateVariables(ContractDefinition const& _contract); void initializeStateVariables(ContractDefinition const& _contract); - virtual bool visit(VariableDeclaration const& _variableDeclaration) override; - virtual bool visit(FunctionDefinition const& _function) override; - virtual bool visit(InlineAssembly const& _inlineAssembly) override; - virtual bool visit(IfStatement const& _ifStatement) override; - virtual bool visit(WhileStatement const& _whileStatement) override; - virtual bool visit(ForStatement const& _forStatement) override; - virtual bool visit(Continue const& _continueStatement) override; - virtual bool visit(Break const& _breakStatement) override; - virtual bool visit(Return const& _return) override; - virtual bool visit(Throw const& _throw) override; - virtual bool visit(EmitStatement const& _emit) override; - virtual bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override; - virtual bool visit(ExpressionStatement const& _expressionStatement) override; - virtual bool visit(PlaceholderStatement const&) override; - virtual bool visit(Block const& _block) override; - virtual void endVisit(Block const& _block) override; + bool visit(VariableDeclaration const& _variableDeclaration) override; + bool visit(FunctionDefinition const& _function) override; + bool visit(InlineAssembly const& _inlineAssembly) override; + bool visit(IfStatement const& _ifStatement) override; + bool visit(WhileStatement const& _whileStatement) override; + bool visit(ForStatement const& _forStatement) override; + bool visit(Continue const& _continueStatement) override; + bool visit(Break const& _breakStatement) override; + bool visit(Return const& _return) override; + bool visit(Throw const& _throw) override; + bool visit(EmitStatement const& _emit) override; + bool visit(VariableDeclarationStatement const& _variableDeclarationStatement) override; + bool visit(ExpressionStatement const& _expressionStatement) override; + bool visit(PlaceholderStatement const&) override; + bool visit(Block const& _block) override; + void endVisit(Block const& _block) override; /// Repeatedly visits all function which are referenced but which are not compiled yet. void appendMissingFunctions(); diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index 3d8e86821..9a695b4c9 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -71,17 +71,17 @@ public: void appendConstStateVariableAccessor(const VariableDeclaration& _varDecl); private: - virtual bool visit(Conditional const& _condition) override; - virtual bool visit(Assignment const& _assignment) override; - virtual bool visit(TupleExpression const& _tuple) override; - virtual bool visit(UnaryOperation const& _unaryOperation) override; - virtual bool visit(BinaryOperation const& _binaryOperation) override; - virtual bool visit(FunctionCall const& _functionCall) override; - virtual bool visit(NewExpression const& _newExpression) override; - virtual bool visit(MemberAccess const& _memberAccess) override; - virtual bool visit(IndexAccess const& _indexAccess) override; - virtual void endVisit(Identifier const& _identifier) override; - virtual void endVisit(Literal const& _literal) override; + bool visit(Conditional const& _condition) override; + bool visit(Assignment const& _assignment) override; + bool visit(TupleExpression const& _tuple) override; + bool visit(UnaryOperation const& _unaryOperation) override; + bool visit(BinaryOperation const& _binaryOperation) override; + bool visit(FunctionCall const& _functionCall) override; + bool visit(NewExpression const& _newExpression) override; + bool visit(MemberAccess const& _memberAccess) override; + bool visit(IndexAccess const& _indexAccess) override; + void endVisit(Identifier const& _identifier) override; + void endVisit(Literal const& _literal) override; ///@{ ///@name Append code for various operator types diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index c576f9de9..6054af28a 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -82,8 +82,8 @@ class StackVariable: public LValue public: StackVariable(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); - virtual unsigned sizeOnStack() const override { return 0; } - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + unsigned sizeOnStack() const override { return 0; } + void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, SourceLocation const& _location = SourceLocation(), @@ -108,8 +108,8 @@ class MemoryItem: public LValue { public: MemoryItem(CompilerContext& _compilerContext, Type const& _type, bool _padded = true); - virtual unsigned sizeOnStack() const override { return 1; } - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + unsigned sizeOnStack() const override { return 1; } + void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, SourceLocation const& _location = SourceLocation(), @@ -136,8 +136,8 @@ public: StorageItem(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); /// Constructs the LValue and assumes that the storage reference is already on the stack. StorageItem(CompilerContext& _compilerContext, Type const& _type); - virtual unsigned sizeOnStack() const override { return 2; } - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + unsigned sizeOnStack() const override { return 2; } + void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, SourceLocation const& _location = SourceLocation(), @@ -158,8 +158,8 @@ class StorageByteArrayElement: public LValue public: /// Constructs the LValue and assumes that the storage reference is already on the stack. StorageByteArrayElement(CompilerContext& _compilerContext); - virtual unsigned sizeOnStack() const override { return 2; } - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + unsigned sizeOnStack() const override { return 2; } + void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, SourceLocation const& _location = SourceLocation(), @@ -181,7 +181,7 @@ class StorageArrayLength: public LValue public: /// Constructs the LValue, assumes that the reference to the array head is already on the stack. StorageArrayLength(CompilerContext& _compilerContext, ArrayType const& _arrayType); - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, SourceLocation const& _location = SourceLocation(), @@ -205,8 +205,8 @@ public: /// Constructs the LValue assuming that the other LValues are present on the stack. /// Empty unique_ptrs are possible if e.g. some values should be ignored during assignment. TupleObject(CompilerContext& _compilerContext, std::vector>&& _lvalues); - virtual unsigned sizeOnStack() const override; - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + unsigned sizeOnStack() const override; + void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, SourceLocation const& _location = SourceLocation(), diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 869c9c50a..4a5974aac 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -51,24 +51,24 @@ private: // because the order of expression evaluation is undefined // TODO: or just force a certain order, but people might have a different idea about that. - virtual bool visit(ContractDefinition const& _node) override; - virtual void endVisit(ContractDefinition const& _node) override; - virtual void endVisit(VariableDeclaration const& _node) override; - virtual bool visit(FunctionDefinition const& _node) override; - virtual void endVisit(FunctionDefinition const& _node) override; - virtual bool visit(IfStatement const& _node) override; - virtual bool visit(WhileStatement const& _node) override; - virtual bool visit(ForStatement const& _node) override; - virtual void endVisit(VariableDeclarationStatement const& _node) override; - virtual void endVisit(Assignment const& _node) override; - virtual void endVisit(TupleExpression const& _node) override; - virtual void endVisit(UnaryOperation const& _node) override; - virtual void endVisit(BinaryOperation const& _node) override; - virtual void endVisit(FunctionCall const& _node) override; - virtual void endVisit(Identifier const& _node) override; - virtual void endVisit(Literal const& _node) override; - virtual void endVisit(Return const& _node) override; - virtual bool visit(MemberAccess const& _node) override; + bool visit(ContractDefinition const& _node) override; + void endVisit(ContractDefinition const& _node) override; + void endVisit(VariableDeclaration const& _node) override; + bool visit(FunctionDefinition const& _node) override; + void endVisit(FunctionDefinition const& _node) override; + bool visit(IfStatement const& _node) override; + bool visit(WhileStatement const& _node) override; + bool visit(ForStatement const& _node) override; + void endVisit(VariableDeclarationStatement const& _node) override; + void endVisit(Assignment const& _node) override; + void endVisit(TupleExpression const& _node) override; + void endVisit(UnaryOperation const& _node) override; + void endVisit(BinaryOperation const& _node) override; + void endVisit(FunctionCall const& _node) override; + void endVisit(Identifier const& _node) override; + void endVisit(Literal const& _node) override; + void endVisit(Return const& _node) override; + bool visit(MemberAccess const& _node) override; void arithmeticOperation(BinaryOperation const& _op); void compareOperation(BinaryOperation const& _op); diff --git a/libyul/backends/evm/EVMAssembly.h b/libyul/backends/evm/EVMAssembly.h index 556ed5a58..8f92b6e73 100644 --- a/libyul/backends/evm/EVMAssembly.h +++ b/libyul/backends/evm/EVMAssembly.h @@ -38,42 +38,42 @@ public: virtual ~EVMAssembly() {} /// Set a new source location valid starting from the next instruction. - virtual void setSourceLocation(SourceLocation const& _location) override; + void setSourceLocation(SourceLocation const& _location) override; /// Retrieve the current height of the stack. This does not have to be zero /// at the beginning. - virtual int stackHeight() const override { return m_stackHeight; } + int stackHeight() const override { return m_stackHeight; } /// Append an EVM instruction. - virtual void appendInstruction(solidity::Instruction _instruction) override; + void appendInstruction(solidity::Instruction _instruction) override; /// Append a constant. - virtual void appendConstant(u256 const& _constant) override; + void appendConstant(u256 const& _constant) override; /// Append a label. - virtual void appendLabel(LabelID _labelId) override; + void appendLabel(LabelID _labelId) override; /// Append a label reference. - virtual void appendLabelReference(LabelID _labelId) override; + void appendLabelReference(LabelID _labelId) override; /// Generate a new unique label. - virtual LabelID newLabelId() override; + LabelID newLabelId() override; /// Returns a label identified by the given name. Creates it if it does not yet exist. - virtual LabelID namedLabel(std::string const& _name) override; + LabelID namedLabel(std::string const& _name) override; /// Append a reference to a to-be-linked symbol. /// Currently, we assume that the value is always a 20 byte number. - virtual void appendLinkerSymbol(std::string const& _name) override; + void appendLinkerSymbol(std::string const& _name) override; /// Append a jump instruction. /// @param _stackDiffAfter the stack adjustment after this instruction. - virtual void appendJump(int _stackDiffAfter) override; + void appendJump(int _stackDiffAfter) override; /// Append a jump-to-immediate operation. - virtual void appendJumpTo(LabelID _labelId, int _stackDiffAfter) override; + void appendJumpTo(LabelID _labelId, int _stackDiffAfter) override; /// Append a jump-to-if-immediate operation. - virtual void appendJumpToIf(LabelID _labelId) override; + void appendJumpToIf(LabelID _labelId) override; /// Start a subroutine. - virtual void appendBeginsub(LabelID _labelId, int _arguments) override; + void appendBeginsub(LabelID _labelId, int _arguments) override; /// Call a subroutine. - virtual void appendJumpsub(LabelID _labelId, int _arguments, int _returns) override; + void appendJumpsub(LabelID _labelId, int _arguments, int _returns) override; /// Return from a subroutine. - virtual void appendReturnsub(int _returns, int _stackDiffAfter) override; + void appendReturnsub(int _returns, int _stackDiffAfter) override; /// Append the assembled size as a constant. - virtual void appendAssemblySize() override; + void appendAssemblySize() override; /// Resolves references inside the bytecode and returns the linker object. eth::LinkerObject finalize(); diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index b6aceee3f..95e58a560 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -71,21 +71,21 @@ class ASTCopier: public ExpressionCopier, public StatementCopier { public: virtual ~ASTCopier() = default; - virtual Expression operator()(Literal const& _literal) override; - virtual Statement operator()(Instruction const& _instruction) override; - virtual Expression operator()(Identifier const& _identifier) override; - virtual Expression operator()(FunctionalInstruction const& _instr) override; - virtual Expression operator()(FunctionCall const&) override; - virtual Statement operator()(ExpressionStatement const& _statement) override; - virtual Statement operator()(Label const& _label) override; - virtual Statement operator()(StackAssignment const& _assignment) override; - virtual Statement operator()(Assignment const& _assignment) override; - virtual Statement operator()(VariableDeclaration const& _varDecl) override; - virtual Statement operator()(If const& _if) override; - virtual Statement operator()(Switch const& _switch) override; - virtual Statement operator()(FunctionDefinition const&) override; - virtual Statement operator()(ForLoop const&) override; - virtual Statement operator()(Block const& _block) override; + Expression operator()(Literal const& _literal) override; + Statement operator()(Instruction const& _instruction) override; + Expression operator()(Identifier const& _identifier) override; + Expression operator()(FunctionalInstruction const& _instr) override; + Expression operator()(FunctionCall const&) override; + Statement operator()(ExpressionStatement const& _statement) override; + Statement operator()(Label const& _label) override; + Statement operator()(StackAssignment const& _assignment) override; + Statement operator()(Assignment const& _assignment) override; + Statement operator()(VariableDeclaration const& _varDecl) override; + Statement operator()(If const& _if) override; + Statement operator()(Switch const& _switch) override; + Statement operator()(FunctionDefinition const&) override; + Statement operator()(ForLoop const&) override; + Statement operator()(Block const& _block) override; virtual Expression translate(Expression const& _expression); virtual Statement translate(Statement const& _statement); diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index f8aa0ee1c..16b39f5bf 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -38,7 +38,7 @@ class CommonSubexpressionEliminator: public DataFlowAnalyzer { protected: using ASTModifier::visit; - virtual void visit(Expression& _e) override; + void visit(Expression& _e) override; }; } diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index a0c21eee4..a946529ab 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -45,13 +45,13 @@ class DataFlowAnalyzer: public ASTModifier { public: using ASTModifier::operator(); - virtual void operator()(Assignment& _assignment) override; - virtual void operator()(VariableDeclaration& _varDecl) override; - virtual void operator()(If& _if) override; - virtual void operator()(Switch& _switch) override; - virtual void operator()(FunctionDefinition&) override; - virtual void operator()(ForLoop&) override; - virtual void operator()(Block& _block) override; + void operator()(Assignment& _assignment) override; + void operator()(VariableDeclaration& _varDecl) override; + void operator()(If& _if) override; + void operator()(Switch& _switch) override; + void operator()(FunctionDefinition&) override; + void operator()(ForLoop&) override; + void operator()(Block& _block) override; protected: /// Registers the assignment. diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index bfb65682e..0fcd41d9b 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -52,11 +52,11 @@ public: } protected: - virtual void enterScope(Block const& _block) override; - virtual void leaveScope(Block const& _block) override; - virtual void enterFunction(FunctionDefinition const& _function) override; - virtual void leaveFunction(FunctionDefinition const& _function) override; - virtual YulString translateIdentifier(YulString _name) override; + void enterScope(Block const& _block) override; + void leaveScope(Block const& _block) override; + void enterFunction(FunctionDefinition const& _function) override; + void leaveFunction(FunctionDefinition const& _function) override; + YulString translateIdentifier(YulString _name) override; void enterScopeInternal(solidity::assembly::Scope& _scope); void leaveScopeInternal(solidity::assembly::Scope& _scope); diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index d903664f1..ee98da8fb 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -54,9 +54,9 @@ public: void run(); using ASTModifier::operator(); - virtual void operator()(FunctionDefinition& _fun) override; + void operator()(FunctionDefinition& _fun) override; - virtual void visit(Expression& _expression) override; + void visit(Expression& _expression) override; private: std::map m_inlinableFunctions; diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index 339acbf0b..82274203a 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -63,12 +63,12 @@ public: m_nameDispenser(_nameDispenser) { } - virtual void operator()(FunctionalInstruction&) override; - virtual void operator()(FunctionCall&) override; - virtual void operator()(If&) override; - virtual void operator()(Switch&) override; - virtual void operator()(ForLoop&) override; - virtual void operator()(Block& _block) override; + void operator()(FunctionalInstruction&) override; + void operator()(FunctionCall&) override; + void operator()(If&) override; + void operator()(Switch&) override; + void operator()(ForLoop&) override; + void operator()(Block& _block) override; private: /// Replaces the expression by a variable if it is a function call or functional diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 66ce8e2fe..8243160d3 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -110,7 +110,7 @@ public: m_nameDispenser(_nameDispenser) { } - virtual void operator()(Block& _block) override; + void operator()(Block& _block) override; private: boost::optional> tryInlineStatement(Statement& _statement); @@ -141,10 +141,10 @@ public: using ASTCopier::operator (); - virtual Statement operator()(VariableDeclaration const& _varDecl) override; - virtual Statement operator()(FunctionDefinition const& _funDef) override; + Statement operator()(VariableDeclaration const& _varDecl) override; + Statement operator()(FunctionDefinition const& _funDef) override; - virtual YulString translateIdentifier(YulString _name) override; + YulString translateIdentifier(YulString _name) override; NameDispenser& m_nameDispenser; YulString m_varNamePrefix; diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index baf4bbfc9..a96f042f0 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -49,9 +49,9 @@ public: } using ASTWalker::operator(); - virtual void operator()(Identifier const& _identifier) override; - virtual void operator()(FunctionCall const& _funCall) override; - virtual void operator()(FunctionDefinition const& _function) override; + void operator()(Identifier const& _identifier) override; + void operator()(FunctionCall const& _funCall) override; + void operator()(FunctionDefinition const& _function) override; private: void checkAllowed(YulString _name) diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index 47c7ec79b..e65110a8a 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -41,8 +41,8 @@ public: static size_t codeSize(Block const& _block); private: - virtual void visit(Statement const& _statement) override; - virtual void visit(Expression const& _expression) override; + void visit(Statement const& _statement) override; + void visit(Expression const& _expression) override; private: size_t m_size = 0; diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index b76eec308..8ef0178d5 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -42,8 +42,8 @@ public: } using ASTWalker::operator (); - virtual void operator()(VariableDeclaration const& _varDecl) override; - virtual void operator()(FunctionDefinition const& _funDef) override; + void operator()(VariableDeclaration const& _varDecl) override; + void operator()(FunctionDefinition const& _funDef) override; std::set names() const { return m_names; } private: @@ -75,7 +75,7 @@ class Assignments: public ASTWalker { public: using ASTWalker::operator (); - virtual void operator()(Assignment const& _assignment) override; + void operator()(Assignment const& _assignment) override; std::set const& names() const { return m_names; } private: diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index f82465ebd..f0e7cb018 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -36,7 +36,7 @@ class Rematerialiser: public DataFlowAnalyzer { protected: using ASTModifier::visit; - virtual void visit(Expression& _e) override; + void visit(Expression& _e) override; }; diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index d1539c867..acd5229c3 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -41,8 +41,8 @@ class SSAValueTracker: public ASTWalker { public: using ASTWalker::operator(); - virtual void operator()(VariableDeclaration const& _varDecl) override; - virtual void operator()(Assignment const& _assignment) override; + void operator()(VariableDeclaration const& _varDecl) override; + void operator()(Assignment const& _assignment) override; std::map const& values() const { return m_values; } Expression const* value(YulString _name) const { return m_values.at(_name); } diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index 620a91cb9..a7e8706b5 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -38,12 +38,12 @@ public: MovableChecker() = default; explicit MovableChecker(Expression const& _expression); - virtual void operator()(Identifier const& _identifier) override; - virtual void operator()(FunctionalInstruction const& _functionalInstruction) override; - virtual void operator()(FunctionCall const& _functionCall) override; + void operator()(Identifier const& _identifier) override; + void operator()(FunctionalInstruction const& _functionalInstruction) override; + void operator()(FunctionCall const& _functionCall) override; /// Disallow visiting anything apart from Expressions (this throws). - virtual void visit(Statement const&) override; + void visit(Statement const&) override; using ASTWalker::visit; bool movable() const { return m_movable; } diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index 59ee4620b..3cc4b45e7 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -40,7 +40,7 @@ public: Substitution(std::map const& _substitutions): m_substitutions(_substitutions) {} - virtual Expression translate(Expression const& _expression) override; + Expression translate(Expression const& _expression) override; private: std::map const& m_substitutions; diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index b5aea3dd4..b5b46443f 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -45,7 +45,7 @@ public: explicit UnusedPruner(Block& _ast, std::set const& _externallyUsedFunctions = {}); using ASTModifier::operator(); - virtual void operator()(Block& _block) override; + void operator()(Block& _block) override; // @returns true iff the code changed in the previous run. bool shouldRunAgain() const { return m_shouldRunAgain; } diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h index 6f24bb60d..9760ef660 100644 --- a/test/libsolidity/ASTJSONTest.h +++ b/test/libsolidity/ASTJSONTest.h @@ -39,10 +39,10 @@ public: { return std::unique_ptr(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> m_sources; std::string m_expectation; diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index e9e36aa60..654ce4a00 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -57,10 +57,10 @@ public: { return std::unique_ptr(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); From 01ce43e51ba8ced7f2e53f5e9f9e0ea6b718df64 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 21 Nov 2018 15:13:50 +0100 Subject: [PATCH 032/168] [SMTChecker] Refactor smt::Sort and its usage --- libsolidity/formal/CVC4Interface.cpp | 14 ++-- libsolidity/formal/CVC4Interface.h | 6 +- libsolidity/formal/SMTChecker.cpp | 4 +- libsolidity/formal/SMTChecker.h | 2 +- libsolidity/formal/SMTLib2Interface.cpp | 18 ++-- libsolidity/formal/SMTLib2Interface.h | 4 +- libsolidity/formal/SMTPortfolio.cpp | 2 +- libsolidity/formal/SMTPortfolio.h | 2 +- libsolidity/formal/SolverInterface.h | 106 +++++++++++------------- libsolidity/formal/SymbolicTypes.cpp | 18 +++- libsolidity/formal/SymbolicTypes.h | 4 +- libsolidity/formal/Z3Interface.cpp | 14 ++-- libsolidity/formal/Z3Interface.h | 6 +- 13 files changed, 101 insertions(+), 99 deletions(-) diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index 118229279..6e17eef17 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -50,7 +50,7 @@ void CVC4Interface::pop() m_solver.pop(); } -void CVC4Interface::declareFunction(string _name, vector const& _domain, Sort _codomain) +void CVC4Interface::declareFunction(string _name, vector const& _domain, Sort const& _codomain) { if (!m_functions.count(_name)) { @@ -186,13 +186,13 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr) return arguments[0]; } -CVC4::Type CVC4Interface::cvc4Sort(Sort _sort) +CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort) { - switch (_sort) + switch (_sort.kind) { - case Sort::Bool: + case Kind::Bool: return m_context.booleanType(); - case Sort::Int: + case Kind::Int: return m_context.integerType(); default: break; @@ -202,10 +202,10 @@ CVC4::Type CVC4Interface::cvc4Sort(Sort _sort) return m_context.integerType(); } -vector CVC4Interface::cvc4Sort(vector const& _sorts) +vector CVC4Interface::cvc4Sort(vector const& _sorts) { vector cvc4Sorts; for (auto const& _sort: _sorts) - cvc4Sorts.push_back(cvc4Sort(_sort)); + cvc4Sorts.push_back(cvc4Sort(*_sort)); return cvc4Sorts; } diff --git a/libsolidity/formal/CVC4Interface.h b/libsolidity/formal/CVC4Interface.h index 273dce235..f354c790b 100644 --- a/libsolidity/formal/CVC4Interface.h +++ b/libsolidity/formal/CVC4Interface.h @@ -51,7 +51,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; @@ -60,8 +60,8 @@ public: private: CVC4::Expr toCVC4Expr(Expression const& _expr); - CVC4::Type cvc4Sort(smt::Sort _sort); - std::vector cvc4Sort(std::vector const& _sort); + CVC4::Type cvc4Sort(smt::Sort const& _sort); + std::vector cvc4Sort(std::vector const& _sorts); CVC4::ExprManager m_context; CVC4::SmtEngine m_solver; diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index bbc78c0c7..0a581fc00 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -416,7 +416,7 @@ void SMTChecker::visitGasLeft(FunctionCall const& _funCall) void SMTChecker::visitBlockHash(FunctionCall const& _funCall) { string blockHash = "blockhash"; - defineUninterpretedFunction(blockHash, {smt::Sort::Int}, smt::Sort::Int); + defineUninterpretedFunction(blockHash, {make_shared(smt::Kind::Int)}, smt::Kind::Int); auto const& arguments = _funCall.arguments(); solAssert(arguments.size() == 1, ""); defineExpr(_funCall, m_uninterpretedFunctions.at(blockHash)({expr(*arguments[0])})); @@ -605,7 +605,7 @@ void SMTChecker::defineSpecialVariable(string const& _name, Expression const& _e defineExpr(_expr, m_specialVariables.at(_name)->currentValue()); } -void SMTChecker::defineUninterpretedFunction(string const& _name, vector const& _domain, smt::Sort _codomain) +void SMTChecker::defineUninterpretedFunction(string const& _name, vector const& _domain, smt::Sort const& _codomain) { if (!m_uninterpretedFunctions.count(_name)) m_uninterpretedFunctions.emplace(_name, m_interface->newFunction(_name, _domain, _codomain)); diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 869c9c50a..a641cb5f5 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -83,7 +83,7 @@ private: void inlineFunctionCall(FunctionCall const&); void defineSpecialVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex = false); - void defineUninterpretedFunction(std::string const& _name, std::vector const& _domain, smt::Sort _codomain); + void defineUninterpretedFunction(std::string const& _name, std::vector const& _domain, smt::Sort const& _codomain); /// Division expression in the given type. Requires special treatment because /// of rounding for signed division. diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 545422338..01386dda9 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -64,12 +64,12 @@ void SMTLib2Interface::pop() m_accumulatedOutput.pop_back(); } -void SMTLib2Interface::declareFunction(string _name, vector const& _domain, Sort _codomain) +void SMTLib2Interface::declareFunction(string _name, vector const& _domain, Sort const& _codomain) { // TODO Use domain and codomain as key as well string domain(""); for (auto const& sort: _domain) - domain += toSmtLibSort(sort) + ' '; + domain += toSmtLibSort(*sort) + ' '; if (!m_functions.count(_name)) { m_functions.insert(_name); @@ -79,7 +79,7 @@ void SMTLib2Interface::declareFunction(string _name, vector const& _domain "| (" + domain + ") " + - (_codomain == Sort::Int ? "Int" : "Bool") + + (_codomain.kind == Kind::Int ? "Int" : "Bool") + ")" ); } @@ -143,13 +143,13 @@ string SMTLib2Interface::toSExpr(Expression const& _expr) return sexpr; } -string SMTLib2Interface::toSmtLibSort(Sort _sort) +string SMTLib2Interface::toSmtLibSort(Sort const& _sort) { - switch (_sort) + switch (_sort.kind) { - case Sort::Int: + case Kind::Int: return "Int"; - case Sort::Bool: + case Kind::Bool: return "Bool"; default: solAssert(false, "Invalid SMT sort"); @@ -173,8 +173,8 @@ string SMTLib2Interface::checkSatAndGetValuesCommand(vector const& _ for (size_t i = 0; i < _expressionsToEvaluate.size(); i++) { auto const& e = _expressionsToEvaluate.at(i); - solAssert(e.sort == Sort::Int || e.sort == Sort::Bool, "Invalid sort for expression to evaluate."); - command += "(declare-const |EVALEXPR_" + to_string(i) + "| " + (e.sort == Sort::Int ? "Int" : "Bool") + ")\n"; + solAssert(e.sort->kind == Kind::Int || e.sort->kind == Kind::Bool, "Invalid sort for expression to evaluate."); + command += "(declare-const |EVALEXPR_" + to_string(i) + "| " + (e.sort->kind == Kind::Int ? "Int" : "Bool") + ")\n"; command += "(assert (= |EVALEXPR_" + to_string(i) + "| " + toSExpr(e) + "))\n"; } command += "(check-sat)\n"; diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index 08ad74daf..b140f5557 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -49,7 +49,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; @@ -58,7 +58,7 @@ public: private: std::string toSExpr(Expression const& _expr); - std::string toSmtLibSort(Sort _sort); + std::string toSmtLibSort(Sort const& _sort); void write(std::string _data); diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index e1cde04c6..e01a5accf 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -64,7 +64,7 @@ void SMTPortfolio::pop() s->pop(); } -void SMTPortfolio::declareFunction(string _name, vector const& _domain, Sort _codomain) +void SMTPortfolio::declareFunction(string _name, vector const& _domain, Sort const& _codomain) { for (auto s : m_solvers) s->declareFunction(_name, _domain, _codomain); diff --git a/libsolidity/formal/SMTPortfolio.h b/libsolidity/formal/SMTPortfolio.h index 50bd87d46..712fb545c 100644 --- a/libsolidity/formal/SMTPortfolio.h +++ b/libsolidity/formal/SMTPortfolio.h @@ -49,7 +49,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index a6618fb59..55c0a5634 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -42,21 +42,32 @@ enum class CheckResult SATISFIABLE, UNSATISFIABLE, UNKNOWN, CONFLICTING, ERROR }; -enum class Sort +enum class Kind { Int, Bool }; +struct Sort +{ + Sort(Kind _kind): + kind(_kind) {} + virtual ~Sort() = default; + Kind const kind; + bool operator==(Sort const& _other) const { return kind == _other.kind; } +}; +using SortPointer = std::shared_ptr; + + /// C++ representation of an SMTLIB2 expression. class Expression { friend class SolverInterface; public: - explicit Expression(bool _v): name(_v ? "true" : "false"), sort(Sort::Bool) {} - Expression(size_t _number): name(std::to_string(_number)), sort(Sort::Int) {} - Expression(u256 const& _number): name(_number.str()), sort(Sort::Int) {} - Expression(bigint const& _number): name(_number.str()), sort(Sort::Int) {} + explicit Expression(bool _v): Expression(_v ? "true" : "false", Kind::Bool) {} + Expression(size_t _number): Expression(std::to_string(_number), Kind::Int) {} + Expression(u256 const& _number): Expression(_number.str(), Kind::Int) {} + Expression(bigint const& _number): Expression(_number.str(), Kind::Int) {} Expression(Expression const&) = default; Expression(Expression&&) = default; @@ -85,7 +96,7 @@ public: static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue) { - solAssert(_trueValue.sort == _falseValue.sort, ""); + solAssert(*_trueValue.sort == *_falseValue.sort, ""); return Expression("ite", std::vector{ std::move(_condition), std::move(_trueValue), std::move(_falseValue) }, _trueValue.sort); @@ -98,19 +109,19 @@ public: friend Expression operator!(Expression _a) { - return Expression("not", std::move(_a), Sort::Bool); + return Expression("not", std::move(_a), Kind::Bool); } friend Expression operator&&(Expression _a, Expression _b) { - return Expression("and", std::move(_a), std::move(_b), Sort::Bool); + return Expression("and", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator||(Expression _a, Expression _b) { - return Expression("or", std::move(_a), std::move(_b), Sort::Bool); + return Expression("or", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator==(Expression _a, Expression _b) { - return Expression("=", std::move(_a), std::move(_b), Sort::Bool); + return Expression("=", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator!=(Expression _a, Expression _b) { @@ -118,35 +129,35 @@ public: } friend Expression operator<(Expression _a, Expression _b) { - return Expression("<", std::move(_a), std::move(_b), Sort::Bool); + return Expression("<", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator<=(Expression _a, Expression _b) { - return Expression("<=", std::move(_a), std::move(_b), Sort::Bool); + return Expression("<=", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator>(Expression _a, Expression _b) { - return Expression(">", std::move(_a), std::move(_b), Sort::Bool); + return Expression(">", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator>=(Expression _a, Expression _b) { - return Expression(">=", std::move(_a), std::move(_b), Sort::Bool); + return Expression(">=", std::move(_a), std::move(_b), Kind::Bool); } friend Expression operator+(Expression _a, Expression _b) { - return Expression("+", std::move(_a), std::move(_b), Sort::Int); + return Expression("+", std::move(_a), std::move(_b), Kind::Int); } friend Expression operator-(Expression _a, Expression _b) { - return Expression("-", std::move(_a), std::move(_b), Sort::Int); + return Expression("-", std::move(_a), std::move(_b), Kind::Int); } friend Expression operator*(Expression _a, Expression _b) { - return Expression("*", std::move(_a), std::move(_b), Sort::Int); + return Expression("*", std::move(_a), std::move(_b), Kind::Int); } friend Expression operator/(Expression _a, Expression _b) { - return Expression("/", std::move(_a), std::move(_b), Sort::Int); + return Expression("/", std::move(_a), std::move(_b), Kind::Int); } Expression operator()(std::vector _arguments) const { @@ -154,36 +165,26 @@ public: arguments.empty(), "Attempted function application to non-function." ); - switch (sort) - { - case Sort::Int: - return Expression(name, std::move(_arguments), Sort::Int); - case Sort::Bool: - return Expression(name, std::move(_arguments), Sort::Bool); - default: - solAssert( - false, - "Attempted function application to invalid type." - ); - break; - } + return Expression(name, std::move(_arguments), sort); } std::string name; std::vector arguments; - Sort sort; + SortPointer sort; private: - /// Manual constructor, should only be used by SolverInterface and this class itself. - Expression(std::string _name, std::vector _arguments, Sort _sort): - name(std::move(_name)), arguments(std::move(_arguments)), sort(_sort) {} + /// Manual constructors, should only be used by SolverInterface and this class itself. + Expression(std::string _name, std::vector _arguments, SortPointer _sort): + name(std::move(_name)), arguments(std::move(_arguments)), sort(std::move(_sort)) {} + Expression(std::string _name, std::vector _arguments, Kind _kind): + Expression(std::move(_name), std::move(_arguments), std::make_shared(_kind)) {} - explicit Expression(std::string _name, Sort _sort): - Expression(std::move(_name), std::vector{}, _sort) {} - Expression(std::string _name, Expression _arg, Sort _sort): - Expression(std::move(_name), std::vector{std::move(_arg)}, _sort) {} - Expression(std::string _name, Expression _arg1, Expression _arg2, Sort _sort): - Expression(std::move(_name), std::vector{std::move(_arg1), std::move(_arg2)}, _sort) {} + explicit Expression(std::string _name, Kind _kind): + Expression(std::move(_name), std::vector{}, _kind) {} + Expression(std::string _name, Expression _arg, Kind _kind): + Expression(std::move(_name), std::vector{std::move(_arg)}, _kind) {} + Expression(std::string _name, Expression _arg1, Expression _arg2, Kind _kind): + Expression(std::move(_name), std::vector{std::move(_arg1), std::move(_arg2)}, _kind) {} }; DEV_SIMPLE_EXCEPTION(SolverError); @@ -197,39 +198,26 @@ public: virtual void push() = 0; virtual void pop() = 0; - virtual void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) = 0; - void declareFunction(std::string _name, Sort _domain, Sort _codomain) - { - declareFunction(std::move(_name), std::vector{std::move(_domain)}, std::move(_codomain)); - } - Expression newFunction(std::string _name, std::vector const& _domain, Sort _codomain) + virtual void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) = 0; + Expression newFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) { declareFunction(_name, _domain, _codomain); // Subclasses should do something here - switch (_codomain) - { - case Sort::Int: - return Expression(std::move(_name), {}, Sort::Int); - case Sort::Bool: - return Expression(std::move(_name), {}, Sort::Bool); - default: - solAssert(false, "Function sort not supported."); - break; - } + return Expression(std::move(_name), {}, _codomain.kind); } virtual void declareInteger(std::string _name) = 0; Expression newInteger(std::string _name) { // Subclasses should do something here declareInteger(_name); - return Expression(std::move(_name), {}, Sort::Int); + return Expression(std::move(_name), {}, Kind::Int); } virtual void declareBool(std::string _name) = 0; Expression newBool(std::string _name) { // Subclasses should do something here declareBool(_name); - return Expression(std::move(_name), {}, Sort::Bool); + return Expression(std::move(_name), {}, Kind::Bool); } virtual void addAssertion(Expression const& _expr) = 0; diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 78bf861bf..a3b6e3a8b 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -24,12 +24,24 @@ using namespace std; using namespace dev::solidity; -smt::Sort dev::solidity::smtSort(Type::Category _category) +smt::SortPointer dev::solidity::smtSort(Type const& _type) +{ + switch (smtKind(_type.category())) + { + case smt::Kind::Int: + return make_shared(smt::Kind::Int); + case smt::Kind::Bool: + return make_shared(smt::Kind::Bool); + } + solAssert(false, "Invalid type"); +} + +smt::Kind dev::solidity::smtKind(Type::Category _category) { if (isNumber(_category)) - return smt::Sort::Int; + return smt::Kind::Int; else if (isBool(_category)) - return smt::Sort::Bool; + return smt::Kind::Bool; solAssert(false, "Invalid type"); } diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 2639fcb94..c802c5b46 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -29,7 +29,9 @@ namespace solidity { /// Returns the SMT sort that models the Solidity type _type. -smt::Sort smtSort(Type::Category _type); +smt::SortPointer smtSort(Type const& _type); +/// Returns the SMT kind that models the Solidity type type category _category. +smt::Kind smtKind(Type::Category _category); /// So far int, bool and address are supported. /// Returns true if type is supported. diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 2519e41b7..09696aeba 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -51,7 +51,7 @@ void Z3Interface::pop() m_solver.pop(); } -void Z3Interface::declareFunction(string _name, vector const& _domain, Sort _codomain) +void Z3Interface::declareFunction(string _name, vector const& _domain, Sort const& _codomain) { if (!m_functions.count(_name)) m_functions.insert({_name, m_context.function(_name.c_str(), z3Sort(_domain), z3Sort(_codomain))}); @@ -168,13 +168,13 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) return arguments[0]; } -z3::sort Z3Interface::z3Sort(Sort _sort) +z3::sort Z3Interface::z3Sort(Sort const& _sort) { - switch (_sort) + switch (_sort.kind) { - case Sort::Bool: + case Kind::Bool: return m_context.bool_sort(); - case Sort::Int: + case Kind::Int: return m_context.int_sort(); default: break; @@ -184,10 +184,10 @@ z3::sort Z3Interface::z3Sort(Sort _sort) return m_context.int_sort(); } -z3::sort_vector Z3Interface::z3Sort(vector const& _sorts) +z3::sort_vector Z3Interface::z3Sort(vector const& _sorts) { z3::sort_vector z3Sorts(m_context); for (auto const& _sort: _sorts) - z3Sorts.push_back(z3Sort(_sort)); + z3Sorts.push_back(z3Sort(*_sort)); return z3Sorts; } diff --git a/libsolidity/formal/Z3Interface.h b/libsolidity/formal/Z3Interface.h index 5eae618e8..8c1fcf614 100644 --- a/libsolidity/formal/Z3Interface.h +++ b/libsolidity/formal/Z3Interface.h @@ -40,7 +40,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort _codomain) override; + void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; void declareInteger(std::string _name) override; void declareBool(std::string _name) override; @@ -49,8 +49,8 @@ public: private: z3::expr toZ3Expr(Expression const& _expr); - z3::sort z3Sort(smt::Sort _sort); - z3::sort_vector z3Sort(std::vector const& _sort); + z3::sort z3Sort(smt::Sort const& _sort); + z3::sort_vector z3Sort(std::vector const& _sorts); z3::context m_context; z3::solver m_solver; From dcfa5f4ea02f785a0354f145a78f039da25ca485 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 4 Jul 2017 19:50:51 +0200 Subject: [PATCH 033/168] LLL: add UNSET to remove a variable --- liblll/CodeFragment.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index f37cb8b93..c6ab86f52 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -259,6 +259,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } else if (us == "SET") { + // TODO: move this to be a stack variable (and not a memory variable) if (_t.size() != 3) error(us); int c = 0; @@ -268,6 +269,15 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) m_asm.append((u256)varAddress(firstAsString(), true)); m_asm.append(Instruction::MSTORE); } + else if (us == "UNSET") + { + // TODO: this doesn't actually free up anything, since it is a memory variable (see "SET") + if (_t.size() != 2) + error(); + auto it = _s.vars.find(firstAsString()); + if (it != _s.vars.end()) + _s.vars.erase(it); + } else if (us == "GET") { if (_t.size() != 2) From 7c051f1e321a406c1a57870f75106151ad70047b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 4 Jul 2017 22:53:05 +0200 Subject: [PATCH 034/168] LLL: implement WITH keyword --- liblll/CodeFragment.cpp | 29 +++++++++++++++++++++++++++++ test/liblll/EndToEndTest.cpp | 13 +++++++++++++ 2 files changed, 42 insertions(+) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index c6ab86f52..b32f14e96 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -285,6 +285,35 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) m_asm.append((u256)varAddress(firstAsString())); m_asm.append(Instruction::MLOAD); } + else if (us == "WITH") + { + if (_t.size() != 4) + error(); + string key = firstAsString(); + if (_s.vars.find(key) != _s.vars.end()) + error(string("Symbol already used: ") + key); + + // Create variable + // TODO: move this to be a stack variable (and not a memory variable) + size_t c = 0; + for (auto const& i: _t) + if (c++ == 2) + m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); + m_asm.append((u256)varAddress(key, true)); + m_asm.append(Instruction::MSTORE); + + // Insert sub with variable access, but new state + CompilerState ns = _s; + c = 0; + for (auto const& i: _t) + if (c++ == 3) + m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm); + + // Remove variable + auto it = _s.vars.find(key); + if (it != _s.vars.end()) + _s.vars.erase(it); + } else if (us == "REF") m_asm.append((u256)varAddress(firstAsString())); else if (us == "DEF") diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 60aef7b00..aad89b914 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"( From 6ee764edcb37b51411dde7893a291a6d992d0a09 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 21 Nov 2018 16:59:40 +0100 Subject: [PATCH 035/168] Changelog entry. --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 197419fae..449798a45 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,9 @@ Compiler Features: Bugfixes: +Build System: + * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. + ### 0.5.0 (2018-11-13) From 82055cbb615054725770dc9781b53e751c257474 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Nov 2018 10:57:15 +0100 Subject: [PATCH 036/168] Jumps with annotations cannot be functional. --- libevmasm/AssemblyItem.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index a3a4d6b63..52f246d15 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -117,6 +117,8 @@ int AssemblyItem::returnValues() const bool AssemblyItem::canBeFunctional() const { + if (m_jumpType != JumpType::Ordinary) + return false; switch (m_type) { case Operation: From 69afd094aca6679f3a6c3efccd91aeeefba028b2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Nov 2018 10:58:51 +0100 Subject: [PATCH 037/168] Changelog entry. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 449798a45..df1c6d40b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,7 @@ Compiler Features: Bugfixes: + * Assembly output: Do not mix in/out jump annotations with arguments. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. From 87821c53c3a73d3e35a0e50a7c159d9aa5d6b253 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 14 Nov 2018 14:59:30 +0100 Subject: [PATCH 038/168] Isolating files shared between Yul- and Solidity language frontend. --- libevmasm/Assembly.h | 4 ++-- libevmasm/AssemblyItem.h | 2 +- libevmasm/ConstantOptimiser.h | 2 +- libevmasm/GasMeter.h | 2 +- libevmasm/PathGasMeter.h | 2 +- {libsolidity/interface => liblangutil}/EVMVersion.h | 0 {libsolidity/interface => liblangutil}/ErrorReporter.cpp | 2 +- {libsolidity/interface => liblangutil}/ErrorReporter.h | 4 ++-- {libsolidity/interface => liblangutil}/Exceptions.cpp | 2 +- {libsolidity/interface => liblangutil}/Exceptions.h | 2 +- {libsolidity/parsing => liblangutil}/ParserBase.cpp | 6 +++--- {libsolidity/parsing => liblangutil}/ParserBase.h | 2 +- {libsolidity/parsing => liblangutil}/Scanner.cpp | 4 ++-- {libsolidity/parsing => liblangutil}/Scanner.h | 4 ++-- {libevmasm => liblangutil}/SourceLocation.h | 0 {libsolidity/parsing => liblangutil}/Token.cpp | 2 +- {libsolidity/parsing => liblangutil}/Token.h | 4 ++-- {libsolidity/parsing => liblangutil}/UndefMacros.h | 0 liblll/Compiler.h | 2 +- libsolidity/CMakeLists.txt | 4 ++-- libsolidity/analysis/ConstantEvaluator.cpp | 2 +- libsolidity/analysis/ControlFlowGraph.h | 2 +- libsolidity/analysis/DocStringAnalyser.cpp | 2 +- libsolidity/analysis/NameAndTypeResolver.cpp | 2 +- libsolidity/analysis/PostTypeChecker.cpp | 2 +- libsolidity/analysis/ReferencesResolver.cpp | 4 ++-- libsolidity/analysis/SemVerHandler.h | 2 +- libsolidity/analysis/StaticAnalyzer.cpp | 2 +- libsolidity/analysis/SyntaxChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- libsolidity/analysis/TypeChecker.h | 2 +- libsolidity/analysis/ViewPureChecker.h | 2 +- libsolidity/ast/AST.h | 4 ++-- libsolidity/ast/ASTEnums.h | 2 +- libsolidity/ast/ASTJsonConverter.h | 2 +- libsolidity/ast/Types.h | 4 ++-- libsolidity/codegen/ABIFunctions.h | 2 +- libsolidity/codegen/ArrayUtils.cpp | 2 +- libsolidity/codegen/Compiler.h | 2 +- libsolidity/codegen/CompilerContext.cpp | 4 ++-- libsolidity/codegen/CompilerContext.h | 2 +- libsolidity/codegen/ContractCompiler.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.h | 4 ++-- libsolidity/codegen/LValue.h | 2 +- libsolidity/formal/CVC4Interface.cpp | 2 +- libsolidity/formal/SMTChecker.cpp | 2 +- libsolidity/formal/SMTChecker.h | 2 +- libsolidity/formal/SMTLib2Interface.cpp | 2 +- libsolidity/formal/SMTLib2Interface.h | 2 +- libsolidity/formal/SolverInterface.h | 2 +- libsolidity/formal/Z3Interface.cpp | 2 +- libsolidity/inlineasm/AsmAnalysis.cpp | 2 +- libsolidity/inlineasm/AsmAnalysis.h | 4 ++-- libsolidity/inlineasm/AsmCodeGen.cpp | 2 +- libsolidity/inlineasm/AsmData.h | 2 +- libsolidity/inlineasm/AsmParser.cpp | 4 ++-- libsolidity/inlineasm/AsmParser.h | 2 +- libsolidity/inlineasm/AsmPrinter.cpp | 2 +- libsolidity/inlineasm/AsmScope.h | 2 +- libsolidity/inlineasm/AsmScopeFiller.cpp | 4 ++-- libsolidity/interface/AssemblyStack.cpp | 2 +- libsolidity/interface/AssemblyStack.h | 4 ++-- libsolidity/interface/CompilerStack.cpp | 2 +- libsolidity/interface/CompilerStack.h | 6 +++--- libsolidity/interface/GasEstimator.h | 2 +- libsolidity/interface/SourceReferenceFormatter.cpp | 4 ++-- libsolidity/interface/SourceReferenceFormatter.h | 2 +- libsolidity/interface/Version.cpp | 2 +- libsolidity/parsing/DocStringParser.cpp | 4 ++-- libsolidity/parsing/Parser.cpp | 6 +++--- libsolidity/parsing/Parser.h | 2 +- libyul/backends/evm/EVMAssembly.cpp | 2 +- libyul/backends/evm/EVMCodeTransform.cpp | 2 +- libyul/optimiser/FullInliner.h | 2 +- solc/CommandLineInterface.cpp | 4 ++-- solc/CommandLineInterface.h | 2 +- test/CMakeLists.txt | 3 +++ test/ExecutionFramework.h | 2 +- test/Options.cpp | 4 ++-- test/Options.h | 2 +- test/RPCSession.cpp | 2 +- test/{libevmasm => liblangutil}/SourceLocation.cpp | 2 +- test/libsolidity/ABIDecoderTests.cpp | 2 +- test/libsolidity/ABIEncoderTests.cpp | 2 +- test/libsolidity/AnalysisFramework.cpp | 2 +- test/libsolidity/Assembly.cpp | 6 +++--- test/libsolidity/ErrorCheck.h | 2 +- test/libsolidity/Imports.cpp | 2 +- test/libsolidity/InlineAssembly.cpp | 4 ++-- test/libsolidity/SemVerMatcher.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 4 ++-- test/libsolidity/SolidityExecutionFramework.h | 2 +- test/libsolidity/SolidityExpressionCompiler.cpp | 4 ++-- test/libsolidity/SolidityNatspecJSON.cpp | 2 +- test/libsolidity/SolidityParser.cpp | 4 ++-- test/libsolidity/SolidityScanner.cpp | 2 +- test/libsolidity/SyntaxTest.h | 2 +- test/libyul/Common.cpp | 4 ++-- test/libyul/Parser.cpp | 4 ++-- test/libyul/YulOptimizerTest.cpp | 4 ++-- test/tools/yulopti.cpp | 4 ++-- 101 files changed, 135 insertions(+), 132 deletions(-) rename {libsolidity/interface => liblangutil}/EVMVersion.h (100%) rename {libsolidity/interface => liblangutil}/ErrorReporter.cpp (99%) rename {libsolidity/interface => liblangutil}/ErrorReporter.h (97%) rename {libsolidity/interface => liblangutil}/Exceptions.cpp (97%) rename {libsolidity/interface => liblangutil}/Exceptions.h (98%) rename {libsolidity/parsing => liblangutil}/ParserBase.cpp (95%) rename {libsolidity/parsing => liblangutil}/ParserBase.h (98%) rename {libsolidity/parsing => liblangutil}/Scanner.cpp (99%) rename {libsolidity/parsing => liblangutil}/Scanner.h (99%) rename {libevmasm => liblangutil}/SourceLocation.h (100%) rename {libsolidity/parsing => liblangutil}/Token.cpp (99%) rename {libsolidity/parsing => liblangutil}/Token.h (99%) rename {libsolidity/parsing => liblangutil}/UndefMacros.h (100%) rename test/{libevmasm => liblangutil}/SourceLocation.cpp (97%) diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index 8ef369232..e1993082c 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -18,12 +18,12 @@ #pragma once #include -#include +#include #include #include #include -#include +#include #include #include diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 6187e18f4..802bde255 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "Exceptions.h" using namespace dev::solidity; diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index 2c2b87a0d..04c43c5d6 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index da90b028b..e3909e86c 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h index fb821684d..772df4844 100644 --- a/libevmasm/PathGasMeter.h +++ b/libevmasm/PathGasMeter.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/interface/EVMVersion.h b/liblangutil/EVMVersion.h similarity index 100% rename from libsolidity/interface/EVMVersion.h rename to liblangutil/EVMVersion.h diff --git a/libsolidity/interface/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp similarity index 99% rename from libsolidity/interface/ErrorReporter.cpp rename to liblangutil/ErrorReporter.cpp index 368e25e06..5edb0eeba 100644 --- a/libsolidity/interface/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -20,7 +20,7 @@ * Error helper class. */ -#include +#include #include #include diff --git a/libsolidity/interface/ErrorReporter.h b/liblangutil/ErrorReporter.h similarity index 97% rename from libsolidity/interface/ErrorReporter.h rename to liblangutil/ErrorReporter.h index fd53587a4..72cf16a49 100644 --- a/libsolidity/interface/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -22,8 +22,8 @@ #pragma once -#include -#include +#include +#include namespace dev { diff --git a/libsolidity/interface/Exceptions.cpp b/liblangutil/Exceptions.cpp similarity index 97% rename from libsolidity/interface/Exceptions.cpp rename to liblangutil/Exceptions.cpp index ecadd0b7b..069619ddc 100644 --- a/libsolidity/interface/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -20,7 +20,7 @@ * Solidity exception hierarchy. */ -#include +#include using namespace std; using namespace dev; diff --git a/libsolidity/interface/Exceptions.h b/liblangutil/Exceptions.h similarity index 98% rename from libsolidity/interface/Exceptions.h rename to liblangutil/Exceptions.h index 629b8f3fa..69efd6dd7 100644 --- a/libsolidity/interface/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libsolidity/parsing/ParserBase.cpp b/liblangutil/ParserBase.cpp similarity index 95% rename from libsolidity/parsing/ParserBase.cpp rename to liblangutil/ParserBase.cpp index 1d4cb1e2d..197c2d65c 100644 --- a/libsolidity/parsing/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -20,9 +20,9 @@ * Solidity parser shared functionality. */ -#include -#include -#include +#include +#include +#include using namespace std; using namespace dev; diff --git a/libsolidity/parsing/ParserBase.h b/liblangutil/ParserBase.h similarity index 98% rename from libsolidity/parsing/ParserBase.h rename to liblangutil/ParserBase.h index e01f37d86..0cd94eee3 100644 --- a/libsolidity/parsing/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include namespace dev { diff --git a/libsolidity/parsing/Scanner.cpp b/liblangutil/Scanner.cpp similarity index 99% rename from libsolidity/parsing/Scanner.cpp rename to liblangutil/Scanner.cpp index e9dad2ad2..246f5ea6b 100644 --- a/libsolidity/parsing/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -52,8 +52,8 @@ #include #include -#include -#include +#include +#include using namespace std; diff --git a/libsolidity/parsing/Scanner.h b/liblangutil/Scanner.h similarity index 99% rename from libsolidity/parsing/Scanner.h rename to liblangutil/Scanner.h index 14eeb66e7..d89f0c840 100644 --- a/libsolidity/parsing/Scanner.h +++ b/liblangutil/Scanner.h @@ -54,8 +54,8 @@ #include #include -#include -#include +#include +#include namespace dev { diff --git a/libevmasm/SourceLocation.h b/liblangutil/SourceLocation.h similarity index 100% rename from libevmasm/SourceLocation.h rename to liblangutil/SourceLocation.h diff --git a/libsolidity/parsing/Token.cpp b/liblangutil/Token.cpp similarity index 99% rename from libsolidity/parsing/Token.cpp rename to liblangutil/Token.cpp index dccd9037f..2e754733d 100644 --- a/libsolidity/parsing/Token.cpp +++ b/liblangutil/Token.cpp @@ -41,7 +41,7 @@ // along with solidity. If not, see . #include -#include +#include #include using namespace std; diff --git a/libsolidity/parsing/Token.h b/liblangutil/Token.h similarity index 99% rename from libsolidity/parsing/Token.h rename to liblangutil/Token.h index 81e8dd98b..89dd4c01a 100644 --- a/libsolidity/parsing/Token.h +++ b/liblangutil/Token.h @@ -43,8 +43,8 @@ #pragma once #include -#include -#include +#include +#include #include namespace dev diff --git a/libsolidity/parsing/UndefMacros.h b/liblangutil/UndefMacros.h similarity index 100% rename from libsolidity/parsing/UndefMacros.h rename to liblangutil/UndefMacros.h diff --git a/liblll/Compiler.h b/liblll/Compiler.h index 1ff7d5f81..93235cdd2 100644 --- a/liblll/Compiler.h +++ b/liblll/Compiler.h @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 136d39b1c..5f261f643 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,6 +1,6 @@ # Until we have a clear separation, libyul has to be included here -file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp") -file(GLOB_RECURSE headers "*.h" "../libyul/*.h") +file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp" "../liblangutil/*.cpp") +file(GLOB_RECURSE headers "*.h" "../libyul/*.h" "../liblangutil/*.h") find_package(Z3 QUIET) if (${Z3_FOUND}) diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index f9b00927d..9d041ce5b 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include using namespace std; using namespace dev; diff --git a/libsolidity/analysis/ControlFlowGraph.h b/libsolidity/analysis/ControlFlowGraph.h index 3f4820b80..257ce07f7 100644 --- a/libsolidity/analysis/ControlFlowGraph.h +++ b/libsolidity/analysis/ControlFlowGraph.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index c1b97defc..f91d72f0d 100644 --- a/libsolidity/analysis/DocStringAnalyser.cpp +++ b/libsolidity/analysis/DocStringAnalyser.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index b452a49a3..a6c746ed2 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 240d79739..3f45df421 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 2adc8e775..cae92203f 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -23,12 +23,12 @@ #include #include #include -#include +#include #include #include #include #include -#include +#include #include diff --git a/libsolidity/analysis/SemVerHandler.h b/libsolidity/analysis/SemVerHandler.h index 03a557c56..edf4fbd80 100644 --- a/libsolidity/analysis/SemVerHandler.h +++ b/libsolidity/analysis/SemVerHandler.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include namespace dev { diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 487a5ccac..353c1755c 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 3f9f83735..9ac0478e3 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index c5e6488b4..7531da651 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index ae3ebc523..392a923c5 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include diff --git a/libsolidity/analysis/ViewPureChecker.h b/libsolidity/analysis/ViewPureChecker.h index 1109ad766..9615d04f1 100644 --- a/libsolidity/analysis/ViewPureChecker.h +++ b/libsolidity/analysis/ViewPureChecker.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 23a6078bd..2c44841e8 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -24,12 +24,12 @@ #include -#include +#include #include #include #include -#include +#include #include #include diff --git a/libsolidity/ast/ASTEnums.h b/libsolidity/ast/ASTEnums.h index 5ba21907f..d47a5f05b 100644 --- a/libsolidity/ast/ASTEnums.h +++ b/libsolidity/ast/ASTEnums.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index 8429708cb..da0d840a5 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index fbf11f491..79a656e98 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -22,10 +22,10 @@ #pragma once -#include +#include #include #include -#include +#include #include #include diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index e9ffe4fb4..d2132258b 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index d33f749cf..a4000d605 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 4028ae63d..48d9e9d6b 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include #include diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 6e14d68ab..fa6dfe609 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -25,9 +25,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 5bdc1d19d..63365175a 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -24,7 +24,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 1fdf3483c..c8d9d9d37 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index 9a695b4c9..2bfaab43b 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -25,10 +25,10 @@ #include #include #include -#include +#include #include #include -#include +#include namespace dev { namespace eth diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index 6054af28a..f39eaee1a 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include namespace dev diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index 6e17eef17..8952665f1 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 0a581fc00..a85951901 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 3bf84ac9a..ae9f32e90 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -25,7 +25,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 01386dda9..7a6b558b1 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index b140f5557..f3c58d6b5 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index 55c0a5634..df0361905 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -17,7 +17,7 @@ #pragma once -#include +#include #include #include diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 09696aeba..ac6fbd541 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index ac019c06d..95c8537d3 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index a8673efa5..7ae27ebd0 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -20,8 +20,8 @@ #pragma once -#include -#include +#include +#include #include diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 3a62b232d..ee69b44fb 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index a8d5e3279..e9bf48417 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 1f399edca..3103e2b3d 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -21,8 +21,8 @@ */ #include -#include -#include +#include +#include #include diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h index 41117228d..b3d74df18 100644 --- a/libsolidity/inlineasm/AsmParser.h +++ b/libsolidity/inlineasm/AsmParser.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp index ae0bd1eb0..7151fcfa1 100644 --- a/libsolidity/inlineasm/AsmPrinter.cpp +++ b/libsolidity/inlineasm/AsmPrinter.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index 658480187..12c057169 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index d1f980830..c7625fe03 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -24,8 +24,8 @@ #include #include -#include -#include +#include +#include #include diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 26496de79..26879e8b7 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include #include #include diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index 8132ce632..aad65ffc4 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -21,8 +21,8 @@ #pragma once -#include -#include +#include +#include #include diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index d6a63f1dd..08a248dda 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 9a15fbf08..a7e312ad5 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -23,11 +23,11 @@ #pragma once -#include +#include #include -#include +#include -#include +#include #include #include diff --git a/libsolidity/interface/GasEstimator.h b/libsolidity/interface/GasEstimator.h index ea94d9888..214a3e582 100644 --- a/libsolidity/interface/GasEstimator.h +++ b/libsolidity/interface/GasEstimator.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/libsolidity/interface/SourceReferenceFormatter.cpp index 865907e21..9e2c988ec 100644 --- a/libsolidity/interface/SourceReferenceFormatter.cpp +++ b/libsolidity/interface/SourceReferenceFormatter.cpp @@ -21,8 +21,8 @@ */ #include -#include -#include +#include +#include using namespace std; diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/libsolidity/interface/SourceReferenceFormatter.h index a32babdce..281a4bdcc 100644 --- a/libsolidity/interface/SourceReferenceFormatter.h +++ b/libsolidity/interface/SourceReferenceFormatter.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace dev { diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index b5f68ce8b..b785d5577 100644 --- a/libsolidity/interface/Version.cpp +++ b/libsolidity/interface/Version.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include using namespace dev; diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp index d9588e5ca..17a7b6913 100644 --- a/libsolidity/parsing/DocStringParser.cpp +++ b/libsolidity/parsing/DocStringParser.cpp @@ -1,7 +1,7 @@ #include -#include -#include +#include +#include #include #include diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b17dad9aa..f070620de 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -22,11 +22,11 @@ #include #include -#include +#include #include -#include +#include #include -#include +#include using namespace std; diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index fa9741715..f20f01c55 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -23,7 +23,7 @@ #pragma once #include -#include +#include namespace dev { diff --git a/libyul/backends/evm/EVMAssembly.cpp b/libyul/backends/evm/EVMAssembly.cpp index b37a32313..e4ba37f0f 100644 --- a/libyul/backends/evm/EVMAssembly.cpp +++ b/libyul/backends/evm/EVMAssembly.cpp @@ -22,7 +22,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 650a8c0ab..23e09756f 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 8243160d3..5ebb3bf62 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 844cef901..357d0ab3d 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -26,12 +26,12 @@ #include "license.h" #include -#include +#include #include #include #include #include -#include +#include #include #include #include diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index aa49383a3..8dc003709 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3b6745026..acfc7d00b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,8 @@ 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") @@ -19,6 +21,7 @@ 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} diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index d6de95a39..86c1bcca1 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/test/Options.cpp b/test/Options.cpp index da08eb37d..9f0d6752e 100644 --- a/test/Options.cpp +++ b/test/Options.cpp @@ -23,8 +23,8 @@ #include -#include -#include +#include +#include #include #include diff --git a/test/Options.h b/test/Options.h index 0e8a51dad..af6f06ee4 100644 --- a/test/Options.h +++ b/test/Options.h @@ -19,7 +19,7 @@ #pragma once -#include +#include #include #include diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 9ac24972b..0aae21a7b 100644 --- a/test/RPCSession.cpp +++ b/test/RPCSession.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/test/libevmasm/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp similarity index 97% rename from test/libevmasm/SourceLocation.cpp rename to test/liblangutil/SourceLocation.cpp index 764da3cd6..29cfb6a0b 100644 --- a/test/libevmasm/SourceLocation.cpp +++ b/test/liblangutil/SourceLocation.cpp @@ -20,7 +20,7 @@ * Unit tests for the SourceLocation class. */ -#include +#include #include diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index 94319985d..291ed15aa 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index d2125cc7d..b6e6cedd4 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index ec98026cc..dafd17483 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -27,7 +27,7 @@ #include -#include +#include #include diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 5e1576788..78fa7bcfa 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -22,16 +22,16 @@ #include -#include +#include #include -#include +#include #include #include #include #include #include -#include +#include #include diff --git a/test/libsolidity/ErrorCheck.h b/test/libsolidity/ErrorCheck.h index 8ad81f858..c70a66453 100644 --- a/test/libsolidity/ErrorCheck.h +++ b/test/libsolidity/ErrorCheck.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index dc33d5779..abd659b61 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index a9ce6e499..3079e0321 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -23,8 +23,8 @@ #include #include -#include -#include +#include +#include #include #include #include diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 43951f73d..b2f4b3c28 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 876467370..041f29a8d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -25,8 +25,8 @@ #include -#include -#include +#include +#include #include diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 12687dd1d..ab71a3e03 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include namespace dev diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 309cbf0b8..37183279d 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -22,14 +22,14 @@ #include -#include +#include #include #include #include #include #include #include -#include +#include #include using namespace std; diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index d77050cbd..45191ce1c 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include namespace dev diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 5432e9b51..cf5461ba2 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -22,9 +22,9 @@ #include #include -#include +#include #include -#include +#include #include #include diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 6965d886a..53ec0a4ca 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -20,7 +20,7 @@ * Unit tests for the solidity scanner. */ -#include +#include #include using namespace std; diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index 654ce4a00..0f151e663 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d224bdcd6..b351483e4 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -25,14 +25,14 @@ #include -#include +#include #include #include #include #include -#include +#include #include diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 3f329d282..3a887176a 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -26,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 9e2577177..57c4d7f01 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -41,12 +41,12 @@ #include #include -#include +#include #include #include #include #include -#include +#include #include #include diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 3e96ef356..df5331f75 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -21,13 +21,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include #include From 2518b5314c0c16dcdbbc0b093f5b716e9e85dbc2 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 14 Nov 2018 15:18:55 +0100 Subject: [PATCH 039/168] Splitting out CharStream from Scanner. --- liblangutil/CharStream.cpp | 115 +++++++++++++++++++++++++++++++++++++ liblangutil/CharStream.h | 100 ++++++++++++++++++++++++++++++++ liblangutil/Scanner.cpp | 50 ---------------- liblangutil/Scanner.h | 32 +---------- 4 files changed, 216 insertions(+), 81 deletions(-) create mode 100644 liblangutil/CharStream.cpp create mode 100644 liblangutil/CharStream.h diff --git a/liblangutil/CharStream.cpp b/liblangutil/CharStream.cpp new file mode 100644 index 000000000..04490fa6e --- /dev/null +++ b/liblangutil/CharStream.cpp @@ -0,0 +1,115 @@ +/* + 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 . + + This file is derived from the file "scanner.cc", which was part of the + V8 project. The original copyright header follows: + + Copyright 2006-2012, the V8 project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/** + * @author Christian + * @date 2014 + * Solidity scanner. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace solidity +{ + +char CharStream::advanceAndGet(size_t _chars) +{ + if (isPastEndOfInput()) + return 0; + m_position += _chars; + if (isPastEndOfInput()) + return 0; + return m_source[m_position]; +} + +char CharStream::rollback(size_t _amount) +{ + solAssert(m_position >= _amount, ""); + m_position -= _amount; + return get(); +} + +string CharStream::lineAtPosition(int _position) const +{ + // if _position points to \n, it returns the line before the \n + using size_type = string::size_type; + size_type searchStart = min(m_source.size(), _position); + if (searchStart > 0) + searchStart--; + size_type lineStart = m_source.rfind('\n', searchStart); + if (lineStart == string::npos) + lineStart = 0; + else + lineStart++; + return m_source.substr(lineStart, min(m_source.find('\n', lineStart), + m_source.size()) - lineStart); +} + +tuple CharStream::translatePositionToLineColumn(int _position) const +{ + using size_type = string::size_type; + size_type searchPosition = min(m_source.size(), _position); + int lineNumber = count(m_source.begin(), m_source.begin() + searchPosition, '\n'); + size_type lineStart; + if (searchPosition == 0) + lineStart = 0; + else + { + lineStart = m_source.rfind('\n', searchPosition - 1); + lineStart = lineStart == string::npos ? 0 : lineStart + 1; + } + return tuple(lineNumber, searchPosition - lineStart); +} + +} +} diff --git a/liblangutil/CharStream.h b/liblangutil/CharStream.h new file mode 100644 index 000000000..7c5488a02 --- /dev/null +++ b/liblangutil/CharStream.h @@ -0,0 +1,100 @@ +/* + 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 . + + This file is derived from the file "scanner.h", which was part of the + V8 project. The original copyright header follows: + + Copyright 2006-2012, the V8 project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/** + * @author Christian + * @date 2014 + * Solidity scanner. + */ + +#pragma once + +#include +#include +#include + +namespace dev +{ +namespace solidity +{ + +/** + * Bidirectional stream of characters. + * + * This CharStream is used by lexical analyzers as the source. + */ +class CharStream +{ +public: + CharStream(): m_position(0) {} + explicit CharStream(std::string const& _source): m_source(_source), m_position(0) {} + + int position() const { return m_position; } + bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); } + + char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; } + char advanceAndGet(size_t _chars = 1); + char rollback(size_t _amount); + + void reset() { m_position = 0; } + + std::string const& source() const { return m_source; } + + ///@{ + ///@name Error printing helper functions + /// Functions that help pretty-printing parse errors + /// Do only use in error cases, they are quite expensive. + std::string lineAtPosition(int _position) const; + std::tuple translatePositionToLineColumn(int _position) const; + ///@} + +private: + std::string m_source; + size_t m_position; +}; + +} +} diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 246f5ea6b..beb39a4fa 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -866,55 +866,5 @@ tuple Scanner::scanIdentifierOrKeyword() return TokenTraits::fromIdentifierOrKeyword(m_nextToken.literal); } -char CharStream::advanceAndGet(size_t _chars) -{ - if (isPastEndOfInput()) - return 0; - m_position += _chars; - if (isPastEndOfInput()) - return 0; - return m_source[m_position]; -} - -char CharStream::rollback(size_t _amount) -{ - solAssert(m_position >= _amount, ""); - m_position -= _amount; - return get(); -} - -string CharStream::lineAtPosition(int _position) const -{ - // if _position points to \n, it returns the line before the \n - using size_type = string::size_type; - size_type searchStart = min(m_source.size(), _position); - if (searchStart > 0) - searchStart--; - size_type lineStart = m_source.rfind('\n', searchStart); - if (lineStart == string::npos) - lineStart = 0; - else - lineStart++; - return m_source.substr(lineStart, min(m_source.find('\n', lineStart), - m_source.size()) - lineStart); -} - -tuple CharStream::translatePositionToLineColumn(int _position) const -{ - using size_type = string::size_type; - size_type searchPosition = min(m_source.size(), _position); - int lineNumber = count(m_source.begin(), m_source.begin() + searchPosition, '\n'); - size_type lineStart; - if (searchPosition == 0) - lineStart = 0; - else - { - lineStart = m_source.rfind('\n', searchPosition - 1); - lineStart = lineStart == string::npos ? 0 : lineStart + 1; - } - return tuple(lineNumber, searchPosition - lineStart); -} - - } } diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index d89f0c840..5e5ddfdd8 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -54,6 +54,7 @@ #include #include +#include #include #include @@ -62,41 +63,10 @@ namespace dev namespace solidity { - class AstRawString; class AstValueFactory; class ParserRecorder; -class CharStream -{ -public: - CharStream(): m_position(0) {} - explicit CharStream(std::string const& _source): m_source(_source), m_position(0) {} - int position() const { return m_position; } - bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); } - char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; } - char advanceAndGet(size_t _chars = 1); - char rollback(size_t _amount); - - void reset() { m_position = 0; } - - std::string const& source() const { return m_source; } - - ///@{ - ///@name Error printing helper functions - /// Functions that help pretty-printing parse errors - /// Do only use in error cases, they are quite expensive. - std::string lineAtPosition(int _position) const; - std::tuple translatePositionToLineColumn(int _position) const; - ///@} - -private: - std::string m_source; - size_t m_position; -}; - - - class Scanner { friend class LiteralScope; From 80371e2d25ce3eb868d6f75b99a54af9dc6c1583 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 14 Nov 2018 17:15:39 +0100 Subject: [PATCH 040/168] Ensure liblangutil is compiled and linked as its own static library. --- CMakeLists.txt | 1 + liblangutil/CMakeLists.txt | 6 ++++++ libsolidity/CMakeLists.txt | 6 +++--- 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 liblangutil/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 867696724..ed51e5a7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ include(EthOptions) configure_project(TESTS) add_subdirectory(libdevcore) +add_subdirectory(liblangutil) add_subdirectory(libevmasm) add_subdirectory(libsolidity) add_subdirectory(libsolc) diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt new file mode 100644 index 000000000..722ca840e --- /dev/null +++ b/liblangutil/CMakeLists.txt @@ -0,0 +1,6 @@ +# Solidity Commons Library (Solidity related sharing bits between libsolidity and libyul) +file(GLOB sources "*.cpp") +file(GLOB headers "*.h") + +add_library(langutil ${sources} ${headers}) +target_link_libraries(langutil PUBLIC devcore) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 5f261f643..c57fca16e 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,6 +1,6 @@ # Until we have a clear separation, libyul has to be included here -file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp" "../liblangutil/*.cpp") -file(GLOB_RECURSE headers "*.h" "../libyul/*.h" "../liblangutil/*.h") +file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp") +file(GLOB_RECURSE headers "*.h" "../libyul/*.h") find_package(Z3 QUIET) if (${Z3_FOUND}) @@ -26,7 +26,7 @@ if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) endif() add_library(solidity ${sources} ${headers}) -target_link_libraries(solidity PUBLIC evmasm devcore ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(solidity PUBLIC evmasm langutil devcore ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) if (${Z3_FOUND}) target_link_libraries(solidity PUBLIC ${Z3_LIBRARY}) From d67322a1861d60a88151f7c25d6c3478a9a39acf Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 14 Nov 2018 17:11:55 +0100 Subject: [PATCH 041/168] Introduce namespace `langutil` in liblangutil directory. Also: - Use {}-style list initialisation for SourceLocation construction - Introduce new system includes - Changes the API of the Scanner to take source as value (with move) as opposed to as a reference --- libevmasm/Assembly.cpp | 1 + libevmasm/Assembly.h | 4 +- libevmasm/AssemblyItem.h | 12 +++--- libevmasm/CommonSubexpressionEliminator.cpp | 1 + libevmasm/CommonSubexpressionEliminator.h | 9 +++- libevmasm/ControlFlowGraph.cpp | 2 +- libevmasm/ExpressionClasses.cpp | 2 +- libevmasm/ExpressionClasses.h | 7 +++- libevmasm/KnownState.cpp | 1 + libevmasm/KnownState.h | 21 ++++++---- libevmasm/SimplificationRules.cpp | 2 +- libevmasm/SimplificationRules.h | 9 +++- liblangutil/CharStream.cpp | 11 +---- liblangutil/CharStream.h | 5 +-- liblangutil/ErrorReporter.cpp | 4 +- liblangutil/ErrorReporter.h | 8 +--- liblangutil/Exceptions.cpp | 2 +- liblangutil/Exceptions.h | 25 ++++++----- liblangutil/ParserBase.cpp | 3 +- liblangutil/ParserBase.h | 8 ++-- liblangutil/Scanner.cpp | 16 ++++--- liblangutil/Scanner.h | 16 +++---- liblangutil/SourceLocation.h | 4 +- liblangutil/Token.cpp | 7 +--- liblangutil/Token.h | 10 ++--- libsolidity/analysis/ConstantEvaluator.h | 10 +++-- libsolidity/analysis/ControlFlowAnalyzer.cpp | 2 + libsolidity/analysis/ControlFlowAnalyzer.h | 4 +- libsolidity/analysis/ControlFlowGraph.cpp | 3 +- libsolidity/analysis/ControlFlowGraph.h | 4 +- libsolidity/analysis/DocStringAnalyser.cpp | 1 + libsolidity/analysis/DocStringAnalyser.h | 11 +++-- libsolidity/analysis/NameAndTypeResolver.cpp | 7 ++-- libsolidity/analysis/NameAndTypeResolver.h | 19 +++++---- libsolidity/analysis/PostTypeChecker.cpp | 1 + libsolidity/analysis/PostTypeChecker.h | 14 ++++--- libsolidity/analysis/ReferencesResolver.cpp | 10 ++++- libsolidity/analysis/ReferencesResolver.h | 19 +++++---- libsolidity/analysis/SemVerHandler.h | 3 +- libsolidity/analysis/StaticAnalyzer.cpp | 1 + libsolidity/analysis/StaticAnalyzer.h | 9 +++- libsolidity/analysis/SyntaxChecker.cpp | 1 + libsolidity/analysis/SyntaxChecker.h | 9 +++- libsolidity/analysis/TypeChecker.cpp | 1 + libsolidity/analysis/TypeChecker.h | 11 +++-- libsolidity/analysis/ViewPureChecker.cpp | 3 ++ libsolidity/analysis/ViewPureChecker.h | 20 +++++---- libsolidity/ast/AST.h | 4 +- libsolidity/ast/ASTJsonConverter.cpp | 1 + libsolidity/ast/ASTJsonConverter.h | 7 +++- libsolidity/ast/ASTPrinter.cpp | 1 + libsolidity/ast/Types.cpp | 1 + libsolidity/ast/Types.h | 2 +- libsolidity/codegen/ArrayUtils.cpp | 1 + libsolidity/codegen/CompilerContext.cpp | 4 +- libsolidity/codegen/CompilerUtils.cpp | 1 + libsolidity/codegen/ContractCompiler.cpp | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 1 + libsolidity/codegen/LValue.cpp | 1 + libsolidity/codegen/LValue.h | 42 +++++++++---------- libsolidity/formal/SMTChecker.cpp | 1 + libsolidity/formal/SMTChecker.h | 23 ++++++---- libsolidity/inlineasm/AsmAnalysis.cpp | 1 + libsolidity/inlineasm/AsmAnalysis.h | 23 ++++++---- libsolidity/inlineasm/AsmCodeGen.cpp | 1 + libsolidity/inlineasm/AsmData.h | 40 +++++++++--------- libsolidity/inlineasm/AsmParser.cpp | 1 + libsolidity/inlineasm/AsmParser.h | 12 +++--- libsolidity/inlineasm/AsmScopeFiller.cpp | 1 + libsolidity/inlineasm/AsmScopeFiller.h | 18 ++++---- libsolidity/interface/AssemblyStack.cpp | 1 + libsolidity/interface/AssemblyStack.h | 18 ++++---- libsolidity/interface/CompilerStack.cpp | 1 + libsolidity/interface/CompilerStack.h | 24 ++++++----- libsolidity/interface/GasEstimator.cpp | 1 + .../interface/SourceReferenceFormatter.cpp | 1 + .../interface/SourceReferenceFormatter.h | 14 ++++--- libsolidity/interface/StandardCompiler.cpp | 3 +- libsolidity/parsing/DocStringParser.cpp | 1 + libsolidity/parsing/DocStringParser.h | 11 +++-- libsolidity/parsing/Parser.cpp | 1 + libsolidity/parsing/Parser.h | 15 ++++--- libsolidity/parsing/Token.h | 36 ++++++++++++++++ libyul/backends/evm/AbstractAssembly.h | 8 +++- libyul/backends/evm/EVMAssembly.cpp | 1 + libyul/backends/evm/EVMAssembly.h | 7 +++- libyul/optimiser/ExpressionSplitter.cpp | 1 + libyul/optimiser/SSATransform.cpp | 1 + libyul/optimiser/SimplificationRules.cpp | 1 + libyul/optimiser/SimplificationRules.h | 2 +- solc/CommandLineInterface.cpp | 3 +- test/libevmasm/Assembler.cpp | 1 + test/libevmasm/Optimiser.cpp | 1 + test/liblangutil/SourceLocation.cpp | 5 +-- test/libsolidity/AnalysisFramework.cpp | 3 +- test/libsolidity/AnalysisFramework.h | 8 ++-- test/libsolidity/Assembly.cpp | 1 + test/libsolidity/ErrorCheck.cpp | 1 + test/libsolidity/ErrorCheck.h | 4 +- test/libsolidity/GasMeter.cpp | 1 + test/libsolidity/InlineAssembly.cpp | 1 + test/libsolidity/SMTChecker.cpp | 1 + test/libsolidity/SemVerMatcher.cpp | 1 + test/libsolidity/SolidityExecutionFramework.h | 4 +- .../SolidityExpressionCompiler.cpp | 1 + .../SolidityNameAndTypeResolution.cpp | 1 + test/libsolidity/SolidityNatspecJSON.cpp | 2 + test/libsolidity/SolidityParser.cpp | 1 + test/libsolidity/SolidityScanner.cpp | 1 + test/libsolidity/SolidityTypes.cpp | 1 + test/libsolidity/SyntaxTest.cpp | 1 + test/libsolidity/ViewPureChecker.cpp | 1 + test/libyul/Common.cpp | 1 + test/libyul/Common.h | 12 ++++-- test/libyul/Parser.cpp | 1 + test/libyul/YulOptimizerTest.cpp | 6 ++- test/libyul/YulOptimizerTest.h | 11 +++-- test/tools/yulopti.cpp | 5 ++- 118 files changed, 479 insertions(+), 290 deletions(-) create mode 100644 libsolidity/parsing/Token.h diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index e63194a0b..d80f97c43 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -35,6 +35,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; void Assembly::append(Assembly const& _a) { diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index e1993082c..d846b4756 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -93,7 +93,7 @@ public: void setDeposit(int _deposit) { m_deposit = _deposit; assertThrow(m_deposit >= 0, InvalidDeposit, ""); } /// Changes the source location used for each appended item. - void setSourceLocation(SourceLocation const& _location) { m_currentSourceLocation = _location; } + void setSourceLocation(langutil::SourceLocation const& _location) { m_currentSourceLocation = _location; } /// Assembles the assembly into bytecode. The assembly should not be modified after this call, since the assembled version is cached. LinkerObject const& assemble() const; @@ -178,7 +178,7 @@ protected: int m_deposit = 0; - SourceLocation m_currentSourceLocation; + langutil::SourceLocation m_currentSourceLocation; }; inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a) diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 802bde255..a78751719 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -57,14 +57,14 @@ class AssemblyItem public: enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; - AssemblyItem(u256 _push, SourceLocation const& _location = SourceLocation()): + AssemblyItem(u256 _push, langutil::SourceLocation const& _location = langutil::SourceLocation()): AssemblyItem(Push, _push, _location) { } - AssemblyItem(solidity::Instruction _i, SourceLocation const& _location = SourceLocation()): + AssemblyItem(solidity::Instruction _i, langutil::SourceLocation const& _location = langutil::SourceLocation()): m_type(Operation), m_instruction(_i), m_location(_location) {} - AssemblyItem(AssemblyItemType _type, u256 _data = 0, SourceLocation const& _location = SourceLocation()): + AssemblyItem(AssemblyItemType _type, u256 _data = 0, langutil::SourceLocation const& _location = langutil::SourceLocation()): m_type(_type), m_location(_location) { @@ -124,8 +124,8 @@ public: /// @returns true if the assembly item can be used in a functional context. bool canBeFunctional() const; - void setLocation(SourceLocation const& _location) { m_location = _location; } - SourceLocation const& location() const { return m_location; } + void setLocation(langutil::SourceLocation const& _location) { m_location = _location; } + langutil::SourceLocation const& location() const { return m_location; } void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; } JumpType getJumpType() const { return m_jumpType; } @@ -140,7 +140,7 @@ private: AssemblyItemType m_type; Instruction m_instruction; ///< Only valid if m_type == Operation std::shared_ptr m_data; ///< Only valid if m_type != Operation - SourceLocation m_location; + langutil::SourceLocation m_location; JumpType m_jumpType = JumpType::Ordinary; /// Pushed value for operations with data to be determined during assembly stage, /// e.g. PushSubSize, PushTag, PushSub, etc. diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 04926986d..949d2c75a 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -30,6 +30,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; vector CommonSubexpressionEliminator::getOptimizedItems() { diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index b20de2469..eba25db08 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -34,6 +34,11 @@ #include #include +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -137,10 +142,10 @@ private: bool removeStackTopIfPossible(); /// Appends a dup instruction to m_generatedItems to retrieve the element at the given stack position. - void appendDup(int _fromPosition, SourceLocation const& _location); + void appendDup(int _fromPosition, langutil::SourceLocation const& _location); /// Appends a swap instruction to m_generatedItems to retrieve the element at the given stack position. /// @note this might also remove the last item if it exactly the same swap instruction. - void appendOrRemoveSwap(int _fromPosition, SourceLocation const& _location); + void appendOrRemoveSwap(int _fromPosition, langutil::SourceLocation const& _location); /// Appends the given assembly item. void appendItem(AssemblyItem const& _item); diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 86f16d481..d62f54362 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -275,7 +275,7 @@ void ControlFlowGraph::gatherKnowledge() //@todo in the case of JUMPI, add knowledge about the condition to the state // (for both values of the condition) set tags = state->tagsInExpression( - state->stackElement(state->stackHeight(), SourceLocation()) + state->stackElement(state->stackHeight(), langutil::SourceLocation{}) ); state->feedItem(m_items.at(pc++)); diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index 42a1819a2..abbbbc2c5 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -34,7 +34,7 @@ using namespace std; using namespace dev; using namespace dev::eth; - +using namespace langutil; bool ExpressionClasses::Expression::operator<(ExpressionClasses::Expression const& _other) const { diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index df8082f93..a34844c54 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -31,6 +31,11 @@ #include #include +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -82,7 +87,7 @@ public: void forceEqual(Id _id, AssemblyItem const& _item, Ids const& _arguments, bool _copyItem = true); /// @returns the id of a new class which is different to all other classes. - Id newClass(SourceLocation const& _location); + Id newClass(langutil::SourceLocation const& _location); /// @returns true if the values of the given classes are known to be different (on every input). /// @note that this function might still return false for some different inputs. diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index b6c1bcc9b..a5546e617 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -29,6 +29,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; ostream& KnownState::stream(ostream& _out) const { diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index cd50550ed..3ab1c4b1a 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -46,6 +46,11 @@ #include #include +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -121,9 +126,9 @@ public: /// Retrieves the current equivalence class fo the given stack element (or generates a new /// one if it does not exist yet). - Id stackElement(int _stackHeight, SourceLocation const& _location); + Id stackElement(int _stackHeight, langutil::SourceLocation const& _location); /// @returns the stackElement relative to the current stack height. - Id relativeStackElement(int _stackOffset, SourceLocation const& _location = SourceLocation()); + Id relativeStackElement(int _stackOffset, langutil::SourceLocation const& _location = {}); /// @returns its set of tags if the given expression class is a known tag union; returns a set /// containing the tag if it is a PushTag expression and the empty set otherwise. @@ -142,22 +147,22 @@ private: /// Assigns a new equivalence class to the next sequence number of the given stack element. void setStackElement(int _stackHeight, Id _class); /// Swaps the given stack elements in their next sequence number. - void swapStackElements(int _stackHeightA, int _stackHeightB, SourceLocation const& _location); + void swapStackElements(int _stackHeightA, int _stackHeightB, langutil::SourceLocation const& _location); /// Increments the sequence number, deletes all storage information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if storage was not modified - StoreOperation storeInStorage(Id _slot, Id _value, SourceLocation const& _location); + StoreOperation storeInStorage(Id _slot, Id _value, langutil::SourceLocation const& _location); /// Retrieves the current value at the given slot in storage or creates a new special sload class. - Id loadFromStorage(Id _slot, SourceLocation const& _location); + Id loadFromStorage(Id _slot, langutil::SourceLocation const& _location); /// Increments the sequence number, deletes all memory information that might be overwritten /// and stores the new value at the given slot. /// @returns the store operation, which might be invalid if memory was not modified - StoreOperation storeInMemory(Id _slot, Id _value, SourceLocation const& _location); + StoreOperation storeInMemory(Id _slot, Id _value, langutil::SourceLocation const& _location); /// Retrieves the current value at the given slot in memory or creates a new special mload class. - Id loadFromMemory(Id _slot, SourceLocation const& _location); + Id loadFromMemory(Id _slot, langutil::SourceLocation const& _location); /// Finds or creates a new expression that applies the Keccak-256 hash function to the contents in memory. - Id applyKeccak256(Id _start, Id _length, SourceLocation const& _location); + Id applyKeccak256(Id _start, Id _length, langutil::SourceLocation const& _location); /// @returns a new or already used Id representing the given set of tags. Id tagUnion(std::set _tags); diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index 120d17877..1dce5f1ee 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -38,7 +38,7 @@ using namespace std; using namespace dev; using namespace dev::eth; - +using namespace langutil; SimplificationRule const* Rules::findFirstMatch( Expression const& _expr, diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index fbe5a2b09..fc45a46c3 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -31,6 +31,11 @@ #include #include +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace eth @@ -97,7 +102,7 @@ public: unsigned matchGroup() const { return m_matchGroup; } bool matches(Expression const& _expr, ExpressionClasses const& _classes) const; - AssemblyItem toAssemblyItem(SourceLocation const& _location) const; + AssemblyItem toAssemblyItem(langutil::SourceLocation const& _location) const; std::vector arguments() const { return m_arguments; } /// @returns the id of the matched expression if this pattern is part of a match group. @@ -135,7 +140,7 @@ struct ExpressionTemplate { using Expression = ExpressionClasses::Expression; using Id = ExpressionClasses::Id; - explicit ExpressionTemplate(Pattern const& _pattern, SourceLocation const& _location); + explicit ExpressionTemplate(Pattern const& _pattern, langutil::SourceLocation const& _location); std::string toString() const; bool hasId = false; /// Id of the matched expression, if available. diff --git a/liblangutil/CharStream.cpp b/liblangutil/CharStream.cpp index 04490fa6e..aee7cb3e0 100644 --- a/liblangutil/CharStream.cpp +++ b/liblangutil/CharStream.cpp @@ -52,15 +52,9 @@ #include #include -#include -#include using namespace std; - -namespace dev -{ -namespace solidity -{ +using namespace langutil; char CharStream::advanceAndGet(size_t _chars) { @@ -111,5 +105,4 @@ tuple CharStream::translatePositionToLineColumn(int _position) const return tuple(lineNumber, searchPosition - lineStart); } -} -} + diff --git a/liblangutil/CharStream.h b/liblangutil/CharStream.h index 7c5488a02..72aacacf5 100644 --- a/liblangutil/CharStream.h +++ b/liblangutil/CharStream.h @@ -56,9 +56,7 @@ #include #include -namespace dev -{ -namespace solidity +namespace langutil { /** @@ -97,4 +95,3 @@ private: }; } -} diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index 5edb0eeba..5b6e0072f 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -21,12 +21,12 @@ */ #include -#include +#include #include using namespace std; using namespace dev; -using namespace dev::solidity; +using namespace langutil; ErrorReporter& ErrorReporter::operator=(ErrorReporter const& _errorReporter) { diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 72cf16a49..d90e652ea 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -25,12 +25,8 @@ #include #include -namespace dev +namespace langutil { -namespace solidity -{ - -class ASTNode; class ErrorReporter { @@ -120,7 +116,5 @@ private: const unsigned c_maxErrorsAllowed = 256; }; - -} } diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp index 069619ddc..346313d5e 100644 --- a/liblangutil/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -24,7 +24,7 @@ using namespace std; using namespace dev; -using namespace dev::solidity; +using namespace langutil; Error::Error(Type _type, SourceLocation const& _location, string const& _description): m_type(_type) diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index 69efd6dd7..5ad31ab20 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -24,33 +24,33 @@ #include #include +#include +#include #include #include #include -namespace dev -{ -namespace solidity +namespace langutil { class Error; using ErrorList = std::vector>; -struct CompilerError: virtual Exception {}; -struct InternalCompilerError: virtual Exception {}; -struct FatalError: virtual Exception {}; -struct UnimplementedFeatureError: virtual Exception{}; +struct CompilerError: virtual dev::Exception {}; +struct InternalCompilerError: virtual dev::Exception {}; +struct FatalError: virtual dev::Exception {}; +struct UnimplementedFeatureError: virtual dev::Exception {}; /// Assertion that throws an InternalCompilerError containing the given description if it is not met. #define solAssert(CONDITION, DESCRIPTION) \ - assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION) + assertThrow(CONDITION, ::langutil::InternalCompilerError, DESCRIPTION) #define solUnimplementedAssert(CONDITION, DESCRIPTION) \ - assertThrow(CONDITION, ::dev::solidity::UnimplementedFeatureError, DESCRIPTION) + assertThrow(CONDITION, ::langutil::UnimplementedFeatureError, DESCRIPTION) #define solUnimplemented(DESCRIPTION) \ solUnimplementedAssert(false, DESCRIPTION) -class Error: virtual public Exception +class Error: virtual public dev::Exception { public: enum class Type @@ -98,7 +98,6 @@ private: std::string m_typeName; }; - using errorSourceLocationInfo = std::pair; class SecondarySourceLocation @@ -109,6 +108,7 @@ public: infos.push_back(std::make_pair(_errMsg, _sourceLocation)); return *this; } + /// Limits the number of secondary source locations to 32 and appends a notice to the /// error message. void limitSize(std::string& _message) @@ -124,9 +124,8 @@ public: std::vector infos; }; - using errinfo_sourceLocation = boost::error_info; using errinfo_secondarySourceLocation = boost::error_info; -} + } diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index 197c2d65c..8156f9b9a 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -25,8 +25,7 @@ #include using namespace std; -using namespace dev; -using namespace dev::solidity; +using namespace langutil; std::shared_ptr const& ParserBase::sourceName() const { diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 0cd94eee3..3ecabed5c 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -22,12 +22,11 @@ #pragma once -#include #include +#include +#include -namespace dev -{ -namespace solidity +namespace langutil { class ErrorReporter; @@ -90,4 +89,3 @@ protected: }; } -} diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index beb39a4fa..3d7527d4d 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -50,16 +50,14 @@ * Solidity scanner. */ -#include -#include #include #include +#include +#include using namespace std; -namespace dev -{ -namespace solidity +namespace langutil { namespace @@ -143,10 +141,10 @@ private: }; // end of LiteralScope class -void Scanner::reset(CharStream const& _source, string const& _sourceName) +void Scanner::reset(CharStream _source, string _sourceName) { - m_source = _source; - m_sourceName = make_shared(_sourceName); + m_source = std::move(_source); + m_sourceName = make_shared(std::move(_sourceName)); reset(); } @@ -866,5 +864,5 @@ tuple Scanner::scanIdentifierOrKeyword() return TokenTraits::fromIdentifierOrKeyword(m_nextToken.literal); } -} + } diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index 5e5ddfdd8..da5e3dfb1 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -52,15 +52,13 @@ #pragma once -#include -#include +#include #include #include -#include +#include +#include -namespace dev -{ -namespace solidity +namespace langutil { class AstRawString; @@ -71,13 +69,12 @@ class Scanner { friend class LiteralScope; public: - - explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); } + explicit Scanner(CharStream _source = CharStream(), std::string _sourceName = "") { reset(std::move(_source), std::move(_sourceName)); } std::string source() const { return m_source.source(); } /// Resets the scanner as if newly constructed with _source and _sourceName as input. - void reset(CharStream const& _source, std::string const& _sourceName); + void reset(CharStream _source, std::string _sourceName); /// Resets scanner to the start of input. void reset(); @@ -216,4 +213,3 @@ private: }; } -} diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index b42c3aa98..eeb81e946 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -22,13 +22,13 @@ #pragma once +#include // defines noexcept macro for MSVC #include #include #include #include -#include // defines noexcept macro for MSVC -namespace dev +namespace langutil { /** diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index 2e754733d..cbfd4a8ca 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -40,15 +40,13 @@ // You should have received a copy of the GNU General Public License // along with solidity. If not, see . -#include #include #include +#include using namespace std; -namespace dev -{ -namespace solidity +namespace langutil { void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second) @@ -204,4 +202,3 @@ tuple fromIdentifierOrKeyword(string const& _ } } -} diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 89dd4c01a..0b7d9f71d 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -45,11 +45,12 @@ #include #include #include -#include -namespace dev -{ -namespace solidity +#include +#include +#include + +namespace langutil { // TOKEN_LIST takes a list of 3 macros M, all of which satisfy the @@ -375,4 +376,3 @@ private: }; } -} diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index ac3a24a1f..23ca36286 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -24,12 +24,16 @@ #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity { -class ErrorReporter; class TypeChecker; /** @@ -39,7 +43,7 @@ class ConstantEvaluator: private ASTConstVisitor { public: ConstantEvaluator( - ErrorReporter& _errorReporter, + langutil::ErrorReporter& _errorReporter, size_t _newDepth = 0, std::shared_ptr> _types = std::make_shared>() ): @@ -61,7 +65,7 @@ private: void setType(ASTNode const& _node, TypePointer const& _type); TypePointer type(ASTNode const& _node); - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; /// Current recursion depth. size_t m_depth = 0; std::shared_ptr> m_types; diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index 8a6085528..fe58f0aa8 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -16,8 +16,10 @@ */ #include +#include using namespace std; +using namespace langutil; using namespace dev::solidity; bool ControlFlowAnalyzer::analyze(ASTNode const& _astRoot) diff --git a/libsolidity/analysis/ControlFlowAnalyzer.h b/libsolidity/analysis/ControlFlowAnalyzer.h index aaaf1bff6..411d57ffc 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.h +++ b/libsolidity/analysis/ControlFlowAnalyzer.h @@ -29,7 +29,7 @@ namespace solidity class ControlFlowAnalyzer: private ASTConstVisitor { public: - explicit ControlFlowAnalyzer(CFG const& _cfg, ErrorReporter& _errorReporter): + explicit ControlFlowAnalyzer(CFG const& _cfg, langutil::ErrorReporter& _errorReporter): m_cfg(_cfg), m_errorReporter(_errorReporter) {} bool analyze(ASTNode const& _astRoot); @@ -45,7 +45,7 @@ private: ) const; CFG const& m_cfg; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/analysis/ControlFlowGraph.cpp b/libsolidity/analysis/ControlFlowGraph.cpp index 9b3da0ebc..b8860158e 100644 --- a/libsolidity/analysis/ControlFlowGraph.cpp +++ b/libsolidity/analysis/ControlFlowGraph.cpp @@ -23,6 +23,7 @@ #include using namespace std; +using namespace langutil; using namespace dev::solidity; bool CFG::constructFlow(ASTNode const& _astRoot) @@ -133,4 +134,4 @@ void CFG::applyModifierFlowToFunctionFlow( _functionFlow->entry = copySrcToCopyDst[_modifierFlow.entry]; _functionFlow->exit = copySrcToCopyDst[_modifierFlow.exit]; -} \ No newline at end of file +} diff --git a/libsolidity/analysis/ControlFlowGraph.h b/libsolidity/analysis/ControlFlowGraph.h index 257ce07f7..8fe9fe8ee 100644 --- a/libsolidity/analysis/ControlFlowGraph.h +++ b/libsolidity/analysis/ControlFlowGraph.h @@ -101,7 +101,7 @@ struct ModifierFlow: FunctionFlow class CFG: private ASTConstVisitor { public: - explicit CFG(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + explicit CFG(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} bool constructFlow(ASTNode const& _astRoot); @@ -133,7 +133,7 @@ private: FunctionFlow* _functionFlow ); - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; /// Node container. /// All nodes allocated during the construction of the control flow graph diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index f91d72f0d..69a7a43c2 100644 --- a/libsolidity/analysis/DocStringAnalyser.cpp +++ b/libsolidity/analysis/DocStringAnalyser.cpp @@ -28,6 +28,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; bool DocStringAnalyser::analyseDocStrings(SourceUnit const& _sourceUnit) diff --git a/libsolidity/analysis/DocStringAnalyser.h b/libsolidity/analysis/DocStringAnalyser.h index 827462071..f6b236db6 100644 --- a/libsolidity/analysis/DocStringAnalyser.h +++ b/libsolidity/analysis/DocStringAnalyser.h @@ -25,13 +25,16 @@ #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity { -class ErrorReporter; - /** * Parses and analyses the doc strings. * Stores the parsing results in the AST annotations and reports errors. @@ -39,7 +42,7 @@ class ErrorReporter; class DocStringAnalyser: private ASTConstVisitor { public: - DocStringAnalyser(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + DocStringAnalyser(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} bool analyseDocStrings(SourceUnit const& _sourceUnit); private: @@ -75,7 +78,7 @@ private: void appendError(std::string const& _description); bool m_errorOccured = false; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index a6c746ed2..e40a2c973 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -30,6 +30,7 @@ #include using namespace std; +using namespace langutil; namespace dev { @@ -59,7 +60,7 @@ bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode { DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, _currentScope); } - catch (FatalError const&) + catch (langutil::FatalError const&) { if (m_errorReporter.errors().empty()) throw; // Something is weird here, rather throw again. @@ -129,7 +130,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ASTNode& _node, bool _resolveInsi { return resolveNamesAndTypesInternal(_node, _resolveInsideCode); } - catch (FatalError const&) + catch (langutil::FatalError const&) { if (m_errorReporter.errors().empty()) throw; // Something is weird here, rather throw again. @@ -144,7 +145,7 @@ bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) m_scopes[nullptr]->registerDeclaration(_declaration, nullptr, false, true); solAssert(_declaration.scope() == nullptr, "Updated declaration outside global scope."); } - catch (FatalError const&) + catch (langutil::FatalError const&) { if (m_errorReporter.errors().empty()) throw; // Something is weird here, rather throw again. diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index a72c21e3c..1b034ef4e 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -30,13 +30,16 @@ #include #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity { -class ErrorReporter; - /** * Resolves name references, typenames and sets the (explicitly given) types for all variable * declarations. @@ -50,7 +53,7 @@ public: NameAndTypeResolver( std::vector const& _globals, std::map>& _scopes, - ErrorReporter& _errorReporter + langutil::ErrorReporter& _errorReporter ); /// Registers all declarations found in the AST node, usually a source unit. /// @returns false in case of error. @@ -125,7 +128,7 @@ private: std::map>& m_scopes; DeclarationContainer* m_currentScope = nullptr; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; }; /** @@ -142,7 +145,7 @@ public: DeclarationRegistrationHelper( std::map>& _scopes, ASTNode& _astRoot, - ErrorReporter& _errorReporter, + langutil::ErrorReporter& _errorReporter, ASTNode const* _currentScope = nullptr ); @@ -150,10 +153,10 @@ public: DeclarationContainer& _container, Declaration const& _declaration, std::string const* _name, - SourceLocation const* _errorLocation, + langutil::SourceLocation const* _errorLocation, bool _warnOnShadow, bool _inactive, - ErrorReporter& _errorReporter + langutil::ErrorReporter& _errorReporter ); private: @@ -194,7 +197,7 @@ private: std::map>& m_scopes; ASTNode const* m_currentScope = nullptr; VariableScope* m_currentFunction = nullptr; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 3f45df421..27cbcd459 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -29,6 +29,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h index 8382948aa..e428b81ae 100644 --- a/libsolidity/analysis/PostTypeChecker.h +++ b/libsolidity/analysis/PostTypeChecker.h @@ -23,13 +23,17 @@ #include #include +namespace langutil +{ +class ErrorReporter; +struct SourceLocation; +} + namespace dev { namespace solidity { -class ErrorReporter; - /** * This module performs analyses on the AST that are done after type checking and assignments of types: * - whether there are circular references in constant state variables @@ -39,13 +43,13 @@ class PostTypeChecker: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - PostTypeChecker(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} bool check(ASTNode const& _astRoot); private: /// Adds a new error to the list of errors. - void typeError(SourceLocation const& _location, std::string const& _description); + void typeError(langutil::SourceLocation const& _location, std::string const& _description); bool visit(ContractDefinition const& _contract) override; void endVisit(ContractDefinition const& _contract) override; @@ -57,7 +61,7 @@ private: VariableDeclaration const* findCycle(VariableDeclaration const& _startingFrom); - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; VariableDeclaration const* m_currentConstVariable = nullptr; std::vector m_constVariables; ///< Required for determinism. diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index cae92203f..7ac3ceff9 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -36,9 +36,12 @@ #include using namespace std; -using namespace dev; -using namespace dev::solidity; +using namespace langutil; +namespace dev +{ +namespace solidity +{ bool ReferencesResolver::resolve(ASTNode const& _root) { @@ -454,3 +457,6 @@ void ReferencesResolver::fatalDeclarationError(SourceLocation const& _location, m_errorOccurred = true; m_errorReporter.fatalDeclarationError(_location, _description); } + +} +} diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 34dbca967..32c0553f4 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -28,12 +28,17 @@ #include #include +namespace langutil +{ +class ErrorReporter; +struct SourceLocation; +} + namespace dev { namespace solidity { -class ErrorReporter; class NameAndTypeResolver; /** @@ -44,7 +49,7 @@ class ReferencesResolver: private ASTConstVisitor { public: ReferencesResolver( - ErrorReporter& _errorReporter, + langutil::ErrorReporter& _errorReporter, NameAndTypeResolver& _resolver, bool _resolveInsideCode = false ): @@ -77,18 +82,18 @@ private: void endVisit(VariableDeclaration const& _variable) override; /// Adds a new error to the list of errors. - void typeError(SourceLocation const& _location, std::string const& _description); + void typeError(langutil::SourceLocation const& _location, std::string const& _description); /// Adds a new error to the list of errors and throws to abort reference resolving. - void fatalTypeError(SourceLocation const& _location, std::string const& _description); + void fatalTypeError(langutil::SourceLocation const& _location, std::string const& _description); /// Adds a new error to the list of errors. - void declarationError(SourceLocation const& _location, std::string const& _description); + void declarationError(langutil::SourceLocation const& _location, std::string const& _description); /// Adds a new error to the list of errors and throws to abort reference resolving. - void fatalDeclarationError(SourceLocation const& _location, std::string const& _description); + void fatalDeclarationError(langutil::SourceLocation const& _location, std::string const& _description); - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; NameAndTypeResolver& m_resolver; /// Stack of return parameters. std::vector m_returnParameters; diff --git a/libsolidity/analysis/SemVerHandler.h b/libsolidity/analysis/SemVerHandler.h index edf4fbd80..801856121 100644 --- a/libsolidity/analysis/SemVerHandler.h +++ b/libsolidity/analysis/SemVerHandler.h @@ -22,8 +22,9 @@ #pragma once +#include +#include #include -#include namespace dev { diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 353c1755c..383918412 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -28,6 +28,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit) diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h index f5f3dbce5..ff33fa3a4 100644 --- a/libsolidity/analysis/StaticAnalyzer.h +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -28,6 +28,11 @@ #include #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity @@ -44,7 +49,7 @@ class StaticAnalyzer: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - explicit StaticAnalyzer(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + explicit StaticAnalyzer(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} /// Performs static analysis on the given source unit and all of its sub-nodes. /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings @@ -70,7 +75,7 @@ private: /// @returns the size of this type in storage, including all sub-types. static bigint structureSizeEstimate(Type const& _type, std::set& _structsSeen); - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; /// Flag that indicates whether the current contract definition is a library. bool m_library = false; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 9ac0478e3..a73d7e5c2 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -29,6 +29,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 9e3c46525..c24639555 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -23,6 +23,11 @@ #include #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity @@ -39,7 +44,7 @@ class SyntaxChecker: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - SyntaxChecker(ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + SyntaxChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} bool checkSyntax(ASTNode const& _astRoot); @@ -81,7 +86,7 @@ private: bool visit(StructDefinition const& _struct) override; bool visit(Literal const& _literal) override; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; /// Flag that indicates whether a function modifier actually contains '_'. bool m_placeholderFound = false; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7531da651..69de9f127 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -35,6 +35,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 392a923c5..c98a4c7f2 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -29,13 +29,16 @@ #include #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity { -class ErrorReporter; - /** * The module that performs type analysis on the AST, checks the applicability of operations on * those types and stores errors for invalid operations. @@ -45,7 +48,7 @@ class TypeChecker: private ASTConstVisitor { public: /// @param _errorReporter provides the error logging functionality. - TypeChecker(EVMVersion _evmVersion, ErrorReporter& _errorReporter): + TypeChecker(EVMVersion _evmVersion, langutil::ErrorReporter& _errorReporter): m_evmVersion(_evmVersion), m_errorReporter(_errorReporter) {} @@ -183,7 +186,7 @@ private: /// Flag indicating whether we are currently inside a StructDefinition. bool m_insideStruct = false; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index b0cacc437..3fb4c026f 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -22,10 +22,13 @@ #include #include +#include + #include using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace diff --git a/libsolidity/analysis/ViewPureChecker.h b/libsolidity/analysis/ViewPureChecker.h index 9615d04f1..fd2432a7d 100644 --- a/libsolidity/analysis/ViewPureChecker.h +++ b/libsolidity/analysis/ViewPureChecker.h @@ -21,11 +21,15 @@ #include #include -#include - #include #include +namespace langutil +{ +class ErrorReporter; +struct SourceLocation; +} + namespace dev { namespace solidity @@ -34,7 +38,7 @@ namespace solidity class ViewPureChecker: private ASTConstVisitor { public: - ViewPureChecker(std::vector> const& _ast, ErrorReporter& _errorReporter): + ViewPureChecker(std::vector> const& _ast, langutil::ErrorReporter& _errorReporter): m_ast(_ast), m_errorReporter(_errorReporter) {} bool check(); @@ -43,7 +47,7 @@ private: struct MutabilityAndLocation { StateMutability mutability; - SourceLocation location; + langutil::SourceLocation location; }; bool visit(FunctionDefinition const& _funDef) override; @@ -62,15 +66,15 @@ private: /// Creates appropriate warnings and errors and sets @a m_currentBestMutability. void reportMutability( StateMutability _mutability, - SourceLocation const& _location, - boost::optional const& _nestedLocation = {} + langutil::SourceLocation const& _location, + boost::optional const& _nestedLocation = {} ); std::vector> const& m_ast; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; bool m_errors = false; - MutabilityAndLocation m_bestMutabilityAndLocation = MutabilityAndLocation{StateMutability::Payable, SourceLocation()}; + MutabilityAndLocation m_bestMutabilityAndLocation = MutabilityAndLocation{StateMutability::Payable, langutil::SourceLocation()}; FunctionDefinition const* m_currentFunction = nullptr; std::map m_inferredMutability; }; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 2c44841e8..d23562ad2 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -23,8 +23,8 @@ #pragma once +#include #include -#include #include #include #include @@ -58,6 +58,8 @@ class ASTConstVisitor; class ASTNode: private boost::noncopyable { public: + using SourceLocation = langutil::SourceLocation; + explicit ASTNode(SourceLocation const& _location); virtual ~ASTNode(); diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 2d26ce8a0..6b9f72274 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -27,6 +27,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index da0d840a5..dec3ac96f 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -29,6 +29,11 @@ #include #include +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace solidity @@ -120,7 +125,7 @@ private: std::string const& _nodeName, std::vector>&& _attributes ); - std::string sourceLocationToString(SourceLocation const& _location) const; + std::string sourceLocationToString(langutil::SourceLocation const& _location) const; static std::string namePathToString(std::vector const& _namePath); static Json::Value idOrNull(ASTNode const* _pt) { diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp index 255cb9bec..cdc6ae7de 100644 --- a/libsolidity/ast/ASTPrinter.cpp +++ b/libsolidity/ast/ASTPrinter.cpp @@ -28,6 +28,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 4b31d2e84..0eab75aaf 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -45,6 +45,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 79a656e98..482d6735a 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index a4000d605..4878f9f38 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -30,6 +30,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace solidity; void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType const& _sourceType) const diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index fa6dfe609..9e4f2882f 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ using namespace std; +using namespace langutil; namespace dev { @@ -359,7 +361,7 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared(CharStream(_assembly), "--CODEGEN--"); + auto scanner = make_shared(langutil::CharStream(_assembly), "--CODEGEN--"); auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Strict).parse(scanner, false); #ifdef SOL_OUTPUT_ASM cout << assembly::AsmPrinter()(*parserResult) << endl; diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index a0d110175..93c8cc778 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -32,6 +32,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index c8d9d9d37..7a1dcd709 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -37,6 +37,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index bdf91fbf9..57b513d23 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -36,6 +36,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 790ab309e..6d71d36f9 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -28,6 +28,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace solidity; diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index f39eaee1a..d854857b9 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -55,17 +55,17 @@ public: /// Copies the value of the current lvalue to the top of the stack and, if @a _remove is true, /// also removes the reference from the stack. /// @a _location source location of the current expression, used for error reporting. - virtual void retrieveValue(SourceLocation const& _location, bool _remove = false) const = 0; + virtual void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const = 0; /// Moves a value from the stack to the lvalue. Removes the value if @a _move is true. /// @a _location is the source location of the expression that caused this operation. /// Stack pre: value [lvalue_ref] /// Stack post: if !_move: value_of(lvalue_ref) virtual void storeValue(Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), bool _move = false) const = 0; + langutil::SourceLocation const& _location = {}, bool _move = false) const = 0; /// Stores zero in the lvalue. Removes the reference from the stack if @a _removeReference is true. /// @a _location is the source location of the requested operation virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const = 0; @@ -83,14 +83,14 @@ public: StackVariable(CompilerContext& _compilerContext, VariableDeclaration const& _declaration); unsigned sizeOnStack() const override { return 0; } - void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _move = false ) const override; virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; @@ -109,14 +109,14 @@ class MemoryItem: public LValue public: MemoryItem(CompilerContext& _compilerContext, Type const& _type, bool _padded = true); unsigned sizeOnStack() const override { return 1; } - void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _move = false ) const override; virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; private: @@ -137,14 +137,14 @@ public: /// Constructs the LValue and assumes that the storage reference is already on the stack. StorageItem(CompilerContext& _compilerContext, Type const& _type); unsigned sizeOnStack() const override { return 2; } - void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _move = false ) const override; virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; }; @@ -159,14 +159,14 @@ public: /// Constructs the LValue and assumes that the storage reference is already on the stack. StorageByteArrayElement(CompilerContext& _compilerContext); unsigned sizeOnStack() const override { return 2; } - void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _move = false ) const override; virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; }; @@ -181,14 +181,14 @@ class StorageArrayLength: public LValue public: /// Constructs the LValue, assumes that the reference to the array head is already on the stack. StorageArrayLength(CompilerContext& _compilerContext, ArrayType const& _arrayType); - void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _move = false ) const override; virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; @@ -206,14 +206,14 @@ public: /// Empty unique_ptrs are possible if e.g. some values should be ignored during assignment. TupleObject(CompilerContext& _compilerContext, std::vector>&& _lvalues); unsigned sizeOnStack() const override; - void retrieveValue(SourceLocation const& _location, bool _remove = false) const override; + void retrieveValue(langutil::SourceLocation const& _location, bool _remove = false) const override; virtual void storeValue( Type const& _sourceType, - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _move = false ) const override; virtual void setToZero( - SourceLocation const& _location = SourceLocation(), + langutil::SourceLocation const& _location = {}, bool _removeReference = true ) const override; diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index a85951901..7e75df87b 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -29,6 +29,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; SMTChecker::SMTChecker(ErrorReporter& _errorReporter, ReadCallback::Callback const& _readFileCallback): diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index ae9f32e90..d7f86cbc3 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -31,20 +31,25 @@ #include #include +namespace langutil +{ +class ErrorReporter; +struct SourceLocation; +} + namespace dev { namespace solidity { class VariableUsage; -class ErrorReporter; class SMTChecker: private ASTConstVisitor { public: - SMTChecker(ErrorReporter& _errorReporter, ReadCallback::Callback const& _readCallback); + SMTChecker(langutil::ErrorReporter& _errorReporter, ReadCallback::Callback const& _readCallback); - void analyze(SourceUnit const& _sources, std::shared_ptr const& _scanner); + void analyze(SourceUnit const& _sources, std::shared_ptr const& _scanner); private: // TODO: Check that we do not have concurrent reads and writes to a variable, @@ -89,8 +94,8 @@ private: /// of rounding for signed division. smt::Expression division(smt::Expression _left, smt::Expression _right, IntegerType const& _type); - void assignment(VariableDeclaration const& _variable, Expression const& _value, SourceLocation const& _location); - void assignment(VariableDeclaration const& _variable, smt::Expression const& _value, SourceLocation const& _location); + void assignment(VariableDeclaration const& _variable, Expression const& _value, langutil::SourceLocation const& _location); + void assignment(VariableDeclaration const& _variable, smt::Expression const& _value, langutil::SourceLocation const& _location); /// Maps a variable to an SSA index. using VariableIndices = std::unordered_map; @@ -104,7 +109,7 @@ private: /// Check that a condition can be satisfied. void checkCondition( smt::Expression _condition, - SourceLocation const& _location, + langutil::SourceLocation const& _location, std::string const& _description, std::string const& _additionalValueName = "", smt::Expression* _additionalValue = nullptr @@ -117,7 +122,7 @@ private: std::string const& _description ); /// Checks that the value is in the range given by the type. - void checkUnderOverflow(smt::Expression _value, IntegerType const& _Type, SourceLocation const& _location); + void checkUnderOverflow(smt::Expression _value, IntegerType const& _Type, langutil::SourceLocation const& _location); std::pair> @@ -200,8 +205,8 @@ private: /// Used to retrieve models. std::vector m_uninterpretedTerms; std::vector m_pathConditions; - ErrorReporter& m_errorReporter; - std::shared_ptr m_scanner; + langutil::ErrorReporter& m_errorReporter; + std::shared_ptr m_scanner; /// Stores the current path of function calls. std::vector m_functionPath; diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 95c8537d3..fb96f73c8 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -35,6 +35,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; using namespace dev::solidity::assembly; diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libsolidity/inlineasm/AsmAnalysis.h index 7ae27ebd0..194f736ee 100644 --- a/libsolidity/inlineasm/AsmAnalysis.h +++ b/libsolidity/inlineasm/AsmAnalysis.h @@ -35,11 +35,16 @@ #include #include +namespace langutil +{ +class ErrorReporter; +struct SourceLocation; +} + namespace dev { namespace solidity { -class ErrorReporter; namespace assembly { @@ -55,9 +60,9 @@ class AsmAnalyzer: public boost::static_visitor public: explicit AsmAnalyzer( AsmAnalysisInfo& _analysisInfo, - ErrorReporter& _errorReporter, + langutil::ErrorReporter& _errorReporter, EVMVersion _evmVersion, - boost::optional _errorTypeForLoose, + boost::optional _errorTypeForLoose, AsmFlavour _flavour = AsmFlavour::Loose, yul::ExternalIdentifierAccess::Resolver const& _resolver = yul::ExternalIdentifierAccess::Resolver() ): @@ -90,20 +95,20 @@ public: private: /// Visits the statement and expects it to deposit one item onto the stack. bool expectExpression(Expression const& _expr); - bool expectDeposit(int _deposit, int _oldHeight, SourceLocation const& _location); + bool expectDeposit(int _deposit, int _oldHeight, langutil::SourceLocation const& _location); /// Verifies that a variable to be assigned to exists and has the same size /// as the value, @a _valueSize, unless that is equal to -1. bool checkAssignment(assembly::Identifier const& _assignment, size_t _valueSize = size_t(-1)); Scope& scope(assembly::Block const* _block); - void expectValidType(std::string const& type, SourceLocation const& _location); - void warnOnInstructions(solidity::Instruction _instr, SourceLocation const& _location); + void expectValidType(std::string const& type, langutil::SourceLocation const& _location); + void warnOnInstructions(solidity::Instruction _instr, langutil::SourceLocation const& _location); /// Depending on @a m_flavour and @a m_errorTypeForLoose, throws an internal compiler /// exception (if the flavour is not Loose), reports an error/warning /// (if m_errorTypeForLoose is set) or does nothing. - void checkLooseFeature(SourceLocation const& _location, std::string const& _description); + void checkLooseFeature(langutil::SourceLocation const& _location, std::string const& _description); int m_stackHeight = 0; yul::ExternalIdentifierAccess::Resolver m_resolver; @@ -112,10 +117,10 @@ private: /// "part of the scope but not yet declared") std::set m_activeVariables; AsmAnalysisInfo& m_info; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; EVMVersion m_evmVersion; AsmFlavour m_flavour = AsmFlavour::Loose; - boost::optional m_errorTypeForLoose; + boost::optional m_errorTypeForLoose; }; } diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index ee69b44fb..2800cc7b8 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -46,6 +46,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; using namespace dev::solidity::assembly; diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index e9bf48417..23a9db75c 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -45,56 +45,56 @@ namespace assembly using YulString = dev::yul::YulString; using Type = YulString; -struct TypedName { SourceLocation location; YulString name; Type type; }; +struct TypedName { langutil::SourceLocation location; YulString name; Type type; }; using TypedNameList = std::vector; /// Direct EVM instruction (except PUSHi and JUMPDEST) -struct Instruction { SourceLocation location; solidity::Instruction instruction; }; +struct Instruction { langutil::SourceLocation location; solidity::Instruction instruction; }; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; -struct Literal { SourceLocation location; LiteralKind kind; YulString value; Type type; }; +struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString value; Type type; }; /// External / internal identifier or label reference -struct Identifier { SourceLocation location; YulString name; }; +struct Identifier { langutil::SourceLocation location; YulString name; }; /// Jump label ("name:") -struct Label { SourceLocation location; YulString name; }; +struct Label { langutil::SourceLocation location; YulString name; }; /// Assignment from stack (":= x", moves stack top into x, potentially multiple slots) -struct StackAssignment { SourceLocation location; Identifier variableName; }; +struct StackAssignment { langutil::SourceLocation location; Identifier variableName; }; /// Assignment ("x := mload(20:u256)", expects push-1-expression on the right hand /// side and requires x to occupy exactly one stack slot. /// /// Multiple assignment ("x, y := f()"), where the left hand side variables each occupy /// a single stack slot and expects a single expression on the right hand returning /// the same amount of items as the number of variables. -struct Assignment { SourceLocation location; std::vector variableNames; std::shared_ptr value; }; +struct Assignment { langutil::SourceLocation location; std::vector variableNames; std::shared_ptr value; }; /// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))" -struct FunctionalInstruction { SourceLocation location; solidity::Instruction instruction; std::vector arguments; }; -struct FunctionCall { SourceLocation location; Identifier functionName; std::vector arguments; }; +struct FunctionalInstruction { langutil::SourceLocation location; solidity::Instruction instruction; std::vector arguments; }; +struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector arguments; }; /// Statement that contains only a single expression -struct ExpressionStatement { SourceLocation location; Expression expression; }; +struct ExpressionStatement { langutil::SourceLocation location; Expression expression; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted -struct VariableDeclaration { SourceLocation location; TypedNameList variables; std::shared_ptr value; }; +struct VariableDeclaration { langutil::SourceLocation location; TypedNameList variables; std::shared_ptr value; }; /// Block that creates a scope (frees declared stack variables) -struct Block { SourceLocation location; std::vector statements; }; +struct Block { langutil::SourceLocation location; std::vector statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") -struct FunctionDefinition { SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; +struct FunctionDefinition { langutil::SourceLocation location; YulString name; TypedNameList parameters; TypedNameList returnVariables; Block body; }; /// Conditional execution without "else" part. -struct If { SourceLocation location; std::shared_ptr condition; Block body; }; +struct If { langutil::SourceLocation location; std::shared_ptr condition; Block body; }; /// Switch case or default case -struct Case { SourceLocation location; std::shared_ptr value; Block body; }; +struct Case { langutil::SourceLocation location; std::shared_ptr value; Block body; }; /// Switch statement -struct Switch { SourceLocation location; std::shared_ptr expression; std::vector cases; }; -struct ForLoop { SourceLocation location; Block pre; std::shared_ptr condition; Block post; Block body; }; +struct Switch { langutil::SourceLocation location; std::shared_ptr expression; std::vector cases; }; +struct ForLoop { langutil::SourceLocation location; Block pre; std::shared_ptr condition; Block post; Block body; }; -struct LocationExtractor: boost::static_visitor +struct LocationExtractor: boost::static_visitor { - template SourceLocation operator()(T const& _node) const + template langutil::SourceLocation operator()(T const& _node) const { return _node.location; } }; /// Extracts the source location from an inline assembly node. -template inline SourceLocation locationOf(T const& _node) +template inline langutil::SourceLocation locationOf(T const& _node) { return boost::apply_visitor(LocationExtractor(), _node); } diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 3103e2b3d..b11f70e06 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; using namespace dev::solidity::assembly; diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h index b3d74df18..9e13799a6 100644 --- a/libsolidity/inlineasm/AsmParser.h +++ b/libsolidity/inlineasm/AsmParser.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include namespace dev @@ -34,22 +36,22 @@ namespace solidity namespace assembly { -class Parser: public ParserBase +class Parser: public langutil::ParserBase { public: - explicit Parser(ErrorReporter& _errorReporter, AsmFlavour _flavour = AsmFlavour::Loose): + explicit Parser(langutil::ErrorReporter& _errorReporter, AsmFlavour _flavour = AsmFlavour::Loose): ParserBase(_errorReporter), m_flavour(_flavour) {} /// Parses an inline assembly block starting with `{` and ending with `}`. /// @param _reuseScanner if true, do check for end of input after the `}`. /// @returns an empty shared pointer on error. - std::shared_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); + std::shared_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); protected: using ElementaryOperation = boost::variant; /// Creates an inline assembly node with the given source location. - template T createWithLocation(SourceLocation const& _loc = SourceLocation()) const + template T createWithLocation(langutil::SourceLocation const& _loc = {}) const { T r; r.location = _loc; @@ -62,7 +64,7 @@ protected: r.location.sourceName = sourceName(); return r; } - SourceLocation location() const { return SourceLocation(position(), endPosition(), sourceName()); } + langutil::SourceLocation location() const { return {position(), endPosition(), sourceName()}; } Block parseBlock(); Statement parseStatement(); diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index c7625fe03..09934bd8f 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -36,6 +36,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; using namespace dev::solidity::assembly; diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h index bb023f614..7454fd6c0 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.h +++ b/libsolidity/inlineasm/AsmScopeFiller.h @@ -27,12 +27,16 @@ #include #include -namespace dev -{ -struct SourceLocation; -namespace solidity +namespace langutil { class ErrorReporter; +struct SourceLocation; +} + +namespace dev +{ +namespace solidity +{ namespace assembly { @@ -47,7 +51,7 @@ struct AsmAnalysisInfo; class ScopeFiller: public boost::static_visitor { public: - ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter); + ScopeFiller(AsmAnalysisInfo& _info, langutil::ErrorReporter& _errorReporter); bool operator()(assembly::Instruction const&) { return true; } bool operator()(assembly::Literal const&) { return true; } @@ -68,7 +72,7 @@ public: private: bool registerVariable( TypedName const& _name, - SourceLocation const& _location, + langutil::SourceLocation const& _location, Scope& _scope ); @@ -76,7 +80,7 @@ private: Scope* m_currentScope = nullptr; AsmAnalysisInfo& m_info; - ErrorReporter& m_errorReporter; + langutil::ErrorReporter& m_errorReporter; }; } diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 26879e8b7..5b6b11132 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -36,6 +36,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index aad65ffc4..d6ee33cf8 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -29,11 +29,15 @@ #include #include +namespace langutil +{ +class Scanner; +} + namespace dev { namespace solidity { -class Scanner; namespace assembly { struct AsmAnalysisInfo; @@ -61,7 +65,7 @@ public: {} /// @returns the scanner used during parsing - Scanner const& scanner() const; + langutil::Scanner const& scanner() const; /// Runs parsing and analysis steps, returns false if input cannot be assembled. /// Multiple calls overwrite the previous state. @@ -69,13 +73,13 @@ public: /// Runs analysis step on the supplied block, returns false if input cannot be assembled. /// Multiple calls overwrite the previous state. - bool analyze(assembly::Block const& _block, Scanner const* _scanner = nullptr); + bool analyze(assembly::Block const& _block, langutil::Scanner const* _scanner = nullptr); /// Run the assembly step (should only be called after parseAndAnalyze). MachineAssemblyObject assemble(Machine _machine) const; /// @returns the errors generated during parsing, analysis (and potentially assembly). - ErrorList const& errors() const { return m_errors; } + langutil::ErrorList const& errors() const { return m_errors; } /// Pretty-print the input after having parsed it. std::string print() const; @@ -86,13 +90,13 @@ private: Language m_language = Language::Assembly; EVMVersion m_evmVersion; - std::shared_ptr m_scanner; + std::shared_ptr m_scanner; bool m_analysisSuccessful = false; std::shared_ptr m_parserResult; std::shared_ptr m_analysisInfo; - ErrorList m_errors; - ErrorReporter m_errorReporter; + langutil::ErrorList m_errors; + langutil::ErrorReporter m_errorReporter; }; } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 08a248dda..a56747052 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -58,6 +58,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; boost::optional CompilerStack::parseRemapping(string const& _remapping) diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index a7e312ad5..8c50266ef 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -23,11 +23,12 @@ #pragma once -#include #include -#include +#include +#include #include + #include #include @@ -43,6 +44,11 @@ #include #include +namespace langutil +{ +class Scanner; +} + namespace dev { @@ -57,7 +63,6 @@ namespace solidity { // forward declarations -class Scanner; class ASTNode; class ContractDefinition; class FunctionDefinition; @@ -65,7 +70,6 @@ class SourceUnit; class Compiler; class GlobalContext; class Natspec; -class Error; class DeclarationContainer; /** @@ -100,7 +104,7 @@ public: m_errorReporter(m_errorList) {} /// @returns the list of errors that occurred during parsing and type checking. - ErrorList const& errors() const { return m_errorReporter.errors(); } + langutil::ErrorList const& errors() const { return m_errorReporter.errors(); } /// @returns the current state. State state() const { return m_stackState; } @@ -174,7 +178,7 @@ public: std::map sourceIndices() const; /// @returns the previously used scanner, useful for counting lines during error reporting. - Scanner const& scanner(std::string const& _sourceName) const; + langutil::Scanner const& scanner(std::string const& _sourceName) const; /// @returns the parsed source unit with the supplied name. SourceUnit const& ast(std::string const& _sourceName) const; @@ -182,7 +186,7 @@ public: /// Helper function for logs printing. Do only use in error cases, it's quite expensive. /// line and columns are numbered starting from 1 with following order: /// start line, start column, end line, end column - std::tuple positionFromSourceLocation(SourceLocation const& _sourceLocation) const; + std::tuple positionFromSourceLocation(langutil::SourceLocation const& _sourceLocation) const; /// @returns a list of the contract names in the sources. std::vector contractNames() const; @@ -248,7 +252,7 @@ private: /// The state per source unit. Filled gradually during parsing. struct Source { - std::shared_ptr scanner; + std::shared_ptr scanner; std::shared_ptr ast; bool isLibrary = false; void reset() { scanner.reset(); ast.reset(); } @@ -345,8 +349,8 @@ private: /// This is updated during compilation. std::map> m_scopes; std::map m_contracts; - ErrorList m_errorList; - ErrorReporter m_errorReporter; + langutil::ErrorList m_errorList; + langutil::ErrorReporter m_errorReporter; bool m_metadataLiteralSources = false; State m_stackState = Empty; }; diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 1f20366ed..de6b2ce59 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -35,6 +35,7 @@ using namespace std; using namespace dev; using namespace dev::eth; +using namespace langutil; using namespace dev::solidity; GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimation( diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/libsolidity/interface/SourceReferenceFormatter.cpp index 9e2c988ec..d727afbeb 100644 --- a/libsolidity/interface/SourceReferenceFormatter.cpp +++ b/libsolidity/interface/SourceReferenceFormatter.cpp @@ -25,6 +25,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/libsolidity/interface/SourceReferenceFormatter.h index 281a4bdcc..7dea5254e 100644 --- a/libsolidity/interface/SourceReferenceFormatter.h +++ b/libsolidity/interface/SourceReferenceFormatter.h @@ -25,7 +25,12 @@ #include #include #include -#include + +namespace langutil +{ +struct SourceLocation; +class Scanner; +} namespace dev { @@ -35,13 +40,12 @@ struct Exception; // forward namespace solidity { -class Scanner; // forward class CompilerStack; // forward class SourceReferenceFormatter { public: - using ScannerFromSourceNameFun = std::function; + using ScannerFromSourceNameFun = std::function; explicit SourceReferenceFormatter( std::ostream& _stream, @@ -52,7 +56,7 @@ public: {} /// Prints source location if it is given. - void printSourceLocation(SourceLocation const* _location); + void printSourceLocation(langutil::SourceLocation const* _location); void printExceptionInformation(Exception const& _exception, std::string const& _name); static std::string formatExceptionInformation( @@ -69,7 +73,7 @@ public: } private: /// Prints source name if location is given. - void printSourceName(SourceLocation const* _location); + void printSourceName(langutil::SourceLocation const* _location); std::ostream& m_stream; ScannerFromSourceNameFun m_scannerFromSourceName; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index c8b03a94a..291a1071b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; namespace { @@ -411,7 +412,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value outputSelection = settings.get("outputSelection", Json::Value()); m_compilerStack.setRequestedContractNames(requestedContractNames(outputSelection)); - auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compilerStack.scanner(_sourceName); }; + auto scannerFromSourceName = [&](string const& _sourceName) -> Scanner const& { return m_compilerStack.scanner(_sourceName); }; try { diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp index 17a7b6913..d8927feaa 100644 --- a/libsolidity/parsing/DocStringParser.cpp +++ b/libsolidity/parsing/DocStringParser.cpp @@ -8,6 +8,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; diff --git a/libsolidity/parsing/DocStringParser.h b/libsolidity/parsing/DocStringParser.h index 5f2819cc5..c83b416db 100644 --- a/libsolidity/parsing/DocStringParser.h +++ b/libsolidity/parsing/DocStringParser.h @@ -25,19 +25,22 @@ #include #include +namespace langutil +{ +class ErrorReporter; +} + namespace dev { namespace solidity { -class ErrorReporter; - class DocStringParser { public: /// Parse the given @a _docString and stores the parsed components internally. /// @returns false on error and appends the error to @a _errors. - bool parse(std::string const& _docString, ErrorReporter& _errorReporter); + bool parse(std::string const& _docString, langutil::ErrorReporter& _errorReporter); std::multimap const& tags() const { return m_docTags; } @@ -63,7 +66,7 @@ private: /// Mapping tag name -> content. std::multimap m_docTags; DocTag* m_lastTag = nullptr; - ErrorReporter* m_errorReporter = nullptr; + langutil::ErrorReporter* m_errorReporter = nullptr; bool m_errorsOccurred = false; }; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index f070620de..de5293b4d 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -29,6 +29,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index f20f01c55..15852096a 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -25,19 +25,22 @@ #include #include +namespace langutil +{ +class Scanner; +} + namespace dev { namespace solidity { -class Scanner; - -class Parser: public ParserBase +class Parser: public langutil::ParserBase { public: - explicit Parser(ErrorReporter& _errorReporter): ParserBase(_errorReporter) {} + explicit Parser(langutil::ErrorReporter& _errorReporter): ParserBase(_errorReporter) {} - ASTPointer parse(std::shared_ptr const& _scanner); + ASTPointer parse(std::shared_ptr const& _scanner); private: class ASTNodeFactory; @@ -146,7 +149,7 @@ private: struct IndexAccessedPath { std::vector> path; - std::vector, SourceLocation>> indices; + std::vector, langutil::SourceLocation>> indices; bool empty() const; }; diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h new file mode 100644 index 000000000..d61aefb61 --- /dev/null +++ b/libsolidity/parsing/Token.h @@ -0,0 +1,36 @@ +/* + 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 . +*/ +/** + * Solidity and Yul both share the same Token (and Scanner) API. + * + * This may (or may not) change in the future. But for the time being, we've put both + * at a shared place, and *just* import them. +*/ +#pragma once + +#include + +namespace dev +{ +namespace solidity +{ +namespace TokenTraits = ::langutil::TokenTraits; + +using ::langutil::Token; +using ::langutil::ElementaryTypeNameToken; +} +} diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index d75058f7a..5a1140cb2 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -26,9 +26,13 @@ #include -namespace dev +namespace langutil { struct SourceLocation; +} + +namespace dev +{ namespace solidity { enum class Instruction: uint8_t; @@ -52,7 +56,7 @@ public: virtual ~AbstractAssembly() {} /// Set a new source location valid starting from the next instruction. - virtual void setSourceLocation(SourceLocation const& _location) = 0; + virtual void setSourceLocation(langutil::SourceLocation const& _location) = 0; /// Retrieve the current height of the stack. This does not have to be zero /// at the beginning. virtual int stackHeight() const = 0; diff --git a/libyul/backends/evm/EVMAssembly.cpp b/libyul/backends/evm/EVMAssembly.cpp index e4ba37f0f..791b6226e 100644 --- a/libyul/backends/evm/EVMAssembly.cpp +++ b/libyul/backends/evm/EVMAssembly.cpp @@ -26,6 +26,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::yul; namespace diff --git a/libyul/backends/evm/EVMAssembly.h b/libyul/backends/evm/EVMAssembly.h index 8f92b6e73..c9190634f 100644 --- a/libyul/backends/evm/EVMAssembly.h +++ b/libyul/backends/evm/EVMAssembly.h @@ -26,6 +26,11 @@ #include +namespace langutil +{ +struct SourceLocation; +} + namespace dev { namespace yul @@ -38,7 +43,7 @@ public: virtual ~EVMAssembly() {} /// Set a new source location valid starting from the next instruction. - void setSourceLocation(SourceLocation const& _location) override; + void setSourceLocation(langutil::SourceLocation const& _location) override; /// Retrieve the current height of the stack. This does not have to be zero /// at the beginning. int stackHeight() const override { return m_stackHeight; } diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index a4b7a909b..42730864f 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::yul; using namespace dev::solidity; diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index f209ee7b2..6fb4b08dc 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::yul; using namespace dev::solidity; diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 5721042fd..a15ed3916 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::yul; diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index b608ca91d..bd6aa4de9 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -107,7 +107,7 @@ public: /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. - Expression toExpression(SourceLocation const& _location) const; + Expression toExpression(langutil::SourceLocation const& _location) const; private: Expression const& matchGroupValue() const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 357d0ab3d..b9f0bf79f 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -62,6 +62,7 @@ #include using namespace std; +using namespace langutil; namespace po = boost::program_options; namespace dev @@ -827,7 +828,7 @@ bool CommandLineInterface::processInput() m_compiler.reset(new CompilerStack(fileReader)); - auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); }; + auto scannerFromSourceName = [&](string const& _sourceName) -> Scanner const& { return m_compiler->scanner(_sourceName); }; SourceReferenceFormatter formatter(cerr, scannerFromSourceName); try diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 1c041596a..5ad015949 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -30,6 +30,7 @@ #include using namespace std; +using namespace langutil; using namespace dev::eth; namespace dev diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index c01e87580..c061b7835 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -36,6 +36,7 @@ #include using namespace std; +using namespace langutil; using namespace dev::eth; namespace dev diff --git a/test/liblangutil/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp index 29cfb6a0b..ac7a21736 100644 --- a/test/liblangutil/SourceLocation.cpp +++ b/test/liblangutil/SourceLocation.cpp @@ -24,9 +24,7 @@ #include -namespace dev -{ -namespace solidity +namespace langutil { namespace test { @@ -45,6 +43,5 @@ BOOST_AUTO_TEST_CASE(test_fail) BOOST_AUTO_TEST_SUITE_END() -} } } // end namespaces diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index dafd17483..12d63cb78 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -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 a904617d5..391a21dad 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -45,7 +45,7 @@ class AnalysisFramework { protected: - virtual std::pair + virtual std::pair 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 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 78fa7bcfa..926e29fed 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -39,6 +39,7 @@ #include using namespace std; +using namespace langutil; using namespace dev::eth; namespace dev diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp index fba2c8975..e1f48fb2c 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 c70a66453..c3a2f5226 100644 --- a/test/libsolidity/ErrorCheck.h +++ b/test/libsolidity/ErrorCheck.h @@ -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> const& _expectations); +std::string searchErrors(langutil::ErrorList const& _errors, std::vector> const& _expectations); } } diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 4887dd5b0..61f16c0fe 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -29,6 +29,7 @@ #include using namespace std; +using namespace langutil; using namespace dev::eth; using namespace dev::solidity; using namespace dev::test; diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 3079e0321..31d21490c 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -36,6 +36,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 195004cb4..13fcc5b43 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -25,6 +25,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index b2f4b3c28..2e147847c 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -28,6 +28,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index ab71a3e03..d43e994d7 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -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); }; + auto scannerFromSourceName = [&](std::string const& _sourceName) -> langutil::Scanner const& { return m_compiler.scanner(_sourceName); }; 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 37183279d..a68eb3df3 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -33,6 +33,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 5ec010c7f..757260279 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -33,6 +33,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 45191ce1c..d930f6979 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -27,6 +27,8 @@ #include #include +using namespace langutil; + namespace dev { namespace solidity diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index cf5461ba2..3534dd5ba 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -29,6 +29,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 53ec0a4ca..2d164ae34 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -24,6 +24,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 6f9d4ce8c..c839afd4d 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -26,6 +26,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 91d1681f1..45d32b555 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -25,6 +25,7 @@ #include using namespace dev; +using namespace langutil; using namespace solidity; using namespace dev::solidity::test; using namespace dev::solidity::test::formatting; diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index b7ea1efcb..64e526049 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -28,6 +28,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index b351483e4..8913483f2 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -37,6 +37,7 @@ #include using namespace std; +using namespace langutil; using namespace dev::yul; using namespace dev::solidity; diff --git a/test/libyul/Common.h b/test/libyul/Common.h index ee191494d..390e214f8 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -27,13 +27,17 @@ #include #include -namespace dev -{ -namespace solidity +namespace langutil { class Scanner; class Error; using ErrorList = std::vector>; +} + +namespace dev +{ +namespace solidity +{ namespace assembly { struct AsmAnalysisInfo; @@ -44,7 +48,7 @@ namespace yul namespace test { -void printErrors(solidity::ErrorList const& _errors, solidity::Scanner const& _scanner); +void printErrors(langutil::ErrorList const& _errors, langutil::Scanner const& _scanner); std::pair, std::shared_ptr> parse(std::string const& _source, bool _yul = true); solidity::assembly::Block disambiguate(std::string const& _source, bool _yul = true); diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 3a887176a..4aa3dd5c0 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -36,6 +36,7 @@ #include using namespace std; +using namespace langutil; namespace dev { diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 57c4d7f01..6b2b81c3d 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -21,6 +21,9 @@ #include +#include +#include + #include #include #include @@ -41,12 +44,10 @@ #include #include -#include #include #include #include #include -#include #include #include @@ -54,6 +55,7 @@ #include using namespace dev; +using namespace langutil; using namespace dev::yul; using namespace dev::yul::test; using namespace dev::solidity; diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 7db17ceb7..d11ff8fb3 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -19,14 +19,17 @@ #include +namespace langutil +{ +class Scanner; +class Error; +using ErrorList = std::vector>; +} namespace dev { namespace solidity { -class Scanner; -class Error; -using ErrorList = std::vector>; namespace assembly { struct AsmAnalysisInfo; @@ -58,7 +61,7 @@ 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; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index df5331f75..8bc807d43 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -19,15 +19,15 @@ */ #include +#include +#include #include #include -#include #include #include #include #include #include -#include #include #include @@ -58,6 +58,7 @@ using namespace std; using namespace dev; +using namespace langutil; using namespace dev::solidity; using namespace dev::solidity::assembly; using namespace dev::yul; From 7a26ede827952a10f6ffe3b409104396de46b9ce Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 26 Sep 2018 18:49:30 +0100 Subject: [PATCH 042/168] Fix constructor in AuctionRegistrar --- test/contracts/AuctionRegistrar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index eb274c095..6ce61a6e6 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. } From 90b244d102285974b5a84a308bad5db925cb36a4 Mon Sep 17 00:00:00 2001 From: Javier Tarazaga Date: Sat, 27 Oct 2018 08:13:56 +0200 Subject: [PATCH 043/168] Added Superblocks Lab IDE to the generic section --- docs/resources.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/resources.rst b/docs/resources.rst index e9e656922..4dd617fa3 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -21,9 +21,8 @@ Solidity Integrations * Generic: - * `EthFiddle `_ - Solidity IDE in the Browser. Write and share your solidity code. Uses server-side components. + Solidity IDE in the Browser. Write and share your Solidity code. Uses server-side components. * `Remix `_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. @@ -34,6 +33,9 @@ Solidity Integrations * `Solhint `_ Solidity linter that provides security, style guide and best practice rules for smart contract validation. + * `Superblocks Lab `_ + Browser-based IDE. Built-in browser-based VM and Metamask integration (one click deployment to Testnet/Mainnet). + * Atom: * `Etheratom `_ From 13a142b0395ec6a590f45c724e382e797bffb125 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 21 Nov 2018 16:57:02 +0100 Subject: [PATCH 044/168] [SMTChecker] Add FunctionSort and refactors the solver interface to create variables --- libsolidity/formal/CVC4Interface.cpp | 46 +++++++----------- libsolidity/formal/CVC4Interface.h | 7 +-- libsolidity/formal/SMTChecker.cpp | 13 +++-- libsolidity/formal/SMTChecker.h | 2 +- libsolidity/formal/SMTLib2Interface.cpp | 62 ++++++++++++------------ libsolidity/formal/SMTLib2Interface.h | 10 ++-- libsolidity/formal/SMTPortfolio.cpp | 16 +----- libsolidity/formal/SMTPortfolio.h | 4 +- libsolidity/formal/SolverInterface.h | 50 +++++++++++-------- libsolidity/formal/SymbolicTypes.cpp | 19 ++++++++ libsolidity/formal/SymbolicTypes.h | 1 + libsolidity/formal/SymbolicVariables.cpp | 4 +- libsolidity/formal/Z3Interface.cpp | 28 +++++------ libsolidity/formal/Z3Interface.h | 6 +-- 14 files changed, 137 insertions(+), 131 deletions(-) diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index 8952665f1..cff1717ff 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -33,8 +33,7 @@ CVC4Interface::CVC4Interface(): void CVC4Interface::reset() { - m_constants.clear(); - m_functions.clear(); + m_variables.clear(); m_solver.reset(); m_solver.setOption("produce-models", true); m_solver.setTimeLimit(queryTimeout); @@ -50,25 +49,10 @@ void CVC4Interface::pop() m_solver.pop(); } -void CVC4Interface::declareFunction(string _name, vector const& _domain, Sort const& _codomain) +void CVC4Interface::declareVariable(string const& _name, Sort const& _sort) { - if (!m_functions.count(_name)) - { - CVC4::Type fType = m_context.mkFunctionType(cvc4Sort(_domain), cvc4Sort(_codomain)); - m_functions.insert({_name, m_context.mkVar(_name.c_str(), fType)}); - } -} - -void CVC4Interface::declareInteger(string _name) -{ - if (!m_constants.count(_name)) - m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.integerType())}); -} - -void CVC4Interface::declareBool(string _name) -{ - if (!m_constants.count(_name)) - m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.booleanType())}); + if (!m_variables.count(_name)) + m_variables.insert({_name, m_context.mkVar(_name.c_str(), cvc4Sort(_sort))}); } void CVC4Interface::addAssertion(Expression const& _expr) @@ -129,20 +113,19 @@ pair> CVC4Interface::check(vector const& CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr) { - if (_expr.arguments.empty() && m_constants.count(_expr.name)) - return m_constants.at(_expr.name); + // Variable + if (_expr.arguments.empty() && m_variables.count(_expr.name)) + return m_variables.at(_expr.name); + vector arguments; for (auto const& arg: _expr.arguments) arguments.push_back(toCVC4Expr(arg)); string const& n = _expr.name; - if (m_functions.count(n)) - return m_context.mkExpr(CVC4::kind::APPLY_UF, m_functions[n], arguments); - else if (m_constants.count(n)) - { - solAssert(arguments.empty(), ""); - return m_constants.at(n); - } + // Function application + if (!arguments.empty() && m_variables.count(_expr.name)) + return m_context.mkExpr(CVC4::kind::APPLY_UF, m_variables.at(n), arguments); + // Literal else if (arguments.empty()) { if (n == "true") @@ -194,6 +177,11 @@ CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort) return m_context.booleanType(); case Kind::Int: return m_context.integerType(); + case Kind::Function: + { + FunctionSort const& fSort = dynamic_cast(_sort); + return m_context.mkFunctionType(cvc4Sort(fSort.domain), cvc4Sort(*fSort.codomain)); + } default: break; } diff --git a/libsolidity/formal/CVC4Interface.h b/libsolidity/formal/CVC4Interface.h index f354c790b..bbe238557 100644 --- a/libsolidity/formal/CVC4Interface.h +++ b/libsolidity/formal/CVC4Interface.h @@ -51,9 +51,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; - void declareInteger(std::string _name) override; - void declareBool(std::string _name) override; + void declareVariable(std::string const&, Sort const&) override; void addAssertion(Expression const& _expr) override; std::pair> check(std::vector const& _expressionsToEvaluate) override; @@ -65,8 +63,7 @@ private: CVC4::ExprManager m_context; CVC4::SmtEngine m_solver; - std::map m_constants; - std::map m_functions; + std::map m_variables; }; } diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 7e75df87b..caf7e5faf 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -417,10 +417,15 @@ void SMTChecker::visitGasLeft(FunctionCall const& _funCall) void SMTChecker::visitBlockHash(FunctionCall const& _funCall) { string blockHash = "blockhash"; - defineUninterpretedFunction(blockHash, {make_shared(smt::Kind::Int)}, smt::Kind::Int); auto const& arguments = _funCall.arguments(); solAssert(arguments.size() == 1, ""); - defineExpr(_funCall, m_uninterpretedFunctions.at(blockHash)({expr(*arguments[0])})); + smt::SortPointer paramSort = smtSort(*arguments.at(0)->annotation().type); + smt::SortPointer returnSort = smtSort(*_funCall.annotation().type); + defineUninterpretedFunction( + blockHash, + make_shared(vector{paramSort}, returnSort) + ); + defineExpr(_funCall, m_uninterpretedFunctions.at(blockHash)({expr(*arguments.at(0))})); m_uninterpretedTerms.push_back(&_funCall); } @@ -606,10 +611,10 @@ void SMTChecker::defineSpecialVariable(string const& _name, Expression const& _e defineExpr(_expr, m_specialVariables.at(_name)->currentValue()); } -void SMTChecker::defineUninterpretedFunction(string const& _name, vector const& _domain, smt::Sort const& _codomain) +void SMTChecker::defineUninterpretedFunction(string const& _name, smt::SortPointer _sort) { if (!m_uninterpretedFunctions.count(_name)) - m_uninterpretedFunctions.emplace(_name, m_interface->newFunction(_name, _domain, _codomain)); + m_uninterpretedFunctions.emplace(_name, m_interface->newVariable(_name, _sort)); } void SMTChecker::arithmeticOperation(BinaryOperation const& _op) diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index d7f86cbc3..8ead55646 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -88,7 +88,7 @@ private: void inlineFunctionCall(FunctionCall const&); void defineSpecialVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex = false); - void defineUninterpretedFunction(std::string const& _name, std::vector const& _domain, smt::Sort const& _codomain); + void defineUninterpretedFunction(std::string const& _name, smt::SortPointer _sort); /// Division expression in the given type. Requires special treatment because /// of rounding for signed division. diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 7a6b558b1..bb85860f0 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -47,8 +47,7 @@ void SMTLib2Interface::reset() { m_accumulatedOutput.clear(); m_accumulatedOutput.emplace_back(); - m_constants.clear(); - m_functions.clear(); + m_variables.clear(); write("(set-option :produce-models true)"); write("(set-logic QF_UFLIA)"); } @@ -64,45 +63,39 @@ void SMTLib2Interface::pop() m_accumulatedOutput.pop_back(); } -void SMTLib2Interface::declareFunction(string _name, vector const& _domain, Sort const& _codomain) +void SMTLib2Interface::declareVariable(string const& _name, Sort const& _sort) { - // TODO Use domain and codomain as key as well - string domain(""); - for (auto const& sort: _domain) - domain += toSmtLibSort(*sort) + ' '; - if (!m_functions.count(_name)) + if (_sort.kind == Kind::Function) + declareFunction(_name, _sort); + else if (!m_variables.count(_name)) { - m_functions.insert(_name); + m_variables.insert(_name); + write("(declare-fun |" + _name + "| () " + toSmtLibSort(_sort) + ')'); + } +} + +void SMTLib2Interface::declareFunction(string const& _name, Sort const& _sort) +{ + solAssert(_sort.kind == smt::Kind::Function, ""); + // TODO Use domain and codomain as key as well + if (!m_variables.count(_name)) + { + FunctionSort fSort = dynamic_cast(_sort); + string domain = toSmtLibSort(fSort.domain); + string codomain = toSmtLibSort(*fSort.codomain); + m_variables.insert(_name); write( "(declare-fun |" + _name + - "| (" + + "| " + domain + - ") " + - (_codomain.kind == Kind::Int ? "Int" : "Bool") + + " " + + codomain + ")" ); } } -void SMTLib2Interface::declareInteger(string _name) -{ - if (!m_constants.count(_name)) - { - m_constants.insert(_name); - write("(declare-const |" + _name + "| Int)"); - } -} - -void SMTLib2Interface::declareBool(string _name) -{ - if (!m_constants.count(_name)) - { - m_constants.insert(_name); - write("(declare-const |" + _name + "| Bool)"); - } -} - void SMTLib2Interface::addAssertion(Expression const& _expr) { write("(assert " + toSExpr(_expr) + ")"); @@ -156,6 +149,15 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort) } } +string SMTLib2Interface::toSmtLibSort(vector const& _sorts) +{ + string ssort("("); + for (auto const& sort: _sorts) + ssort += toSmtLibSort(*sort) + " "; + ssort += ")"; + return ssort; +} + void SMTLib2Interface::write(string _data) { solAssert(!m_accumulatedOutput.empty(), ""); diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index f3c58d6b5..4f72d27c4 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -49,16 +49,17 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; - void declareInteger(std::string _name) override; - void declareBool(std::string _name) override; + void declareVariable(std::string const&, Sort const&) override; void addAssertion(Expression const& _expr) override; std::pair> check(std::vector const& _expressionsToEvaluate) override; private: + void declareFunction(std::string const&, Sort const&); + std::string toSExpr(Expression const& _expr); std::string toSmtLibSort(Sort const& _sort); + std::string toSmtLibSort(std::vector const& _sort); void write(std::string _data); @@ -70,8 +71,7 @@ private: ReadCallback::Callback m_queryCallback; std::vector m_accumulatedOutput; - std::set m_constants; - std::set m_functions; + std::set m_variables; }; } diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index e01a5accf..224e5cd61 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -64,22 +64,10 @@ void SMTPortfolio::pop() s->pop(); } -void SMTPortfolio::declareFunction(string _name, vector const& _domain, Sort const& _codomain) +void SMTPortfolio::declareVariable(string const& _name, Sort const& _sort) { for (auto s : m_solvers) - s->declareFunction(_name, _domain, _codomain); -} - -void SMTPortfolio::declareInteger(string _name) -{ - for (auto s : m_solvers) - s->declareInteger(_name); -} - -void SMTPortfolio::declareBool(string _name) -{ - for (auto s : m_solvers) - s->declareBool(_name); + s->declareVariable(_name, _sort); } void SMTPortfolio::addAssertion(Expression const& _expr) diff --git a/libsolidity/formal/SMTPortfolio.h b/libsolidity/formal/SMTPortfolio.h index 712fb545c..12e2be669 100644 --- a/libsolidity/formal/SMTPortfolio.h +++ b/libsolidity/formal/SMTPortfolio.h @@ -49,9 +49,7 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; - void declareInteger(std::string _name) override; - void declareBool(std::string _name) override; + void declareVariable(std::string const&, Sort const&) override; void addAssertion(Expression const& _expr) override; std::pair> check(std::vector const& _expressionsToEvaluate) override; diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index df0361905..551ef8e92 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -45,7 +45,8 @@ enum class CheckResult enum class Kind { Int, - Bool + Bool, + Function }; struct Sort @@ -58,6 +59,25 @@ struct Sort }; using SortPointer = std::shared_ptr; +struct FunctionSort: public Sort +{ + FunctionSort(std::vector _domain, SortPointer _codomain): + Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {} + std::vector domain; + SortPointer codomain; + bool operator==(FunctionSort const& _other) const + { + if (!std::equal( + domain.begin(), + domain.end(), + _other.domain.begin(), + [&](SortPointer _a, SortPointer _b) { return *_a == *_b; } + ) + ) + return false; + return Sort::operator==(_other) && *codomain == *_other.codomain; + } +}; /// C++ representation of an SMTLIB2 expression. class Expression @@ -162,10 +182,12 @@ public: Expression operator()(std::vector _arguments) const { solAssert( - arguments.empty(), + sort->kind == Kind::Function, "Attempted function application to non-function." ); - return Expression(name, std::move(_arguments), sort); + auto fSort = dynamic_cast(sort.get()); + solAssert(fSort, ""); + return Expression(name, std::move(_arguments), fSort->codomain); } std::string name; @@ -198,26 +220,12 @@ public: virtual void push() = 0; virtual void pop() = 0; - virtual void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) = 0; - Expression newFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) - { - declareFunction(_name, _domain, _codomain); - // Subclasses should do something here - return Expression(std::move(_name), {}, _codomain.kind); - } - virtual void declareInteger(std::string _name) = 0; - Expression newInteger(std::string _name) + virtual void declareVariable(std::string const& _name, Sort const& _sort) = 0; + Expression newVariable(std::string _name, SortPointer _sort) { // Subclasses should do something here - declareInteger(_name); - return Expression(std::move(_name), {}, Kind::Int); - } - virtual void declareBool(std::string _name) = 0; - Expression newBool(std::string _name) - { - // Subclasses should do something here - declareBool(_name); - return Expression(std::move(_name), {}, Kind::Bool); + declareVariable(_name, *_sort); + return Expression(std::move(_name), {}, std::move(_sort)); } virtual void addAssertion(Expression const& _expr) = 0; diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index a3b6e3a8b..2d0107c55 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -32,10 +32,29 @@ smt::SortPointer dev::solidity::smtSort(Type const& _type) return make_shared(smt::Kind::Int); case smt::Kind::Bool: return make_shared(smt::Kind::Bool); + case smt::Kind::Function: + { + auto fType = dynamic_cast(&_type); + solAssert(fType, ""); + vector parameterSorts = smtSort(fType->parameterTypes()); + auto returnTypes = fType->returnParameterTypes(); + // TODO remove this when we support tuples. + solAssert(returnTypes.size() == 1, ""); + smt::SortPointer returnSort = smtSort(*returnTypes.at(0)); + return make_shared(parameterSorts, returnSort); + } } solAssert(false, "Invalid type"); } +vector dev::solidity::smtSort(vector const& _types) +{ + vector sorts; + for (auto const& type: _types) + sorts.push_back(smtSort(*type)); + return sorts; +} + smt::Kind dev::solidity::smtKind(Type::Category _category) { if (isNumber(_category)) diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index c802c5b46..6af2a0a0d 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -30,6 +30,7 @@ namespace solidity /// Returns the SMT sort that models the Solidity type _type. smt::SortPointer smtSort(Type const& _type); +std::vector smtSort(std::vector const& _types); /// Returns the SMT kind that models the Solidity type type category _category. smt::Kind smtKind(Type::Category _category); diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 194c843ec..399e18f80 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -59,7 +59,7 @@ SymbolicBoolVariable::SymbolicBoolVariable( smt::Expression SymbolicBoolVariable::valueAtIndex(int _index) const { - return m_interface.newBool(uniqueSymbol(_index)); + return m_interface.newVariable(uniqueSymbol(_index), make_shared(smt::Kind::Bool)); } void SymbolicBoolVariable::setZeroValue() @@ -83,7 +83,7 @@ SymbolicIntVariable::SymbolicIntVariable( smt::Expression SymbolicIntVariable::valueAtIndex(int _index) const { - return m_interface.newInteger(uniqueSymbol(_index)); + return m_interface.newVariable(uniqueSymbol(_index), make_shared(smt::Kind::Int)); } void SymbolicIntVariable::setZeroValue() diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index ac6fbd541..162b0c237 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -51,22 +51,22 @@ void Z3Interface::pop() m_solver.pop(); } -void Z3Interface::declareFunction(string _name, vector const& _domain, Sort const& _codomain) +void Z3Interface::declareVariable(string const& _name, Sort const& _sort) { + if (_sort.kind == Kind::Function) + declareFunction(_name, _sort); + else if (!m_constants.count(_name)) + m_constants.insert({_name, m_context.constant(_name.c_str(), z3Sort(_sort))}); +} + +void Z3Interface::declareFunction(string const& _name, Sort const& _sort) +{ + solAssert(_sort.kind == smt::Kind::Function, ""); if (!m_functions.count(_name)) - m_functions.insert({_name, m_context.function(_name.c_str(), z3Sort(_domain), z3Sort(_codomain))}); -} - -void Z3Interface::declareInteger(string _name) -{ - if (!m_constants.count(_name)) - m_constants.insert({_name, m_context.int_const(_name.c_str())}); -} - -void Z3Interface::declareBool(string _name) -{ - if (!m_constants.count(_name)) - m_constants.insert({_name, m_context.bool_const(_name.c_str())}); + { + FunctionSort fSort = dynamic_cast(_sort); + m_functions.insert({_name, m_context.function(_name.c_str(), z3Sort(fSort.domain), z3Sort(*fSort.codomain))}); + } } void Z3Interface::addAssertion(Expression const& _expr) diff --git a/libsolidity/formal/Z3Interface.h b/libsolidity/formal/Z3Interface.h index 8c1fcf614..86e1badd1 100644 --- a/libsolidity/formal/Z3Interface.h +++ b/libsolidity/formal/Z3Interface.h @@ -40,14 +40,14 @@ public: void push() override; void pop() override; - void declareFunction(std::string _name, std::vector const& _domain, Sort const& _codomain) override; - void declareInteger(std::string _name) override; - void declareBool(std::string _name) override; + void declareVariable(std::string const& _name, Sort const& _sort) override; void addAssertion(Expression const& _expr) override; std::pair> check(std::vector const& _expressionsToEvaluate) override; private: + void declareFunction(std::string const& _name, Sort const& _sort); + z3::expr toZ3Expr(Expression const& _expr); z3::sort z3Sort(smt::Sort const& _sort); z3::sort_vector z3Sort(std::vector const& _sorts); From 20accf1a90e6b3dd077c67e6d31d1c56fedad5f5 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Thu, 22 Nov 2018 11:24:12 +0100 Subject: [PATCH 045/168] [SMTChecker] Add ArraySort and array operations --- libsolidity/formal/CVC4Interface.cpp | 9 +++++ libsolidity/formal/SMTLib2Interface.cpp | 5 +++ libsolidity/formal/SolverInterface.h | 51 ++++++++++++++++++++++++- libsolidity/formal/SymbolicTypes.cpp | 4 ++ libsolidity/formal/Z3Interface.cpp | 9 +++++ 5 files changed, 76 insertions(+), 2 deletions(-) diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index cff1717ff..de5e4430c 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -164,6 +164,10 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr) return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]); else if (n == "/") return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]); + else if (n == "select") + return m_context.mkExpr(CVC4::kind::SELECT, arguments[0], arguments[1]); + else if (n == "store") + return m_context.mkExpr(CVC4::kind::STORE, arguments[0], arguments[1], arguments[2]); // Cannot reach here. solAssert(false, ""); return arguments[0]; @@ -182,6 +186,11 @@ CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort) FunctionSort const& fSort = dynamic_cast(_sort); return m_context.mkFunctionType(cvc4Sort(fSort.domain), cvc4Sort(*fSort.codomain)); } + case Kind::Array: + { + auto const& arraySort = dynamic_cast(_sort); + return m_context.mkArrayType(cvc4Sort(*arraySort.domain), cvc4Sort(*arraySort.range)); + } default: break; } diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index bb85860f0..55c72cfc3 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -144,6 +144,11 @@ string SMTLib2Interface::toSmtLibSort(Sort const& _sort) return "Int"; case Kind::Bool: return "Bool"; + case Kind::Array: + { + auto const& arraySort = dynamic_cast(_sort); + return "(Array " + toSmtLibSort(*arraySort.domain) + ' ' + toSmtLibSort(*arraySort.range) + ')'; + } default: solAssert(false, "Invalid SMT sort"); } diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index 551ef8e92..17e6904c7 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -46,7 +46,8 @@ enum class Kind { Int, Bool, - Function + Function, + Array }; struct Sort @@ -79,6 +80,20 @@ struct FunctionSort: public Sort } }; +struct ArraySort: public Sort +{ + /// _domain is the sort of the indices + /// _range is the sort of the values + ArraySort(SortPointer _domain, SortPointer _range): + Sort(Kind::Array), domain(std::move(_domain)), range(std::move(_range)) {} + SortPointer domain; + SortPointer range; + bool operator==(ArraySort const& _other) const + { + return Sort::operator==(_other) && *domain == *_other.domain && *range == *_other.range; + } +}; + /// C++ representation of an SMTLIB2 expression. class Expression { @@ -109,7 +124,9 @@ public: {"+", 2}, {"-", 2}, {"*", 2}, - {"/", 2} + {"/", 2}, + {"select", 2}, + {"store", 3} }; return operatorsArity.count(name) && operatorsArity.at(name) == arguments.size(); } @@ -127,6 +144,36 @@ public: return !std::move(_a) || std::move(_b); } + /// select is the SMT representation of an array index access. + static Expression select(Expression _array, Expression _index) + { + solAssert(_array.sort->kind == Kind::Array, ""); + auto const& arraySort = dynamic_cast(_array.sort.get()); + solAssert(arraySort, ""); + solAssert(*arraySort->domain == *_index.sort, ""); + return Expression( + "select", + std::vector{std::move(_array), std::move(_index)}, + arraySort->range + ); + } + + /// store is the SMT representation of an assignment to array index. + /// The function is pure and returns the modified array. + static Expression store(Expression _array, Expression _index, Expression _element) + { + solAssert(_array.sort->kind == Kind::Array, ""); + auto const& arraySort = dynamic_cast(_array.sort.get()); + solAssert(arraySort, ""); + solAssert(*arraySort->domain == *_index.sort, ""); + solAssert(*arraySort->range == *_element.sort, ""); + return Expression( + "store", + std::vector{std::move(_array), std::move(_index), std::move(_element)}, + _array.sort + ); + } + friend Expression operator!(Expression _a) { return Expression("not", std::move(_a), Kind::Bool); diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 2d0107c55..a12ab142b 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -43,6 +43,10 @@ smt::SortPointer dev::solidity::smtSort(Type const& _type) smt::SortPointer returnSort = smtSort(*returnTypes.at(0)); return make_shared(parameterSorts, returnSort); } + case smt::Kind::Array: + { + solUnimplementedAssert(false, "Invalid type"); + } } solAssert(false, "Invalid type"); } diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index 162b0c237..cb01dc618 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -163,6 +163,10 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) return arguments[0] * arguments[1]; else if (n == "/") return arguments[0] / arguments[1]; + else if (n == "select") + return z3::select(arguments[0], arguments[1]); + else if (n == "store") + return z3::store(arguments[0], arguments[1], arguments[2]); // Cannot reach here. solAssert(false, ""); return arguments[0]; @@ -176,6 +180,11 @@ z3::sort Z3Interface::z3Sort(Sort const& _sort) return m_context.bool_sort(); case Kind::Int: return m_context.int_sort(); + case Kind::Array: + { + auto const& arraySort = dynamic_cast(_sort); + return m_context.array_sort(z3Sort(*arraySort.domain), z3Sort(*arraySort.range)); + } default: break; } From 636da48e82f64224a8611dabad1b8a1a019fcfd4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 1 Aug 2018 22:37:46 +0100 Subject: [PATCH 046/168] Move most of SMTChecker tests from C++ to isoltest But keep divison in C++ because results differ between different solvers --- test/libsolidity/SMTChecker.cpp | 593 ------------------ .../smtCheckerTests/001_smoke.test.sol | 3 + .../smtCheckerTests/002_simple_overflow.sol | 6 + .../smtCheckerTests/003_warn_on_typecast.sol | 8 + .../smtCheckerTests/004_warn_on_struct.sol | 12 + .../smtCheckerTests/005_simple_assert.sol | 6 + .../006_simple_assert_with_require.sol | 4 + .../007_assignment_in_declaration.sol | 4 + ...unction_call_does_not_clear_local_vars.sol | 13 + .../009_branches_merge_variables.sol | 10 + .../010_branches_merge_variables.sol | 11 + .../011_branches_merge_variables.sol | 12 + .../012_branches_merge_variables.sol | 13 + .../013_branches_merge_variables.sol | 13 + .../014_branches_merge_variables.sol | 13 + .../015_branches_assert_condition.sol | 12 + .../016_branches_assert_condition.sol | 16 + .../017_ways_to_merge_variables.sol | 12 + .../018_ways_to_merge_variables.sol | 12 + .../019_ways_to_merge_variables.sol | 12 + .../smtCheckerTests/020_bool_simple.sol | 8 + .../smtCheckerTests/021_bool_simple.sol | 8 + .../smtCheckerTests/022_bool_simple.sol | 7 + .../smtCheckerTests/023_bool_simple.sol | 10 + .../smtCheckerTests/024_bool_simple.sol | 7 + .../smtCheckerTests/025_bool_simple.sol | 9 + .../smtCheckerTests/026_bool_int_mixed.sol | 9 + .../smtCheckerTests/027_bool_int_mixed.sol | 8 + .../smtCheckerTests/028_bool_int_mixed.sol | 21 + .../029_storage_value_vars.sol | 22 + .../030_storage_value_vars.sol | 12 + .../031_storage_value_vars.sol | 25 + .../032_storage_value_vars.sol | 10 + .../smtCheckerTests/033_while_loop_simple.sol | 13 + .../smtCheckerTests/034_while_loop_simple.sol | 9 + .../smtCheckerTests/035_while_loop_simple.sol | 11 + .../smtCheckerTests/036_while_loop_simple.sol | 11 + .../smtCheckerTests/037_while_loop_simple.sol | 12 + .../038_constant_condition.sol | 9 + .../039_constant_condition.sol | 9 + .../040_constant_condition.sol | 9 + .../smtCheckerTests/041_for_loop.sol | 8 + .../smtCheckerTests/042_for_loop.sol | 8 + .../smtCheckerTests/043_for_loop.sol | 8 + .../smtCheckerTests/044_for_loop.sol | 10 + .../smtCheckerTests/045_for_loop.sol | 12 + .../smtCheckerTests/046_for_loop.sol | 12 + 47 files changed, 489 insertions(+), 593 deletions(-) create mode 100644 test/libsolidity/smtCheckerTests/001_smoke.test.sol create mode 100644 test/libsolidity/smtCheckerTests/002_simple_overflow.sol create mode 100644 test/libsolidity/smtCheckerTests/003_warn_on_typecast.sol create mode 100644 test/libsolidity/smtCheckerTests/004_warn_on_struct.sol create mode 100644 test/libsolidity/smtCheckerTests/005_simple_assert.sol create mode 100644 test/libsolidity/smtCheckerTests/006_simple_assert_with_require.sol create mode 100644 test/libsolidity/smtCheckerTests/007_assignment_in_declaration.sol create mode 100644 test/libsolidity/smtCheckerTests/008_function_call_does_not_clear_local_vars.sol create mode 100644 test/libsolidity/smtCheckerTests/009_branches_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/010_branches_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/011_branches_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/012_branches_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/013_branches_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/014_branches_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/015_branches_assert_condition.sol create mode 100644 test/libsolidity/smtCheckerTests/016_branches_assert_condition.sol create mode 100644 test/libsolidity/smtCheckerTests/017_ways_to_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/018_ways_to_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/019_ways_to_merge_variables.sol create mode 100644 test/libsolidity/smtCheckerTests/020_bool_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/021_bool_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/022_bool_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/023_bool_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/024_bool_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/025_bool_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/026_bool_int_mixed.sol create mode 100644 test/libsolidity/smtCheckerTests/027_bool_int_mixed.sol create mode 100644 test/libsolidity/smtCheckerTests/028_bool_int_mixed.sol create mode 100644 test/libsolidity/smtCheckerTests/029_storage_value_vars.sol create mode 100644 test/libsolidity/smtCheckerTests/030_storage_value_vars.sol create mode 100644 test/libsolidity/smtCheckerTests/031_storage_value_vars.sol create mode 100644 test/libsolidity/smtCheckerTests/032_storage_value_vars.sol create mode 100644 test/libsolidity/smtCheckerTests/033_while_loop_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/034_while_loop_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/035_while_loop_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/036_while_loop_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/037_while_loop_simple.sol create mode 100644 test/libsolidity/smtCheckerTests/038_constant_condition.sol create mode 100644 test/libsolidity/smtCheckerTests/039_constant_condition.sol create mode 100644 test/libsolidity/smtCheckerTests/040_constant_condition.sol create mode 100644 test/libsolidity/smtCheckerTests/041_for_loop.sol create mode 100644 test/libsolidity/smtCheckerTests/042_for_loop.sol create mode 100644 test/libsolidity/smtCheckerTests/043_for_loop.sol create mode 100644 test/libsolidity/smtCheckerTests/044_for_loop.sol create mode 100644 test/libsolidity/smtCheckerTests/045_for_loop.sol create mode 100644 test/libsolidity/smtCheckerTests/046_for_loop.sol diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 13fcc5b43..a49618bd1 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -56,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{ - "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{ - "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{ - "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/smtCheckerTests/001_smoke.test.sol b/test/libsolidity/smtCheckerTests/001_smoke.test.sol new file mode 100644 index 000000000..8b7b77da6 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/001_smoke.test.sol @@ -0,0 +1,3 @@ +pragma experimental SMTChecker; +contract C { +} diff --git a/test/libsolidity/smtCheckerTests/002_simple_overflow.sol b/test/libsolidity/smtCheckerTests/002_simple_overflow.sol new file mode 100644 index 000000000..894ff1a46 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/002_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/003_warn_on_typecast.sol b/test/libsolidity/smtCheckerTests/003_warn_on_typecast.sol new file mode 100644 index 000000000..be7854146 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/003_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/004_warn_on_struct.sol b/test/libsolidity/smtCheckerTests/004_warn_on_struct.sol new file mode 100644 index 000000000..c50df07a3 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/004_warn_on_struct.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +pragma experimental ABIEncoderV2; +contract C { + struct A { uint a; uint b; } + function f() public pure returns (A memory) { + return A({ a: 1, b: 2 }); + } +} +// ---- +// Warning: (32-65): Experimental features are turned on. Do not use experimental features on live deployments. +// Warning: (150-158): Assertion checker does not yet support the type of this variable. +// Warning: (177-194): Assertion checker does not yet implement this expression. diff --git a/test/libsolidity/smtCheckerTests/005_simple_assert.sol b/test/libsolidity/smtCheckerTests/005_simple_assert.sol new file mode 100644 index 000000000..8bd6e61a6 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/005_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/006_simple_assert_with_require.sol b/test/libsolidity/smtCheckerTests/006_simple_assert_with_require.sol new file mode 100644 index 000000000..b66ae2457 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/006_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/smtCheckerTests/007_assignment_in_declaration.sol b/test/libsolidity/smtCheckerTests/007_assignment_in_declaration.sol new file mode 100644 index 000000000..0c701672d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/007_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/008_function_call_does_not_clear_local_vars.sol b/test/libsolidity/smtCheckerTests/008_function_call_does_not_clear_local_vars.sol new file mode 100644 index 000000000..b42602240 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/008_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/009_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/009_branches_merge_variables.sol new file mode 100644 index 000000000..f93e32e41 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/009_branches_merge_variables.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/010_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/010_branches_merge_variables.sol new file mode 100644 index 000000000..c00ef787a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/010_branches_merge_variables.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/011_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/011_branches_merge_variables.sol new file mode 100644 index 000000000..4e18aa881 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/011_branches_merge_variables.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/012_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/012_branches_merge_variables.sol new file mode 100644 index 000000000..e3a027044 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/012_branches_merge_variables.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/013_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/013_branches_merge_variables.sol new file mode 100644 index 000000000..0bd1cf3a0 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/013_branches_merge_variables.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/014_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/014_branches_merge_variables.sol new file mode 100644 index 000000000..8e4771792 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/014_branches_merge_variables.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/015_branches_assert_condition.sol b/test/libsolidity/smtCheckerTests/015_branches_assert_condition.sol new file mode 100644 index 000000000..64f6e0121 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/015_branches_assert_condition.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/016_branches_assert_condition.sol b/test/libsolidity/smtCheckerTests/016_branches_assert_condition.sol new file mode 100644 index 000000000..e39ab844a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/016_branches_assert_condition.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/017_ways_to_merge_variables.sol b/test/libsolidity/smtCheckerTests/017_ways_to_merge_variables.sol new file mode 100644 index 000000000..16d6fdfef --- /dev/null +++ b/test/libsolidity/smtCheckerTests/017_ways_to_merge_variables.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/018_ways_to_merge_variables.sol b/test/libsolidity/smtCheckerTests/018_ways_to_merge_variables.sol new file mode 100644 index 000000000..e25ab20f7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/018_ways_to_merge_variables.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/019_ways_to_merge_variables.sol b/test/libsolidity/smtCheckerTests/019_ways_to_merge_variables.sol new file mode 100644 index 000000000..03ae7216d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/019_ways_to_merge_variables.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/020_bool_simple.sol b/test/libsolidity/smtCheckerTests/020_bool_simple.sol new file mode 100644 index 000000000..76b4b08b8 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/020_bool_simple.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/021_bool_simple.sol b/test/libsolidity/smtCheckerTests/021_bool_simple.sol new file mode 100644 index 000000000..5c166c022 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/021_bool_simple.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/022_bool_simple.sol b/test/libsolidity/smtCheckerTests/022_bool_simple.sol new file mode 100644 index 000000000..1d2ab49f7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/022_bool_simple.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/023_bool_simple.sol b/test/libsolidity/smtCheckerTests/023_bool_simple.sol new file mode 100644 index 000000000..c40404a43 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/023_bool_simple.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/024_bool_simple.sol b/test/libsolidity/smtCheckerTests/024_bool_simple.sol new file mode 100644 index 000000000..4cecebbc7 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/024_bool_simple.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/025_bool_simple.sol b/test/libsolidity/smtCheckerTests/025_bool_simple.sol new file mode 100644 index 000000000..90350bb64 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/025_bool_simple.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/026_bool_int_mixed.sol b/test/libsolidity/smtCheckerTests/026_bool_int_mixed.sol new file mode 100644 index 000000000..d611cc177 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/026_bool_int_mixed.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/027_bool_int_mixed.sol b/test/libsolidity/smtCheckerTests/027_bool_int_mixed.sol new file mode 100644 index 000000000..24640c5a8 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/027_bool_int_mixed.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/028_bool_int_mixed.sol b/test/libsolidity/smtCheckerTests/028_bool_int_mixed.sol new file mode 100644 index 000000000..f872e82ff --- /dev/null +++ b/test/libsolidity/smtCheckerTests/028_bool_int_mixed.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/029_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/029_storage_value_vars.sol new file mode 100644 index 000000000..84f6c77e4 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/029_storage_value_vars.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/030_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/030_storage_value_vars.sol new file mode 100644 index 000000000..bceddb380 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/030_storage_value_vars.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/031_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/031_storage_value_vars.sol new file mode 100644 index 000000000..39049b99e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/031_storage_value_vars.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/032_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/032_storage_value_vars.sol new file mode 100644 index 000000000..88b6b0aea --- /dev/null +++ b/test/libsolidity/smtCheckerTests/032_storage_value_vars.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/033_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/033_while_loop_simple.sol new file mode 100644 index 000000000..074be86f4 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/033_while_loop_simple.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/034_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/034_while_loop_simple.sol new file mode 100644 index 000000000..92a3f0fed --- /dev/null +++ b/test/libsolidity/smtCheckerTests/034_while_loop_simple.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/035_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/035_while_loop_simple.sol new file mode 100644 index 000000000..a37df888b --- /dev/null +++ b/test/libsolidity/smtCheckerTests/035_while_loop_simple.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/036_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/036_while_loop_simple.sol new file mode 100644 index 000000000..f71da8650 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/036_while_loop_simple.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/037_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/037_while_loop_simple.sol new file mode 100644 index 000000000..41559c99e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/037_while_loop_simple.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/038_constant_condition.sol b/test/libsolidity/smtCheckerTests/038_constant_condition.sol new file mode 100644 index 000000000..b9fae4ee0 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/038_constant_condition.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/039_constant_condition.sol b/test/libsolidity/smtCheckerTests/039_constant_condition.sol new file mode 100644 index 000000000..aaa613eab --- /dev/null +++ b/test/libsolidity/smtCheckerTests/039_constant_condition.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/040_constant_condition.sol b/test/libsolidity/smtCheckerTests/040_constant_condition.sol new file mode 100644 index 000000000..f22cd65e5 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/040_constant_condition.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/041_for_loop.sol b/test/libsolidity/smtCheckerTests/041_for_loop.sol new file mode 100644 index 000000000..8988efadb --- /dev/null +++ b/test/libsolidity/smtCheckerTests/041_for_loop.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/042_for_loop.sol b/test/libsolidity/smtCheckerTests/042_for_loop.sol new file mode 100644 index 000000000..58c9f3a78 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/042_for_loop.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/043_for_loop.sol b/test/libsolidity/smtCheckerTests/043_for_loop.sol new file mode 100644 index 000000000..8bf9bdc7e --- /dev/null +++ b/test/libsolidity/smtCheckerTests/043_for_loop.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/044_for_loop.sol b/test/libsolidity/smtCheckerTests/044_for_loop.sol new file mode 100644 index 000000000..4d082026d --- /dev/null +++ b/test/libsolidity/smtCheckerTests/044_for_loop.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/045_for_loop.sol b/test/libsolidity/smtCheckerTests/045_for_loop.sol new file mode 100644 index 000000000..2c84960fc --- /dev/null +++ b/test/libsolidity/smtCheckerTests/045_for_loop.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/046_for_loop.sol b/test/libsolidity/smtCheckerTests/046_for_loop.sol new file mode 100644 index 000000000..90c4c3287 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/046_for_loop.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(). From 109cfcef6902c0c3550e6e56b328183386c69c67 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 2 Aug 2018 03:25:22 +0100 Subject: [PATCH 047/168] Drop numbering in front of the SMTChecker tests --- ...ssignment_in_declaration.sol => assignment_in_declaration.sol} | 0 .../{026_bool_int_mixed.sol => bool_int_mixed_1.sol} | 0 .../{027_bool_int_mixed.sol => bool_int_mixed_2.sol} | 0 .../{028_bool_int_mixed.sol => bool_int_mixed_3.sol} | 0 .../smtCheckerTests/{020_bool_simple.sol => bool_simple_1.sol} | 0 .../smtCheckerTests/{021_bool_simple.sol => bool_simple_2.sol} | 0 .../smtCheckerTests/{022_bool_simple.sol => bool_simple_3.sol} | 0 .../smtCheckerTests/{023_bool_simple.sol => bool_simple_4.sol} | 0 .../smtCheckerTests/{024_bool_simple.sol => bool_simple_5.sol} | 0 .../smtCheckerTests/{025_bool_simple.sol => bool_simple_6.sol} | 0 ...nches_assert_condition.sol => branches_assert_condition_1.sol} | 0 ...nches_assert_condition.sol => branches_assert_condition_2.sol} | 0 ...ranches_merge_variables.sol => branches_merge_variables_1.sol} | 0 ...ranches_merge_variables.sol => branches_merge_variables_2.sol} | 0 ...ranches_merge_variables.sol => branches_merge_variables_3.sol} | 0 ...ranches_merge_variables.sol => branches_merge_variables_4.sol} | 0 ...ranches_merge_variables.sol => branches_merge_variables_5.sol} | 0 ...ranches_merge_variables.sol => branches_merge_variables_6.sol} | 0 .../{038_constant_condition.sol => constant_condition_1.sol} | 0 .../{039_constant_condition.sol => constant_condition_2.sol} | 0 .../{040_constant_condition.sol => constant_condition_3.sol} | 0 .../smtCheckerTests/{041_for_loop.sol => for_loop_1.sol} | 0 .../smtCheckerTests/{042_for_loop.sol => for_loop_2.sol} | 0 .../smtCheckerTests/{043_for_loop.sol => for_loop_3.sol} | 0 .../smtCheckerTests/{044_for_loop.sol => for_loop_4.sol} | 0 .../smtCheckerTests/{045_for_loop.sol => for_loop_5.sol} | 0 .../smtCheckerTests/{046_for_loop.sol => for_loop_6.sol} | 0 ...local_vars.sol => function_call_does_not_clear_local_vars.sol} | 0 .../smtCheckerTests/{005_simple_assert.sol => simple_assert.sol} | 0 ...ple_assert_with_require.sol => simple_assert_with_require.sol} | 0 .../{002_simple_overflow.sol => simple_overflow.sol} | 0 .../smtCheckerTests/{001_smoke.test.sol => smoke_test.sol} | 0 .../{029_storage_value_vars.sol => storage_value_vars_1.sol} | 0 .../{030_storage_value_vars.sol => storage_value_vars_2.sol} | 0 .../{031_storage_value_vars.sol => storage_value_vars_3.sol} | 0 .../{032_storage_value_vars.sol => storage_value_vars_4.sol} | 0 .../{004_warn_on_struct.sol => warn_on_struct.sol} | 0 .../{003_warn_on_typecast.sol => warn_on_typecast.sol} | 0 ..._ways_to_merge_variables.sol => ways_to_merge_variables_1.sol} | 0 ..._ways_to_merge_variables.sol => ways_to_merge_variables_2.sol} | 0 ..._ways_to_merge_variables.sol => ways_to_merge_variables_3.sol} | 0 .../{033_while_loop_simple.sol => while_loop_simple_1.sol} | 0 .../{034_while_loop_simple.sol => while_loop_simple_2.sol} | 0 .../{035_while_loop_simple.sol => while_loop_simple_3.sol} | 0 .../{036_while_loop_simple.sol => while_loop_simple_4.sol} | 0 .../{037_while_loop_simple.sol => while_loop_simple_5.sol} | 0 46 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/smtCheckerTests/{007_assignment_in_declaration.sol => assignment_in_declaration.sol} (100%) rename test/libsolidity/smtCheckerTests/{026_bool_int_mixed.sol => bool_int_mixed_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{027_bool_int_mixed.sol => bool_int_mixed_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{028_bool_int_mixed.sol => bool_int_mixed_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{020_bool_simple.sol => bool_simple_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{021_bool_simple.sol => bool_simple_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{022_bool_simple.sol => bool_simple_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{023_bool_simple.sol => bool_simple_4.sol} (100%) rename test/libsolidity/smtCheckerTests/{024_bool_simple.sol => bool_simple_5.sol} (100%) rename test/libsolidity/smtCheckerTests/{025_bool_simple.sol => bool_simple_6.sol} (100%) rename test/libsolidity/smtCheckerTests/{015_branches_assert_condition.sol => branches_assert_condition_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{016_branches_assert_condition.sol => branches_assert_condition_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{009_branches_merge_variables.sol => branches_merge_variables_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{010_branches_merge_variables.sol => branches_merge_variables_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{011_branches_merge_variables.sol => branches_merge_variables_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{012_branches_merge_variables.sol => branches_merge_variables_4.sol} (100%) rename test/libsolidity/smtCheckerTests/{013_branches_merge_variables.sol => branches_merge_variables_5.sol} (100%) rename test/libsolidity/smtCheckerTests/{014_branches_merge_variables.sol => branches_merge_variables_6.sol} (100%) rename test/libsolidity/smtCheckerTests/{038_constant_condition.sol => constant_condition_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{039_constant_condition.sol => constant_condition_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{040_constant_condition.sol => constant_condition_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{041_for_loop.sol => for_loop_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{042_for_loop.sol => for_loop_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{043_for_loop.sol => for_loop_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{044_for_loop.sol => for_loop_4.sol} (100%) rename test/libsolidity/smtCheckerTests/{045_for_loop.sol => for_loop_5.sol} (100%) rename test/libsolidity/smtCheckerTests/{046_for_loop.sol => for_loop_6.sol} (100%) rename test/libsolidity/smtCheckerTests/{008_function_call_does_not_clear_local_vars.sol => function_call_does_not_clear_local_vars.sol} (100%) rename test/libsolidity/smtCheckerTests/{005_simple_assert.sol => simple_assert.sol} (100%) rename test/libsolidity/smtCheckerTests/{006_simple_assert_with_require.sol => simple_assert_with_require.sol} (100%) rename test/libsolidity/smtCheckerTests/{002_simple_overflow.sol => simple_overflow.sol} (100%) rename test/libsolidity/smtCheckerTests/{001_smoke.test.sol => smoke_test.sol} (100%) rename test/libsolidity/smtCheckerTests/{029_storage_value_vars.sol => storage_value_vars_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{030_storage_value_vars.sol => storage_value_vars_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{031_storage_value_vars.sol => storage_value_vars_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{032_storage_value_vars.sol => storage_value_vars_4.sol} (100%) rename test/libsolidity/smtCheckerTests/{004_warn_on_struct.sol => warn_on_struct.sol} (100%) rename test/libsolidity/smtCheckerTests/{003_warn_on_typecast.sol => warn_on_typecast.sol} (100%) rename test/libsolidity/smtCheckerTests/{017_ways_to_merge_variables.sol => ways_to_merge_variables_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{018_ways_to_merge_variables.sol => ways_to_merge_variables_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{019_ways_to_merge_variables.sol => ways_to_merge_variables_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{033_while_loop_simple.sol => while_loop_simple_1.sol} (100%) rename test/libsolidity/smtCheckerTests/{034_while_loop_simple.sol => while_loop_simple_2.sol} (100%) rename test/libsolidity/smtCheckerTests/{035_while_loop_simple.sol => while_loop_simple_3.sol} (100%) rename test/libsolidity/smtCheckerTests/{036_while_loop_simple.sol => while_loop_simple_4.sol} (100%) rename test/libsolidity/smtCheckerTests/{037_while_loop_simple.sol => while_loop_simple_5.sol} (100%) diff --git a/test/libsolidity/smtCheckerTests/007_assignment_in_declaration.sol b/test/libsolidity/smtCheckerTests/assignment_in_declaration.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/007_assignment_in_declaration.sol rename to test/libsolidity/smtCheckerTests/assignment_in_declaration.sol diff --git a/test/libsolidity/smtCheckerTests/026_bool_int_mixed.sol b/test/libsolidity/smtCheckerTests/bool_int_mixed_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/026_bool_int_mixed.sol rename to test/libsolidity/smtCheckerTests/bool_int_mixed_1.sol diff --git a/test/libsolidity/smtCheckerTests/027_bool_int_mixed.sol b/test/libsolidity/smtCheckerTests/bool_int_mixed_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/027_bool_int_mixed.sol rename to test/libsolidity/smtCheckerTests/bool_int_mixed_2.sol diff --git a/test/libsolidity/smtCheckerTests/028_bool_int_mixed.sol b/test/libsolidity/smtCheckerTests/bool_int_mixed_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/028_bool_int_mixed.sol rename to test/libsolidity/smtCheckerTests/bool_int_mixed_3.sol diff --git a/test/libsolidity/smtCheckerTests/020_bool_simple.sol b/test/libsolidity/smtCheckerTests/bool_simple_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/020_bool_simple.sol rename to test/libsolidity/smtCheckerTests/bool_simple_1.sol diff --git a/test/libsolidity/smtCheckerTests/021_bool_simple.sol b/test/libsolidity/smtCheckerTests/bool_simple_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/021_bool_simple.sol rename to test/libsolidity/smtCheckerTests/bool_simple_2.sol diff --git a/test/libsolidity/smtCheckerTests/022_bool_simple.sol b/test/libsolidity/smtCheckerTests/bool_simple_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/022_bool_simple.sol rename to test/libsolidity/smtCheckerTests/bool_simple_3.sol diff --git a/test/libsolidity/smtCheckerTests/023_bool_simple.sol b/test/libsolidity/smtCheckerTests/bool_simple_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/023_bool_simple.sol rename to test/libsolidity/smtCheckerTests/bool_simple_4.sol diff --git a/test/libsolidity/smtCheckerTests/024_bool_simple.sol b/test/libsolidity/smtCheckerTests/bool_simple_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/024_bool_simple.sol rename to test/libsolidity/smtCheckerTests/bool_simple_5.sol diff --git a/test/libsolidity/smtCheckerTests/025_bool_simple.sol b/test/libsolidity/smtCheckerTests/bool_simple_6.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/025_bool_simple.sol rename to test/libsolidity/smtCheckerTests/bool_simple_6.sol diff --git a/test/libsolidity/smtCheckerTests/015_branches_assert_condition.sol b/test/libsolidity/smtCheckerTests/branches_assert_condition_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/015_branches_assert_condition.sol rename to test/libsolidity/smtCheckerTests/branches_assert_condition_1.sol diff --git a/test/libsolidity/smtCheckerTests/016_branches_assert_condition.sol b/test/libsolidity/smtCheckerTests/branches_assert_condition_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/016_branches_assert_condition.sol rename to test/libsolidity/smtCheckerTests/branches_assert_condition_2.sol diff --git a/test/libsolidity/smtCheckerTests/009_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/branches_merge_variables_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/009_branches_merge_variables.sol rename to test/libsolidity/smtCheckerTests/branches_merge_variables_1.sol diff --git a/test/libsolidity/smtCheckerTests/010_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/branches_merge_variables_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/010_branches_merge_variables.sol rename to test/libsolidity/smtCheckerTests/branches_merge_variables_2.sol diff --git a/test/libsolidity/smtCheckerTests/011_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/branches_merge_variables_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/011_branches_merge_variables.sol rename to test/libsolidity/smtCheckerTests/branches_merge_variables_3.sol diff --git a/test/libsolidity/smtCheckerTests/012_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/branches_merge_variables_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/012_branches_merge_variables.sol rename to test/libsolidity/smtCheckerTests/branches_merge_variables_4.sol diff --git a/test/libsolidity/smtCheckerTests/013_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/branches_merge_variables_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/013_branches_merge_variables.sol rename to test/libsolidity/smtCheckerTests/branches_merge_variables_5.sol diff --git a/test/libsolidity/smtCheckerTests/014_branches_merge_variables.sol b/test/libsolidity/smtCheckerTests/branches_merge_variables_6.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/014_branches_merge_variables.sol rename to test/libsolidity/smtCheckerTests/branches_merge_variables_6.sol diff --git a/test/libsolidity/smtCheckerTests/038_constant_condition.sol b/test/libsolidity/smtCheckerTests/constant_condition_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/038_constant_condition.sol rename to test/libsolidity/smtCheckerTests/constant_condition_1.sol diff --git a/test/libsolidity/smtCheckerTests/039_constant_condition.sol b/test/libsolidity/smtCheckerTests/constant_condition_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/039_constant_condition.sol rename to test/libsolidity/smtCheckerTests/constant_condition_2.sol diff --git a/test/libsolidity/smtCheckerTests/040_constant_condition.sol b/test/libsolidity/smtCheckerTests/constant_condition_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/040_constant_condition.sol rename to test/libsolidity/smtCheckerTests/constant_condition_3.sol diff --git a/test/libsolidity/smtCheckerTests/041_for_loop.sol b/test/libsolidity/smtCheckerTests/for_loop_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/041_for_loop.sol rename to test/libsolidity/smtCheckerTests/for_loop_1.sol diff --git a/test/libsolidity/smtCheckerTests/042_for_loop.sol b/test/libsolidity/smtCheckerTests/for_loop_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/042_for_loop.sol rename to test/libsolidity/smtCheckerTests/for_loop_2.sol diff --git a/test/libsolidity/smtCheckerTests/043_for_loop.sol b/test/libsolidity/smtCheckerTests/for_loop_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/043_for_loop.sol rename to test/libsolidity/smtCheckerTests/for_loop_3.sol diff --git a/test/libsolidity/smtCheckerTests/044_for_loop.sol b/test/libsolidity/smtCheckerTests/for_loop_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/044_for_loop.sol rename to test/libsolidity/smtCheckerTests/for_loop_4.sol diff --git a/test/libsolidity/smtCheckerTests/045_for_loop.sol b/test/libsolidity/smtCheckerTests/for_loop_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/045_for_loop.sol rename to test/libsolidity/smtCheckerTests/for_loop_5.sol diff --git a/test/libsolidity/smtCheckerTests/046_for_loop.sol b/test/libsolidity/smtCheckerTests/for_loop_6.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/046_for_loop.sol rename to test/libsolidity/smtCheckerTests/for_loop_6.sol diff --git a/test/libsolidity/smtCheckerTests/008_function_call_does_not_clear_local_vars.sol b/test/libsolidity/smtCheckerTests/function_call_does_not_clear_local_vars.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/008_function_call_does_not_clear_local_vars.sol rename to test/libsolidity/smtCheckerTests/function_call_does_not_clear_local_vars.sol diff --git a/test/libsolidity/smtCheckerTests/005_simple_assert.sol b/test/libsolidity/smtCheckerTests/simple_assert.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/005_simple_assert.sol rename to test/libsolidity/smtCheckerTests/simple_assert.sol diff --git a/test/libsolidity/smtCheckerTests/006_simple_assert_with_require.sol b/test/libsolidity/smtCheckerTests/simple_assert_with_require.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/006_simple_assert_with_require.sol rename to test/libsolidity/smtCheckerTests/simple_assert_with_require.sol diff --git a/test/libsolidity/smtCheckerTests/002_simple_overflow.sol b/test/libsolidity/smtCheckerTests/simple_overflow.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/002_simple_overflow.sol rename to test/libsolidity/smtCheckerTests/simple_overflow.sol diff --git a/test/libsolidity/smtCheckerTests/001_smoke.test.sol b/test/libsolidity/smtCheckerTests/smoke_test.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/001_smoke.test.sol rename to test/libsolidity/smtCheckerTests/smoke_test.sol diff --git a/test/libsolidity/smtCheckerTests/029_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/storage_value_vars_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/029_storage_value_vars.sol rename to test/libsolidity/smtCheckerTests/storage_value_vars_1.sol diff --git a/test/libsolidity/smtCheckerTests/030_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/storage_value_vars_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/030_storage_value_vars.sol rename to test/libsolidity/smtCheckerTests/storage_value_vars_2.sol diff --git a/test/libsolidity/smtCheckerTests/031_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/storage_value_vars_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/031_storage_value_vars.sol rename to test/libsolidity/smtCheckerTests/storage_value_vars_3.sol diff --git a/test/libsolidity/smtCheckerTests/032_storage_value_vars.sol b/test/libsolidity/smtCheckerTests/storage_value_vars_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/032_storage_value_vars.sol rename to test/libsolidity/smtCheckerTests/storage_value_vars_4.sol diff --git a/test/libsolidity/smtCheckerTests/004_warn_on_struct.sol b/test/libsolidity/smtCheckerTests/warn_on_struct.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/004_warn_on_struct.sol rename to test/libsolidity/smtCheckerTests/warn_on_struct.sol diff --git a/test/libsolidity/smtCheckerTests/003_warn_on_typecast.sol b/test/libsolidity/smtCheckerTests/warn_on_typecast.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/003_warn_on_typecast.sol rename to test/libsolidity/smtCheckerTests/warn_on_typecast.sol diff --git a/test/libsolidity/smtCheckerTests/017_ways_to_merge_variables.sol b/test/libsolidity/smtCheckerTests/ways_to_merge_variables_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/017_ways_to_merge_variables.sol rename to test/libsolidity/smtCheckerTests/ways_to_merge_variables_1.sol diff --git a/test/libsolidity/smtCheckerTests/018_ways_to_merge_variables.sol b/test/libsolidity/smtCheckerTests/ways_to_merge_variables_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/018_ways_to_merge_variables.sol rename to test/libsolidity/smtCheckerTests/ways_to_merge_variables_2.sol diff --git a/test/libsolidity/smtCheckerTests/019_ways_to_merge_variables.sol b/test/libsolidity/smtCheckerTests/ways_to_merge_variables_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/019_ways_to_merge_variables.sol rename to test/libsolidity/smtCheckerTests/ways_to_merge_variables_3.sol diff --git a/test/libsolidity/smtCheckerTests/033_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/while_loop_simple_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/033_while_loop_simple.sol rename to test/libsolidity/smtCheckerTests/while_loop_simple_1.sol diff --git a/test/libsolidity/smtCheckerTests/034_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/while_loop_simple_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/034_while_loop_simple.sol rename to test/libsolidity/smtCheckerTests/while_loop_simple_2.sol diff --git a/test/libsolidity/smtCheckerTests/035_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/while_loop_simple_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/035_while_loop_simple.sol rename to test/libsolidity/smtCheckerTests/while_loop_simple_3.sol diff --git a/test/libsolidity/smtCheckerTests/036_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/while_loop_simple_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/036_while_loop_simple.sol rename to test/libsolidity/smtCheckerTests/while_loop_simple_4.sol diff --git a/test/libsolidity/smtCheckerTests/037_while_loop_simple.sol b/test/libsolidity/smtCheckerTests/while_loop_simple_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/037_while_loop_simple.sol rename to test/libsolidity/smtCheckerTests/while_loop_simple_5.sol From 4a71080ae575390a72421572396c37fd977b0115 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 14 Nov 2018 17:08:53 +0100 Subject: [PATCH 048/168] Remove pragma ABIEncoderV2 from smt test --- .../libsolidity/smtCheckerTests/warn_on_struct.sol | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/libsolidity/smtCheckerTests/warn_on_struct.sol b/test/libsolidity/smtCheckerTests/warn_on_struct.sol index c50df07a3..6d9afe7cd 100644 --- a/test/libsolidity/smtCheckerTests/warn_on_struct.sol +++ b/test/libsolidity/smtCheckerTests/warn_on_struct.sol @@ -1,12 +1,14 @@ pragma experimental SMTChecker; -pragma experimental ABIEncoderV2; + contract C { struct A { uint a; uint b; } - function f() public pure returns (A memory) { - return A({ a: 1, b: 2 }); + function f() public pure returns (uint) { + A memory a = A({ a: 1, b: 2 }); } } // ---- -// Warning: (32-65): Experimental features are turned on. Do not use experimental features on live deployments. -// Warning: (150-158): Assertion checker does not yet support the type of this variable. -// Warning: (177-194): Assertion checker does not yet implement this expression. +// 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. From 32fe4768a9f9a3872eec541c1e7b3f3c94c8428c Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 14 Nov 2018 17:14:07 +0100 Subject: [PATCH 049/168] Organize smt tests in subdirectories --- test/libsolidity/smtCheckerTests/{ => complex}/warn_on_struct.sol | 0 .../smtCheckerTests/{ => complex}/warn_on_typecast.sol | 0 .../{ => control_flow}/assignment_in_declaration.sol | 0 .../{ => control_flow}/branches_assert_condition_1.sol | 0 .../{ => control_flow}/branches_assert_condition_2.sol | 0 .../{ => control_flow}/branches_merge_variables_1.sol | 0 .../{ => control_flow}/branches_merge_variables_2.sol | 0 .../{ => control_flow}/branches_merge_variables_3.sol | 0 .../{ => control_flow}/branches_merge_variables_4.sol | 0 .../{ => control_flow}/branches_merge_variables_5.sol | 0 .../{ => control_flow}/branches_merge_variables_6.sol | 0 .../{ => control_flow}/ways_to_merge_variables_1.sol | 0 .../{ => control_flow}/ways_to_merge_variables_2.sol | 0 .../{ => control_flow}/ways_to_merge_variables_3.sol | 0 .../{ => functions}/function_call_does_not_clear_local_vars.sol | 0 test/libsolidity/smtCheckerTests/{ => loops}/for_loop_1.sol | 0 test/libsolidity/smtCheckerTests/{ => loops}/for_loop_2.sol | 0 test/libsolidity/smtCheckerTests/{ => loops}/for_loop_3.sol | 0 test/libsolidity/smtCheckerTests/{ => loops}/for_loop_4.sol | 0 test/libsolidity/smtCheckerTests/{ => loops}/for_loop_5.sol | 0 test/libsolidity/smtCheckerTests/{ => loops}/for_loop_6.sol | 0 .../smtCheckerTests/{ => loops}/while_loop_simple_1.sol | 0 .../smtCheckerTests/{ => loops}/while_loop_simple_2.sol | 0 .../smtCheckerTests/{ => loops}/while_loop_simple_3.sol | 0 .../smtCheckerTests/{ => loops}/while_loop_simple_4.sol | 0 .../smtCheckerTests/{ => loops}/while_loop_simple_5.sol | 0 .../smtCheckerTests/{ => overflow}/simple_overflow.sol | 0 test/libsolidity/smtCheckerTests/{ => simple}/smoke_test.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_int_mixed_1.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_int_mixed_2.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_int_mixed_3.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_simple_1.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_simple_2.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_simple_3.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_simple_4.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_simple_5.sol | 0 test/libsolidity/smtCheckerTests/{ => types}/bool_simple_6.sol | 0 .../smtCheckerTests/{ => types}/storage_value_vars_1.sol | 0 .../smtCheckerTests/{ => types}/storage_value_vars_2.sol | 0 .../smtCheckerTests/{ => types}/storage_value_vars_3.sol | 0 .../smtCheckerTests/{ => types}/storage_value_vars_4.sol | 0 .../{ => verification_target}/constant_condition_1.sol | 0 .../{ => verification_target}/constant_condition_2.sol | 0 .../{ => verification_target}/constant_condition_3.sol | 0 .../smtCheckerTests/{ => verification_target}/simple_assert.sol | 0 .../{ => verification_target}/simple_assert_with_require.sol | 0 46 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/smtCheckerTests/{ => complex}/warn_on_struct.sol (100%) rename test/libsolidity/smtCheckerTests/{ => complex}/warn_on_typecast.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/assignment_in_declaration.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_assert_condition_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_assert_condition_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_merge_variables_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_merge_variables_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_merge_variables_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_merge_variables_4.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_merge_variables_5.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/branches_merge_variables_6.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/ways_to_merge_variables_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/ways_to_merge_variables_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => control_flow}/ways_to_merge_variables_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => functions}/function_call_does_not_clear_local_vars.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/for_loop_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/for_loop_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/for_loop_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/for_loop_4.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/for_loop_5.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/for_loop_6.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/while_loop_simple_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/while_loop_simple_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/while_loop_simple_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/while_loop_simple_4.sol (100%) rename test/libsolidity/smtCheckerTests/{ => loops}/while_loop_simple_5.sol (100%) rename test/libsolidity/smtCheckerTests/{ => overflow}/simple_overflow.sol (100%) rename test/libsolidity/smtCheckerTests/{ => simple}/smoke_test.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_int_mixed_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_int_mixed_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_int_mixed_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_simple_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_simple_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_simple_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_simple_4.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_simple_5.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/bool_simple_6.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/storage_value_vars_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/storage_value_vars_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/storage_value_vars_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => types}/storage_value_vars_4.sol (100%) rename test/libsolidity/smtCheckerTests/{ => verification_target}/constant_condition_1.sol (100%) rename test/libsolidity/smtCheckerTests/{ => verification_target}/constant_condition_2.sol (100%) rename test/libsolidity/smtCheckerTests/{ => verification_target}/constant_condition_3.sol (100%) rename test/libsolidity/smtCheckerTests/{ => verification_target}/simple_assert.sol (100%) rename test/libsolidity/smtCheckerTests/{ => verification_target}/simple_assert_with_require.sol (100%) diff --git a/test/libsolidity/smtCheckerTests/warn_on_struct.sol b/test/libsolidity/smtCheckerTests/complex/warn_on_struct.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/warn_on_struct.sol rename to test/libsolidity/smtCheckerTests/complex/warn_on_struct.sol diff --git a/test/libsolidity/smtCheckerTests/warn_on_typecast.sol b/test/libsolidity/smtCheckerTests/complex/warn_on_typecast.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/warn_on_typecast.sol rename to test/libsolidity/smtCheckerTests/complex/warn_on_typecast.sol diff --git a/test/libsolidity/smtCheckerTests/assignment_in_declaration.sol b/test/libsolidity/smtCheckerTests/control_flow/assignment_in_declaration.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/assignment_in_declaration.sol rename to test/libsolidity/smtCheckerTests/control_flow/assignment_in_declaration.sol diff --git a/test/libsolidity/smtCheckerTests/branches_assert_condition_1.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_assert_condition_1.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_1.sol diff --git a/test/libsolidity/smtCheckerTests/branches_assert_condition_2.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_assert_condition_2.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_assert_condition_2.sol diff --git a/test/libsolidity/smtCheckerTests/branches_merge_variables_1.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_merge_variables_1.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_1.sol diff --git a/test/libsolidity/smtCheckerTests/branches_merge_variables_2.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_merge_variables_2.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_2.sol diff --git a/test/libsolidity/smtCheckerTests/branches_merge_variables_3.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_merge_variables_3.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_3.sol diff --git a/test/libsolidity/smtCheckerTests/branches_merge_variables_4.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_merge_variables_4.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_4.sol diff --git a/test/libsolidity/smtCheckerTests/branches_merge_variables_5.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_merge_variables_5.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_5.sol diff --git a/test/libsolidity/smtCheckerTests/branches_merge_variables_6.sol b/test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_6.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/branches_merge_variables_6.sol rename to test/libsolidity/smtCheckerTests/control_flow/branches_merge_variables_6.sol diff --git a/test/libsolidity/smtCheckerTests/ways_to_merge_variables_1.sol b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/ways_to_merge_variables_1.sol rename to test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_1.sol diff --git a/test/libsolidity/smtCheckerTests/ways_to_merge_variables_2.sol b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/ways_to_merge_variables_2.sol rename to test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_2.sol diff --git a/test/libsolidity/smtCheckerTests/ways_to_merge_variables_3.sol b/test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/ways_to_merge_variables_3.sol rename to test/libsolidity/smtCheckerTests/control_flow/ways_to_merge_variables_3.sol diff --git a/test/libsolidity/smtCheckerTests/function_call_does_not_clear_local_vars.sol b/test/libsolidity/smtCheckerTests/functions/function_call_does_not_clear_local_vars.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/function_call_does_not_clear_local_vars.sol rename to test/libsolidity/smtCheckerTests/functions/function_call_does_not_clear_local_vars.sol diff --git a/test/libsolidity/smtCheckerTests/for_loop_1.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/for_loop_1.sol rename to test/libsolidity/smtCheckerTests/loops/for_loop_1.sol diff --git a/test/libsolidity/smtCheckerTests/for_loop_2.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/for_loop_2.sol rename to test/libsolidity/smtCheckerTests/loops/for_loop_2.sol diff --git a/test/libsolidity/smtCheckerTests/for_loop_3.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/for_loop_3.sol rename to test/libsolidity/smtCheckerTests/loops/for_loop_3.sol diff --git a/test/libsolidity/smtCheckerTests/for_loop_4.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/for_loop_4.sol rename to test/libsolidity/smtCheckerTests/loops/for_loop_4.sol diff --git a/test/libsolidity/smtCheckerTests/for_loop_5.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/for_loop_5.sol rename to test/libsolidity/smtCheckerTests/loops/for_loop_5.sol diff --git a/test/libsolidity/smtCheckerTests/for_loop_6.sol b/test/libsolidity/smtCheckerTests/loops/for_loop_6.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/for_loop_6.sol rename to test/libsolidity/smtCheckerTests/loops/for_loop_6.sol diff --git a/test/libsolidity/smtCheckerTests/while_loop_simple_1.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/while_loop_simple_1.sol rename to test/libsolidity/smtCheckerTests/loops/while_loop_simple_1.sol diff --git a/test/libsolidity/smtCheckerTests/while_loop_simple_2.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/while_loop_simple_2.sol rename to test/libsolidity/smtCheckerTests/loops/while_loop_simple_2.sol diff --git a/test/libsolidity/smtCheckerTests/while_loop_simple_3.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/while_loop_simple_3.sol rename to test/libsolidity/smtCheckerTests/loops/while_loop_simple_3.sol diff --git a/test/libsolidity/smtCheckerTests/while_loop_simple_4.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/while_loop_simple_4.sol rename to test/libsolidity/smtCheckerTests/loops/while_loop_simple_4.sol diff --git a/test/libsolidity/smtCheckerTests/while_loop_simple_5.sol b/test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/while_loop_simple_5.sol rename to test/libsolidity/smtCheckerTests/loops/while_loop_simple_5.sol diff --git a/test/libsolidity/smtCheckerTests/simple_overflow.sol b/test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/simple_overflow.sol rename to test/libsolidity/smtCheckerTests/overflow/simple_overflow.sol diff --git a/test/libsolidity/smtCheckerTests/smoke_test.sol b/test/libsolidity/smtCheckerTests/simple/smoke_test.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/smoke_test.sol rename to test/libsolidity/smtCheckerTests/simple/smoke_test.sol diff --git a/test/libsolidity/smtCheckerTests/bool_int_mixed_1.sol b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_int_mixed_1.sol rename to test/libsolidity/smtCheckerTests/types/bool_int_mixed_1.sol diff --git a/test/libsolidity/smtCheckerTests/bool_int_mixed_2.sol b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_int_mixed_2.sol rename to test/libsolidity/smtCheckerTests/types/bool_int_mixed_2.sol diff --git a/test/libsolidity/smtCheckerTests/bool_int_mixed_3.sol b/test/libsolidity/smtCheckerTests/types/bool_int_mixed_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_int_mixed_3.sol rename to test/libsolidity/smtCheckerTests/types/bool_int_mixed_3.sol diff --git a/test/libsolidity/smtCheckerTests/bool_simple_1.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_simple_1.sol rename to test/libsolidity/smtCheckerTests/types/bool_simple_1.sol diff --git a/test/libsolidity/smtCheckerTests/bool_simple_2.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_simple_2.sol rename to test/libsolidity/smtCheckerTests/types/bool_simple_2.sol diff --git a/test/libsolidity/smtCheckerTests/bool_simple_3.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_simple_3.sol rename to test/libsolidity/smtCheckerTests/types/bool_simple_3.sol diff --git a/test/libsolidity/smtCheckerTests/bool_simple_4.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_simple_4.sol rename to test/libsolidity/smtCheckerTests/types/bool_simple_4.sol diff --git a/test/libsolidity/smtCheckerTests/bool_simple_5.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_5.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_simple_5.sol rename to test/libsolidity/smtCheckerTests/types/bool_simple_5.sol diff --git a/test/libsolidity/smtCheckerTests/bool_simple_6.sol b/test/libsolidity/smtCheckerTests/types/bool_simple_6.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/bool_simple_6.sol rename to test/libsolidity/smtCheckerTests/types/bool_simple_6.sol diff --git a/test/libsolidity/smtCheckerTests/storage_value_vars_1.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/storage_value_vars_1.sol rename to test/libsolidity/smtCheckerTests/types/storage_value_vars_1.sol diff --git a/test/libsolidity/smtCheckerTests/storage_value_vars_2.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/storage_value_vars_2.sol rename to test/libsolidity/smtCheckerTests/types/storage_value_vars_2.sol diff --git a/test/libsolidity/smtCheckerTests/storage_value_vars_3.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/storage_value_vars_3.sol rename to test/libsolidity/smtCheckerTests/types/storage_value_vars_3.sol diff --git a/test/libsolidity/smtCheckerTests/storage_value_vars_4.sol b/test/libsolidity/smtCheckerTests/types/storage_value_vars_4.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/storage_value_vars_4.sol rename to test/libsolidity/smtCheckerTests/types/storage_value_vars_4.sol diff --git a/test/libsolidity/smtCheckerTests/constant_condition_1.sol b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_1.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/constant_condition_1.sol rename to test/libsolidity/smtCheckerTests/verification_target/constant_condition_1.sol diff --git a/test/libsolidity/smtCheckerTests/constant_condition_2.sol b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_2.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/constant_condition_2.sol rename to test/libsolidity/smtCheckerTests/verification_target/constant_condition_2.sol diff --git a/test/libsolidity/smtCheckerTests/constant_condition_3.sol b/test/libsolidity/smtCheckerTests/verification_target/constant_condition_3.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/constant_condition_3.sol rename to test/libsolidity/smtCheckerTests/verification_target/constant_condition_3.sol diff --git a/test/libsolidity/smtCheckerTests/simple_assert.sol b/test/libsolidity/smtCheckerTests/verification_target/simple_assert.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/simple_assert.sol rename to test/libsolidity/smtCheckerTests/verification_target/simple_assert.sol diff --git a/test/libsolidity/smtCheckerTests/simple_assert_with_require.sol b/test/libsolidity/smtCheckerTests/verification_target/simple_assert_with_require.sol similarity index 100% rename from test/libsolidity/smtCheckerTests/simple_assert_with_require.sol rename to test/libsolidity/smtCheckerTests/verification_target/simple_assert_with_require.sol From 06189ae57f2f556f21499938fca8f9c0db82779e Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Mon, 19 Nov 2018 15:17:39 +0100 Subject: [PATCH 050/168] Add assert and tests for bound functions --- libsolidity/codegen/ExpressionCompiler.cpp | 3 +++ test/libsolidity/SolidityEndToEndTest.cpp | 19 +++++++++++++++++++ .../syntaxTests/bound/bound_all.sol | 10 ++++++++++ .../syntaxTests/bound/bound_call.sol | 7 +++++++ .../syntaxTests/bound/bound_no_call.sol | 7 +++++++ 5 files changed, 46 insertions(+) create mode 100644 test/libsolidity/syntaxTests/bound/bound_all.sol create mode 100644 test/libsolidity/syntaxTests/bound/bound_call.sol create mode 100644 test/libsolidity/syntaxTests/bound/bound_no_call.sol diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 57b513d23..b0d172864 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -529,6 +529,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { bool shortcutTaken = false; if (auto identifier = dynamic_cast(&_functionCall.expression())) + { + solAssert(!function.bound(), ""); if (auto functionDef = dynamic_cast(identifier->annotation().referencedDeclaration)) { // Do not directly visit the identifier, because this way, we can avoid @@ -537,6 +539,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().pushCombinedFunctionEntryLabel(m_context.resolveVirtualFunction(*functionDef), false); shortcutTaken = true; } + } if (!shortcutTaken) _functionCall.expression().accept(*this); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 041f29a8d..e591432a3 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -9388,6 +9388,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{{"L", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(7))); +} + BOOST_AUTO_TEST_CASE(bound_function_in_var) { char const* sourceCode = R"( diff --git a/test/libsolidity/syntaxTests/bound/bound_all.sol b/test/libsolidity/syntaxTests/bound/bound_all.sol new file mode 100644 index 000000000..29f55b880 --- /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 000000000..281f19b43 --- /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 000000000..dcb3c3c59 --- /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; + } +} From 9e964852cc1da9a30ba9ff995f5b9c5d10ea2d4a Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 14:41:07 +0100 Subject: [PATCH 051/168] Rename 'asMemberFunction' to widen its purpose. --- libsolidity/ast/Types.cpp | 8 ++++---- libsolidity/ast/Types.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 0eab75aaf..95f461ecd 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -443,7 +443,7 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition continue; seenFunctions.insert(function); FunctionType funType(*function, false); - if (auto fun = funType.asMemberFunction(true, true)) + if (auto fun = funType.asCallableFunction(true, true)) if (_type.isImplicitlyConvertibleTo(*fun->selfType())) members.push_back(MemberList::Member(function->name(), fun, function)); } @@ -1970,7 +1970,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con for (auto const& it: m_contract.interfaceFunctions()) members.push_back(MemberList::Member( it.second->declaration().name(), - it.second->asMemberFunction(m_contract.isLibrary()), + it.second->asCallableFunction(m_contract.isLibrary()), &it.second->declaration() )); } @@ -3059,7 +3059,7 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con ); } -FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) const +FunctionTypePointer FunctionType::asCallableFunction(bool _inLibrary, bool _bound) const { if (_bound && m_parameterTypes.empty()) return FunctionTypePointer(); @@ -3201,7 +3201,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current if (function->isVisibleAsLibraryMember()) members.push_back(MemberList::Member( function->name(), - FunctionType(*function).asMemberFunction(true), + FunctionType(*function).asCallableFunction(true), function )); if (isBase) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 482d6735a..3b3b2bdff 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1154,14 +1154,14 @@ public: /// of the parameters to false. TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const; - /// @returns a copy of this function type where all return parameters of dynamic size are - /// removed and the location of reference types is changed from CallData to Memory. - /// This is needed if external functions are called on other contracts, as they cannot return - /// dynamic values. + /// @returns a copy of this function type where the location of reference types is changed + /// from CallData to Memory. This is the type that would be used when the function is + /// called, as opposed to the parameter types that are available inside the function body. + /// Also supports variants to be used for library or bound calls. /// Returns empty shared pointer on a failure. Namely, if a bound function has no parameters. /// @param _inLibrary if true, uses DelegateCall as location. /// @param _bound if true, the arguments are placed as `arg1.functionName(arg2, ..., argn)`. - FunctionTypePointer asMemberFunction(bool _inLibrary, bool _bound = false) const; + FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const; private: static TypePointers parseElementaryTypeVector(strings const& _types); From 92ba8a95f6f1348c2bc71eea4b550a7f33b13ec7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 15:37:26 +0100 Subject: [PATCH 052/168] Make asCallableFunction to never fail and assert abount parameter size if bound instead. --- libsolidity/ast/Types.cpp | 13 +++++++------ libsolidity/ast/Types.h | 3 +-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 95f461ecd..102e43e9a 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -442,10 +442,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function)) continue; seenFunctions.insert(function); - FunctionType funType(*function, false); - if (auto fun = funType.asCallableFunction(true, true)) - if (_type.isImplicitlyConvertibleTo(*fun->selfType())) - members.push_back(MemberList::Member(function->name(), fun, function)); + if (function->parameters().empty()) + continue; + FunctionTypePointer fun = FunctionType(*function, false).asCallableFunction(true, true); + if (_type.isImplicitlyConvertibleTo(*fun->selfType())) + members.push_back(MemberList::Member(function->name(), fun, function)); } } return members; @@ -3061,8 +3062,8 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con FunctionTypePointer FunctionType::asCallableFunction(bool _inLibrary, bool _bound) const { - if (_bound && m_parameterTypes.empty()) - return FunctionTypePointer(); + if (_bound) + solAssert(!m_parameterTypes.empty(), ""); TypePointers parameterTypes; for (auto const& t: m_parameterTypes) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3b3b2bdff..953aa557d 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1158,9 +1158,8 @@ public: /// from CallData to Memory. This is the type that would be used when the function is /// called, as opposed to the parameter types that are available inside the function body. /// Also supports variants to be used for library or bound calls. - /// Returns empty shared pointer on a failure. Namely, if a bound function has no parameters. /// @param _inLibrary if true, uses DelegateCall as location. - /// @param _bound if true, the arguments are placed as `arg1.functionName(arg2, ..., argn)`. + /// @param _bound if true, the function type is set to be bound. FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const; private: From 62e801ed706b967f7bb878823ee4fff69dde9922 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 14:50:50 +0100 Subject: [PATCH 053/168] Use callable function for virtual resolution. --- libsolidity/codegen/CompilerContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 9e4f2882f..eb33f6889 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -415,7 +415,7 @@ FunctionDefinition const& CompilerContext::resolveVirtualFunction( if ( function->name() == name && !function->isConstructor() && - FunctionType(*function).hasEqualParameterTypes(functionType) + FunctionType(*function).asCallableFunction(false)->hasEqualParameterTypes(functionType) ) return *function; solAssert(false, "Super function " + name + " not found."); From 780990516b5285c74010c2791a13e01e668ed2dd Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 22 Nov 2018 11:33:58 +0000 Subject: [PATCH 054/168] Fix storebytecode.sh for bytecode comparison --- scripts/bytecodecompare/storebytecode.sh | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/bytecodecompare/storebytecode.sh b/scripts/bytecodecompare/storebytecode.sh index ccf6e60ea..b14b23d0e 100755 --- a/scripts/bytecodecompare/storebytecode.sh +++ b/scripts/bytecodecompare/storebytecode.sh @@ -58,7 +58,7 @@ for (var optimize of [false, true]) if (filename !== undefined) { var inputs = {} - inputs[filename] = fs.readFileSync(filename).toString() + inputs[filename] = { content: fs.readFileSync(filename).toString() } var input = { language: 'Solidity', sources: inputs, @@ -68,16 +68,22 @@ for (var optimize of [false, true]) } } var result = JSON.parse(compiler.compile(JSON.stringify(input))) - if (!('contracts' in result) || Object.keys(result['contracts']).length === 0) + if ( + !('contracts' in result) || + Object.keys(result['contracts']).length === 0 || + !result['contracts'][filename] || + Object.keys(result['contracts'][filename]).length === 0 + ) { + // NOTE: do not exit here because this may be run on source which cannot be compiled console.log(filename + ': ERROR') } else { - for (var contractName in result['contracts']) + for (var contractName in result['contracts'][filename]) { - console.log(contractName + ' ' + result['contracts'][contractName].evm.bytecode.object) - console.log(contractName + ' ' + result['contracts'][contractName].metadata) + console.log(contractName + ' ' + result['contracts'][filename][contractName].evm.bytecode.object) + console.log(contractName + ' ' + result['contracts'][filename][contractName].metadata) } } } From ec84a7dc9b7ed9cfd5b562ee570c6ad13bdfbeb7 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Thu, 22 Nov 2018 14:48:31 +0100 Subject: [PATCH 055/168] [SMTChecker] Refactor setZeroValue and setUnknownValue --- libsolidity/formal/SMTChecker.cpp | 18 +++++++++++---- libsolidity/formal/SMTChecker.h | 2 ++ libsolidity/formal/SymbolicTypes.cpp | 29 ++++++++++++++++++++++++ libsolidity/formal/SymbolicTypes.h | 10 ++++++++ libsolidity/formal/SymbolicVariables.cpp | 22 ------------------ libsolidity/formal/SymbolicVariables.h | 21 +++-------------- 6 files changed, 58 insertions(+), 44 deletions(-) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index caf7e5faf..bb9b498fc 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -409,7 +409,7 @@ void SMTChecker::visitGasLeft(FunctionCall const& _funCall) auto const& symbolicVar = m_specialVariables.at(gasLeft); unsigned index = symbolicVar->index(); // We set the current value to unknown anyway to add type constraints. - symbolicVar->setUnknownValue(); + setUnknownValue(*symbolicVar); if (index > 0) m_interface->addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1)); } @@ -597,7 +597,7 @@ void SMTChecker::defineSpecialVariable(string const& _name, Expression const& _e { auto result = newSymbolicVariable(*_expr.annotation().type, _name, *m_interface); m_specialVariables.emplace(_name, result.second); - result.second->setUnknownValue(); + setUnknownValue(*result.second); if (result.first) m_errorReporter.warning( _expr.location(), @@ -1071,13 +1071,23 @@ smt::Expression SMTChecker::newValue(VariableDeclaration const& _decl) void SMTChecker::setZeroValue(VariableDeclaration const& _decl) { solAssert(knownVariable(_decl), ""); - m_variables.at(&_decl)->setZeroValue(); + setZeroValue(*m_variables.at(&_decl)); +} + +void SMTChecker::setZeroValue(SymbolicVariable& _variable) +{ + smt::setSymbolicZeroValue(_variable, *m_interface); } void SMTChecker::setUnknownValue(VariableDeclaration const& _decl) { solAssert(knownVariable(_decl), ""); - m_variables.at(&_decl)->setUnknownValue(); + setUnknownValue(*m_variables.at(&_decl)); +} + +void SMTChecker::setUnknownValue(SymbolicVariable& _variable) +{ + smt::setSymbolicUnknownValue(_variable, *m_interface); } smt::Expression SMTChecker::expr(Expression const& _e) diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 8ead55646..5f51beb73 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -157,8 +157,10 @@ private: /// Sets the value of the declaration to zero. void setZeroValue(VariableDeclaration const& _decl); + void setZeroValue(SymbolicVariable& _variable); /// Resets the variable to an unknown value (in its range). void setUnknownValue(VariableDeclaration const& decl); + void setUnknownValue(SymbolicVariable& _variable); /// Returns the expression corresponding to the AST node. Throws if the expression does not exist. smt::Expression expr(Expression const& _e); diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index a12ab142b..c297c807a 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -169,3 +169,32 @@ smt::Expression dev::solidity::maxValue(IntegerType const& _type) { return smt::Expression(_type.maxValue()); } + +void dev::solidity::smt::setSymbolicZeroValue(SymbolicVariable const& _variable, smt::SolverInterface& _interface) +{ + setSymbolicZeroValue(_variable.currentValue(), _variable.type(), _interface); +} + +void dev::solidity::smt::setSymbolicZeroValue(smt::Expression _expr, TypePointer const& _type, smt::SolverInterface& _interface) +{ + if (isInteger(_type->category())) + _interface.addAssertion(_expr == 0); + else if (isBool(_type->category())) + _interface.addAssertion(_expr == smt::Expression(false)); +} + +void dev::solidity::smt::setSymbolicUnknownValue(SymbolicVariable const& _variable, smt::SolverInterface& _interface) +{ + setSymbolicUnknownValue(_variable.currentValue(), _variable.type(), _interface); +} + +void dev::solidity::smt::setSymbolicUnknownValue(smt::Expression _expr, TypePointer const& _type, smt::SolverInterface& _interface) +{ + if (isInteger(_type->category())) + { + auto intType = dynamic_cast(_type.get()); + solAssert(intType, ""); + _interface.addAssertion(_expr >= minValue(*intType)); + _interface.addAssertion(_expr <= maxValue(*intType)); + } +} diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 6af2a0a0d..984653b3b 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -55,5 +55,15 @@ std::pair> newSymbolicVariable(Type cons smt::Expression minValue(IntegerType const& _type); smt::Expression maxValue(IntegerType const& _type); +namespace smt +{ + +void setSymbolicZeroValue(SymbolicVariable const& _variable, smt::SolverInterface& _interface); +void setSymbolicZeroValue(smt::Expression _expr, TypePointer const& _type, smt::SolverInterface& _interface); +void setSymbolicUnknownValue(SymbolicVariable const& _variable, smt::SolverInterface& _interface); +void setSymbolicUnknownValue(smt::Expression _expr, TypePointer const& _type, smt::SolverInterface& _interface); + +} + } } diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 399e18f80..efaeb97a6 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -62,15 +62,6 @@ smt::Expression SymbolicBoolVariable::valueAtIndex(int _index) const return m_interface.newVariable(uniqueSymbol(_index), make_shared(smt::Kind::Bool)); } -void SymbolicBoolVariable::setZeroValue() -{ - m_interface.addAssertion(currentValue() == smt::Expression(false)); -} - -void SymbolicBoolVariable::setUnknownValue() -{ -} - SymbolicIntVariable::SymbolicIntVariable( TypePointer _type, string const& _uniqueName, @@ -86,19 +77,6 @@ smt::Expression SymbolicIntVariable::valueAtIndex(int _index) const return m_interface.newVariable(uniqueSymbol(_index), make_shared(smt::Kind::Int)); } -void SymbolicIntVariable::setZeroValue() -{ - m_interface.addAssertion(currentValue() == 0); -} - -void SymbolicIntVariable::setUnknownValue() -{ - auto intType = dynamic_cast(m_type.get()); - solAssert(intType, ""); - m_interface.addAssertion(currentValue() >= minValue(*intType)); - m_interface.addAssertion(currentValue() <= maxValue(*intType)); -} - SymbolicAddressVariable::SymbolicAddressVariable( string const& _uniqueName, smt::SolverInterface& _interface diff --git a/libsolidity/formal/SymbolicVariables.h b/libsolidity/formal/SymbolicVariables.h index 13b944a5a..fcf32760c 100644 --- a/libsolidity/formal/SymbolicVariables.h +++ b/libsolidity/formal/SymbolicVariables.h @@ -64,20 +64,15 @@ public: unsigned index() const { return m_ssa->index(); } unsigned& index() { return m_ssa->index(); } - /// Sets the var to the default value of its type. - /// Inherited types must implement. - virtual void setZeroValue() = 0; - /// The unknown value is the full range of valid values. - /// It is sub-type dependent, but not mandatory. - virtual void setUnknownValue() {} + TypePointer const& type() const { return m_type; } protected: std::string uniqueSymbol(unsigned _index) const; - TypePointer m_type = nullptr; + TypePointer m_type; std::string m_uniqueName; smt::SolverInterface& m_interface; - std::shared_ptr m_ssa = nullptr; + std::shared_ptr m_ssa; }; /** @@ -92,11 +87,6 @@ public: smt::SolverInterface& _interface ); - /// Sets the var to false. - void setZeroValue(); - /// Does nothing since the SMT solver already knows the valid values for Bool. - void setUnknownValue(); - protected: smt::Expression valueAtIndex(int _index) const; }; @@ -113,11 +103,6 @@ public: smt::SolverInterface& _interface ); - /// Sets the var to 0. - void setZeroValue(); - /// Sets the variable to the full valid value range. - void setUnknownValue(); - protected: smt::Expression valueAtIndex(int _index) const; }; From a781bda5958d2632306118965747fe79cc86f34d Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 14:55:30 +0100 Subject: [PATCH 056/168] Correct style. --- libsolidity/analysis/TypeChecker.cpp | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 69de9f127..7a41f94ee 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -400,42 +400,42 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr } } -void TypeChecker::checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super) +void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super) { - FunctionType functionType(function); - FunctionType superType(super); + FunctionType functionType(_function); + FunctionType superType(_super); if (!functionType.hasEqualParameterTypes(superType)) return; - if (!function.annotation().superFunction) - function.annotation().superFunction = &super; + if (!_function.annotation().superFunction) + _function.annotation().superFunction = &_super; - if (function.visibility() != super.visibility()) + if (_function.visibility() != _super.visibility()) { // visibility is enforced to be external in interfaces, but a contract can override that with public if ( - super.inContractKind() == ContractDefinition::ContractKind::Interface && - function.inContractKind() != ContractDefinition::ContractKind::Interface && - function.visibility() == FunctionDefinition::Visibility::Public + _super.inContractKind() == ContractDefinition::ContractKind::Interface && + _function.inContractKind() != ContractDefinition::ContractKind::Interface && + _function.visibility() == FunctionDefinition::Visibility::Public ) return; - overrideError(function, super, "Overriding function visibility differs."); + overrideError(_function, _super, "Overriding function visibility differs."); } - else if (function.stateMutability() != super.stateMutability()) + else if (_function.stateMutability() != _super.stateMutability()) overrideError( - function, - super, + _function, + _super, "Overriding function changes state mutability from \"" + - stateMutabilityToString(super.stateMutability()) + + stateMutabilityToString(_super.stateMutability()) + "\" to \"" + - stateMutabilityToString(function.stateMutability()) + + stateMutabilityToString(_function.stateMutability()) + "\"." ); else if (functionType != superType) - overrideError(function, super, "Overriding function return types differ."); + overrideError(_function, _super, "Overriding function return types differ."); } void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message) From 87d1276dc850e1c72876cde651031b4abffb46bc Mon Sep 17 00:00:00 2001 From: liangdzou Date: Thu, 13 Sep 2018 10:36:14 +0800 Subject: [PATCH 057/168] Notify user on successful run without output. --- solc/CommandLineInterface.cpp | 197 ++++++++++++++++++++-------------- 1 file changed, 117 insertions(+), 80 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index b9f0bf79f..b523f0521 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -70,6 +70,24 @@ namespace dev namespace solidity { +bool g_hasOutput = false; + +std::ostream& sout() +{ + g_hasOutput = true; + return cout; +} + +std::ostream& serr(bool _used = true) +{ + if (_used) + g_hasOutput = true; + return cerr; +} + +#define cout +#define cerr + static string const g_stdinFileNameStr = ""; static string const g_strAbi = "abi"; static string const g_strAllowPaths = "allow-paths"; @@ -181,7 +199,7 @@ static set const g_machineArgs static void version() { - cout << + sout() << "solc, the solidity compiler commandline interface" << endl << "Version: " << @@ -192,9 +210,9 @@ static void version() static void license() { - cout << otherLicenses << endl; + sout() << otherLicenses << endl; // This is a static variable generated by cmake from LICENSE.txt - cout << licenseText << endl; + sout() << licenseText << endl; exit(0); } @@ -230,8 +248,8 @@ void CommandLineInterface::handleBinary(string const& _contract) createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin", objectWithLinkRefsHex(m_compiler->object(_contract))); else { - cout << "Binary: " << endl; - cout << objectWithLinkRefsHex(m_compiler->object(_contract)) << endl; + sout() << "Binary: " << endl; + sout() << objectWithLinkRefsHex(m_compiler->object(_contract)) << endl; } } if (m_args.count(g_argBinaryRuntime)) @@ -240,8 +258,8 @@ void CommandLineInterface::handleBinary(string const& _contract) createFile(m_compiler->filesystemFriendlyName(_contract) + ".bin-runtime", objectWithLinkRefsHex(m_compiler->runtimeObject(_contract))); else { - cout << "Binary of the runtime part: " << endl; - cout << objectWithLinkRefsHex(m_compiler->runtimeObject(_contract)) << endl; + sout() << "Binary of the runtime part: " << endl; + sout() << objectWithLinkRefsHex(m_compiler->runtimeObject(_contract)) << endl; } } } @@ -252,9 +270,9 @@ void CommandLineInterface::handleOpcode(string const& _contract) createFile(m_compiler->filesystemFriendlyName(_contract) + ".opcode", solidity::disassemble(m_compiler->object(_contract).bytecode)); else { - cout << "Opcodes: " << endl; - cout << solidity::disassemble(m_compiler->object(_contract).bytecode); - cout << endl; + sout() << "Opcodes: " << endl; + sout() << solidity::disassemble(m_compiler->object(_contract).bytecode); + sout() << endl; } } @@ -279,7 +297,7 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) if (m_args.count(g_argOutputDir)) createFile(m_compiler->filesystemFriendlyName(_contract) + ".signatures", out); else - cout << "Function signatures: " << endl << out; + sout() << "Function signatures: " << endl << out; } void CommandLineInterface::handleMetadata(string const& _contract) @@ -291,7 +309,7 @@ void CommandLineInterface::handleMetadata(string const& _contract) if (m_args.count(g_argOutputDir)) createFile(m_compiler->filesystemFriendlyName(_contract) + "_meta.json", data); else - cout << "Metadata: " << endl << data << endl; + sout() << "Metadata: " << endl << data << endl; } void CommandLineInterface::handleABI(string const& _contract) @@ -303,7 +321,7 @@ void CommandLineInterface::handleABI(string const& _contract) if (m_args.count(g_argOutputDir)) createFile(m_compiler->filesystemFriendlyName(_contract) + ".abi", data); else - cout << "Contract JSON ABI " << endl << data << endl; + sout() << "Contract JSON ABI " << endl << data << endl; } void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contract) @@ -337,8 +355,8 @@ void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contra createFile(m_compiler->filesystemFriendlyName(_contract) + suffix, output); else { - cout << title << endl; - cout << output << endl; + sout() << title << endl; + sout() << output << endl; } } @@ -347,39 +365,39 @@ void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contra void CommandLineInterface::handleGasEstimation(string const& _contract) { Json::Value estimates = m_compiler->gasEstimates(_contract); - cout << "Gas estimation:" << endl; + sout() << "Gas estimation:" << endl; if (estimates["creation"].isObject()) { Json::Value creation = estimates["creation"]; - cout << "construction:" << endl; - cout << " " << creation["executionCost"].asString(); - cout << " + " << creation["codeDepositCost"].asString(); - cout << " = " << creation["totalCost"].asString() << endl; + sout() << "construction:" << endl; + sout() << " " << creation["executionCost"].asString(); + sout() << " + " << creation["codeDepositCost"].asString(); + sout() << " = " << creation["totalCost"].asString() << endl; } if (estimates["external"].isObject()) { Json::Value externalFunctions = estimates["external"]; - cout << "external:" << endl; + sout() << "external:" << endl; for (auto const& name: externalFunctions.getMemberNames()) { if (name.empty()) - cout << " fallback:\t"; + sout() << " fallback:\t"; else - cout << " " << name << ":\t"; - cout << externalFunctions[name].asString() << endl; + sout() << " " << name << ":\t"; + sout() << externalFunctions[name].asString() << endl; } } if (estimates["internal"].isObject()) { Json::Value internalFunctions = estimates["internal"]; - cout << "internal:" << endl; + sout() << "internal:" << endl; for (auto const& name: internalFunctions.getMemberNames()) { - cout << " " << name << ":\t"; - cout << internalFunctions[name].asString() << endl; + sout() << " " << name << ":\t"; + sout() << internalFunctions[name].asString() << endl; } } } @@ -401,7 +419,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() } else { - cerr << "Invalid remapping: \"" << path << "\"." << endl; + serr() << "Invalid remapping: \"" << path << "\"." << endl; return false; } } @@ -414,11 +432,11 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() { if (!ignoreMissing) { - cerr << infile << " is not found." << endl; + serr() << infile << " is not found." << endl; return false; } else - cerr << infile << " is not found. Skipping." << endl; + serr() << infile << " is not found. Skipping." << endl; continue; } @@ -427,11 +445,11 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() { if (!ignoreMissing) { - cerr << infile << " is not a valid file." << endl; + serr() << infile << " is not a valid file." << endl; return false; } else - cerr << infile << " is not a valid file. Skipping." << endl; + serr() << infile << " is not a valid file. Skipping." << endl; continue; } @@ -445,7 +463,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() m_sourceCodes[g_stdinFileName] = dev::readStandardInput(); if (m_sourceCodes.size() == 0) { - cerr << "No input files given. If you wish to use the standard input please specify \"-\" explicitly." << endl; + serr() << "No input files given. If you wish to use the standard input please specify \"-\" explicitly." << endl; return false; } @@ -476,7 +494,7 @@ bool CommandLineInterface::parseLibraryOption(string const& _input) auto colon = lib.rfind(':'); if (colon == string::npos) { - cerr << "Colon separator missing in library address specifier \"" << lib << "\"" << endl; + serr() << "Colon separator missing in library address specifier \"" << lib << "\"" << endl; return false; } string libName(lib.begin(), lib.begin() + colon); @@ -487,26 +505,26 @@ bool CommandLineInterface::parseLibraryOption(string const& _input) addrString = addrString.substr(2); if (addrString.empty()) { - cerr << "Empty address provided for library \"" << libName << "\": " << endl; - cerr << "Note that there should not be any whitespace after the colon." << endl; + serr() << "Empty address provided for library \"" << libName << "\": " << endl; + serr() << "Note that there should not be any whitespace after the colon." << endl; return false; } else if (addrString.length() != 40) { - cerr << "Invalid length for address for library \"" << libName << "\": " << addrString.length() << " instead of 40 characters." << endl; + serr() << "Invalid length for address for library \"" << libName << "\": " << addrString.length() << " instead of 40 characters." << endl; return false; } if (!passesAddressChecksum(addrString, false)) { - cerr << "Invalid checksum on address for library \"" << libName << "\": " << addrString << endl; - cerr << "The correct checksum is " << dev::getChecksummedAddress(addrString) << endl; + serr() << "Invalid checksum on address for library \"" << libName << "\": " << addrString << endl; + serr() << "The correct checksum is " << dev::getChecksummedAddress(addrString) << endl; return false; } bytes binAddr = fromHex(addrString); h160 address(binAddr, h160::AlignRight); if (binAddr.size() > 20 || address == h160()) { - cerr << "Invalid address for library \"" << libName << "\": " << addrString << endl; + serr() << "Invalid address for library \"" << libName << "\": " << addrString << endl; return false; } m_libraries[libName] = address; @@ -526,7 +544,7 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da string pathName = (p / _fileName).string(); if (fs::exists(pathName) && !m_args.count(g_strOverwrite)) { - cerr << "Refusing to overwrite existing file \"" << pathName << "\" (use --overwrite to force)." << endl; + serr() << "Refusing to overwrite existing file \"" << pathName << "\" (use --overwrite to force)." << endl; m_error = true; return; } @@ -543,6 +561,8 @@ void CommandLineInterface::createJson(string const& _fileName, string const& _js bool CommandLineInterface::parseArguments(int _argc, char** _argv) { + g_hasOutput = false; + // Declare the supported options. po::options_description desc(R"(solc, the Solidity commandline compiler. @@ -667,13 +687,13 @@ Allowed options)", } catch (po::error const& _exception) { - cerr << _exception.what() << endl; + serr() << _exception.what() << endl; return false; } if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1)) { - cout << desc; + sout() << desc; return false; } @@ -695,7 +715,7 @@ Allowed options)", for (string const& item: boost::split(requests, m_args[g_argCombinedJson].as(), boost::is_any_of(","))) if (!g_combinedJsonArgs.count(item)) { - cerr << "Invalid option to --combined-json: " << item << endl; + serr() << "Invalid option to --combined-json: " << item << endl; return false; } } @@ -759,9 +779,7 @@ bool CommandLineInterface::processInput() // path comparison in later parts of the code, so we need to strip // it. if (filesystem_path.filename() == ".") - { filesystem_path.remove_filename(); - } m_allowedDirectories.push_back(filesystem_path); } } @@ -770,7 +788,7 @@ bool CommandLineInterface::processInput() { string input = dev::readStandardInput(); StandardCompiler compiler(fileReader); - cout << compiler.compile(input) << endl; + sout() << compiler.compile(input) << endl; return true; } @@ -788,7 +806,7 @@ bool CommandLineInterface::processInput() boost::optional versionOption = EVMVersion::fromString(versionOptionStr); if (!versionOption) { - cerr << "Invalid option for --evm-version: " << versionOptionStr << endl; + serr() << "Invalid option for --evm-version: " << versionOptionStr << endl; return false; } m_evmVersion = *versionOption; @@ -813,7 +831,7 @@ bool CommandLineInterface::processInput() targetMachine = Machine::eWasm; else { - cerr << "Invalid option for --machine: " << machine << endl; + serr() << "Invalid option for --machine: " << machine << endl; return false; } } @@ -829,7 +847,7 @@ bool CommandLineInterface::processInput() m_compiler.reset(new CompilerStack(fileReader)); auto scannerFromSourceName = [&](string const& _sourceName) -> Scanner const& { return m_compiler->scanner(_sourceName); }; - SourceReferenceFormatter formatter(cerr, scannerFromSourceName); + SourceReferenceFormatter formatter(serr(false), scannerFromSourceName); try { @@ -850,48 +868,55 @@ bool CommandLineInterface::processInput() bool successful = m_compiler->compile(); for (auto const& error: m_compiler->errors()) + { + g_hasOutput = true; formatter.printExceptionInformation( *error, (error->type() == Error::Type::Warning) ? "Warning" : "Error" ); + } if (!successful) return false; } catch (CompilerError const& _exception) { + g_hasOutput = true; formatter.printExceptionInformation(_exception, "Compiler error"); return false; } catch (InternalCompilerError const& _exception) { - cerr << "Internal compiler error during compilation:" << endl + serr() << "Internal compiler error during compilation:" << endl << boost::diagnostic_information(_exception); return false; } catch (UnimplementedFeatureError const& _exception) { - cerr << "Unimplemented feature:" << endl + serr() << "Unimplemented feature:" << endl << boost::diagnostic_information(_exception); return false; } catch (Error const& _error) { if (_error.type() == Error::Type::DocstringParsingError) - cerr << "Documentation parsing error: " << *boost::get_error_info(_error) << endl; + serr() << "Documentation parsing error: " << *boost::get_error_info(_error) << endl; else + { + g_hasOutput = true; formatter.printExceptionInformation(_error, _error.typeName()); + } return false; } catch (Exception const& _exception) { - cerr << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; + serr() << "Exception during compilation: " << boost::diagnostic_information(_exception) << endl; return false; } catch (...) { - cerr << "Unknown exception during compilation." << endl; + serr() << "Unknown exception during compilation." << endl; return false; } @@ -972,7 +997,7 @@ void CommandLineInterface::handleCombinedJSON() if (m_args.count(g_argOutputDir)) createJson("combined", json); else - cout << json << endl; + sout() << json << endl; } void CommandLineInterface::handleAst(string const& _argStr) @@ -1028,10 +1053,10 @@ void CommandLineInterface::handleAst(string const& _argStr) } else { - cout << title << endl << endl; + sout() << title << endl << endl; for (auto const& sourceCode: m_sourceCodes) { - cout << endl << "======= " << sourceCode.first << " =======" << endl; + sout() << endl << "======= " << sourceCode.first << " =======" << endl; if (_argStr == g_argAst) { ASTPrinter printer( @@ -1039,10 +1064,10 @@ void CommandLineInterface::handleAst(string const& _argStr) sourceCode.second, gasCosts ); - printer.print(cout); + printer.print(sout()); } else - ASTJsonConverter(legacyFormat, m_compiler->sourceIndices()).print(cout, m_compiler->ast(sourceCode.first)); + ASTJsonConverter(legacyFormat, m_compiler->sourceIndices()).print(sout(), m_compiler->ast(sourceCode.first)); } } } @@ -1090,7 +1115,7 @@ bool CommandLineInterface::link() if (it == end) break; if (end - it < placeholderSize) { - cerr << "Error in binary object file " << src.first << " at position " << (end - src.second.begin()) << endl; + serr() << "Error in binary object file " << src.first << " at position " << (end - src.second.begin()) << endl; return false; } @@ -1101,7 +1126,7 @@ bool CommandLineInterface::link() copy(hexStr.begin(), hexStr.end(), it); } else - cerr << "Reference \"" << name << "\" in file \"" << src.first << "\" still unresolved." << endl; + serr() << "Reference \"" << name << "\" in file \"" << src.first << "\" still unresolved." << endl; it += placeholderSize; } // Remove hints for resolved libraries. @@ -1117,17 +1142,18 @@ void CommandLineInterface::writeLinkedFiles() { for (auto const& src: m_sourceCodes) if (src.first == g_stdinFileName) - cout << src.second << endl; + sout() << src.second << endl; else { ofstream outFile(src.first); outFile << src.second; if (!outFile) { - cerr << "Could not write to file " << src.first << ". Aborting." << endl; + serr() << "Could not write to file " << src.first << ". Aborting." << endl; return; } } + sout() << "Linking completed." << endl; } string CommandLineInterface::libraryPlaceholderHint(string const& _libraryName) @@ -1164,12 +1190,12 @@ bool CommandLineInterface::assemble( } catch (Exception const& _exception) { - cerr << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl; + serr() << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl; return false; } catch (...) { - cerr << "Unknown exception in assembler." << endl; + serr() << "Unknown exception in assembler." << endl; return false; } } @@ -1178,13 +1204,16 @@ bool CommandLineInterface::assemble( { auto const& stack = sourceAndStack.second; auto scannerFromSourceName = [&](string const&) -> Scanner const& { return stack.scanner(); }; - SourceReferenceFormatter formatter(cerr, scannerFromSourceName); + SourceReferenceFormatter formatter(serr(false), scannerFromSourceName); for (auto const& error: stack.errors()) + { + g_hasOutput = true; formatter.printExceptionInformation( *error, (error->type() == Error::Type::Warning) ? "Warning" : "Error" ); + } if (!Error::containsOnlyWarnings(stack.errors())) successful = false; } @@ -1198,11 +1227,11 @@ bool CommandLineInterface::assemble( _targetMachine == AssemblyStack::Machine::EVM ? "EVM" : _targetMachine == AssemblyStack::Machine::EVM15 ? "EVM 1.5" : "eWasm"; - cout << endl << "======= " << src.first << " (" << machine << ") =======" << endl; + sout() << endl << "======= " << src.first << " (" << machine << ") =======" << endl; AssemblyStack& stack = assemblyStacks[src.first]; - cout << endl << "Pretty printed source:" << endl; - cout << stack.print() << endl; + sout() << endl << "Pretty printed source:" << endl; + sout() << stack.print() << endl; MachineAssemblyObject object; try @@ -1211,26 +1240,26 @@ bool CommandLineInterface::assemble( } catch (Exception const& _exception) { - cerr << "Exception while assembling: " << boost::diagnostic_information(_exception) << endl; + serr() << "Exception while assembling: " << boost::diagnostic_information(_exception) << endl; return false; } catch (...) { - cerr << "Unknown exception while assembling." << endl; + serr() << "Unknown exception while assembling." << endl; return false; } - cout << endl << "Binary representation:" << endl; + sout() << endl << "Binary representation:" << endl; if (object.bytecode) - cout << object.bytecode->toHex() << endl; + sout() << object.bytecode->toHex() << endl; else - cerr << "No binary representation found." << endl; + serr() << "No binary representation found." << endl; - cout << endl << "Text representation:" << endl; + sout() << endl << "Text representation:" << endl; if (!object.assembly.empty()) - cout << object.assembly << endl; + sout() << object.assembly << endl; else - cerr << "No text representation found." << endl; + serr() << "No text representation found." << endl; } return true; @@ -1249,7 +1278,7 @@ void CommandLineInterface::outputCompilationResults() for (string const& contract: contracts) { if (needsHumanTargetedStdout(m_args)) - cout << endl << "======= " << contract << " =======" << endl; + sout() << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? if (m_args.count(g_argAsm) || m_args.count(g_argAsmJson)) @@ -1266,7 +1295,7 @@ void CommandLineInterface::outputCompilationResults() } else { - cout << "EVM assembly:" << endl << ret << endl; + sout() << "EVM assembly:" << endl << ret << endl; } } @@ -1280,6 +1309,14 @@ void CommandLineInterface::outputCompilationResults() handleNatspec(true, contract); handleNatspec(false, contract); } // end of contracts iteration + + if (!g_hasOutput) + { + if (m_args.count(g_argOutputDir)) + sout() << "Compiler run successful. Artifact(s) can be found in directory " << m_args.at(g_argOutputDir).as() << "." << endl; + else + serr() << "Compiler run successful, no output requested." << endl; + } } } From 958f2a5b403206b5c8c0bfe1475d74d25d58c4c1 Mon Sep 17 00:00:00 2001 From: Lazaridis <35095758+lazaridiscom@users.noreply.github.com> Date: Thu, 22 Nov 2018 21:22:10 +0200 Subject: [PATCH 058/168] Mention third party licenses. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a448e8c7..c7065c093 100644 --- a/README.md +++ b/README.md @@ -62,5 +62,6 @@ if you want to help. [@chriseth](https://github.com/chriseth) ## License -Solidity is licensed under [GNU General Public License v3.0](https://github.com/ethereum/solidity/blob/develop/LICENSE.txt) +Solidity is licensed under [GNU General Public License v3.0](LICENSE.txt) +Some third-party code has its [own licensing terms](cmake/templates/license.h.in). From 640e3ca5969cee1332489297ac2c2d7d9a1e770e Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 20:37:24 +0100 Subject: [PATCH 059/168] Update paths to CharStream, Scanner and Token files. --- cmake/templates/license.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/templates/license.h.in b/cmake/templates/license.h.in index 4f22d8f4d..31e2e17da 100644 --- a/cmake/templates/license.h.in +++ b/cmake/templates/license.h.in @@ -67,7 +67,7 @@ jsoncpp: license you like. scanner/token: - The libsolidity/parsing/{scanner,token}.{h,cpp} files are dervied from + The liblangutil/{CharStream,Scanner,Token}.{h,cpp} files are dervied from code originating from the V8 project licensed under the following terms: Copyright 2006-2012, the V8 project authors. All rights reserved. From 3672506de96fcc9bd403603e071c819652a59f14 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 21:03:24 +0100 Subject: [PATCH 060/168] Fix bytecode report file. --- scripts/bytecodecompare/storebytecode.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/bytecodecompare/storebytecode.sh b/scripts/bytecodecompare/storebytecode.sh index b14b23d0e..4208d67ff 100755 --- a/scripts/bytecodecompare/storebytecode.sh +++ b/scripts/bytecodecompare/storebytecode.sh @@ -82,8 +82,8 @@ for (var optimize of [false, true]) { for (var contractName in result['contracts'][filename]) { - console.log(contractName + ' ' + result['contracts'][filename][contractName].evm.bytecode.object) - console.log(contractName + ' ' + result['contracts'][filename][contractName].metadata) + console.log(filename + ':' + contractName + ' ' + result['contracts'][filename][contractName].evm.bytecode.object) + console.log(filename + ':' + contractName + ' ' + result['contracts'][filename][contractName].metadata) } } } From d686807153dd85471bac9d426c494601397b0ab4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 20:51:40 +0100 Subject: [PATCH 061/168] Style --- libsolidity/formal/SolverInterface.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index 17e6904c7..fd1abd611 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -55,8 +55,9 @@ struct Sort Sort(Kind _kind): kind(_kind) {} virtual ~Sort() = default; - Kind const kind; bool operator==(Sort const& _other) const { return kind == _other.kind; } + + Kind const kind; }; using SortPointer = std::shared_ptr; @@ -64,8 +65,6 @@ struct FunctionSort: public Sort { FunctionSort(std::vector _domain, SortPointer _codomain): Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {} - std::vector domain; - SortPointer codomain; bool operator==(FunctionSort const& _other) const { if (!std::equal( @@ -73,11 +72,13 @@ struct FunctionSort: public Sort domain.end(), _other.domain.begin(), [&](SortPointer _a, SortPointer _b) { return *_a == *_b; } - ) - ) + )) return false; return Sort::operator==(_other) && *codomain == *_other.codomain; } + + std::vector domain; + SortPointer codomain; }; struct ArraySort: public Sort @@ -86,12 +87,13 @@ struct ArraySort: public Sort /// _range is the sort of the values ArraySort(SortPointer _domain, SortPointer _range): Sort(Kind::Array), domain(std::move(_domain)), range(std::move(_range)) {} - SortPointer domain; - SortPointer range; bool operator==(ArraySort const& _other) const { return Sort::operator==(_other) && *domain == *_other.domain && *range == *_other.range; } + + SortPointer domain; + SortPointer range; }; /// C++ representation of an SMTLIB2 expression. From bb10be789c269927e593b41d37aa0637db68bbe1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 13 Oct 2017 15:19:53 +0200 Subject: [PATCH 062/168] Inject SMTLIB2 queries and responses via standard-json-io. --- Changelog.md | 1 + libsolidity/formal/SMTChecker.cpp | 4 ++-- libsolidity/formal/SMTChecker.h | 7 +++++- libsolidity/formal/SMTLib2Interface.cpp | 21 ++++++++++-------- libsolidity/formal/SMTLib2Interface.h | 10 +++++++-- libsolidity/formal/SMTPortfolio.cpp | 6 +++--- libsolidity/formal/SMTPortfolio.h | 6 +++++- libsolidity/formal/SolverInterface.h | 3 +++ libsolidity/interface/CompilerStack.cpp | 5 ++++- libsolidity/interface/CompilerStack.h | 10 ++++++++- libsolidity/interface/StandardCompiler.cpp | 25 ++++++++++++++++++++++ 11 files changed, 78 insertions(+), 20 deletions(-) diff --git a/Changelog.md b/Changelog.md index 449798a45..ca904ffc0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Language Features: Compiler Features: * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. + * SMTChecker: SMTLib2 queries and responses passed via standard JSON compiler interface. * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. * SMTChecker: Support internal bound function calls. diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index bb9b498fc..0af171a74 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -32,8 +32,8 @@ using namespace dev; using namespace langutil; using namespace dev::solidity; -SMTChecker::SMTChecker(ErrorReporter& _errorReporter, ReadCallback::Callback const& _readFileCallback): - m_interface(make_shared(_readFileCallback)), +SMTChecker::SMTChecker(ErrorReporter& _errorReporter, map const& _smtlib2Responses): + m_interface(make_shared(_smtlib2Responses)), m_errorReporter(_errorReporter) { } diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 5f51beb73..347248486 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -47,10 +47,15 @@ class VariableUsage; class SMTChecker: private ASTConstVisitor { public: - SMTChecker(langutil::ErrorReporter& _errorReporter, ReadCallback::Callback const& _readCallback); + SMTChecker(langutil::ErrorReporter& _errorReporter, std::map const& _smtlib2Responses); void analyze(SourceUnit const& _sources, std::shared_ptr const& _scanner); + /// This is used if the SMT solver is not directly linked into this binary. + /// @returns a list of inputs to the SMT solver that were not part of the argument to + /// the constructor. + std::vector unhandledQueries() { return m_interface->unhandledQueries(); } + private: // TODO: Check that we do not have concurrent reads and writes to a variable, // because the order of expression evaluation is undefined diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 55c72cfc3..80ecc715d 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -20,6 +20,8 @@ #include #include +#include + #include #include #include @@ -37,8 +39,8 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::smt; -SMTLib2Interface::SMTLib2Interface(ReadCallback::Callback const& _queryCallback): - m_queryCallback(_queryCallback) +SMTLib2Interface::SMTLib2Interface(map const& _smtlib2Responses): + m_smtlib2Responses(_smtlib2Responses) { reset(); } @@ -212,11 +214,12 @@ vector SMTLib2Interface::parseValues(string::const_iterator _start, stri string SMTLib2Interface::querySolver(string const& _input) { - if (!m_queryCallback) - BOOST_THROW_EXCEPTION(SolverError() << errinfo_comment("No SMT solver available.")); - - ReadCallback::Result queryResult = m_queryCallback(_input); - if (!queryResult.success) - BOOST_THROW_EXCEPTION(SolverError() << errinfo_comment(queryResult.responseOrErrorMessage)); - return queryResult.responseOrErrorMessage; + h256 inputHash = dev::keccak256(_input); + if (m_smtlib2Responses.count(inputHash)) + return m_smtlib2Responses.at(inputHash); + else + { + m_unhandledQueries.push_back(_input); + return "unknown\n"; + } } diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index 4f72d27c4..c67101ae5 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -22,6 +22,8 @@ #include #include +#include + #include #include @@ -42,7 +44,7 @@ namespace smt class SMTLib2Interface: public SolverInterface, public boost::noncopyable { public: - explicit SMTLib2Interface(ReadCallback::Callback const& _queryCallback); + explicit SMTLib2Interface(std::map const& _smtlib2Responses); void reset() override; @@ -54,6 +56,8 @@ public: void addAssertion(Expression const& _expr) override; std::pair> check(std::vector const& _expressionsToEvaluate) override; + std::vector unhandledQueries() override { return m_unhandledQueries; } + private: void declareFunction(std::string const&, Sort const&); @@ -69,9 +73,11 @@ private: /// Communicates with the solver via the callback. Throws SMTSolverError on error. std::string querySolver(std::string const& _input); - ReadCallback::Callback m_queryCallback; + std::map const& m_smtlib2Responses; std::vector m_accumulatedOutput; std::set m_variables; + + std::vector m_unhandledQueries; }; } diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index 224e5cd61..4c5913805 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -32,7 +32,7 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::smt; -SMTPortfolio::SMTPortfolio(ReadCallback::Callback const& _readCallback) +SMTPortfolio::SMTPortfolio(map const& _smtlib2Responses) { #ifdef HAVE_Z3 m_solvers.emplace_back(make_shared()); @@ -41,9 +41,9 @@ SMTPortfolio::SMTPortfolio(ReadCallback::Callback const& _readCallback) m_solvers.emplace_back(make_shared()); #endif #if !defined (HAVE_Z3) && !defined (HAVE_CVC4) - m_solvers.emplace_back(make_shared(_readCallback)), + m_solvers.emplace_back(make_shared(_smtlib2Responses)), #endif - (void)_readCallback; + (void)_smtlib2Responses; } void SMTPortfolio::reset() diff --git a/libsolidity/formal/SMTPortfolio.h b/libsolidity/formal/SMTPortfolio.h index 12e2be669..7f5ba37ee 100644 --- a/libsolidity/formal/SMTPortfolio.h +++ b/libsolidity/formal/SMTPortfolio.h @@ -22,8 +22,11 @@ #include +#include + #include +#include #include namespace dev @@ -42,7 +45,7 @@ namespace smt class SMTPortfolio: public SolverInterface, public boost::noncopyable { public: - SMTPortfolio(ReadCallback::Callback const& _readCallback); + SMTPortfolio(std::map const& _smtlib2Responses); void reset() override; @@ -54,6 +57,7 @@ public: void addAssertion(Expression const& _expr) override; std::pair> check(std::vector const& _expressionsToEvaluate) override; + std::vector unhandledQueries() override { return m_solvers.at(0)->unhandledQueries(); } private: static bool solverAnswered(CheckResult result); diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index fd1abd611..cc8214de8 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -284,6 +284,9 @@ public: virtual std::pair> check(std::vector const& _expressionsToEvaluate) = 0; + /// @returns a list of queries that the system was not able to respond to. + virtual std::vector unhandledQueries() { return {}; } + protected: // SMT query timeout in milliseconds. static int const queryTimeout = 10000; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a56747052..ae85276e1 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -107,6 +107,8 @@ void CompilerStack::reset(bool _keepSources) m_stackState = Empty; m_sources.clear(); } + m_smtlib2Responses.clear(); + m_unhandledSMTLib2Queries.clear(); m_libraries.clear(); m_evmVersion = EVMVersion(); m_optimize = false; @@ -283,9 +285,10 @@ bool CompilerStack::analyze() if (noErrors) { - SMTChecker smtChecker(m_errorReporter, m_smtQuery); + SMTChecker smtChecker(m_errorReporter, m_smtlib2Responses); for (Source const* source: m_sourceOrder) smtChecker.analyze(*source->ast, source->scanner); + m_unhandledSMTLib2Queries += smtChecker.unhandledQueries(); } } catch(FatalError const&) diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 8c50266ef..3fceed242 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -153,6 +153,13 @@ public: /// @returns true if a source object by the name already existed and was replaced. bool addSource(std::string const& _name, std::string const& _content, bool _isLibrary = false); + /// Adds a response to an SMTLib2 query (identified by the hash of the query input). + void addSMTLib2Response(h256 const& _hash, std::string const& _response) { m_smtlib2Responses[_hash] = _response; } + + /// @returns a list of unhandled queries to the SMT solver (has to be supplied in a second run + /// by calling @a addSMTLib2Response. + std::vector const& unhandledSMTQueries() const { return m_unhandledSMTLib2Queries; } + /// Parses all source units that were added /// @returns false on error. bool parse(); @@ -334,7 +341,6 @@ private: ) const; ReadCallback::Callback m_readFile; - ReadCallback::Callback m_smtQuery; bool m_optimize = false; unsigned m_optimizeRuns = 200; EVMVersion m_evmVersion; @@ -344,6 +350,8 @@ private: /// "context:prefix=target" std::vector m_remappings; std::map m_sources; + std::vector m_unhandledSMTLib2Queries; + std::map m_smtlib2Responses; std::shared_ptr m_globalContext; std::vector m_sourceOrder; /// This is updated during compilation. diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 291a1071b..59c28cd9a 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -319,6 +319,27 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) return formatFatalError("JSONError", "Invalid input source specified."); } + Json::Value const& auxInputs = _input["auxiliaryInput"]; + if (!!auxInputs) + { + Json::Value const& smtlib2Responses = auxInputs["smtlib2"]; + if (!!smtlib2Responses) + for (auto const& hashString: smtlib2Responses.getMemberNames()) + { + h256 hash; + try + { + hash = h256(hashString); + } + catch (dev::BadHexCharacter const&) + { + return formatFatalError("JSONError", "Invalid hex encoding of SMTLib2 auxiliary input."); + } + + m_compilerStack.addSMTLib2Response(hash, smtlib2Responses[hashString].asString()); + } + } + Json::Value const& settings = _input.get("settings", Json::Value()); if (settings.isMember("evmVersion")) @@ -518,6 +539,10 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) if (errors.size() > 0) output["errors"] = errors; + if (!m_compilerStack.unhandledSMTQueries().empty()) + for (string const& query: m_compilerStack.unhandledSMTQueries()) + output["auxiliaryInputRequested"]["smtlib2"]["0x" + keccak256(query).hex()] = query; + output["sources"] = Json::objectValue; unsigned sourceIndex = 0; for (string const& sourceName: analysisSuccess ? m_compilerStack.sourceNames() : vector()) From 54bed454f6e7a53f51ec7e9bda7805900a2c8472 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 13 Oct 2017 17:57:58 +0200 Subject: [PATCH 063/168] Rename function and warn if responses are supplied for Z3. --- libsolidity/formal/SMTPortfolio.cpp | 8 +++++++- libsolidity/interface/CompilerStack.h | 8 ++++---- libsolidity/interface/StandardCompiler.cpp | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index 4c5913805..515d6f32c 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -41,7 +41,13 @@ SMTPortfolio::SMTPortfolio(map const& _smtlib2Responses) m_solvers.emplace_back(make_shared()); #endif #if !defined (HAVE_Z3) && !defined (HAVE_CVC4) - m_solvers.emplace_back(make_shared(_smtlib2Responses)), + m_solvers.emplace_back(make_shared(_smtlib2Responses)); +#else + if (!_smtlib2Responses.empty()) + m_errorReporter.warning( + "Query responses for smtlib2 were given in the auxiliary input, " + "but this Solidity binary uses an SMT solver directly." + ); #endif (void)_smtlib2Responses; } diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 3fceed242..2c7add3b0 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -156,10 +156,6 @@ public: /// Adds a response to an SMTLib2 query (identified by the hash of the query input). void addSMTLib2Response(h256 const& _hash, std::string const& _response) { m_smtlib2Responses[_hash] = _response; } - /// @returns a list of unhandled queries to the SMT solver (has to be supplied in a second run - /// by calling @a addSMTLib2Response. - std::vector const& unhandledSMTQueries() const { return m_unhandledSMTLib2Queries; } - /// Parses all source units that were added /// @returns false on error. bool parse(); @@ -195,6 +191,10 @@ public: /// start line, start column, end line, end column std::tuple positionFromSourceLocation(langutil::SourceLocation const& _sourceLocation) const; + /// @returns a list of unhandled queries to the SMT solver (has to be supplied in a second run + /// by calling @a addSMTLib2Response). + std::vector const& unhandledSMTLib2Queries() const { return m_unhandledSMTLib2Queries; } + /// @returns a list of the contract names in the sources. std::vector contractNames() const; diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 59c28cd9a..a3cb90b1b 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -539,8 +539,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) if (errors.size() > 0) output["errors"] = errors; - if (!m_compilerStack.unhandledSMTQueries().empty()) - for (string const& query: m_compilerStack.unhandledSMTQueries()) + if (!m_compilerStack.unhandledSMTLib2Queries().empty()) + for (string const& query: m_compilerStack.unhandledSMTLib2Queries()) output["auxiliaryInputRequested"]["smtlib2"]["0x" + keccak256(query).hex()] = query; output["sources"] = Json::objectValue; From f44be616c96159fca18ad2f9ca4a1c0cb4218490 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Fri, 3 Aug 2018 16:48:20 +0200 Subject: [PATCH 064/168] Renaming json fields smtlib2queries and smtlib2responses --- libsolidity/interface/StandardCompiler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index a3cb90b1b..bf33b7897 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -322,7 +322,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) Json::Value const& auxInputs = _input["auxiliaryInput"]; if (!!auxInputs) { - Json::Value const& smtlib2Responses = auxInputs["smtlib2"]; + Json::Value const& smtlib2Responses = auxInputs["smtlib2responses"]; if (!!smtlib2Responses) for (auto const& hashString: smtlib2Responses.getMemberNames()) { @@ -541,7 +541,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input) if (!m_compilerStack.unhandledSMTLib2Queries().empty()) for (string const& query: m_compilerStack.unhandledSMTLib2Queries()) - output["auxiliaryInputRequested"]["smtlib2"]["0x" + keccak256(query).hex()] = query; + output["auxiliaryInputRequested"]["smtlib2queries"]["0x" + keccak256(query).hex()] = query; output["sources"] = Json::objectValue; unsigned sourceIndex = 0; From f3c2309c736ffcdb84fc133106b05d1be1eda95a Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Fri, 3 Aug 2018 17:04:56 +0200 Subject: [PATCH 065/168] Display better error message in SMTLib2 --- libsolidity/formal/SMTLib2Interface.cpp | 8 ++++---- libsolidity/formal/SMTLib2Interface.h | 4 ++-- libsolidity/formal/SMTPortfolio.cpp | 6 ++++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 80ecc715d..3cfa01b19 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -39,8 +39,8 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::smt; -SMTLib2Interface::SMTLib2Interface(map const& _smtlib2Responses): - m_smtlib2Responses(_smtlib2Responses) +SMTLib2Interface::SMTLib2Interface(map const& _queryResponses): + m_queryResponses(_queryResponses) { reset(); } @@ -215,8 +215,8 @@ vector SMTLib2Interface::parseValues(string::const_iterator _start, stri string SMTLib2Interface::querySolver(string const& _input) { h256 inputHash = dev::keccak256(_input); - if (m_smtlib2Responses.count(inputHash)) - return m_smtlib2Responses.at(inputHash); + if (m_queryResponses.count(inputHash)) + return m_queryResponses.at(inputHash); else { m_unhandledQueries.push_back(_input); diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index c67101ae5..55fc4096d 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -44,7 +44,7 @@ namespace smt class SMTLib2Interface: public SolverInterface, public boost::noncopyable { public: - explicit SMTLib2Interface(std::map const& _smtlib2Responses); + explicit SMTLib2Interface(std::map const& _queryResponses); void reset() override; @@ -73,10 +73,10 @@ private: /// Communicates with the solver via the callback. Throws SMTSolverError on error. std::string querySolver(std::string const& _input); - std::map const& m_smtlib2Responses; std::vector m_accumulatedOutput; std::set m_variables; + std::map const& m_queryResponses; std::vector m_unhandledQueries; }; diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index 515d6f32c..2c95c3fa3 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -45,8 +45,10 @@ SMTPortfolio::SMTPortfolio(map const& _smtlib2Responses) #else if (!_smtlib2Responses.empty()) m_errorReporter.warning( - "Query responses for smtlib2 were given in the auxiliary input, " - "but this Solidity binary uses an SMT solver directly." + "SMT-LIB2 query responses were given in the auxiliary input, " + "but this Solidity binary uses an SMT solver (Z3/CVC4) directly." + "These responses will be ignored." + "Consider disabling Z3/CVC4 at compilation time in order to use SMT-LIB2 responses." ); #endif (void)_smtlib2Responses; From dee0c4ded8636f2e8d157df79745ce907fa47c75 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Tue, 14 Aug 2018 12:34:53 +0200 Subject: [PATCH 066/168] Error message stays in the SMTChecker --- libsolidity/formal/SMTChecker.cpp | 9 +++++++++ libsolidity/formal/SMTPortfolio.cpp | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 0af171a74..5b7807f7e 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -36,6 +36,15 @@ SMTChecker::SMTChecker(ErrorReporter& _errorReporter, map const& _ m_interface(make_shared(_smtlib2Responses)), m_errorReporter(_errorReporter) { +#if defined (HAVE_Z3) || defined (HAVE_CVC4) + if (!_smtlib2Responses.empty()) + m_errorReporter.warning( + "SMT-LIB2 query responses were given in the auxiliary input, " + "but this Solidity binary uses an SMT solver (Z3/CVC4) directly." + "These responses will be ignored." + "Consider disabling Z3/CVC4 at compilation time in order to use SMT-LIB2 responses." + ); +#endif } void SMTChecker::analyze(SourceUnit const& _source, shared_ptr const& _scanner) diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index 2c95c3fa3..6bdbd3108 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -42,14 +42,6 @@ SMTPortfolio::SMTPortfolio(map const& _smtlib2Responses) #endif #if !defined (HAVE_Z3) && !defined (HAVE_CVC4) m_solvers.emplace_back(make_shared(_smtlib2Responses)); -#else - if (!_smtlib2Responses.empty()) - m_errorReporter.warning( - "SMT-LIB2 query responses were given in the auxiliary input, " - "but this Solidity binary uses an SMT solver (Z3/CVC4) directly." - "These responses will be ignored." - "Consider disabling Z3/CVC4 at compilation time in order to use SMT-LIB2 responses." - ); #endif (void)_smtlib2Responses; } From 6251a289dd55cc54f8da5a907dc4982a4b5e57fa Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Fri, 24 Aug 2018 12:02:56 +0200 Subject: [PATCH 067/168] Testing with smtlib2 interface always there --- libsolidity/formal/SMTPortfolio.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libsolidity/formal/SMTPortfolio.cpp b/libsolidity/formal/SMTPortfolio.cpp index 6bdbd3108..2a109b894 100644 --- a/libsolidity/formal/SMTPortfolio.cpp +++ b/libsolidity/formal/SMTPortfolio.cpp @@ -23,9 +23,7 @@ #ifdef HAVE_CVC4 #include #endif -#if !defined (HAVE_Z3) && !defined (HAVE_CVC4) #include -#endif using namespace std; using namespace dev; @@ -34,16 +32,13 @@ using namespace dev::solidity::smt; SMTPortfolio::SMTPortfolio(map const& _smtlib2Responses) { + m_solvers.emplace_back(make_shared(_smtlib2Responses)); #ifdef HAVE_Z3 m_solvers.emplace_back(make_shared()); #endif #ifdef HAVE_CVC4 m_solvers.emplace_back(make_shared()); #endif -#if !defined (HAVE_Z3) && !defined (HAVE_CVC4) - m_solvers.emplace_back(make_shared(_smtlib2Responses)); -#endif - (void)_smtlib2Responses; } void SMTPortfolio::reset() From bc5d152e860fdefd9792937b46af8e3eabce1dc1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 23 Nov 2018 09:54:27 +0100 Subject: [PATCH 068/168] Update docs/types.rst Co-Authored-By: ChrisChinchilla --- docs/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index e01e2f775..cf123055d 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -13,7 +13,7 @@ Solidity provides several elementary types which can be combined to form complex In addition, types can interact with each other in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. -The concept of "undefined" or "null" values do not exist in Solidity. To handle any unexpected values, you should use the :ref:`revert function` to revert the whole transaction. +The concept of "undefined" or "null" values do not exist in Solidity. To handle any unexpected values, you should use the :ref:`revert function` to revert the whole transaction, or return a tuple with a second `bool` value denoting success. .. index:: ! value type, ! type;value From 9c1bdb74b97ea46c621dca430cd401589f800214 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Fri, 23 Nov 2018 10:16:30 +0100 Subject: [PATCH 069/168] Add default value details --- docs/types.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index cf123055d..5a0acfbb4 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -13,7 +13,10 @@ Solidity provides several elementary types which can be combined to form complex In addition, types can interact with each other in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. -The concept of "undefined" or "null" values do not exist in Solidity. To handle any unexpected values, you should use the :ref:`revert function` to revert the whole transaction, or return a tuple with a second `bool` value denoting success. +The concept of "undefined" or "null" values do not exist in Solidity, but newly +declared variables always have a :ref:`default value` dependent +on its type. To handle any unexpected values, you should use the :ref:`revert function` to revert the whole transaction, or return a +tuple with a second `bool` value denoting success. .. index:: ! value type, ! type;value From 10e6d2897d09511ca3253287694a28d05fa6b9e0 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 11:16:52 +0100 Subject: [PATCH 070/168] Moving files from libsolidity/inlineasm/*.{cpp,h} to libyul/. --- {libsolidity/inlineasm => libyul}/AsmAnalysis.cpp | 0 {libsolidity/inlineasm => libyul}/AsmAnalysis.h | 0 {libsolidity/inlineasm => libyul}/AsmAnalysisInfo.cpp | 0 {libsolidity/inlineasm => libyul}/AsmAnalysisInfo.h | 0 {libsolidity/inlineasm => libyul}/AsmCodeGen.cpp | 0 {libsolidity/inlineasm => libyul}/AsmCodeGen.h | 0 {libsolidity/inlineasm => libyul}/AsmData.h | 0 {libsolidity/inlineasm => libyul}/AsmDataForward.h | 0 {libsolidity/inlineasm => libyul}/AsmParser.cpp | 0 {libsolidity/inlineasm => libyul}/AsmParser.h | 0 {libsolidity/inlineasm => libyul}/AsmPrinter.cpp | 0 {libsolidity/inlineasm => libyul}/AsmPrinter.h | 0 {libsolidity/inlineasm => libyul}/AsmScope.cpp | 0 {libsolidity/inlineasm => libyul}/AsmScope.h | 0 {libsolidity/inlineasm => libyul}/AsmScopeFiller.cpp | 0 {libsolidity/inlineasm => libyul}/AsmScopeFiller.h | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename {libsolidity/inlineasm => libyul}/AsmAnalysis.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmAnalysis.h (100%) rename {libsolidity/inlineasm => libyul}/AsmAnalysisInfo.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmAnalysisInfo.h (100%) rename {libsolidity/inlineasm => libyul}/AsmCodeGen.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmCodeGen.h (100%) rename {libsolidity/inlineasm => libyul}/AsmData.h (100%) rename {libsolidity/inlineasm => libyul}/AsmDataForward.h (100%) rename {libsolidity/inlineasm => libyul}/AsmParser.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmParser.h (100%) rename {libsolidity/inlineasm => libyul}/AsmPrinter.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmPrinter.h (100%) rename {libsolidity/inlineasm => libyul}/AsmScope.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmScope.h (100%) rename {libsolidity/inlineasm => libyul}/AsmScopeFiller.cpp (100%) rename {libsolidity/inlineasm => libyul}/AsmScopeFiller.h (100%) diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp similarity index 100% rename from libsolidity/inlineasm/AsmAnalysis.cpp rename to libyul/AsmAnalysis.cpp diff --git a/libsolidity/inlineasm/AsmAnalysis.h b/libyul/AsmAnalysis.h similarity index 100% rename from libsolidity/inlineasm/AsmAnalysis.h rename to libyul/AsmAnalysis.h diff --git a/libsolidity/inlineasm/AsmAnalysisInfo.cpp b/libyul/AsmAnalysisInfo.cpp similarity index 100% rename from libsolidity/inlineasm/AsmAnalysisInfo.cpp rename to libyul/AsmAnalysisInfo.cpp diff --git a/libsolidity/inlineasm/AsmAnalysisInfo.h b/libyul/AsmAnalysisInfo.h similarity index 100% rename from libsolidity/inlineasm/AsmAnalysisInfo.h rename to libyul/AsmAnalysisInfo.h diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libyul/AsmCodeGen.cpp similarity index 100% rename from libsolidity/inlineasm/AsmCodeGen.cpp rename to libyul/AsmCodeGen.cpp diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libyul/AsmCodeGen.h similarity index 100% rename from libsolidity/inlineasm/AsmCodeGen.h rename to libyul/AsmCodeGen.h diff --git a/libsolidity/inlineasm/AsmData.h b/libyul/AsmData.h similarity index 100% rename from libsolidity/inlineasm/AsmData.h rename to libyul/AsmData.h diff --git a/libsolidity/inlineasm/AsmDataForward.h b/libyul/AsmDataForward.h similarity index 100% rename from libsolidity/inlineasm/AsmDataForward.h rename to libyul/AsmDataForward.h diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libyul/AsmParser.cpp similarity index 100% rename from libsolidity/inlineasm/AsmParser.cpp rename to libyul/AsmParser.cpp diff --git a/libsolidity/inlineasm/AsmParser.h b/libyul/AsmParser.h similarity index 100% rename from libsolidity/inlineasm/AsmParser.h rename to libyul/AsmParser.h diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libyul/AsmPrinter.cpp similarity index 100% rename from libsolidity/inlineasm/AsmPrinter.cpp rename to libyul/AsmPrinter.cpp diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libyul/AsmPrinter.h similarity index 100% rename from libsolidity/inlineasm/AsmPrinter.h rename to libyul/AsmPrinter.h diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libyul/AsmScope.cpp similarity index 100% rename from libsolidity/inlineasm/AsmScope.cpp rename to libyul/AsmScope.cpp diff --git a/libsolidity/inlineasm/AsmScope.h b/libyul/AsmScope.h similarity index 100% rename from libsolidity/inlineasm/AsmScope.h rename to libyul/AsmScope.h diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libyul/AsmScopeFiller.cpp similarity index 100% rename from libsolidity/inlineasm/AsmScopeFiller.cpp rename to libyul/AsmScopeFiller.cpp diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libyul/AsmScopeFiller.h similarity index 100% rename from libsolidity/inlineasm/AsmScopeFiller.h rename to libyul/AsmScopeFiller.h From 0f4ed52a719af90b52a15eb6709f46f03d4108b9 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 11:18:57 +0100 Subject: [PATCH 071/168] Rewrite header paths to adapt to recent `git mv` of libsolidity/inlineasm to libyul --- libsolidity/analysis/ReferencesResolver.cpp | 6 +++--- libsolidity/analysis/TypeChecker.cpp | 6 +++--- libsolidity/analysis/ViewPureChecker.cpp | 2 +- libsolidity/ast/ASTJsonConverter.cpp | 4 ++-- libsolidity/codegen/CompilerContext.cpp | 10 +++++----- libsolidity/codegen/ContractCompiler.cpp | 2 +- libsolidity/interface/AssemblyStack.cpp | 10 +++++----- libsolidity/parsing/Parser.cpp | 2 +- libyul/ASTDataForward.h | 2 +- libyul/AsmAnalysis.cpp | 10 +++++----- libyul/AsmAnalysis.h | 4 ++-- libyul/AsmAnalysisInfo.cpp | 4 ++-- libyul/AsmAnalysisInfo.h | 2 +- libyul/AsmCodeGen.cpp | 12 ++++++------ libyul/AsmCodeGen.h | 2 +- libyul/AsmData.h | 2 +- libyul/AsmParser.cpp | 2 +- libyul/AsmParser.h | 2 +- libyul/AsmPrinter.cpp | 4 ++-- libyul/AsmPrinter.h | 2 +- libyul/AsmScope.cpp | 2 +- libyul/AsmScopeFiller.cpp | 8 ++++---- libyul/AsmScopeFiller.h | 2 +- libyul/backends/evm/EVMCodeTransform.cpp | 4 ++-- libyul/backends/evm/EVMCodeTransform.h | 2 +- libyul/optimiser/ASTCopier.cpp | 2 +- libyul/optimiser/ASTWalker.cpp | 2 +- libyul/optimiser/BlockFlattener.cpp | 2 +- libyul/optimiser/CommonSubexpressionEliminator.cpp | 2 +- libyul/optimiser/DataFlowAnalyzer.cpp | 2 +- libyul/optimiser/Disambiguator.cpp | 4 ++-- libyul/optimiser/Disambiguator.h | 2 +- libyul/optimiser/ExpressionInliner.cpp | 2 +- libyul/optimiser/ExpressionJoiner.cpp | 2 +- libyul/optimiser/ExpressionSimplifier.cpp | 2 +- libyul/optimiser/ExpressionSplitter.cpp | 2 +- libyul/optimiser/ForLoopInitRewriter.cpp | 2 +- libyul/optimiser/FullInliner.cpp | 2 +- libyul/optimiser/FunctionGrouper.cpp | 2 +- libyul/optimiser/FunctionHoister.cpp | 2 +- .../optimiser/InlinableExpressionFunctionFinder.cpp | 2 +- libyul/optimiser/MainFunction.cpp | 2 +- libyul/optimiser/Metrics.cpp | 2 +- libyul/optimiser/NameCollector.cpp | 2 +- libyul/optimiser/NameDispenser.cpp | 2 +- libyul/optimiser/RedundantAssignEliminator.cpp | 2 +- libyul/optimiser/Rematerialiser.cpp | 2 +- libyul/optimiser/SSATransform.cpp | 2 +- libyul/optimiser/SSAValueTracker.cpp | 2 +- libyul/optimiser/Semantics.cpp | 2 +- libyul/optimiser/SimplificationRules.cpp | 2 +- libyul/optimiser/SimplificationRules.h | 2 +- libyul/optimiser/Substitution.cpp | 2 +- libyul/optimiser/Suite.cpp | 6 +++--- libyul/optimiser/SyntacticalEquality.cpp | 2 +- libyul/optimiser/UnusedPruner.cpp | 2 +- libyul/optimiser/Utilities.cpp | 2 +- libyul/optimiser/VarDeclPropagator.cpp | 2 +- libyul/optimiser/VarDeclPropagator.h | 2 +- test/libyul/Common.cpp | 6 +++--- test/libyul/Common.h | 2 +- test/libyul/Inliner.cpp | 2 +- test/libyul/Parser.cpp | 6 +++--- test/libyul/YulOptimizerTest.cpp | 6 +++--- test/tools/yulopti.cpp | 10 +++++----- 65 files changed, 107 insertions(+), 107 deletions(-) diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 7ac3ceff9..7399b344a 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -25,9 +25,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 69de9f127..3cf4d79f7 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -27,9 +27,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 3fb4c026f..a6236e7b9 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 6b9f72274..bd6deb6ef 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -23,8 +23,8 @@ #include #include #include -#include -#include +#include +#include using namespace std; using namespace langutil; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 9e4f2882f..5117567f4 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -29,10 +29,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -43,7 +43,7 @@ // Change to "define" to output all intermediate code #undef SOL_OUTPUT_ASM #ifdef SOL_OUTPUT_ASM -#include +#include #endif diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 7a1dcd709..b2a3e05f0 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -21,7 +21,7 @@ */ #include -#include +#include #include #include #include diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 5b6b11132..5d8343896 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -23,11 +23,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index de5293b4d..1ec10a728 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include using namespace std; diff --git a/libyul/ASTDataForward.h b/libyul/ASTDataForward.h index 8c49e68f6..16dc74114 100644 --- a/libyul/ASTDataForward.h +++ b/libyul/ASTDataForward.h @@ -21,7 +21,7 @@ #pragma once -#include +#include namespace dev { diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index fb96f73c8..34c5fbb67 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -18,12 +18,12 @@ * Analyzer part of inline assembly. */ -#include +#include -#include -#include -#include -#include +#include +#include +#include +#include #include diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index 194f736ee..edca5b50b 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -23,11 +23,11 @@ #include #include -#include +#include #include -#include +#include #include #include diff --git a/libyul/AsmAnalysisInfo.cpp b/libyul/AsmAnalysisInfo.cpp index 22318b12d..450c0f8f6 100644 --- a/libyul/AsmAnalysisInfo.cpp +++ b/libyul/AsmAnalysisInfo.cpp @@ -18,9 +18,9 @@ * Information generated during analyzer part of inline assembly. */ -#include +#include -#include +#include #include diff --git a/libyul/AsmAnalysisInfo.h b/libyul/AsmAnalysisInfo.h index bd3b28c4c..372ff3ed8 100644 --- a/libyul/AsmAnalysisInfo.h +++ b/libyul/AsmAnalysisInfo.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libyul/AsmCodeGen.cpp b/libyul/AsmCodeGen.cpp index 2800cc7b8..862337a7c 100644 --- a/libyul/AsmCodeGen.cpp +++ b/libyul/AsmCodeGen.cpp @@ -20,13 +20,13 @@ * Code-generating part of inline assembly. */ -#include +#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include #include diff --git a/libyul/AsmCodeGen.h b/libyul/AsmCodeGen.h index bbc31397b..e5e53c0d8 100644 --- a/libyul/AsmCodeGen.h +++ b/libyul/AsmCodeGen.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include diff --git a/libyul/AsmData.h b/libyul/AsmData.h index 23a9db75c..e7af61bbd 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include #include diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index b11f70e06..0d3bc32f0 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -20,7 +20,7 @@ * Solidity inline assembly parser. */ -#include +#include #include #include diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 9e13799a6..874b4d6d5 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 7151fcfa1..49e2f33be 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -20,8 +20,8 @@ * Converts a parsed assembly into its textual form. */ -#include -#include +#include +#include #include #include diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index 720489750..ab0c9a088 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -22,7 +22,7 @@ #pragma once -#include +#include #include diff --git a/libyul/AsmScope.cpp b/libyul/AsmScope.cpp index 10893b96b..0d7aca577 100644 --- a/libyul/AsmScope.cpp +++ b/libyul/AsmScope.cpp @@ -18,7 +18,7 @@ * Scopes for identifiers. */ -#include +#include using namespace std; using namespace dev; diff --git a/libyul/AsmScopeFiller.cpp b/libyul/AsmScopeFiller.cpp index 09934bd8f..2070d8de6 100644 --- a/libyul/AsmScopeFiller.cpp +++ b/libyul/AsmScopeFiller.cpp @@ -18,11 +18,11 @@ * Module responsible for registering identifiers inside their scopes. */ -#include +#include -#include -#include -#include +#include +#include +#include #include #include diff --git a/libyul/AsmScopeFiller.h b/libyul/AsmScopeFiller.h index 7454fd6c0..fbd65bbac 100644 --- a/libyul/AsmScopeFiller.h +++ b/libyul/AsmScopeFiller.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 23e09756f..3cf1061a6 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -20,8 +20,8 @@ #include -#include -#include +#include +#include #include diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index c0de8ad61..f4696e812 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -22,7 +22,7 @@ #include -#include +#include #include #include diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index d0c8dd456..d4781ec27 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/ASTWalker.cpp b/libyul/optimiser/ASTWalker.cpp index e29dda6bc..ed4a07ad9 100644 --- a/libyul/optimiser/ASTWalker.cpp +++ b/libyul/optimiser/ASTWalker.cpp @@ -20,7 +20,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/BlockFlattener.cpp b/libyul/optimiser/BlockFlattener.cpp index 04f3ad7f5..4552e3f1a 100644 --- a/libyul/optimiser/BlockFlattener.cpp +++ b/libyul/optimiser/BlockFlattener.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see . */ #include -#include +#include #include #include #include diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 64605362d..118d14ad7 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 134777d03..7642948a5 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 4303f412d..f6553ef63 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -22,8 +22,8 @@ #include -#include -#include +#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 0fcd41d9b..032bfedce 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index 07e881912..2a1b8e639 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index 7e57a629e..647e27053 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 64e9d7e75..2c67c77aa 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 42730864f..54a03620e 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/ForLoopInitRewriter.cpp b/libyul/optimiser/ForLoopInitRewriter.cpp index 0decf5e22..b5e59884a 100644 --- a/libyul/optimiser/ForLoopInitRewriter.cpp +++ b/libyul/optimiser/ForLoopInitRewriter.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see . */ #include -#include +#include #include #include diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index c9057cf34..a77f12f3f 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include diff --git a/libyul/optimiser/FunctionGrouper.cpp b/libyul/optimiser/FunctionGrouper.cpp index 3d2e53220..dc721caee 100644 --- a/libyul/optimiser/FunctionGrouper.cpp +++ b/libyul/optimiser/FunctionGrouper.cpp @@ -21,7 +21,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/FunctionHoister.cpp b/libyul/optimiser/FunctionHoister.cpp index c196dead1..d5c25e231 100644 --- a/libyul/optimiser/FunctionHoister.cpp +++ b/libyul/optimiser/FunctionHoister.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index deaaee979..b15d17cea 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -22,7 +22,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/MainFunction.cpp b/libyul/optimiser/MainFunction.cpp index f33065988..5f3350310 100644 --- a/libyul/optimiser/MainFunction.cpp +++ b/libyul/optimiser/MainFunction.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 066c6b58c..5107fc590 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -20,7 +20,7 @@ #include -#include +#include using namespace dev; using namespace dev::yul; diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index 36f55b993..7da001f8b 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -20,7 +20,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index 3c870fa51..0109e606e 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -22,7 +22,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/RedundantAssignEliminator.cpp index b7217074b..e10fd549e 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/RedundantAssignEliminator.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index 38d50ef4a..8578748fb 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 6fb4b08dc..dd9817753 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/SSAValueTracker.cpp b/libyul/optimiser/SSAValueTracker.cpp index 491117da4..24776498f 100644 --- a/libyul/optimiser/SSAValueTracker.cpp +++ b/libyul/optimiser/SSAValueTracker.cpp @@ -21,7 +21,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index 3c49016ee..f16a16306 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index a15ed3916..48945fbcb 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index bd6aa4de9..de8bcf209 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -25,7 +25,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/Substitution.cpp b/libyul/optimiser/Substitution.cpp index 9b3d4c032..dbac5cf62 100644 --- a/libyul/optimiser/Substitution.cpp +++ b/libyul/optimiser/Substitution.cpp @@ -20,7 +20,7 @@ #include -#include +#include using namespace std; using namespace dev; diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 4d6dad45b..db6dbf3e0 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -36,10 +36,10 @@ #include #include -#include -#include +#include +#include -#include +#include #include diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 66912383a..092f9d825 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 71e867985..2072f42ba 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include diff --git a/libyul/optimiser/Utilities.cpp b/libyul/optimiser/Utilities.cpp index df01ed39b..e41fd15d8 100644 --- a/libyul/optimiser/Utilities.cpp +++ b/libyul/optimiser/Utilities.cpp @@ -20,7 +20,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/VarDeclPropagator.cpp b/libyul/optimiser/VarDeclPropagator.cpp index 537b7020d..855b82150 100644 --- a/libyul/optimiser/VarDeclPropagator.cpp +++ b/libyul/optimiser/VarDeclPropagator.cpp @@ -16,7 +16,7 @@ */ #include -#include +#include #include #include #include diff --git a/libyul/optimiser/VarDeclPropagator.h b/libyul/optimiser/VarDeclPropagator.h index 4522d23ae..ffecd2175 100644 --- a/libyul/optimiser/VarDeclPropagator.h +++ b/libyul/optimiser/VarDeclPropagator.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 8913483f2..ae7686b7d 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -27,9 +27,9 @@ #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/test/libyul/Common.h b/test/libyul/Common.h index 390e214f8..8241bfe1a 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index 66810298e..38d2491f0 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 4aa3dd5c0..957973d07 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -23,9 +23,9 @@ #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 6b2b81c3d..a8ad56807 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -44,9 +44,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 8bc807d43..4e916b497 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -21,12 +21,12 @@ #include #include #include -#include -#include +#include +#include #include -#include -#include -#include +#include +#include +#include #include #include From 0ff4cbe51ba653397a1937c8c08b3d09541492ef Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Thu, 15 Nov 2018 16:47:52 +0100 Subject: [PATCH 072/168] Add SMTChecker tests for standard JSON --- libdevcore/JSON.cpp | 8 ++ libdevcore/JSON.h | 7 + test/boostTest.cpp | 10 ++ test/libsolidity/SMTCheckerJSONTest.cpp | 128 ++++++++++++++++++ test/libsolidity/SMTCheckerJSONTest.h | 53 ++++++++ test/libsolidity/SyntaxTest.cpp | 5 + test/libsolidity/SyntaxTest.h | 4 +- .../smtCheckerTestsJSON/multi.json | 11 ++ .../libsolidity/smtCheckerTestsJSON/multi.sol | 13 ++ .../smtCheckerTestsJSON/simple.json | 9 ++ .../smtCheckerTestsJSON/simple.sol | 10 ++ test/tools/CMakeLists.txt | 2 +- test/tools/isoltest.cpp | 12 ++ 13 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 test/libsolidity/SMTCheckerJSONTest.cpp create mode 100644 test/libsolidity/SMTCheckerJSONTest.h create mode 100644 test/libsolidity/smtCheckerTestsJSON/multi.json create mode 100644 test/libsolidity/smtCheckerTestsJSON/multi.sol create mode 100644 test/libsolidity/smtCheckerTestsJSON/simple.json create mode 100644 test/libsolidity/smtCheckerTestsJSON/simple.sol diff --git a/libdevcore/JSON.cpp b/libdevcore/JSON.cpp index 6317cc896..086fae500 100644 --- a/libdevcore/JSON.cpp +++ b/libdevcore/JSON.cpp @@ -21,6 +21,8 @@ #include "JSON.h" +#include "CommonIO.h" + #include #include #include @@ -111,4 +113,10 @@ bool jsonParse(string const& _input, Json::Value& _json, string *_errs /* = null return parse(readerBuilder, _input, _json, _errs); } +bool jsonParseFile(string const& _fileName, Json::Value& _json, string *_errs /* = nullptr */) +{ + return jsonParse(readFileAsString(_fileName), _json, _errs); +} + + } // namespace dev diff --git a/libdevcore/JSON.h b/libdevcore/JSON.h index 1ce822cd4..ecb934673 100644 --- a/libdevcore/JSON.h +++ b/libdevcore/JSON.h @@ -48,4 +48,11 @@ bool jsonParseStrict(std::string const& _input, Json::Value& _json, std::string* /// \return \c true if the document was successfully parsed, \c false if an error occurred. bool jsonParse(std::string const& _input, Json::Value& _json, std::string* _errs = nullptr); +/// Parse a JSON string (@a _input) and writes resulting JSON object to (@a _json) +/// \param _input file containing JSON input +/// \param _json [out] resulting JSON object +/// \param _errs [out] Formatted error messages +/// \return \c true if the document was successfully parsed, \c false if an error occurred. +bool jsonParseFile(std::string const& _fileName, Json::Value& _json, std::string* _errs = nullptr); + } diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 5352ef858..6ff6d2d2a 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -146,12 +147,21 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) dev::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: { diff --git a/test/libsolidity/SMTCheckerJSONTest.cpp b/test/libsolidity/SMTCheckerJSONTest.cpp new file mode 100644 index 000000000..6e1329a96 --- /dev/null +++ b/test/libsolidity/SMTCheckerJSONTest.cpp @@ -0,0 +1,128 @@ +/* + 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 . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) +{ + BOOST_REQUIRE_MESSAGE(boost::algorithm::ends_with(_filename, ".sol"), "Invalid test contract file name: \"" + _filename + "\"."); + + string jsonFilename = _filename.substr(0, _filename.size() - 4) + ".json"; + BOOST_CHECK(jsonParseFile(jsonFilename, m_smtResponses)); + BOOST_CHECK(m_smtResponses.isObject()); +} + +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 outHashes = hashesFromJson(result, "auxiliaryInputRequested", "smtlib2queries"); + + // This is the list of responses provided in the test + string auxInput("auxiliaryInput"); + BOOST_CHECK(m_smtResponses.isMember(auxInput)); + vector inHashes = hashesFromJson(m_smtResponses, auxInput, "smtlib2responses"); + + // Ensure that the provided list matches the requested one + BOOST_CHECK_MESSAGE( + outHashes == inHashes, + "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); + + BOOST_CHECK(endResult.isMember("errors")); + Json::Value const& errors = endResult["errors"]; + for (auto const& error: errors) + { + BOOST_CHECK(error.isMember("type") && error["type"].isString()); + BOOST_CHECK(error.isMember("message") && error["message"].isString()); + if (!error.isMember("sourceLocation")) + continue; + Json::Value const& location = error["sourceLocation"]; + BOOST_CHECK(location.isMember("start") && location["start"].isInt()); + BOOST_CHECK(location.isMember("end") && location["end"].isInt()); + int start = location["start"].asInt(); + int end = location["end"].asInt(); + if (start >= static_cast(versionPragma.size())) + start -= versionPragma.size(); + if (end >= static_cast(versionPragma.size())) + end -= versionPragma.size(); + m_errorList.emplace_back(SyntaxTestError{ + error["type"].asString(), + error["message"].asString(), + start, + end + }); + } + + return printExpectationAndError(_stream, _linePrefix, _formatted); +} + +vector SMTCheckerTest::hashesFromJson(Json::Value const& _jsonObj, string const& _auxInput, string const& _smtlib) +{ + vector 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; + BOOST_REQUIRE(jsonParse(input, source)); + return source; +} diff --git a/test/libsolidity/SMTCheckerJSONTest.h b/test/libsolidity/SMTCheckerJSONTest.h new file mode 100644 index 000000000..cf41acac5 --- /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 . +*/ + +#pragma once + +#include + +#include + +#include + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class SMTCheckerTest: public SyntaxTest +{ +public: + static std::unique_ptr create(std::string const& _filename) + { + return std::unique_ptr(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 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/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 45d32b555..c47ea599c 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -92,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 0f151e663..d286f9341 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -67,7 +67,7 @@ public: } static std::string errorMessage(Exception const& _e); -private: +protected: static void printErrorList( std::ostream& _stream, std::vector 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 parseExpectations(std::istream& _stream); std::string m_source; diff --git a/test/libsolidity/smtCheckerTestsJSON/multi.json b/test/libsolidity/smtCheckerTestsJSON/multi.json new file mode 100644 index 000000000..2ed5150d6 --- /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 000000000..e0d69b1d0 --- /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 000000000..fd976b63d --- /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 000000000..6bc7193db --- /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/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 19a1d9581..a0fbe140f 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -6,5 +6,5 @@ target_link_libraries(yulopti PRIVATE solidity ${Boost_PROGRAM_OPTIONS_LIBRARIES add_executable(isoltest isoltest.cpp ../Options.cpp ../Common.cpp ../libsolidity/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 1b6fd54a8..f8e2dc58e 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -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: "; From 713d94476ec5ba61901b538c622c8cca6873c2af Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 11:31:45 +0100 Subject: [PATCH 073/168] Reorder some include files and group 's together (as much as possible) --- libsolidity/analysis/ReferencesResolver.cpp | 2 +- libsolidity/analysis/ViewPureChecker.cpp | 2 +- libsolidity/codegen/CompilerContext.cpp | 5 ++--- libsolidity/codegen/ContractCompiler.cpp | 6 +++--- libsolidity/interface/AssemblyStack.cpp | 5 ++--- libsolidity/interface/CompilerStack.cpp | 7 ++++--- libsolidity/parsing/Parser.cpp | 4 ++-- libyul/AsmCodeGen.cpp | 9 +++++---- libyul/AsmData.h | 4 ++-- libyul/optimiser/CommonSubexpressionEliminator.cpp | 1 - libyul/optimiser/DataFlowAnalyzer.cpp | 1 - libyul/optimiser/DataFlowAnalyzer.h | 1 - libyul/optimiser/Disambiguator.cpp | 1 - libyul/optimiser/Disambiguator.h | 4 +--- libyul/optimiser/ExpressionInliner.cpp | 1 - libyul/optimiser/ExpressionInliner.h | 1 - libyul/optimiser/ExpressionJoiner.cpp | 1 - libyul/optimiser/ExpressionJoiner.h | 1 - libyul/optimiser/ExpressionSimplifier.cpp | 1 - libyul/optimiser/FullInliner.cpp | 1 - libyul/optimiser/FunctionHoister.cpp | 1 - libyul/optimiser/FunctionHoister.h | 1 - libyul/optimiser/InlinableExpressionFunctionFinder.cpp | 1 - libyul/optimiser/NameDispenser.cpp | 1 - libyul/optimiser/RedundantAssignEliminator.cpp | 1 - libyul/optimiser/RedundantAssignEliminator.h | 1 - libyul/optimiser/Rematerialiser.cpp | 1 - libyul/optimiser/SSATransform.cpp | 1 - libyul/optimiser/SSATransform.h | 1 - libyul/optimiser/Semantics.cpp | 1 - libyul/optimiser/SimplificationRules.cpp | 1 - libyul/optimiser/SimplificationRules.h | 1 - libyul/optimiser/Substitution.h | 1 - libyul/optimiser/Suite.cpp | 2 -- libyul/optimiser/SyntacticalEquality.cpp | 1 - libyul/optimiser/UnusedPruner.cpp | 1 - test/libyul/Common.cpp | 7 +++---- test/libyul/Inliner.cpp | 1 - test/libyul/YulOptimizerTest.cpp | 7 +++---- 39 files changed, 29 insertions(+), 61 deletions(-) diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 7399b344a..1593c3e03 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -23,12 +23,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index a6236e7b9..7839ecd34 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -19,8 +19,8 @@ #include -#include #include +#include #include diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 5117567f4..32be521c9 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -25,15 +25,14 @@ #include #include #include -#include -#include #include -#include #include #include #include #include #include +#include +#include #include diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index b2a3e05f0..815c2a4ff 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -21,11 +21,11 @@ */ #include -#include -#include -#include #include #include +#include +#include +#include #include #include diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 5d8343896..cd8b125e8 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -28,12 +28,11 @@ #include #include #include - -#include - #include #include +#include + using namespace std; using namespace dev; using namespace langutil; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a56747052..f3c15cc9f 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -45,10 +44,12 @@ #include #include -#include - #include +#include + +#include + #include #include diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 1ec10a728..560d8e8b4 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -22,11 +22,11 @@ #include #include -#include #include -#include #include +#include #include +#include using namespace std; using namespace langutil; diff --git a/libyul/AsmCodeGen.cpp b/libyul/AsmCodeGen.cpp index 862337a7c..5bc2fee38 100644 --- a/libyul/AsmCodeGen.cpp +++ b/libyul/AsmCodeGen.cpp @@ -28,13 +28,14 @@ #include #include -#include -#include -#include - #include #include +#include +#include + +#include + #include #include diff --git a/libyul/AsmData.h b/libyul/AsmData.h index e7af61bbd..6979d29cc 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -24,11 +24,11 @@ #include +#include + #include #include -#include - #include #include diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index 118d14ad7..fc78b1ad7 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -24,7 +24,6 @@ #include #include #include - #include using namespace std; diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 7642948a5..046f466c3 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -25,7 +25,6 @@ #include #include #include - #include #include diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index a946529ab..f83543c55 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -23,7 +23,6 @@ #pragma once #include - #include #include diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index f6553ef63..e8c31aea1 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -21,7 +21,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 032bfedce..b2f80e476 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -21,12 +21,10 @@ #pragma once #include - +#include #include #include -#include - #include #include diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index 2a1b8e639..abc006d43 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -23,7 +23,6 @@ #include #include #include - #include #include diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index ee98da8fb..46c27080a 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -20,7 +20,6 @@ #pragma once #include - #include #include diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index 647e27053..90301bad8 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -24,7 +24,6 @@ #include #include #include - #include #include diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index 0cc619811..62d3beb9e 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -21,7 +21,6 @@ #pragma once #include - #include #include diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 2c67c77aa..8746a783b 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -23,7 +23,6 @@ #include #include #include - #include #include diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index a77f12f3f..47299f5fc 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -27,7 +27,6 @@ #include #include #include - #include #include diff --git a/libyul/optimiser/FunctionHoister.cpp b/libyul/optimiser/FunctionHoister.cpp index d5c25e231..517559687 100644 --- a/libyul/optimiser/FunctionHoister.cpp +++ b/libyul/optimiser/FunctionHoister.cpp @@ -22,7 +22,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 823b9e2b8..298948951 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -22,7 +22,6 @@ #pragma once #include - #include namespace dev diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index b15d17cea..22267b622 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -21,7 +21,6 @@ #include #include - #include using namespace std; diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index 0109e606e..11e854776 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -21,7 +21,6 @@ #include #include - #include using namespace std; diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/RedundantAssignEliminator.cpp index e10fd549e..f415a36cb 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/RedundantAssignEliminator.cpp @@ -22,7 +22,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/RedundantAssignEliminator.h index 76106aae1..bffbb07ad 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/RedundantAssignEliminator.h @@ -22,7 +22,6 @@ #pragma once #include - #include #include diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index 8578748fb..b9a127bbe 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -23,7 +23,6 @@ #include #include #include - #include using namespace std; diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index dd9817753..ae84dd948 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -23,7 +23,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index bb6425491..69638904b 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -21,7 +21,6 @@ #pragma once #include - #include #include diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index f16a16306..ad9b19226 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -21,7 +21,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 48945fbcb..ec5379fc5 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -24,7 +24,6 @@ #include #include #include - #include #include diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index de8bcf209..3d3d8d2b9 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -24,7 +24,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index 3cc4b45e7..6a0679f5c 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -21,7 +21,6 @@ #pragma once #include - #include #include diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index db6dbf3e0..b69206331 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -35,10 +35,8 @@ #include #include #include - #include #include - #include #include diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index 092f9d825..ff4ff81b5 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -21,7 +21,6 @@ #include #include - #include #include diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 2072f42ba..484e74756 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -24,7 +24,6 @@ #include #include #include - #include #include diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index ae7686b7d..5851555a1 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -23,15 +23,14 @@ #include +#include + #include - -#include - #include #include #include -#include +#include #include #include diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index 38d2491f0..0f82dee3d 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -26,7 +26,6 @@ #include #include #include - #include #include diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index a8ad56807..02a63ae34 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -21,9 +21,6 @@ #include -#include -#include - #include #include #include @@ -43,12 +40,14 @@ #include #include #include - #include #include #include #include +#include +#include + #include #include From 3734f40d315439f8a791967a6adfda8cf9fd1e55 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 11:39:40 +0100 Subject: [PATCH 074/168] CMake: Isolate libyul into its own static library --- CMakeLists.txt | 1 + libsolidity/CMakeLists.txt | 6 +++--- libyul/CMakeLists.txt | 43 ++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 2 +- 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 libyul/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index ed51e5a7f..b22ade233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ configure_project(TESTS) add_subdirectory(libdevcore) add_subdirectory(liblangutil) add_subdirectory(libevmasm) +add_subdirectory(libyul) add_subdirectory(libsolidity) add_subdirectory(libsolc) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index c57fca16e..c40087f05 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,6 +1,6 @@ # Until we have a clear separation, libyul has to be included here -file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp") -file(GLOB_RECURSE headers "*.h" "../libyul/*.h") +file(GLOB_RECURSE sources "*.cpp") +file(GLOB_RECURSE headers "*.h") find_package(Z3 QUIET) if (${Z3_FOUND}) @@ -26,7 +26,7 @@ if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) endif() add_library(solidity ${sources} ${headers}) -target_link_libraries(solidity PUBLIC evmasm langutil devcore ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) +target_link_libraries(solidity PUBLIC yul evmasm langutil devcore ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) if (${Z3_FOUND}) target_link_libraries(solidity PUBLIC ${Z3_LIBRARY}) diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt new file mode 100644 index 000000000..8fbea6899 --- /dev/null +++ b/libyul/CMakeLists.txt @@ -0,0 +1,43 @@ +add_library(yul + AsmAnalysis.cpp + AsmAnalysisInfo.cpp + AsmCodeGen.cpp + AsmParser.cpp + AsmPrinter.cpp + AsmScope.cpp + AsmScopeFiller.cpp + backends/evm/EVMAssembly.cpp + backends/evm/EVMCodeTransform.cpp + optimiser/ASTCopier.cpp + optimiser/ASTWalker.cpp + optimiser/BlockFlattener.cpp + optimiser/CommonSubexpressionEliminator.cpp + optimiser/DataFlowAnalyzer.cpp + optimiser/Disambiguator.cpp + optimiser/ExpressionInliner.cpp + optimiser/ExpressionJoiner.cpp + optimiser/ExpressionSimplifier.cpp + optimiser/ExpressionSplitter.cpp + optimiser/ForLoopInitRewriter.cpp + optimiser/FullInliner.cpp + optimiser/FunctionGrouper.cpp + optimiser/FunctionHoister.cpp + optimiser/InlinableExpressionFunctionFinder.cpp + optimiser/MainFunction.cpp + optimiser/Metrics.cpp + optimiser/NameCollector.cpp + optimiser/NameDispenser.cpp + optimiser/RedundantAssignEliminator.cpp + optimiser/Rematerialiser.cpp + optimiser/SSATransform.cpp + optimiser/SSAValueTracker.cpp + optimiser/Semantics.cpp + optimiser/SimplificationRules.cpp + optimiser/Substitution.cpp + optimiser/Suite.cpp + optimiser/SyntacticalEquality.cpp + optimiser/UnusedPruner.cpp + optimiser/Utilities.cpp + optimiser/VarDeclPropagator.cpp +) +target_link_libraries(yul PUBLIC devcore) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index acfc7d00b..10b78bdcd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,7 +27,7 @@ add_executable(soltest ${sources} ${headers} ${liblll_sources} ${liblll_headers} ${libsolidity_sources} ${libsolidity_headers} ) -target_link_libraries(soltest PRIVATE libsolc solidity 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) From 58a744f06d407dc9e982b955b794bd8c6f61765c Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 12:57:31 +0100 Subject: [PATCH 075/168] Replace all occurrences of NULL with nullptr. --- liblangutil/Token.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 0b7d9f71d..d997b138c 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -56,7 +56,7 @@ namespace langutil // TOKEN_LIST takes a list of 3 macros M, all of which satisfy the // same signature M(name, string, precedence), where name is the // symbolic token name, string is the corresponding syntactic symbol -// (or NULL, for literals), and precedence is the precedence (or 0). +// (or nullptr, for literals), and precedence is the precedence (or 0). // The parameters are invoked for token categories as follows: // // T: Non-keyword tokens @@ -211,17 +211,17 @@ namespace langutil T(BytesM, "bytesM", 0) \ T(FixedMxN, "fixedMxN", 0) \ T(UFixedMxN, "ufixedMxN", 0) \ - T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ + T(TypesEnd, nullptr, 0) /* used as type enum end marker */ \ \ /* Literals */ \ K(TrueLiteral, "true", 0) \ K(FalseLiteral, "false", 0) \ - T(Number, NULL, 0) \ - T(StringLiteral, NULL, 0) \ - T(CommentLiteral, NULL, 0) \ + T(Number, nullptr, 0) \ + T(StringLiteral, nullptr, 0) \ + T(CommentLiteral, nullptr, 0) \ \ /* Identifiers (not keywords or future reserved words). */ \ - T(Identifier, NULL, 0) \ + T(Identifier, nullptr, 0) \ \ /* Keywords reserved for future use. */ \ K(Abstract, "abstract", 0) \ @@ -267,7 +267,7 @@ namespace langutil T(IllegalHex, "ILLEGAL_HEX", 0) \ \ /* Scanner-internal use only. */ \ - T(Whitespace, NULL, 0) + T(Whitespace, nullptr, 0) // All token values. // attention! msvc issue: @@ -329,7 +329,7 @@ namespace TokenTraits char const* name(Token tok); // @returns a string corresponding to the JS token string - // (.e., "<" for the token LT) or NULL if the token doesn't + // (.e., "<" for the token LT) or nullptr if the token doesn't // have a (unique) string (e.g. an IDENTIFIER). char const* toString(Token tok); From ec47c8946ba5f78563b7eca2512b3cee68db45b4 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 21 Nov 2018 12:42:34 +0100 Subject: [PATCH 076/168] Isolating libyul library API into its own namespace `yul`. --- libsolidity/analysis/ReferencesResolver.cpp | 6 +- libsolidity/analysis/TypeChecker.cpp | 8 +-- libsolidity/analysis/ViewPureChecker.cpp | 30 ++++---- libsolidity/ast/AST.h | 18 ++--- libsolidity/ast/ASTAnnotations.h | 16 ++--- libsolidity/ast/ASTJsonConverter.cpp | 4 +- libsolidity/ast/ASTJsonConverter.h | 2 +- libsolidity/codegen/CompilerContext.cpp | 16 ++--- libsolidity/codegen/ContractCompiler.cpp | 6 +- libsolidity/interface/AssemblyStack.cpp | 24 +++---- libsolidity/interface/AssemblyStack.h | 17 ++--- libsolidity/parsing/Parser.cpp | 4 +- libyul/ASTDataForward.h | 30 -------- libyul/AsmAnalysis.cpp | 31 +++++---- libyul/AsmAnalysis.h | 52 +++++++------- libyul/AsmAnalysisInfo.h | 12 +--- libyul/AsmCodeGen.cpp | 10 +-- libyul/AsmCodeGen.h | 10 ++- libyul/AsmData.h | 14 +--- libyul/AsmDataForward.h | 8 +-- libyul/AsmParser.cpp | 68 +++++++++---------- libyul/AsmParser.h | 14 ++-- libyul/AsmPrinter.cpp | 24 +++---- libyul/AsmPrinter.h | 40 +++++------ libyul/AsmScope.cpp | 12 ++-- libyul/AsmScope.h | 28 +++----- libyul/AsmScopeFiller.cpp | 6 +- libyul/AsmScopeFiller.h | 40 +++++------ libyul/Exceptions.h | 7 +- libyul/YulString.h | 3 - libyul/backends/evm/AbstractAssembly.h | 21 +++--- libyul/backends/evm/EVMAssembly.cpp | 2 +- libyul/backends/evm/EVMAssembly.h | 13 ++-- libyul/backends/evm/EVMCodeTransform.cpp | 18 +++-- libyul/backends/evm/EVMCodeTransform.h | 32 ++++----- libyul/optimiser/ASTCopier.cpp | 2 +- libyul/optimiser/ASTCopier.h | 3 - libyul/optimiser/ASTWalker.cpp | 2 +- libyul/optimiser/ASTWalker.h | 3 - libyul/optimiser/BlockFlattener.cpp | 2 +- libyul/optimiser/BlockFlattener.h | 3 - .../CommonSubexpressionEliminator.cpp | 2 +- .../optimiser/CommonSubexpressionEliminator.h | 3 - libyul/optimiser/DataFlowAnalyzer.cpp | 2 +- libyul/optimiser/DataFlowAnalyzer.h | 3 - libyul/optimiser/Disambiguator.cpp | 4 +- libyul/optimiser/Disambiguator.h | 13 ++-- libyul/optimiser/ExpressionInliner.cpp | 2 +- libyul/optimiser/ExpressionInliner.h | 3 - libyul/optimiser/ExpressionJoiner.cpp | 2 +- libyul/optimiser/ExpressionJoiner.h | 3 - libyul/optimiser/ExpressionSimplifier.cpp | 2 +- libyul/optimiser/ExpressionSimplifier.h | 3 - libyul/optimiser/ExpressionSplitter.cpp | 2 +- libyul/optimiser/ExpressionSplitter.h | 3 - libyul/optimiser/ForLoopInitRewriter.cpp | 2 +- libyul/optimiser/ForLoopInitRewriter.h | 3 - libyul/optimiser/FullInliner.cpp | 2 +- libyul/optimiser/FullInliner.h | 3 - libyul/optimiser/FunctionGrouper.cpp | 2 +- libyul/optimiser/FunctionGrouper.h | 3 - libyul/optimiser/FunctionHoister.cpp | 2 +- libyul/optimiser/FunctionHoister.h | 3 - .../InlinableExpressionFunctionFinder.cpp | 2 +- .../InlinableExpressionFunctionFinder.h | 3 - libyul/optimiser/MainFunction.cpp | 2 +- libyul/optimiser/MainFunction.h | 3 - libyul/optimiser/Metrics.cpp | 2 +- libyul/optimiser/Metrics.h | 3 - libyul/optimiser/NameCollector.cpp | 2 +- libyul/optimiser/NameCollector.h | 3 - libyul/optimiser/NameDispenser.cpp | 2 +- libyul/optimiser/NameDispenser.h | 3 - .../optimiser/RedundantAssignEliminator.cpp | 2 +- libyul/optimiser/RedundantAssignEliminator.h | 3 - libyul/optimiser/Rematerialiser.cpp | 2 +- libyul/optimiser/Rematerialiser.h | 3 - libyul/optimiser/SSATransform.cpp | 2 +- libyul/optimiser/SSATransform.h | 3 - libyul/optimiser/SSAValueTracker.cpp | 2 +- libyul/optimiser/SSAValueTracker.h | 3 - libyul/optimiser/Semantics.cpp | 2 +- libyul/optimiser/Semantics.h | 3 - libyul/optimiser/SimplificationRules.cpp | 8 +-- libyul/optimiser/SimplificationRules.h | 17 ++--- libyul/optimiser/Substitution.cpp | 2 +- libyul/optimiser/Substitution.h | 3 - libyul/optimiser/Suite.cpp | 4 +- libyul/optimiser/Suite.h | 14 +--- libyul/optimiser/SyntacticalEquality.cpp | 2 +- libyul/optimiser/SyntacticalEquality.h | 3 - libyul/optimiser/UnusedPruner.cpp | 2 +- libyul/optimiser/UnusedPruner.h | 3 - libyul/optimiser/Utilities.cpp | 4 +- libyul/optimiser/Utilities.h | 3 - libyul/optimiser/VarDeclPropagator.cpp | 5 +- libyul/optimiser/VarDeclPropagator.h | 3 - test/boostTest.cpp | 2 +- test/libyul/Common.cpp | 20 +++--- test/libyul/Common.h | 13 ++-- test/libyul/Inliner.cpp | 4 +- test/libyul/Parser.cpp | 16 ++--- test/libyul/YulOptimizerTest.cpp | 16 ++--- test/libyul/YulOptimizerTest.h | 15 ++-- test/tools/yulopti.cpp | 11 ++- 105 files changed, 366 insertions(+), 582 deletions(-) diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 1593c3e03..c4931d980 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -273,7 +273,7 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) ErrorList errors; ErrorReporter errorsIgnored(errors); yul::ExternalIdentifierAccess::Resolver resolver = - [&](assembly::Identifier const& _identifier, yul::IdentifierContext, bool _crossesFunctionBoundary) { + [&](yul::Identifier const& _identifier, yul::IdentifierContext, bool _crossesFunctionBoundary) { auto declarations = m_resolver.nameFromCurrentScope(_identifier.name.str()); bool isSlot = boost::algorithm::ends_with(_identifier.name.str(), "_slot"); bool isOffset = boost::algorithm::ends_with(_identifier.name.str(), "_offset"); @@ -314,9 +314,9 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) // Will be re-generated later with correct information // We use the latest EVM version because we will re-run it anyway. - assembly::AsmAnalysisInfo analysisInfo; + yul::AsmAnalysisInfo analysisInfo; boost::optional errorTypeForLoose = Error::Type::SyntaxError; - assembly::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), errorTypeForLoose, assembly::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations()); + yul::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), errorTypeForLoose, yul::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations()); return false; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3cf4d79f7..4e63875b3 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -954,7 +954,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) // External references have already been resolved in a prior stage and stored in the annotation. // We run the resolve step again regardless. yul::ExternalIdentifierAccess::Resolver identifierAccess = [&]( - assembly::Identifier const& _identifier, + yul::Identifier const& _identifier, yul::IdentifierContext _context, bool ) @@ -1039,13 +1039,13 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) return size_t(1); }; solAssert(!_inlineAssembly.annotation().analysisInfo, ""); - _inlineAssembly.annotation().analysisInfo = make_shared(); - assembly::AsmAnalyzer analyzer( + _inlineAssembly.annotation().analysisInfo = make_shared(); + yul::AsmAnalyzer analyzer( *_inlineAssembly.annotation().analysisInfo, m_errorReporter, m_evmVersion, Error::Type::SyntaxError, - assembly::AsmFlavour::Loose, + yul::AsmFlavour::Loose, identifierAccess ); if (!analyzer.analyze(_inlineAssembly.operations())) diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 7839ecd34..1112d6825 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -40,48 +40,48 @@ public: explicit AssemblyViewPureChecker(std::function _reportMutability): m_reportMutability(_reportMutability) {} - void operator()(assembly::Label const&) { } - void operator()(assembly::Instruction const& _instruction) + void operator()(yul::Label const&) { } + void operator()(yul::Instruction const& _instruction) { checkInstruction(_instruction.location, _instruction.instruction); } - void operator()(assembly::Literal const&) {} - void operator()(assembly::Identifier const&) {} - void operator()(assembly::FunctionalInstruction const& _instr) + void operator()(yul::Literal const&) {} + void operator()(yul::Identifier const&) {} + void operator()(yul::FunctionalInstruction const& _instr) { checkInstruction(_instr.location, _instr.instruction); for (auto const& arg: _instr.arguments) boost::apply_visitor(*this, arg); } - void operator()(assembly::ExpressionStatement const& _expr) + void operator()(yul::ExpressionStatement const& _expr) { boost::apply_visitor(*this, _expr.expression); } - void operator()(assembly::StackAssignment const&) {} - void operator()(assembly::Assignment const& _assignment) + void operator()(yul::StackAssignment const&) {} + void operator()(yul::Assignment const& _assignment) { boost::apply_visitor(*this, *_assignment.value); } - void operator()(assembly::VariableDeclaration const& _varDecl) + void operator()(yul::VariableDeclaration const& _varDecl) { if (_varDecl.value) boost::apply_visitor(*this, *_varDecl.value); } - void operator()(assembly::FunctionDefinition const& _funDef) + void operator()(yul::FunctionDefinition const& _funDef) { (*this)(_funDef.body); } - void operator()(assembly::FunctionCall const& _funCall) + void operator()(yul::FunctionCall const& _funCall) { for (auto const& arg: _funCall.arguments) boost::apply_visitor(*this, arg); } - void operator()(assembly::If const& _if) + void operator()(yul::If const& _if) { boost::apply_visitor(*this, *_if.condition); (*this)(_if.body); } - void operator()(assembly::Switch const& _switch) + void operator()(yul::Switch const& _switch) { boost::apply_visitor(*this, *_switch.expression); for (auto const& _case: _switch.cases) @@ -91,14 +91,14 @@ public: (*this)(_case.body); } } - void operator()(assembly::ForLoop const& _for) + void operator()(yul::ForLoop const& _for) { (*this)(_for.pre); boost::apply_visitor(*this, *_for.condition); (*this)(_for.body); (*this)(_for.post); } - void operator()(assembly::Block const& _block) + void operator()(yul::Block const& _block) { for (auto const& s: _block.statements) boost::apply_visitor(*this, s); diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index d23562ad2..2f418b09f 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -41,6 +41,12 @@ #include #include +namespace yul +{ +// Forward-declaration to +struct Block; +} + namespace dev { namespace solidity @@ -1028,12 +1034,6 @@ public: StatementAnnotation& annotation() const override; }; -namespace assembly -{ -// Forward-declaration to AsmData.h -struct Block; -} - /** * Inline assembly. */ @@ -1043,18 +1043,18 @@ public: InlineAssembly( SourceLocation const& _location, ASTPointer const& _docString, - std::shared_ptr const& _operations + std::shared_ptr const& _operations ): Statement(_location, _docString), m_operations(_operations) {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; - assembly::Block const& operations() const { return *m_operations; } + yul::Block const& operations() const { return *m_operations; } InlineAssemblyAnnotation& annotation() const override; private: - std::shared_ptr m_operations; + std::shared_ptr m_operations; }; /** diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index e0b3f4927..e9cc905e9 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -30,6 +30,12 @@ #include #include +namespace yul +{ + struct AsmAnalysisInfo; + struct Identifier; +} + namespace dev { namespace solidity @@ -120,12 +126,6 @@ struct StatementAnnotation: ASTAnnotation, DocumentedAnnotation { }; -namespace assembly -{ - struct AsmAnalysisInfo; - struct Identifier; -} - struct InlineAssemblyAnnotation: StatementAnnotation { struct ExternalIdentifierInfo @@ -137,9 +137,9 @@ struct InlineAssemblyAnnotation: StatementAnnotation }; /// Mapping containing resolved references to external identifiers and their value size - std::map externalReferences; + std::map externalReferences; /// Information generated during analysis phase. - std::shared_ptr analysisInfo; + std::shared_ptr analysisInfo; }; struct ReturnAnnotation: StatementAnnotation diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index bd6deb6ef..b9054692d 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -172,7 +172,7 @@ void ASTJsonConverter::appendExpressionAttributes( _attributes += exprAttributes; } -Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair _info) const +Json::Value ASTJsonConverter::inlineAssemblyIdentifierToJson(pair _info) const { Json::Value tuple(Json::objectValue); tuple["src"] = sourceLocationToString(_info.first->location); @@ -465,7 +465,7 @@ bool ASTJsonConverter::visit(InlineAssembly const& _node) } } setJsonNode(_node, "InlineAssembly", { - make_pair("operations", Json::Value(assembly::AsmPrinter()(_node.operations()))), + make_pair("operations", Json::Value(yul::AsmPrinter()(_node.operations()))), make_pair("externalReferences", std::move(externalReferences)) }); return false; diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index dec3ac96f..ef0a217a9 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -135,7 +135,7 @@ private: { return _node ? toJson(*_node) : Json::nullValue; } - Json::Value inlineAssemblyIdentifierToJson(std::pair _info) const; + Json::Value inlineAssemblyIdentifierToJson(std::pair _info) const; static std::string location(VariableDeclaration::Location _location); static std::string contractKind(ContractDefinition::ContractKind _kind); static std::string functionCallKind(FunctionCallKind _kind); diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 32be521c9..d1bf29fc2 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -323,7 +323,7 @@ void CompilerContext::appendInlineAssembly( yul::ExternalIdentifierAccess identifierAccess; identifierAccess.resolve = [&]( - assembly::Identifier const& _identifier, + yul::Identifier const& _identifier, yul::IdentifierContext, bool ) @@ -332,7 +332,7 @@ void CompilerContext::appendInlineAssembly( return it == _localVariables.end() ? size_t(-1) : 1; }; identifierAccess.generateCode = [&]( - assembly::Identifier const& _identifier, + yul::Identifier const& _identifier, yul::IdentifierContext _context, yul::AbstractAssembly& _assembly ) @@ -361,19 +361,19 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); auto scanner = make_shared(langutil::CharStream(_assembly), "--CODEGEN--"); - auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Strict).parse(scanner, false); + auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); #ifdef SOL_OUTPUT_ASM - cout << assembly::AsmPrinter()(*parserResult) << endl; + cout << yul::AsmPrinter()(*parserResult) << endl; #endif - assembly::AsmAnalysisInfo analysisInfo; + yul::AsmAnalysisInfo analysisInfo; bool analyzerResult = false; if (parserResult) - analyzerResult = assembly::AsmAnalyzer( + analyzerResult = yul::AsmAnalyzer( analysisInfo, errorReporter, m_evmVersion, boost::none, - assembly::AsmFlavour::Strict, + yul::AsmFlavour::Strict, identifierAccess.resolve ).analyze(*parserResult); if (!parserResult || !errorReporter.errors().empty() || !analyzerResult) @@ -395,7 +395,7 @@ void CompilerContext::appendInlineAssembly( } solAssert(errorReporter.errors().empty(), "Failed to analyze inline assembly block."); - assembly::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system); + yul::CodeGenerator::assemble(*parserResult, analysisInfo, *m_asm, identifierAccess, _system); // Reset the source location to the one of the node (instead of the CODEGEN source location) updateSourceLocation(); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 815c2a4ff..157d5fa7f 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -496,14 +496,14 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) { unsigned startStackHeight = m_context.stackHeight(); yul::ExternalIdentifierAccess identifierAccess; - identifierAccess.resolve = [&](assembly::Identifier const& _identifier, yul::IdentifierContext, bool) + identifierAccess.resolve = [&](yul::Identifier const& _identifier, yul::IdentifierContext, bool) { auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier); if (ref == _inlineAssembly.annotation().externalReferences.end()) return size_t(-1); return ref->second.valueSize; }; - identifierAccess.generateCode = [&](assembly::Identifier const& _identifier, yul::IdentifierContext _context, yul::AbstractAssembly& _assembly) + identifierAccess.generateCode = [&](yul::Identifier const& _identifier, yul::IdentifierContext _context, yul::AbstractAssembly& _assembly) { auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier); solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), ""); @@ -615,7 +615,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) } }; solAssert(_inlineAssembly.annotation().analysisInfo, ""); - assembly::CodeGenerator::assemble( + yul::CodeGenerator::assemble( _inlineAssembly.operations(), *_inlineAssembly.annotation().analysisInfo, m_context.nonConstAssembly(), diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index cd8b125e8..31959d930 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -40,19 +40,19 @@ using namespace dev::solidity; namespace { -assembly::AsmFlavour languageToAsmFlavour(AssemblyStack::Language _language) +yul::AsmFlavour languageToAsmFlavour(AssemblyStack::Language _language) { switch (_language) { case AssemblyStack::Language::Assembly: - return assembly::AsmFlavour::Loose; + return yul::AsmFlavour::Loose; case AssemblyStack::Language::StrictAssembly: - return assembly::AsmFlavour::Strict; + return yul::AsmFlavour::Strict; case AssemblyStack::Language::Yul: - return assembly::AsmFlavour::Yul; + return yul::AsmFlavour::Yul; } solAssert(false, ""); - return assembly::AsmFlavour::Yul; + return yul::AsmFlavour::Yul; } } @@ -69,7 +69,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string m_errors.clear(); m_analysisSuccessful = false; m_scanner = make_shared(CharStream(_source), _sourceName); - m_parserResult = assembly::Parser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); + m_parserResult = yul::Parser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; solAssert(m_parserResult, ""); @@ -77,21 +77,21 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string return analyzeParsed(); } -bool AssemblyStack::analyze(assembly::Block const& _block, Scanner const* _scanner) +bool AssemblyStack::analyze(yul::Block const& _block, Scanner const* _scanner) { m_errors.clear(); m_analysisSuccessful = false; if (_scanner) m_scanner = make_shared(*_scanner); - m_parserResult = make_shared(_block); + m_parserResult = make_shared(_block); return analyzeParsed(); } bool AssemblyStack::analyzeParsed() { - m_analysisInfo = make_shared(); - assembly::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language)); + m_analysisInfo = make_shared(); + yul::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language)); m_analysisSuccessful = analyzer.analyze(*m_parserResult); return m_analysisSuccessful; } @@ -108,7 +108,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const { MachineAssemblyObject object; eth::Assembly assembly; - assembly::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly); + yul::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly); object.bytecode = make_shared(assembly.assemble()); object.assembly = assembly.assemblyString(); return object; @@ -132,5 +132,5 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const string AssemblyStack::print() const { solAssert(m_parserResult, ""); - return assembly::AsmPrinter(m_language == Language::Yul)(*m_parserResult); + return yul::AsmPrinter(m_language == Language::Yul)(*m_parserResult); } diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index d6ee33cf8..03b811db0 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -34,16 +34,17 @@ namespace langutil class Scanner; } -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct AsmAnalysisInfo; struct Block; } +namespace dev +{ +namespace solidity +{ + struct MachineAssemblyObject { std::shared_ptr bytecode; @@ -73,7 +74,7 @@ public: /// Runs analysis step on the supplied block, returns false if input cannot be assembled. /// Multiple calls overwrite the previous state. - bool analyze(assembly::Block const& _block, langutil::Scanner const* _scanner = nullptr); + bool analyze(yul::Block const& _block, langutil::Scanner const* _scanner = nullptr); /// Run the assembly step (should only be called after parseAndAnalyze). MachineAssemblyObject assemble(Machine _machine) const; @@ -93,8 +94,8 @@ private: std::shared_ptr m_scanner; bool m_analysisSuccessful = false; - std::shared_ptr m_parserResult; - std::shared_ptr m_analysisInfo; + std::shared_ptr m_parserResult; + std::shared_ptr m_analysisInfo; langutil::ErrorList m_errors; langutil::ErrorReporter m_errorReporter; }; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 560d8e8b4..ffe2be83d 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1012,8 +1012,8 @@ ASTPointer Parser::parseInlineAssembly(ASTPointer con m_scanner->next(); } - assembly::Parser asmParser(m_errorReporter); - shared_ptr block = asmParser.parse(m_scanner, true); + yul::Parser asmParser(m_errorReporter); + shared_ptr block = asmParser.parse(m_scanner, true); nodeFactory.markEndPosition(); return nodeFactory.createNode(_docString, block); } diff --git a/libyul/ASTDataForward.h b/libyul/ASTDataForward.h index 16dc74114..dffe1c748 100644 --- a/libyul/ASTDataForward.h +++ b/libyul/ASTDataForward.h @@ -23,33 +23,3 @@ #include -namespace dev -{ -namespace yul -{ - -using Instruction = solidity::assembly::Instruction; -using Literal = solidity::assembly::Literal; -using Label = solidity::assembly::Label; -using StackAssignment = solidity::assembly::StackAssignment; -using Identifier = solidity::assembly::Identifier; -using Assignment = solidity::assembly::Assignment; -using VariableDeclaration = solidity::assembly::VariableDeclaration; -using FunctionalInstruction = solidity::assembly::FunctionalInstruction; -using FunctionDefinition = solidity::assembly::FunctionDefinition; -using FunctionCall = solidity::assembly::FunctionCall; -using If = solidity::assembly::If; -using Case = solidity::assembly::Case; -using Switch = solidity::assembly::Switch; -using ForLoop = solidity::assembly::ForLoop; -using ExpressionStatement = solidity::assembly::ExpressionStatement; -using Block = solidity::assembly::Block; - -using TypedName = solidity::assembly::TypedName; -class YulString; - -using Expression = boost::variant; -using Statement = boost::variant; - -} -} diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index 34c5fbb67..d3f6de846 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -36,8 +36,9 @@ using namespace std; using namespace dev; using namespace langutil; +using namespace yul; +using namespace dev; using namespace dev::solidity; -using namespace dev::solidity::assembly; namespace { @@ -65,7 +66,7 @@ bool AsmAnalyzer::operator()(Label const& _label) return true; } -bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) +bool AsmAnalyzer::operator()(yul::Instruction const& _instruction) { checkLooseFeature( _instruction.location, @@ -78,11 +79,11 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) return true; } -bool AsmAnalyzer::operator()(assembly::Literal const& _literal) +bool AsmAnalyzer::operator()(Literal const& _literal) { expectValidType(_literal.type.str(), _literal.location); ++m_stackHeight; - if (_literal.kind == assembly::LiteralKind::String && _literal.value.str().size() > 32) + if (_literal.kind == LiteralKind::String && _literal.value.str().size() > 32) { m_errorReporter.typeError( _literal.location, @@ -90,7 +91,7 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal) ); return false; } - else if (_literal.kind == assembly::LiteralKind::Number && bigint(_literal.value.str()) > u256(-1)) + else if (_literal.kind == LiteralKind::Number && bigint(_literal.value.str()) > u256(-1)) { m_errorReporter.typeError( _literal.location, @@ -98,7 +99,7 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal) ); return false; } - else if (_literal.kind == assembly::LiteralKind::Boolean) + else if (_literal.kind == LiteralKind::Boolean) { solAssert(m_flavour == AsmFlavour::Yul, ""); solAssert(_literal.value == YulString{string("true")} || _literal.value == YulString{string("false")}, ""); @@ -107,7 +108,7 @@ bool AsmAnalyzer::operator()(assembly::Literal const& _literal) return true; } -bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier) +bool AsmAnalyzer::operator()(Identifier const& _identifier) { solAssert(!_identifier.name.empty(), ""); size_t numErrorsBefore = m_errorReporter.errors().size(); @@ -177,7 +178,7 @@ bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr) return success; } -bool AsmAnalyzer::operator()(assembly::ExpressionStatement const& _statement) +bool AsmAnalyzer::operator()(ExpressionStatement const& _statement) { int initialStackHeight = m_stackHeight; bool success = boost::apply_visitor(*this, _statement.expression); @@ -198,7 +199,7 @@ bool AsmAnalyzer::operator()(assembly::ExpressionStatement const& _statement) return success; } -bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment) +bool AsmAnalyzer::operator()(StackAssignment const& _assignment) { checkLooseFeature( _assignment.location, @@ -209,7 +210,7 @@ bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment) return success; } -bool AsmAnalyzer::operator()(assembly::Assignment const& _assignment) +bool AsmAnalyzer::operator()(Assignment const& _assignment) { solAssert(_assignment.value, ""); int const expectedItems = _assignment.variableNames.size(); @@ -235,7 +236,7 @@ bool AsmAnalyzer::operator()(assembly::Assignment const& _assignment) return success; } -bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) +bool AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) { bool success = true; int const numVariables = _varDecl.variables.size(); @@ -261,7 +262,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) return success; } -bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) +bool AsmAnalyzer::operator()(FunctionDefinition const& _funDef) { solAssert(!_funDef.name.empty(), ""); Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get(); @@ -283,7 +284,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef) return success; } -bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall) +bool AsmAnalyzer::operator()(FunctionCall const& _funCall) { solAssert(!_funCall.functionName.name.empty(), ""); bool success = true; @@ -397,7 +398,7 @@ bool AsmAnalyzer::operator()(Switch const& _switch) return success; } -bool AsmAnalyzer::operator()(assembly::ForLoop const& _for) +bool AsmAnalyzer::operator()(ForLoop const& _for) { solAssert(_for.condition, ""); @@ -486,7 +487,7 @@ bool AsmAnalyzer::expectDeposit(int _deposit, int _oldHeight, SourceLocation con return true; } -bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t _valueSize) +bool AsmAnalyzer::checkAssignment(Identifier const& _variable, size_t _valueSize) { solAssert(!_variable.name.empty(), ""); bool success = true; diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index edca5b50b..34e32eb01 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -41,11 +41,7 @@ class ErrorReporter; struct SourceLocation; } -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct AsmAnalysisInfo; @@ -61,10 +57,10 @@ public: explicit AsmAnalyzer( AsmAnalysisInfo& _analysisInfo, langutil::ErrorReporter& _errorReporter, - EVMVersion _evmVersion, + dev::solidity::EVMVersion _evmVersion, boost::optional _errorTypeForLoose, AsmFlavour _flavour = AsmFlavour::Loose, - yul::ExternalIdentifierAccess::Resolver const& _resolver = yul::ExternalIdentifierAccess::Resolver() + ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver() ): m_resolver(_resolver), m_info(_analysisInfo), @@ -74,23 +70,23 @@ public: m_errorTypeForLoose(_errorTypeForLoose) {} - bool analyze(assembly::Block const& _block); + bool analyze(Block const& _block); - bool operator()(assembly::Instruction const&); - bool operator()(assembly::Literal const& _literal); - bool operator()(assembly::Identifier const&); - bool operator()(assembly::FunctionalInstruction const& _functionalInstruction); - bool operator()(assembly::Label const& _label); - bool operator()(assembly::ExpressionStatement const&); - bool operator()(assembly::StackAssignment const&); - bool operator()(assembly::Assignment const& _assignment); - bool operator()(assembly::VariableDeclaration const& _variableDeclaration); - bool operator()(assembly::FunctionDefinition const& _functionDefinition); - bool operator()(assembly::FunctionCall const& _functionCall); - bool operator()(assembly::If const& _if); - bool operator()(assembly::Switch const& _switch); - bool operator()(assembly::ForLoop const& _forLoop); - bool operator()(assembly::Block const& _block); + bool operator()(Instruction const&); + bool operator()(Literal const& _literal); + bool operator()(Identifier const&); + bool operator()(FunctionalInstruction const& _functionalInstruction); + bool operator()(Label const& _label); + bool operator()(ExpressionStatement const&); + bool operator()(StackAssignment const&); + bool operator()(Assignment const& _assignment); + bool operator()(VariableDeclaration const& _variableDeclaration); + bool operator()(FunctionDefinition const& _functionDefinition); + bool operator()(FunctionCall const& _functionCall); + bool operator()(If const& _if); + bool operator()(Switch const& _switch); + bool operator()(ForLoop const& _forLoop); + bool operator()(Block const& _block); private: /// Visits the statement and expects it to deposit one item onto the stack. @@ -99,11 +95,11 @@ private: /// Verifies that a variable to be assigned to exists and has the same size /// as the value, @a _valueSize, unless that is equal to -1. - bool checkAssignment(assembly::Identifier const& _assignment, size_t _valueSize = size_t(-1)); + bool checkAssignment(Identifier const& _assignment, size_t _valueSize = size_t(-1)); - Scope& scope(assembly::Block const* _block); + Scope& scope(Block const* _block); void expectValidType(std::string const& type, langutil::SourceLocation const& _location); - void warnOnInstructions(solidity::Instruction _instr, langutil::SourceLocation const& _location); + void warnOnInstructions(dev::solidity::Instruction _instr, langutil::SourceLocation const& _location); /// Depending on @a m_flavour and @a m_errorTypeForLoose, throws an internal compiler /// exception (if the flavour is not Loose), reports an error/warning @@ -118,11 +114,9 @@ private: std::set m_activeVariables; AsmAnalysisInfo& m_info; langutil::ErrorReporter& m_errorReporter; - EVMVersion m_evmVersion; + dev::solidity::EVMVersion m_evmVersion; AsmFlavour m_flavour = AsmFlavour::Loose; boost::optional m_errorTypeForLoose; }; } -} -} diff --git a/libyul/AsmAnalysisInfo.h b/libyul/AsmAnalysisInfo.h index 372ff3ed8..08a35ade0 100644 --- a/libyul/AsmAnalysisInfo.h +++ b/libyul/AsmAnalysisInfo.h @@ -28,11 +28,7 @@ #include #include -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct Scope; @@ -40,13 +36,11 @@ struct Scope; struct AsmAnalysisInfo { using StackHeightInfo = std::map; - using Scopes = std::map>; + using Scopes = std::map>; Scopes scopes; StackHeightInfo stackHeightInfo; /// Virtual blocks which will be used for scopes for function arguments and return values. - std::map> virtualBlocks; + std::map> virtualBlocks; }; } -} -} diff --git a/libyul/AsmCodeGen.cpp b/libyul/AsmCodeGen.cpp index 5bc2fee38..23bf395d9 100644 --- a/libyul/AsmCodeGen.cpp +++ b/libyul/AsmCodeGen.cpp @@ -48,10 +48,10 @@ using namespace std; using namespace dev; using namespace langutil; +using namespace yul; using namespace dev::solidity; -using namespace dev::solidity::assembly; -class EthAssemblyAdapter: public yul::AbstractAssembly +class EthAssemblyAdapter: public AbstractAssembly { public: explicit EthAssemblyAdapter(eth::Assembly& _assembly): @@ -143,16 +143,16 @@ private: eth::Assembly& m_assembly; }; -void assembly::CodeGenerator::assemble( +void CodeGenerator::assemble( Block const& _parsedData, AsmAnalysisInfo& _analysisInfo, eth::Assembly& _assembly, - yul::ExternalIdentifierAccess const& _identifierAccess, + ExternalIdentifierAccess const& _identifierAccess, bool _useNamedLabelsForFunctions ) { EthAssemblyAdapter assemblyAdapter(_assembly); - yul::CodeTransform( + CodeTransform( assemblyAdapter, _analysisInfo, false, diff --git a/libyul/AsmCodeGen.h b/libyul/AsmCodeGen.h index e5e53c0d8..fd5ac0a1d 100644 --- a/libyul/AsmCodeGen.h +++ b/libyul/AsmCodeGen.h @@ -32,9 +32,9 @@ namespace eth { class Assembly; } -namespace solidity -{ -namespace assembly +} + +namespace yul { struct Block; @@ -45,12 +45,10 @@ public: static void assemble( Block const& _parsedData, AsmAnalysisInfo& _analysisInfo, - eth::Assembly& _assembly, + dev::eth::Assembly& _assembly, yul::ExternalIdentifierAccess const& _identifierAccess = yul::ExternalIdentifierAccess(), bool _useNamedLabelsForFunctions = false ); }; } -} -} diff --git a/libyul/AsmData.h b/libyul/AsmData.h index 6979d29cc..86c373a49 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -23,7 +23,6 @@ #pragma once #include - #include #include @@ -35,21 +34,16 @@ #include #include -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { -using YulString = dev::yul::YulString; using Type = YulString; struct TypedName { langutil::SourceLocation location; YulString name; Type type; }; using TypedNameList = std::vector; /// Direct EVM instruction (except PUSHi and JUMPDEST) -struct Instruction { langutil::SourceLocation location; solidity::Instruction instruction; }; +struct Instruction { langutil::SourceLocation location; dev::solidity::Instruction instruction; }; /// Literal number or string (up to 32 bytes) enum class LiteralKind { Number, Boolean, String }; struct Literal { langutil::SourceLocation location; LiteralKind kind; YulString value; Type type; }; @@ -67,7 +61,7 @@ struct StackAssignment { langutil::SourceLocation location; Identifier variableN /// the same amount of items as the number of variables. struct Assignment { langutil::SourceLocation location; std::vector variableNames; std::shared_ptr value; }; /// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))" -struct FunctionalInstruction { langutil::SourceLocation location; solidity::Instruction instruction; std::vector arguments; }; +struct FunctionalInstruction { langutil::SourceLocation location; dev::solidity::Instruction instruction; std::vector arguments; }; struct FunctionCall { langutil::SourceLocation location; Identifier functionName; std::vector arguments; }; /// Statement that contains only a single expression struct ExpressionStatement { langutil::SourceLocation location; Expression expression; }; @@ -100,5 +94,3 @@ template inline langutil::SourceLocation locationOf(T const& _node) } } -} -} diff --git a/libyul/AsmDataForward.h b/libyul/AsmDataForward.h index 69cf8f1d9..046c82487 100644 --- a/libyul/AsmDataForward.h +++ b/libyul/AsmDataForward.h @@ -24,11 +24,7 @@ #include -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct Instruction; @@ -61,5 +57,3 @@ enum class AsmFlavour }; } -} -} diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 0d3bc32f0..2ce94f852 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -32,10 +32,10 @@ using namespace std; using namespace dev; using namespace langutil; +using namespace yul; using namespace dev::solidity; -using namespace dev::solidity::assembly; -shared_ptr Parser::parse(std::shared_ptr const& _scanner, bool _reuseScanner) +shared_ptr Parser::parse(std::shared_ptr const& _scanner, bool _reuseScanner) { m_recursionDepth = 0; try @@ -54,10 +54,10 @@ shared_ptr Parser::parse(std::shared_ptr const& _scann return nullptr; } -assembly::Block Parser::parseBlock() +Block Parser::parseBlock() { RecursionGuard recursionGuard(*this); - assembly::Block block = createWithLocation(); + Block block = createWithLocation(); expectToken(Token::LBrace); while (currentToken() != Token::RBrace) block.statements.emplace_back(parseStatement()); @@ -66,7 +66,7 @@ assembly::Block Parser::parseBlock() return block; } -assembly::Statement Parser::parseStatement() +Statement Parser::parseStatement() { RecursionGuard recursionGuard(*this); switch (currentToken()) @@ -79,7 +79,7 @@ assembly::Statement Parser::parseStatement() return parseBlock(); case Token::If: { - assembly::If _if = createWithLocation(); + If _if = createWithLocation(); m_scanner->next(); _if.condition = make_shared(parseExpression()); _if.body = parseBlock(); @@ -87,7 +87,7 @@ assembly::Statement Parser::parseStatement() } case Token::Switch: { - assembly::Switch _switch = createWithLocation(); + Switch _switch = createWithLocation(); m_scanner->next(); _switch.expression = make_shared(parseExpression()); while (m_scanner->currentToken() == Token::Case) @@ -109,7 +109,7 @@ assembly::Statement Parser::parseStatement() { if (m_flavour != AsmFlavour::Loose) break; - assembly::StackAssignment assignment = createWithLocation(); + StackAssignment assignment = createWithLocation(); advance(); expectToken(Token::Colon); assignment.variableName.location = location(); @@ -139,9 +139,9 @@ assembly::Statement Parser::parseStatement() { // if a comma follows, a multiple assignment is assumed - if (elementary.type() != typeid(assembly::Identifier)) + if (elementary.type() != typeid(Identifier)) fatalParserError("Label name / variable name must precede \",\" (multiple assignment)."); - assembly::Identifier const& identifier = boost::get(elementary); + Identifier const& identifier = boost::get(elementary); Assignment assignment = createWithLocation(identifier.location); assignment.variableNames.emplace_back(identifier); @@ -150,9 +150,9 @@ assembly::Statement Parser::parseStatement() { expectToken(Token::Comma); elementary = parseElementaryOperation(); - if (elementary.type() != typeid(assembly::Identifier)) + if (elementary.type() != typeid(Identifier)) fatalParserError("Variable name expected in multiple assignment."); - assignment.variableNames.emplace_back(boost::get(elementary)); + assignment.variableNames.emplace_back(boost::get(elementary)); } while (currentToken() == Token::Comma); @@ -165,15 +165,15 @@ assembly::Statement Parser::parseStatement() } case Token::Colon: { - if (elementary.type() != typeid(assembly::Identifier)) + if (elementary.type() != typeid(Identifier)) fatalParserError("Label name / variable name must precede \":\"."); - assembly::Identifier const& identifier = boost::get(elementary); + Identifier const& identifier = boost::get(elementary); advance(); // identifier:=: should be parsed as identifier: =: (i.e. a label), // while identifier:= (being followed by a non-colon) as identifier := (assignment). if (currentToken() == Token::Assign && peekNextToken() != Token::Colon) { - assembly::Assignment assignment = createWithLocation(identifier.location); + Assignment assignment = createWithLocation(identifier.location); if (m_flavour != AsmFlavour::Yul && instructions().count(identifier.name.str())) fatalParserError("Cannot use instruction names for identifier names."); advance(); @@ -197,36 +197,36 @@ assembly::Statement Parser::parseStatement() fatalParserError("Call or assignment expected."); break; } - if (elementary.type() == typeid(assembly::Identifier)) + if (elementary.type() == typeid(Identifier)) { - Expression expr = boost::get(elementary); + Expression expr = boost::get(elementary); return ExpressionStatement{locationOf(expr), expr}; } - else if (elementary.type() == typeid(assembly::Literal)) + else if (elementary.type() == typeid(Literal)) { - Expression expr = boost::get(elementary); + Expression expr = boost::get(elementary); return ExpressionStatement{locationOf(expr), expr}; } else { - solAssert(elementary.type() == typeid(assembly::Instruction), "Invalid elementary operation."); - return boost::get(elementary); + solAssert(elementary.type() == typeid(Instruction), "Invalid elementary operation."); + return boost::get(elementary); } } -assembly::Case Parser::parseCase() +Case Parser::parseCase() { RecursionGuard recursionGuard(*this); - assembly::Case _case = createWithLocation(); + Case _case = createWithLocation(); if (m_scanner->currentToken() == Token::Default) m_scanner->next(); else if (m_scanner->currentToken() == Token::Case) { m_scanner->next(); ElementaryOperation literal = parseElementaryOperation(); - if (literal.type() != typeid(assembly::Literal)) + if (literal.type() != typeid(Literal)) fatalParserError("Literal expected."); - _case.value = make_shared(boost::get(std::move(literal))); + _case.value = make_shared(boost::get(std::move(literal))); } else fatalParserError("Case or default case expected."); @@ -235,7 +235,7 @@ assembly::Case Parser::parseCase() return _case; } -assembly::ForLoop Parser::parseForLoop() +ForLoop Parser::parseForLoop() { RecursionGuard recursionGuard(*this); ForLoop forLoop = createWithLocation(); @@ -248,7 +248,7 @@ assembly::ForLoop Parser::parseForLoop() return forLoop; } -assembly::Expression Parser::parseExpression() +Expression Parser::parseExpression() { RecursionGuard recursionGuard(*this); // In strict mode, this might parse a plain Instruction, but @@ -293,12 +293,12 @@ assembly::Expression Parser::parseExpression() Instruction& instr = boost::get(operation); return FunctionalInstruction{std::move(instr.location), instr.instruction, {}}; } - else if (operation.type() == typeid(assembly::Identifier)) - return boost::get(operation); + else if (operation.type() == typeid(Identifier)) + return boost::get(operation); else { - solAssert(operation.type() == typeid(assembly::Literal), ""); - return boost::get(operation); + solAssert(operation.type() == typeid(Literal), ""); + return boost::get(operation); } } @@ -420,7 +420,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() return ret; } -assembly::VariableDeclaration Parser::parseVariableDeclaration() +VariableDeclaration Parser::parseVariableDeclaration() { RecursionGuard recursionGuard(*this); VariableDeclaration varDecl = createWithLocation(); @@ -445,7 +445,7 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration() return varDecl; } -assembly::FunctionDefinition Parser::parseFunctionDefinition() +FunctionDefinition Parser::parseFunctionDefinition() { RecursionGuard recursionGuard(*this); FunctionDefinition funDef = createWithLocation(); @@ -477,7 +477,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) +Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) { RecursionGuard recursionGuard(*this); if (_initialOp.type() == typeid(Instruction)) diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 874b4d6d5..cea3b6679 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -29,11 +29,7 @@ #include #include -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { class Parser: public langutil::ParserBase @@ -48,7 +44,7 @@ public: std::shared_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); protected: - using ElementaryOperation = boost::variant; + using ElementaryOperation = boost::variant; /// Creates an inline assembly node with the given source location. template T createWithLocation(langutil::SourceLocation const& _loc = {}) const @@ -71,7 +67,7 @@ protected: Case parseCase(); ForLoop parseForLoop(); /// Parses a functional expression that has to push exactly one stack element - assembly::Expression parseExpression(); + Expression parseExpression(); static std::map const& instructions(); static std::map const& instructionNames(); /// Parses an elementary operation, i.e. a literal, identifier or instruction. @@ -80,7 +76,7 @@ protected: ElementaryOperation parseElementaryOperation(); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - assembly::Expression parseCall(ElementaryOperation&& _initialOp); + Expression parseCall(ElementaryOperation&& _initialOp); TypedName parseTypedName(); std::string expectAsmIdentifier(); @@ -91,5 +87,3 @@ private: }; } -} -} diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 49e2f33be..eaaba9f3d 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -35,19 +35,19 @@ using namespace std; using namespace dev; +using namespace yul; using namespace dev::solidity; -using namespace dev::solidity::assembly; //@TODO source locations -string AsmPrinter::operator()(assembly::Instruction const& _instruction) +string AsmPrinter::operator()(yul::Instruction const& _instruction) { solAssert(!m_yul, ""); solAssert(isValidInstruction(_instruction.instruction), "Invalid instruction"); return boost::to_lower_copy(instructionInfo(_instruction.instruction).name); } -string AsmPrinter::operator()(assembly::Literal const& _literal) +string AsmPrinter::operator()(Literal const& _literal) { switch (_literal.kind) { @@ -90,13 +90,13 @@ string AsmPrinter::operator()(assembly::Literal const& _literal) return "\"" + out + "\"" + appendTypeName(_literal.type); } -string AsmPrinter::operator()(assembly::Identifier const& _identifier) +string AsmPrinter::operator()(Identifier const& _identifier) { solAssert(!_identifier.name.empty(), "Invalid identifier."); return _identifier.name.str(); } -string AsmPrinter::operator()(assembly::FunctionalInstruction const& _functionalInstruction) +string AsmPrinter::operator()(FunctionalInstruction const& _functionalInstruction) { solAssert(!m_yul, ""); solAssert(isValidInstruction(_functionalInstruction.instruction), "Invalid instruction"); @@ -114,21 +114,21 @@ string AsmPrinter::operator()(ExpressionStatement const& _statement) return boost::apply_visitor(*this, _statement.expression); } -string AsmPrinter::operator()(assembly::Label const& _label) +string AsmPrinter::operator()(Label const& _label) { solAssert(!m_yul, ""); solAssert(!_label.name.empty(), "Invalid label."); return _label.name.str() + ":"; } -string AsmPrinter::operator()(assembly::StackAssignment const& _assignment) +string AsmPrinter::operator()(StackAssignment const& _assignment) { solAssert(!m_yul, ""); solAssert(!_assignment.variableName.name.empty(), "Invalid variable name."); return "=: " + (*this)(_assignment.variableName); } -string AsmPrinter::operator()(assembly::Assignment const& _assignment) +string AsmPrinter::operator()(Assignment const& _assignment) { solAssert(_assignment.variableNames.size() >= 1, ""); string variables = (*this)(_assignment.variableNames.front()); @@ -137,7 +137,7 @@ string AsmPrinter::operator()(assembly::Assignment const& _assignment) return variables + " := " + boost::apply_visitor(*this, *_assignment.value); } -string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDeclaration) +string AsmPrinter::operator()(VariableDeclaration const& _variableDeclaration) { string out = "let "; out += boost::algorithm::join( @@ -154,7 +154,7 @@ string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDecl return out; } -string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition) +string AsmPrinter::operator()(FunctionDefinition const& _functionDefinition) { solAssert(!_functionDefinition.name.empty(), "Invalid function name."); string out = "function " + _functionDefinition.name.str() + "("; @@ -179,7 +179,7 @@ string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefin return out + "\n" + (*this)(_functionDefinition.body); } -string AsmPrinter::operator()(assembly::FunctionCall const& _functionCall) +string AsmPrinter::operator()(FunctionCall const& _functionCall) { return (*this)(_functionCall.functionName) + "(" + @@ -210,7 +210,7 @@ string AsmPrinter::operator()(Switch const& _switch) return out; } -string AsmPrinter::operator()(assembly::ForLoop const& _forLoop) +string AsmPrinter::operator()(ForLoop const& _forLoop) { solAssert(_forLoop.condition, "Invalid for loop condition."); string out = "for "; diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index ab0c9a088..61dfc18c9 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -28,11 +28,7 @@ #include -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { class AsmPrinter: public boost::static_visitor @@ -40,29 +36,27 @@ class AsmPrinter: public boost::static_visitor public: explicit AsmPrinter(bool _yul = false): m_yul(_yul) {} - std::string operator()(assembly::Instruction const& _instruction); - std::string operator()(assembly::Literal const& _literal); - std::string operator()(assembly::Identifier const& _identifier); - std::string operator()(assembly::FunctionalInstruction const& _functionalInstruction); - std::string operator()(assembly::ExpressionStatement const& _expr); - std::string operator()(assembly::Label const& _label); - std::string operator()(assembly::StackAssignment const& _assignment); - std::string operator()(assembly::Assignment const& _assignment); - std::string operator()(assembly::VariableDeclaration const& _variableDeclaration); - std::string operator()(assembly::FunctionDefinition const& _functionDefinition); - std::string operator()(assembly::FunctionCall const& _functionCall); - std::string operator()(assembly::If const& _if); - std::string operator()(assembly::Switch const& _switch); - std::string operator()(assembly::ForLoop const& _forLoop); - std::string operator()(assembly::Block const& _block); + std::string operator()(Instruction const& _instruction); + std::string operator()(Literal const& _literal); + std::string operator()(Identifier const& _identifier); + std::string operator()(FunctionalInstruction const& _functionalInstruction); + std::string operator()(ExpressionStatement const& _expr); + std::string operator()(Label const& _label); + std::string operator()(StackAssignment const& _assignment); + std::string operator()(Assignment const& _assignment); + std::string operator()(VariableDeclaration const& _variableDeclaration); + std::string operator()(FunctionDefinition const& _functionDefinition); + std::string operator()(FunctionCall const& _functionCall); + std::string operator()(If const& _if); + std::string operator()(Switch const& _switch); + std::string operator()(ForLoop const& _forLoop); + std::string operator()(Block const& _block); private: std::string formatTypedName(TypedName _variable) const; - std::string appendTypeName(yul::YulString _type) const; + std::string appendTypeName(YulString _type) const; bool m_yul = false; }; } -} -} diff --git a/libyul/AsmScope.cpp b/libyul/AsmScope.cpp index 0d7aca577..b71f2367e 100644 --- a/libyul/AsmScope.cpp +++ b/libyul/AsmScope.cpp @@ -22,9 +22,9 @@ using namespace std; using namespace dev; -using namespace dev::solidity::assembly; +using namespace yul; -bool Scope::registerLabel(yul::YulString _name) +bool Scope::registerLabel(YulString _name) { if (exists(_name)) return false; @@ -32,7 +32,7 @@ bool Scope::registerLabel(yul::YulString _name) return true; } -bool Scope::registerVariable(yul::YulString _name, YulType const& _type) +bool Scope::registerVariable(YulString _name, YulType const& _type) { if (exists(_name)) return false; @@ -42,7 +42,7 @@ bool Scope::registerVariable(yul::YulString _name, YulType const& _type) return true; } -bool Scope::registerFunction(yul::YulString _name, std::vector const& _arguments, std::vector const& _returns) +bool Scope::registerFunction(YulString _name, std::vector const& _arguments, std::vector const& _returns) { if (exists(_name)) return false; @@ -50,7 +50,7 @@ bool Scope::registerFunction(yul::YulString _name, std::vector const& _ return true; } -Scope::Identifier* Scope::lookup(yul::YulString _name) +Scope::Identifier* Scope::lookup(YulString _name) { bool crossedFunctionBoundary = false; for (Scope* s = this; s; s = s->superScope) @@ -70,7 +70,7 @@ Scope::Identifier* Scope::lookup(yul::YulString _name) return nullptr; } -bool Scope::exists(yul::YulString _name) const +bool Scope::exists(YulString _name) const { if (identifiers.count(_name)) return true; diff --git a/libyul/AsmScope.h b/libyul/AsmScope.h index 12c057169..2a8ef49e8 100644 --- a/libyul/AsmScope.h +++ b/libyul/AsmScope.h @@ -32,16 +32,12 @@ #include #include -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct Scope { - using YulType = yul::YulString; + using YulType = YulString; using LabelID = size_t; struct Variable { YulType type; }; @@ -53,13 +49,13 @@ struct Scope }; using Identifier = boost::variant; - using Visitor = GenericVisitor; - using NonconstVisitor = GenericVisitor; + using Visitor = dev::GenericVisitor; + using NonconstVisitor = dev::GenericVisitor; - bool registerVariable(yul::YulString _name, YulType const& _type); - bool registerLabel(yul::YulString _name); + bool registerVariable(YulString _name, YulType const& _type); + bool registerLabel(YulString _name); bool registerFunction( - yul::YulString _name, + YulString _name, std::vector const& _arguments, std::vector const& _returns ); @@ -69,12 +65,12 @@ struct Scope /// will any lookups across assembly boundaries. /// The pointer will be invalidated if the scope is modified. /// @param _crossedFunction if true, we already crossed a function boundary during recursive lookup - Identifier* lookup(yul::YulString _name); + Identifier* lookup(YulString _name); /// Looks up the identifier in this and super scopes (will not find variables across function /// boundaries and generally stops at assembly boundaries) and calls the visitor, returns /// false if not found. template - bool lookup(yul::YulString _name, V const& _visitor) + bool lookup(YulString _name, V const& _visitor) { if (Identifier* id = lookup(_name)) { @@ -86,7 +82,7 @@ struct Scope } /// @returns true if the name exists in this scope or in super scopes (also searches /// across function and assembly boundaries). - bool exists(yul::YulString _name) const; + bool exists(YulString _name) const; /// @returns the number of variables directly registered inside the scope. size_t numberOfVariables() const; @@ -97,9 +93,7 @@ struct Scope /// If true, variables from the super scope are not visible here (other identifiers are), /// but they are still taken into account to prevent shadowing. bool functionScope = false; - std::map identifiers; + std::map identifiers; }; } -} -} diff --git a/libyul/AsmScopeFiller.cpp b/libyul/AsmScopeFiller.cpp index 2070d8de6..ee797d6a8 100644 --- a/libyul/AsmScopeFiller.cpp +++ b/libyul/AsmScopeFiller.cpp @@ -37,8 +37,8 @@ using namespace std; using namespace dev; using namespace langutil; +using namespace yul; using namespace dev::solidity; -using namespace dev::solidity::assembly; ScopeFiller::ScopeFiller(AsmAnalysisInfo& _info, ErrorReporter& _errorReporter): m_info(_info), m_errorReporter(_errorReporter) @@ -65,7 +65,7 @@ bool ScopeFiller::operator()(Label const& _item) return true; } -bool ScopeFiller::operator()(assembly::VariableDeclaration const& _varDecl) +bool ScopeFiller::operator()(VariableDeclaration const& _varDecl) { for (auto const& variable: _varDecl.variables) if (!registerVariable(variable, _varDecl.location, *m_currentScope)) @@ -73,7 +73,7 @@ bool ScopeFiller::operator()(assembly::VariableDeclaration const& _varDecl) return true; } -bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef) +bool ScopeFiller::operator()(FunctionDefinition const& _funDef) { bool success = true; vector arguments; diff --git a/libyul/AsmScopeFiller.h b/libyul/AsmScopeFiller.h index fbd65bbac..e8fb88d5f 100644 --- a/libyul/AsmScopeFiller.h +++ b/libyul/AsmScopeFiller.h @@ -33,11 +33,7 @@ class ErrorReporter; struct SourceLocation; } -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct TypedName; @@ -53,21 +49,21 @@ class ScopeFiller: public boost::static_visitor public: ScopeFiller(AsmAnalysisInfo& _info, langutil::ErrorReporter& _errorReporter); - bool operator()(assembly::Instruction const&) { return true; } - bool operator()(assembly::Literal const&) { return true; } - bool operator()(assembly::Identifier const&) { return true; } - bool operator()(assembly::FunctionalInstruction const&) { return true; } - bool operator()(assembly::ExpressionStatement const& _expr); - bool operator()(assembly::Label const& _label); - bool operator()(assembly::StackAssignment const&) { return true; } - bool operator()(assembly::Assignment const&) { return true; } - bool operator()(assembly::VariableDeclaration const& _variableDeclaration); - bool operator()(assembly::FunctionDefinition const& _functionDefinition); - bool operator()(assembly::FunctionCall const&) { return true; } - bool operator()(assembly::If const& _if); - bool operator()(assembly::Switch const& _switch); - bool operator()(assembly::ForLoop const& _forLoop); - bool operator()(assembly::Block const& _block); + bool operator()(Instruction const&) { return true; } + bool operator()(Literal const&) { return true; } + bool operator()(Identifier const&) { return true; } + bool operator()(FunctionalInstruction const&) { return true; } + bool operator()(ExpressionStatement const& _expr); + bool operator()(Label const& _label); + bool operator()(StackAssignment const&) { return true; } + bool operator()(Assignment const&) { return true; } + bool operator()(VariableDeclaration const& _variableDeclaration); + bool operator()(FunctionDefinition const& _functionDefinition); + bool operator()(FunctionCall const&) { return true; } + bool operator()(If const& _if); + bool operator()(Switch const& _switch); + bool operator()(ForLoop const& _forLoop); + bool operator()(Block const& _block); private: bool registerVariable( @@ -76,7 +72,7 @@ private: Scope& _scope ); - Scope& scope(assembly::Block const* _block); + Scope& scope(Block const* _block); Scope* m_currentScope = nullptr; AsmAnalysisInfo& m_info; @@ -84,5 +80,3 @@ private: }; } -} -} diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index 0c421dbfb..e10e53ef1 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -23,18 +23,15 @@ #include #include -namespace dev -{ namespace yul { -struct YulException: virtual Exception {}; +struct YulException: virtual dev::Exception {}; struct OptimizerException: virtual YulException {}; struct YulAssertion: virtual YulException {}; /// Assertion that throws an YulAssertion containing the given description if it is not met. #define yulAssert(CONDITION, DESCRIPTION) \ - assertThrow(CONDITION, ::dev::yul::YulException, DESCRIPTION) + assertThrow(CONDITION, ::yul::YulException, DESCRIPTION) } -} diff --git a/libyul/YulString.h b/libyul/YulString.h index ad900a703..2179c23b2 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -27,8 +27,6 @@ #include #include -namespace dev -{ namespace yul { @@ -130,4 +128,3 @@ private: }; } -} diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 5a1140cb2..97b1d3052 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -22,6 +22,7 @@ #pragma once +#include #include #include @@ -36,14 +37,13 @@ namespace dev namespace solidity { enum class Instruction: uint8_t; -namespace assembly +} +} + +namespace yul { struct Instruction; struct Identifier; -} -} -namespace yul -{ /// /// Assembly class that abstracts both the libevmasm assembly and the new Yul assembly. @@ -61,9 +61,9 @@ public: /// at the beginning. virtual int stackHeight() const = 0; /// Append an EVM instruction. - virtual void appendInstruction(solidity::Instruction _instruction) = 0; + virtual void appendInstruction(dev::solidity::Instruction _instruction) = 0; /// Append a constant. - virtual void appendConstant(u256 const& _constant) = 0; + virtual void appendConstant(dev::u256 const& _constant) = 0; /// Append a label. virtual void appendLabel(LabelID _labelId) = 0; /// Append a label reference. @@ -106,18 +106,15 @@ enum class IdentifierContext { LValue, RValue }; /// to inline assembly (not used in standalone assembly mode). struct ExternalIdentifierAccess { - using Resolver = std::function; + using Resolver = std::function; /// Resolve an external reference given by the identifier in the given context. /// @returns the size of the value (number of stack slots) or size_t(-1) if not found. Resolver resolve; - using CodeGenerator = std::function; + using CodeGenerator = std::function; /// Generate code for retrieving the value (rvalue context) or storing the value (lvalue context) /// of an identifier. The code should be appended to the assembly. In rvalue context, the value is supposed /// to be put onto the stack, in lvalue context, the value is assumed to be at the top of the stack. CodeGenerator generateCode; }; - - -} } diff --git a/libyul/backends/evm/EVMAssembly.cpp b/libyul/backends/evm/EVMAssembly.cpp index 791b6226e..99506317a 100644 --- a/libyul/backends/evm/EVMAssembly.cpp +++ b/libyul/backends/evm/EVMAssembly.cpp @@ -27,7 +27,7 @@ using namespace std; using namespace dev; using namespace langutil; -using namespace dev::yul; +using namespace yul; namespace { diff --git a/libyul/backends/evm/EVMAssembly.h b/libyul/backends/evm/EVMAssembly.h index c9190634f..d0a437ccd 100644 --- a/libyul/backends/evm/EVMAssembly.h +++ b/libyul/backends/evm/EVMAssembly.h @@ -31,8 +31,6 @@ namespace langutil struct SourceLocation; } -namespace dev -{ namespace yul { @@ -48,9 +46,9 @@ public: /// at the beginning. int stackHeight() const override { return m_stackHeight; } /// Append an EVM instruction. - void appendInstruction(solidity::Instruction _instruction) override; + void appendInstruction(dev::solidity::Instruction _instruction) override; /// Append a constant. - void appendConstant(u256 const& _constant) override; + void appendConstant(dev::u256 const& _constant) override; /// Append a label. void appendLabel(LabelID _labelId) override; /// Append a label reference. @@ -81,17 +79,17 @@ public: void appendAssemblySize() override; /// Resolves references inside the bytecode and returns the linker object. - eth::LinkerObject finalize(); + dev::eth::LinkerObject finalize(); private: void setLabelToCurrentPosition(AbstractAssembly::LabelID _labelId); void appendLabelReferenceInternal(AbstractAssembly::LabelID _labelId); - void updateReference(size_t pos, size_t size, u256 value); + void updateReference(size_t pos, size_t size, dev::u256 value); bool m_evm15 = false; ///< if true, switch to evm1.5 mode LabelID m_nextLabelId = 0; int m_stackHeight = 0; - bytes m_bytecode; + dev::bytes m_bytecode; std::map m_namedLabels; std::map m_labelPositions; std::map m_labelReferences; @@ -99,4 +97,3 @@ private: }; } -} diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 3cf1061a6..12abd754f 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -29,11 +29,9 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; -using Scope = dev::solidity::assembly::Scope; - void CodeTransform::operator()(VariableDeclaration const& _varDecl) { solAssert(m_scope, ""); @@ -147,7 +145,7 @@ void CodeTransform::operator()(FunctionalInstruction const& _instruction) solAssert(_instruction.arguments.size() == 1, ""); } m_assembly.setSourceLocation(_instruction.location); - auto label = labelFromIdentifier(boost::get(_instruction.arguments.at(0))); + auto label = labelFromIdentifier(boost::get(_instruction.arguments.at(0))); if (isJumpI) m_assembly.appendJumpToIf(label); else @@ -163,7 +161,7 @@ void CodeTransform::operator()(FunctionalInstruction const& _instruction) checkStackHeight(&_instruction); } -void CodeTransform::operator()(assembly::Identifier const& _identifier) +void CodeTransform::operator()(Identifier const& _identifier) { m_assembly.setSourceLocation(_identifier.location); // First search internals, then externals. @@ -197,12 +195,12 @@ void CodeTransform::operator()(assembly::Identifier const& _identifier) checkStackHeight(&_identifier); } -void CodeTransform::operator()(assembly::Literal const& _literal) +void CodeTransform::operator()(Literal const& _literal) { m_assembly.setSourceLocation(_literal.location); - if (_literal.kind == assembly::LiteralKind::Number) + if (_literal.kind == LiteralKind::Number) m_assembly.appendConstant(u256(_literal.value.str())); - else if (_literal.kind == assembly::LiteralKind::Boolean) + else if (_literal.kind == LiteralKind::Boolean) { if (_literal.value.str() == "true") m_assembly.appendConstant(u256(1)); @@ -217,7 +215,7 @@ void CodeTransform::operator()(assembly::Literal const& _literal) checkStackHeight(&_literal); } -void CodeTransform::operator()(assembly::Instruction const& _instruction) +void CodeTransform::operator()(yul::Instruction const& _instruction) { solAssert(!m_evm15 || _instruction.instruction != solidity::Instruction::JUMP, "Bare JUMP instruction used for EVM1.5"); solAssert(!m_evm15 || _instruction.instruction != solidity::Instruction::JUMPI, "Bare JUMPI instruction used for EVM1.5"); @@ -522,7 +520,7 @@ void CodeTransform::generateAssignment(Identifier const& _variableName) } } -int CodeTransform::variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap) const +int CodeTransform::variableHeightDiff(Scope::Variable const& _var, bool _forSwap) const { solAssert(m_context->variableStackHeights.count(&_var), ""); int heightDiff = m_assembly.stackHeight() - m_context->variableStackHeights[&_var]; diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index f4696e812..bf195dcdb 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -27,18 +27,14 @@ #include #include -namespace dev -{ -namespace solidity +namespace langutil { class ErrorReporter; -namespace assembly -{ -struct AsmAnalysisInfo; -} } + namespace yul { +struct AsmAnalysisInfo; class EVMAssembly; class CodeTransform: public boost::static_visitor<> @@ -47,8 +43,8 @@ public: /// Create the code transformer. /// @param _identifierAccess used to resolve identifiers external to the inline assembly CodeTransform( - yul::AbstractAssembly& _assembly, - solidity::assembly::AsmAnalysisInfo& _analysisInfo, + AbstractAssembly& _assembly, + AsmAnalysisInfo& _analysisInfo, bool _yul = false, bool _evm15 = false, ExternalIdentifierAccess const& _identifierAccess = ExternalIdentifierAccess(), @@ -69,15 +65,14 @@ public: protected: struct Context { - using Scope = solidity::assembly::Scope; std::map labelIDs; std::map functionEntryIDs; std::map variableStackHeights; }; CodeTransform( - yul::AbstractAssembly& _assembly, - solidity::assembly::AsmAnalysisInfo& _analysisInfo, + AbstractAssembly& _assembly, + AsmAnalysisInfo& _analysisInfo, bool _yul, bool _evm15, ExternalIdentifierAccess const& _identifierAccess, @@ -116,8 +111,8 @@ private: AbstractAssembly::LabelID labelFromIdentifier(Identifier const& _identifier); /// @returns the label ID corresponding to the given label, allocating a new one if /// necessary. - AbstractAssembly::LabelID labelID(solidity::assembly::Scope::Label const& _label); - AbstractAssembly::LabelID functionEntryID(YulString _name, solidity::assembly::Scope::Function const& _function); + AbstractAssembly::LabelID labelID(Scope::Label const& _label); + AbstractAssembly::LabelID functionEntryID(YulString _name, Scope::Function const& _function); /// Generates code for an expression that is supposed to return a single value. void visitExpression(Expression const& _expression); @@ -133,15 +128,15 @@ private: /// Determines the stack height difference to the given variables. Throws /// if it is not yet in scope or the height difference is too large. Returns /// the (positive) stack height difference otherwise. - int variableHeightDiff(solidity::assembly::Scope::Variable const& _var, bool _forSwap) const; + int variableHeightDiff(Scope::Variable const& _var, bool _forSwap) const; void expectDeposit(int _deposit, int _oldHeight) const; void checkStackHeight(void const* _astElement) const; - yul::AbstractAssembly& m_assembly; - solidity::assembly::AsmAnalysisInfo& m_info; - solidity::assembly::Scope* m_scope = nullptr; + AbstractAssembly& m_assembly; + AsmAnalysisInfo& m_info; + Scope* m_scope = nullptr; bool m_yul = false; bool m_evm15 = false; bool m_useNamedLabelsForFunctions = false; @@ -155,4 +150,3 @@ private: }; } -} diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index d4781ec27..f18b0e6bb 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -28,7 +28,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; Statement ASTCopier::operator()(Instruction const&) { diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 95e58a560..7daf74b8f 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -31,8 +31,6 @@ #include #include -namespace dev -{ namespace yul { @@ -123,4 +121,3 @@ std::vector ASTCopier::translateVector(std::vector const& _values) } -} diff --git a/libyul/optimiser/ASTWalker.cpp b/libyul/optimiser/ASTWalker.cpp index ed4a07ad9..0d5680072 100644 --- a/libyul/optimiser/ASTWalker.cpp +++ b/libyul/optimiser/ASTWalker.cpp @@ -26,7 +26,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; diff --git a/libyul/optimiser/ASTWalker.h b/libyul/optimiser/ASTWalker.h index 38cb85ead..9647c3235 100644 --- a/libyul/optimiser/ASTWalker.h +++ b/libyul/optimiser/ASTWalker.h @@ -32,8 +32,6 @@ #include #include -namespace dev -{ namespace yul { @@ -120,4 +118,3 @@ protected: }; } -} diff --git a/libyul/optimiser/BlockFlattener.cpp b/libyul/optimiser/BlockFlattener.cpp index 4552e3f1a..e6f085247 100644 --- a/libyul/optimiser/BlockFlattener.cpp +++ b/libyul/optimiser/BlockFlattener.cpp @@ -22,7 +22,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void BlockFlattener::operator()(Block& _block) { diff --git a/libyul/optimiser/BlockFlattener.h b/libyul/optimiser/BlockFlattener.h index 88c49ddae..b732422d7 100644 --- a/libyul/optimiser/BlockFlattener.h +++ b/libyul/optimiser/BlockFlattener.h @@ -18,8 +18,6 @@ #include -namespace dev -{ namespace yul { @@ -31,4 +29,3 @@ public: }; } -} diff --git a/libyul/optimiser/CommonSubexpressionEliminator.cpp b/libyul/optimiser/CommonSubexpressionEliminator.cpp index fc78b1ad7..9b8513337 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.cpp +++ b/libyul/optimiser/CommonSubexpressionEliminator.cpp @@ -28,7 +28,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void CommonSubexpressionEliminator::visit(Expression& _e) { diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index 16b39f5bf..ac1ebe3ac 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -23,8 +23,6 @@ #include -namespace dev -{ namespace yul { @@ -42,4 +40,3 @@ protected: }; } -} diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 046f466c3..64c67b383 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -33,7 +33,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void DataFlowAnalyzer::operator()(Assignment& _assignment) { diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index f83543c55..cd134d48e 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -28,8 +28,6 @@ #include #include -namespace dev -{ namespace yul { @@ -87,4 +85,3 @@ protected: }; } -} diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index e8c31aea1..fda5895be 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -26,11 +26,9 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; -using Scope = dev::solidity::assembly::Scope; - YulString Disambiguator::translateIdentifier(YulString _originalName) { if ((m_externallyUsedIdentifiers.count(_originalName))) diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index b2f80e476..4dd278e65 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -30,8 +30,6 @@ #include -namespace dev -{ namespace yul { @@ -42,7 +40,7 @@ class Disambiguator: public ASTCopier { public: explicit Disambiguator( - solidity::assembly::AsmAnalysisInfo const& _analysisInfo, + AsmAnalysisInfo const& _analysisInfo, std::set const& _externallyUsedIdentifiers = {} ): m_info(_analysisInfo), m_externallyUsedIdentifiers(_externallyUsedIdentifiers), m_nameDispenser(m_externallyUsedIdentifiers) @@ -56,16 +54,15 @@ protected: void leaveFunction(FunctionDefinition const& _function) override; YulString translateIdentifier(YulString _name) override; - void enterScopeInternal(solidity::assembly::Scope& _scope); - void leaveScopeInternal(solidity::assembly::Scope& _scope); + void enterScopeInternal(Scope& _scope); + void leaveScopeInternal(Scope& _scope); - solidity::assembly::AsmAnalysisInfo const& m_info; + AsmAnalysisInfo const& m_info; std::set const& m_externallyUsedIdentifiers; - std::vector m_scopes; + std::vector m_scopes; std::map m_translations; NameDispenser m_nameDispenser; }; } -} diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index abc006d43..27d43ac0f 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -29,7 +29,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void ExpressionInliner::run() diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index 46c27080a..681b0db4e 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -27,8 +27,6 @@ #include -namespace dev -{ namespace yul { @@ -68,4 +66,3 @@ private: } -} diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index 90301bad8..de2b5d53f 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -32,7 +32,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void ExpressionJoiner::operator()(FunctionalInstruction& _instruction) diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index 62d3beb9e..2d680b5cb 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -25,8 +25,6 @@ #include -namespace dev -{ namespace yul { @@ -98,4 +96,3 @@ private: }; } -} diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index 8746a783b..cda44e8e0 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -29,7 +29,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index 5965a1bb6..83e82b2b1 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -24,8 +24,6 @@ #include -namespace dev -{ namespace yul { @@ -52,4 +50,3 @@ private: }; } -} diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 54a03620e..a3b2dc110 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -32,7 +32,7 @@ using namespace std; using namespace dev; using namespace langutil; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void ExpressionSplitter::operator()(FunctionalInstruction& _instruction) diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index 82274203a..e5b86adc5 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -27,8 +27,6 @@ #include -namespace dev -{ namespace yul { @@ -83,4 +81,3 @@ private: }; } -} diff --git a/libyul/optimiser/ForLoopInitRewriter.cpp b/libyul/optimiser/ForLoopInitRewriter.cpp index b5e59884a..80d39248c 100644 --- a/libyul/optimiser/ForLoopInitRewriter.cpp +++ b/libyul/optimiser/ForLoopInitRewriter.cpp @@ -21,7 +21,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void ForLoopInitRewriter::operator()(Block& _block) { diff --git a/libyul/optimiser/ForLoopInitRewriter.h b/libyul/optimiser/ForLoopInitRewriter.h index 64f537111..e925c6c2e 100644 --- a/libyul/optimiser/ForLoopInitRewriter.h +++ b/libyul/optimiser/ForLoopInitRewriter.h @@ -18,8 +18,6 @@ #include -namespace dev -{ namespace yul { @@ -36,4 +34,3 @@ public: }; } -} diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index 47299f5fc..8ae26fbb5 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -36,7 +36,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; FullInliner::FullInliner(Block& _ast, NameDispenser& _dispenser): diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 5ebb3bf62..161d19457 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -33,8 +33,6 @@ #include -namespace dev -{ namespace yul { @@ -153,4 +151,3 @@ public: } -} diff --git a/libyul/optimiser/FunctionGrouper.cpp b/libyul/optimiser/FunctionGrouper.cpp index dc721caee..02ce22cdb 100644 --- a/libyul/optimiser/FunctionGrouper.cpp +++ b/libyul/optimiser/FunctionGrouper.cpp @@ -27,7 +27,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; diff --git a/libyul/optimiser/FunctionGrouper.h b/libyul/optimiser/FunctionGrouper.h index 63cfbfb13..508daf5d7 100644 --- a/libyul/optimiser/FunctionGrouper.h +++ b/libyul/optimiser/FunctionGrouper.h @@ -23,8 +23,6 @@ #include -namespace dev -{ namespace yul { @@ -43,4 +41,3 @@ public: }; } -} diff --git a/libyul/optimiser/FunctionHoister.cpp b/libyul/optimiser/FunctionHoister.cpp index 517559687..bd1c781b0 100644 --- a/libyul/optimiser/FunctionHoister.cpp +++ b/libyul/optimiser/FunctionHoister.cpp @@ -28,7 +28,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void FunctionHoister::operator()(Block& _block) diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 298948951..3d53aa89f 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -24,8 +24,6 @@ #include #include -namespace dev -{ namespace yul { @@ -48,4 +46,3 @@ private: }; } -} diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index 22267b622..662cdf250 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void InlinableExpressionFunctionFinder::operator()(Identifier const& _identifier) { diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index a96f042f0..f64155dec 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -25,8 +25,6 @@ #include -namespace dev -{ namespace yul { @@ -66,4 +64,3 @@ private: }; } -} diff --git a/libyul/optimiser/MainFunction.cpp b/libyul/optimiser/MainFunction.cpp index 5f3350310..63eea2dba 100644 --- a/libyul/optimiser/MainFunction.cpp +++ b/libyul/optimiser/MainFunction.cpp @@ -30,7 +30,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void MainFunction::operator()(Block& _block) diff --git a/libyul/optimiser/MainFunction.h b/libyul/optimiser/MainFunction.h index 4a73283a8..f4a643039 100644 --- a/libyul/optimiser/MainFunction.h +++ b/libyul/optimiser/MainFunction.h @@ -23,8 +23,6 @@ #include -namespace dev -{ namespace yul { @@ -38,4 +36,3 @@ public: }; } -} diff --git a/libyul/optimiser/Metrics.cpp b/libyul/optimiser/Metrics.cpp index 5107fc590..a5557fb34 100644 --- a/libyul/optimiser/Metrics.cpp +++ b/libyul/optimiser/Metrics.cpp @@ -23,7 +23,7 @@ #include using namespace dev; -using namespace dev::yul; +using namespace yul; size_t CodeSize::codeSize(Statement const& _statement) { diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index e65110a8a..ca2446004 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -22,8 +22,6 @@ #include -namespace dev -{ namespace yul { @@ -49,4 +47,3 @@ private: }; } -} diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index 7da001f8b..f90798271 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -24,7 +24,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void NameCollector::operator()(VariableDeclaration const& _varDecl) { diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index 8ef0178d5..c177a3996 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -25,8 +25,6 @@ #include #include -namespace dev -{ namespace yul { @@ -83,4 +81,3 @@ private: }; } -} diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index 11e854776..e7cdc60fc 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; NameDispenser::NameDispenser(Block const& _ast): NameDispenser(NameCollector(_ast).names()) diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 7311440b4..1d31fd38d 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -25,8 +25,6 @@ #include -namespace dev -{ namespace yul { @@ -58,4 +56,3 @@ private: }; } -} diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/RedundantAssignEliminator.cpp index f415a36cb..7b18e8ca1 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/RedundantAssignEliminator.cpp @@ -30,7 +30,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void RedundantAssignEliminator::operator()(Identifier const& _identifier) diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/RedundantAssignEliminator.h index bffbb07ad..014a7c77f 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/RedundantAssignEliminator.h @@ -26,8 +26,6 @@ #include -namespace dev -{ namespace yul { @@ -189,4 +187,3 @@ private: }; } -} diff --git a/libyul/optimiser/Rematerialiser.cpp b/libyul/optimiser/Rematerialiser.cpp index b9a127bbe..4180bfc36 100644 --- a/libyul/optimiser/Rematerialiser.cpp +++ b/libyul/optimiser/Rematerialiser.cpp @@ -27,7 +27,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void Rematerialiser::visit(Expression& _e) { diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index f0e7cb018..b3841519d 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -22,8 +22,6 @@ #include -namespace dev -{ namespace yul { @@ -41,4 +39,3 @@ protected: }; } -} diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index ae84dd948..928c08597 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -31,7 +31,7 @@ using namespace std; using namespace dev; using namespace langutil; -using namespace dev::yul; +using namespace yul; using namespace dev::solidity; void SSATransform::operator()(Identifier& _identifier) diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 69638904b..2f069284d 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -25,8 +25,6 @@ #include -namespace dev -{ namespace yul { @@ -94,4 +92,3 @@ private: }; } -} diff --git a/libyul/optimiser/SSAValueTracker.cpp b/libyul/optimiser/SSAValueTracker.cpp index 24776498f..35b29b042 100644 --- a/libyul/optimiser/SSAValueTracker.cpp +++ b/libyul/optimiser/SSAValueTracker.cpp @@ -25,7 +25,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void SSAValueTracker::operator()(Assignment const& _assignment) { diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index acd5229c3..e182e0133 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -26,8 +26,6 @@ #include #include -namespace dev -{ namespace yul { @@ -54,4 +52,3 @@ private: }; } -} diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index ad9b19226..91bb2709a 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -29,7 +29,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; MovableChecker::MovableChecker(Expression const& _expression) { diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index a7e8706b5..70c50806f 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -24,8 +24,6 @@ #include -namespace dev -{ namespace yul { @@ -57,4 +55,3 @@ private: }; } -} diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index ec5379fc5..b3190fefb 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -31,7 +31,7 @@ using namespace std; using namespace dev; using namespace langutil; -using namespace dev::yul; +using namespace yul; SimplificationRule const* SimplificationRules::findFirstMatch( @@ -123,7 +123,7 @@ bool Pattern::matches(Expression const& _expr, map if (expr->type() != typeid(Literal)) return false; Literal const& literal = boost::get(*expr); - if (literal.kind != assembly::LiteralKind::Number) + if (literal.kind != LiteralKind::Number) return false; if (m_data && *m_data != u256(literal.value.str())) return false; @@ -193,7 +193,7 @@ Expression Pattern::toExpression(SourceLocation const& _location) const if (m_kind == PatternKind::Constant) { assertThrow(m_data, OptimizerException, "No match group and no constant value given."); - return Literal{_location, assembly::LiteralKind::Number, YulString{formatNumber(*m_data)}, {}}; + return Literal{_location, LiteralKind::Number, YulString{formatNumber(*m_data)}, {}}; } else if (m_kind == PatternKind::Operation) { @@ -208,7 +208,7 @@ Expression Pattern::toExpression(SourceLocation const& _location) const u256 Pattern::d() const { Literal const& literal = boost::get(matchGroupValue()); - assertThrow(literal.kind == assembly::LiteralKind::Number, OptimizerException, ""); + assertThrow(literal.kind == LiteralKind::Number, OptimizerException, ""); assertThrow(isValidDecimal(literal.value.str()) || isValidHex(literal.value.str()), OptimizerException, ""); return u256(literal.value.str()); } diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 3d3d8d2b9..023a61f7d 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -31,8 +31,6 @@ #include #include -namespace dev -{ namespace yul { @@ -85,11 +83,11 @@ public: /// Matches any expression. Pattern(PatternKind _kind = PatternKind::Any): m_kind(_kind) {} // Matches a specific constant value. - Pattern(unsigned _value): Pattern(u256(_value)) {} + Pattern(unsigned _value): Pattern(dev::u256(_value)) {} // Matches a specific constant value. - Pattern(u256 const& _value): m_kind(PatternKind::Constant), m_data(std::make_shared(_value)) {} + Pattern(dev::u256 const& _value): m_kind(PatternKind::Constant), m_data(std::make_shared(_value)) {} // Matches a given instruction with given arguments - Pattern(solidity::Instruction _instruction, std::vector const& _arguments = {}); + Pattern(dev::solidity::Instruction _instruction, std::vector const& _arguments = {}); /// Sets this pattern to be part of the match group with the identifier @a _group. /// Inside one rule, all patterns in the same match group have to match expressions from the /// same expression equivalence class. @@ -100,9 +98,9 @@ public: std::vector arguments() const { return m_arguments; } /// @returns the data of the matched expression if this pattern is part of a match group. - u256 d() const; + dev::u256 d() const; - solidity::Instruction instruction() const; + dev::solidity::Instruction instruction() const; /// Turns this pattern into an actual expression. Should only be called /// for patterns resulting from an action, i.e. with match groups assigned. @@ -112,12 +110,11 @@ private: Expression const& matchGroupValue() const; PatternKind m_kind = PatternKind::Any; - solidity::Instruction m_instruction; ///< Only valid if m_kind is Operation - std::shared_ptr m_data; ///< Only valid if m_kind is Constant + dev::solidity::Instruction m_instruction; ///< Only valid if m_kind is Operation + std::shared_ptr m_data; ///< Only valid if m_kind is Constant std::vector m_arguments; unsigned m_matchGroup = 0; std::map* m_matchGroups = nullptr; }; } -} diff --git a/libyul/optimiser/Substitution.cpp b/libyul/optimiser/Substitution.cpp index dbac5cf62..bc9efe962 100644 --- a/libyul/optimiser/Substitution.cpp +++ b/libyul/optimiser/Substitution.cpp @@ -24,7 +24,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; Expression Substitution::translate(Expression const& _expression) { diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index 6a0679f5c..41f73b923 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -25,8 +25,6 @@ #include -namespace dev -{ namespace yul { @@ -46,4 +44,3 @@ private: }; } -} diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index b69206331..36f0e1ebd 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -43,11 +43,11 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; void OptimiserSuite::run( Block& _ast, - solidity::assembly::AsmAnalysisInfo const& _analysisInfo, + AsmAnalysisInfo const& _analysisInfo, set const& _externallyUsedIdentifiers ) { diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 5b564c56f..3f23ee9f9 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -25,18 +25,11 @@ #include -namespace dev -{ -namespace solidity -{ -namespace assembly -{ -struct AsmAnalysisInfo; -} -} namespace yul { +struct AsmAnalysisInfo; + /** * Optimiser suite that combines all steps and also provides the settings for the heuristics */ @@ -45,11 +38,10 @@ class OptimiserSuite public: static void run( Block& _ast, - solidity::assembly::AsmAnalysisInfo const& _analysisInfo, + AsmAnalysisInfo const& _analysisInfo, std::set const& _externallyUsedIdentifiers = {} ); }; } -} diff --git a/libyul/optimiser/SyntacticalEquality.cpp b/libyul/optimiser/SyntacticalEquality.cpp index ff4ff81b5..99ce06e5c 100644 --- a/libyul/optimiser/SyntacticalEquality.cpp +++ b/libyul/optimiser/SyntacticalEquality.cpp @@ -27,7 +27,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; bool SyntacticalEqualityChecker::equal(Expression const& _e1, Expression const& _e2) { diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index e9fbebe0a..46527a661 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -24,8 +24,6 @@ #include -namespace dev -{ namespace yul { @@ -47,4 +45,3 @@ protected: }; } -} diff --git a/libyul/optimiser/UnusedPruner.cpp b/libyul/optimiser/UnusedPruner.cpp index 484e74756..31aead82c 100644 --- a/libyul/optimiser/UnusedPruner.cpp +++ b/libyul/optimiser/UnusedPruner.cpp @@ -30,7 +30,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; UnusedPruner::UnusedPruner(Block& _ast, set const& _externallyUsedFunctions) { diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index b5b46443f..64e02b35f 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -26,8 +26,6 @@ #include #include -namespace dev -{ namespace yul { @@ -62,4 +60,3 @@ private: }; } -} diff --git a/libyul/optimiser/Utilities.cpp b/libyul/optimiser/Utilities.cpp index e41fd15d8..b8cdd3391 100644 --- a/libyul/optimiser/Utilities.cpp +++ b/libyul/optimiser/Utilities.cpp @@ -28,9 +28,9 @@ using namespace std; using namespace dev; -using namespace dev::yul; +using namespace yul; -void dev::yul::removeEmptyBlocks(Block& _block) +void yul::removeEmptyBlocks(Block& _block) { auto isEmptyBlock = [](Statement const& _st) -> bool { return _st.type() == typeid(Block) && boost::get(_st).statements.empty(); diff --git a/libyul/optimiser/Utilities.h b/libyul/optimiser/Utilities.h index 5b18a27cf..11c9fa194 100644 --- a/libyul/optimiser/Utilities.h +++ b/libyul/optimiser/Utilities.h @@ -22,8 +22,6 @@ #include -namespace dev -{ namespace yul { @@ -31,4 +29,3 @@ namespace yul void removeEmptyBlocks(Block& _block); } -} diff --git a/libyul/optimiser/VarDeclPropagator.cpp b/libyul/optimiser/VarDeclPropagator.cpp index 855b82150..bf974f44c 100644 --- a/libyul/optimiser/VarDeclPropagator.cpp +++ b/libyul/optimiser/VarDeclPropagator.cpp @@ -24,10 +24,7 @@ using namespace std; using namespace dev; -using namespace dev::yul; - -using dev::solidity::assembly::TypedName; -using dev::solidity::assembly::TypedNameList; +using namespace yul; void VarDeclPropagator::operator()(Block& _block) { diff --git a/libyul/optimiser/VarDeclPropagator.h b/libyul/optimiser/VarDeclPropagator.h index ffecd2175..7a68d3266 100644 --- a/libyul/optimiser/VarDeclPropagator.h +++ b/libyul/optimiser/VarDeclPropagator.h @@ -25,8 +25,6 @@ #include #include -namespace dev -{ namespace yul { @@ -60,4 +58,3 @@ private: }; } -} diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 5352ef858..966badfc0 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -143,7 +143,7 @@ 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( diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 5851555a1..d7785287a 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -37,10 +37,10 @@ using namespace std; using namespace langutil; -using namespace dev::yul; +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> dev::yul::test::parse(string const& _source, bool _yul) +pair, shared_ptr> 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(CharStream(_source), ""); - auto parserResult = assembly::Parser(errorReporter, flavour).parse(scanner, false); + auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false); if (parserResult) { BOOST_REQUIRE(errorReporter.errors().empty()); - auto analysisInfo = make_shared(); - assembly::AsmAnalyzer analyzer( + auto analysisInfo = make_shared(); + yul::AsmAnalyzer analyzer( *analysisInfo, errorReporter, dev::test::Options::get().evmVersion(), @@ -83,13 +83,13 @@ pair, shared_ptr> 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(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 8241bfe1a..a1c64ca5d 100644 --- a/test/libyul/Common.h +++ b/test/libyul/Common.h @@ -34,26 +34,21 @@ class Error; using ErrorList = std::vector>; } -namespace dev -{ -namespace solidity -{ -namespace assembly +namespace yul { struct AsmAnalysisInfo; } -} + namespace yul { namespace test { void printErrors(langutil::ErrorList const& _errors, langutil::Scanner const& _scanner); -std::pair, std::shared_ptr> +std::pair, std::shared_ptr> 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 0f82dee3d..631cda086 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -35,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/Parser.cpp b/test/libyul/Parser.cpp index 957973d07..6f9463627 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -36,11 +36,10 @@ #include using namespace std; +using namespace dev; using namespace langutil; -namespace dev -{ -namespace solidity +namespace yul { namespace test { @@ -53,16 +52,16 @@ bool parse(string const& _source, ErrorReporter& errorReporter) try { auto scanner = make_shared(CharStream(_source)); - auto parserResult = assembly::Parser(errorReporter, assembly::AsmFlavour::Yul).parse(scanner, false); + 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); } } @@ -117,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,6 +301,5 @@ 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 02a63ae34..9c2da4930 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -55,8 +55,8 @@ using namespace dev; using namespace langutil; -using namespace dev::yul; -using namespace dev::yul::test; +using namespace yul; +using namespace yul::test; using namespace dev::solidity; using namespace dev::solidity::test; using namespace std; @@ -92,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 ast; - shared_ptr analysisInfo; + shared_ptr analysisInfo; if (!parse(_stream, _linePrefix, _formatted)) return false; @@ -256,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 = make_shared(CharStream(m_source), ""); - m_ast = assembly::Parser(errorReporter, flavour).parse(scanner, false); + 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::AsmAnalyzer analyzer( + m_analysisInfo = make_shared(); + yul::AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, dev::test::Options::get().evmVersion(), diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index d11ff8fb3..72c4299fc 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -26,22 +26,18 @@ class Error; using ErrorList = std::vector>; } -namespace dev -{ -namespace solidity -{ -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 create(std::string const& _filename) @@ -68,11 +64,10 @@ private: std::string m_optimizerStep; std::string m_expectation; - std::shared_ptr m_ast; - std::shared_ptr m_analysisInfo; + std::shared_ptr m_ast; + std::shared_ptr m_analysisInfo; std::string m_obtainedResult; }; } } -} diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 4e916b497..7a1471370 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -60,8 +60,7 @@ 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; @@ -83,14 +82,14 @@ public: { ErrorReporter errorReporter(m_errors); shared_ptr scanner = make_shared(CharStream(_input), ""); - m_ast = assembly::Parser(errorReporter, assembly::AsmFlavour::Strict).parse(scanner, false); + 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(); + m_analysisInfo = make_shared(); AsmAnalyzer analyzer( *m_analysisInfo, errorReporter, @@ -118,7 +117,7 @@ public: return; if (!disambiguated) { - *m_ast = boost::get(Disambiguator(*m_analysisInfo)(*m_ast)); + *m_ast = boost::get(Disambiguator(*m_analysisInfo)(*m_ast)); m_analysisInfo.reset(); m_nameDispenser = make_shared(*m_ast); disambiguated = true; @@ -187,7 +186,7 @@ public: private: ErrorList m_errors; - shared_ptr m_ast; + shared_ptr m_ast; shared_ptr m_analysisInfo; shared_ptr m_nameDispenser; }; From 8dd0338d127b50e60d50f978be68605e8f8faee5 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 21 Nov 2018 12:43:41 +0100 Subject: [PATCH 077/168] Remove superfluous libyul/ASTDataForward.h and include libyul/AsmDataForward directly instead. --- libyul/ASTDataForward.h | 25 ------------------- libyul/backends/evm/EVMCodeTransform.h | 2 +- libyul/optimiser/ASTCopier.h | 2 +- libyul/optimiser/ASTWalker.h | 2 +- libyul/optimiser/Disambiguator.h | 2 +- libyul/optimiser/ExpressionInliner.h | 2 +- libyul/optimiser/ExpressionJoiner.h | 2 +- libyul/optimiser/ExpressionSimplifier.h | 2 +- libyul/optimiser/ExpressionSplitter.h | 2 +- libyul/optimiser/FullInliner.h | 2 +- libyul/optimiser/FunctionGrouper.h | 2 +- libyul/optimiser/FunctionHoister.h | 2 +- .../InlinableExpressionFunctionFinder.h | 2 +- libyul/optimiser/MainFunction.h | 2 +- libyul/optimiser/NameDispenser.h | 2 +- libyul/optimiser/RedundantAssignEliminator.h | 2 +- libyul/optimiser/SSATransform.h | 2 +- libyul/optimiser/SimplificationRules.h | 2 +- libyul/optimiser/Suite.h | 2 +- libyul/optimiser/SyntacticalEquality.h | 2 +- libyul/optimiser/Utilities.h | 2 +- libyul/optimiser/VarDeclPropagator.h | 2 +- 22 files changed, 21 insertions(+), 46 deletions(-) delete mode 100644 libyul/ASTDataForward.h diff --git a/libyul/ASTDataForward.h b/libyul/ASTDataForward.h deleted file mode 100644 index dffe1c748..000000000 --- a/libyul/ASTDataForward.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - 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 . -*/ -/** - * @date 2017 - * Pull in some identifiers from the solidity::assembly namespace. - */ - -#pragma once - -#include - diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index bf195dcdb..d559f85a7 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -20,7 +20,7 @@ #include -#include +#include #include diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 7daf74b8f..4d2f18aea 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libyul/optimiser/ASTWalker.h b/libyul/optimiser/ASTWalker.h index 9647c3235..b59b405ed 100644 --- a/libyul/optimiser/ASTWalker.h +++ b/libyul/optimiser/ASTWalker.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 4dd278e65..bb83417b8 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include #include #include diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index 681b0db4e..14e80c0a5 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include #include diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index 2d680b5cb..643d62b0a 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -20,7 +20,7 @@ */ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index 83e82b2b1..fe3507f8e 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index e5b86adc5..d4d2b3f61 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -20,7 +20,7 @@ */ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 161d19457..a8fe76c67 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -19,7 +19,7 @@ */ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/FunctionGrouper.h b/libyul/optimiser/FunctionGrouper.h index 508daf5d7..3b3f48a71 100644 --- a/libyul/optimiser/FunctionGrouper.h +++ b/libyul/optimiser/FunctionGrouper.h @@ -21,7 +21,7 @@ #pragma once -#include +#include namespace yul { diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 3d53aa89f..310920696 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include namespace yul diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index f64155dec..afde8a2a7 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/MainFunction.h b/libyul/optimiser/MainFunction.h index f4a643039..96acc0ac8 100644 --- a/libyul/optimiser/MainFunction.h +++ b/libyul/optimiser/MainFunction.h @@ -21,7 +21,7 @@ #pragma once -#include +#include namespace yul { diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 1d31fd38d..664a52652 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -19,7 +19,7 @@ */ #pragma once -#include +#include #include diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/RedundantAssignEliminator.h index 014a7c77f..54d658234 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/RedundantAssignEliminator.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 2f069284d..4cb62f238 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -20,7 +20,7 @@ */ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index 023a61f7d..16aaba045 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 3f23ee9f9..795326b42 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include #include diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 46527a661..63c51b4fe 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -20,7 +20,7 @@ #pragma once -#include +#include #include diff --git a/libyul/optimiser/Utilities.h b/libyul/optimiser/Utilities.h index 11c9fa194..c543b1196 100644 --- a/libyul/optimiser/Utilities.h +++ b/libyul/optimiser/Utilities.h @@ -20,7 +20,7 @@ #pragma once -#include +#include namespace yul { diff --git a/libyul/optimiser/VarDeclPropagator.h b/libyul/optimiser/VarDeclPropagator.h index 7a68d3266..1908c2142 100644 --- a/libyul/optimiser/VarDeclPropagator.h +++ b/libyul/optimiser/VarDeclPropagator.h @@ -17,7 +17,7 @@ #pragma once -#include +#include #include #include #include From f57ef36c0e5fdefcb0893c51d466f6b4bb674797 Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Fri, 23 Nov 2018 17:16:18 +0100 Subject: [PATCH 078/168] Update docs/types.rst Co-Authored-By: ChrisChinchilla --- docs/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index 5a0acfbb4..39238f8fe 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -13,7 +13,7 @@ Solidity provides several elementary types which can be combined to form complex In addition, types can interact with each other in expressions containing operators. For a quick reference of the various operators, see :ref:`order`. -The concept of "undefined" or "null" values do not exist in Solidity, but newly +The concept of "undefined" or "null" values does not exist in Solidity, but newly declared variables always have a :ref:`default value` dependent on its type. To handle any unexpected values, you should use the :ref:`revert function` to revert the whole transaction, or return a tuple with a second `bool` value denoting success. From e454737a3cf389ee400a9ef1d9f252c579a2ceea Mon Sep 17 00:00:00 2001 From: Lazaridis Date: Thu, 22 Nov 2018 18:37:19 +0200 Subject: [PATCH 079/168] adapt to latest code changes --- liblangutil/Scanner.cpp | 30 +++++++++------- liblangutil/Token.h | 12 +++++++ libsolidity/parsing/Parser.cpp | 24 +++++++++++++ test/libsolidity/SolidityScanner.cpp | 35 ++++++++++--------- .../inlineAssembly/invalid/invalid_number.sol | 2 +- ..._fixed_conversion_leading_zeroes_check.sol | 2 +- .../syntaxTests/string/string_new_line.sol | 2 +- .../string/string_terminated_by_backslash.sol | 2 +- .../string/string_unterminated.sol | 2 +- .../string_unterminated_no_new_line.sol | 2 +- .../syntaxTests/unicode_escape_literals.sol | 2 +- 11 files changed, 79 insertions(+), 36 deletions(-) diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 3d7527d4d..091e9b89a 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -311,7 +311,7 @@ Token Scanner::skipMultiLineComment() } } // Unterminated multi-line comment. - return Token::Illegal; + return Token::IllegalCommentTerminator; } Token Scanner::scanMultiLineDocComment() @@ -362,7 +362,7 @@ Token Scanner::scanMultiLineDocComment() } literal.complete(); if (!endFound) - return Token::Illegal; + return Token::IllegalCommentTerminator; else return Token::CommentLiteral; } @@ -392,7 +392,7 @@ Token Scanner::scanSlash() { // doxygen style /** natspec comment if (!advance()) /* slash star comment before EOS */ - return Token::Illegal; + return Token::IllegalCommentTerminator; else if (m_char == '*') { advance(); //consume the last '*' at /** @@ -409,8 +409,9 @@ Token Scanner::scanSlash() comment = scanMultiLineDocComment(); m_nextSkippedComment.location.end = sourcePos(); m_nextSkippedComment.token = comment; - if (comment == Token::Illegal) - return Token::Illegal; + // @todo possibly: if (comment.isIllegal) return comment; to pass all errors + if (comment == Token::IllegalCommentTerminator) + return Token::IllegalCommentTerminator; else return Token::Whitespace; } @@ -620,6 +621,7 @@ void Scanner::scanToken() else if (isSourcePastEndOfInput()) token = Token::EOS; else + // @todo verfiy if this is actually an "IllegalUnknown" case token = selectToken(Token::Illegal); break; } @@ -713,13 +715,13 @@ Token Scanner::scanString() if (c == '\\') { if (isSourcePastEndOfInput() || !scanEscape()) - return Token::Illegal; + return Token::IllegalStringEscape; } else addLiteralChar(c); } if (m_char != quote) - return Token::Illegal; + return Token::IllegalStringEndQuote; literal.complete(); advance(); // consume quote return Token::StringLiteral; @@ -767,7 +769,8 @@ Token Scanner::scanNumber(char _charSeen) // we have already seen a decimal point of the float addLiteralChar('.'); if (m_char == '_') - return Token::Illegal; + // @todo add test-case (change of return value did not break test) + return Token::IllegalNumberSeparator; scanDecimalDigits(); // we know we have at least one digit } else @@ -784,14 +787,14 @@ Token Scanner::scanNumber(char _charSeen) kind = HEX; addLiteralCharAndAdvance(); if (!isHexDigit(m_char)) - return Token::Illegal; // we must have at least one hex digit after 'x' + return Token::IllegalHexDigit; // we must have at least one hex digit after 'x' while (isHexDigit(m_char) || m_char == '_') // We keep the underscores for later validation addLiteralCharAndAdvance(); } else if (isDecimalDigit(m_char)) // We do not allow octal numbers - return Token::Illegal; + return Token::IllegalOctalNotAllowed; } // Parse decimal digits and allow trailing fractional part. if (kind == DECIMAL) @@ -823,7 +826,8 @@ Token Scanner::scanNumber(char _charSeen) { solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); if (kind != DECIMAL) - return Token::Illegal; + // @todo add test (change introduced no failing) + return Token::IllegalExponent; else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') { // Recover from wrongly placed underscore as delimiter in literal with scientific @@ -839,7 +843,7 @@ Token Scanner::scanNumber(char _charSeen) if (m_char == '+' || m_char == '-') addLiteralCharAndAdvance(); if (!isDecimalDigit(m_char)) - return Token::Illegal; // we must have at least one decimal digit after 'e'/'E' + return Token::IllegalExponent; // we must have at least one decimal digit after 'e'/'E' scanDecimalDigits(); } // The source character immediately following a numeric literal must @@ -847,7 +851,7 @@ Token Scanner::scanNumber(char _charSeen) // section 7.8.3, page 17 (note that we read only one decimal digit // if the value is 0). if (isDecimalDigit(m_char) || isIdentifierStart(m_char)) - return Token::Illegal; + return Token::IllegalNumberEnd; literal.complete(); return Token::Number; } diff --git a/liblangutil/Token.h b/liblangutil/Token.h index d997b138c..55d474f51 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -265,6 +265,15 @@ namespace langutil T(Illegal, "ILLEGAL", 0) \ /* Illegal hex token */ \ T(IllegalHex, "ILLEGAL_HEX", 0) \ + T(IllegalCommentTerminator, "ILLEGAL_COMMENT_TERMINATOR", 0) \ + T(IllegalStringEscape, "ILLEGAL_STRING_ESCAPE", 0) \ + T(IllegalStringEndQuote, "ILLEGAL_STRING_END_QUOTE", 0) \ + T(IllegalNumberSeparator, "ILLEGAL_NUMER_SEPARATOR", 0) \ + T(IllegalHexDigit, "ILLEGAL_HEX_DIGIT", 0) \ + T(IllegalOctalNotAllowed, "ILLEGAL_OCTAL_NOT_ALLOWED", 0) \ + T(IllegalExponent, "ILLEGAL_EXPONENT", 0) \ + T(IllegalNumberEnd, "ILLEGAL_NUMBER_END", 0) \ + T(IllegalEnd, NULL, 0) /* used as type Illegal enum end marker */ \ \ /* Scanner-internal use only. */ \ T(Whitespace, nullptr, 0) @@ -312,6 +321,9 @@ namespace TokenTraits constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; } constexpr bool isReservedKeyword(Token op) { return (Token::Abstract <= op && op <= Token::Unchecked); } + // @returns true if token is illegal + constexpr bool isIllegal(Token tok) { return Token::Illegal <= tok && tok < Token::IllegalEnd; }; + inline Token AssignmentToBinaryOp(Token op) { solAssert(isAssignmentOp(op) && op != Token::Assign, ""); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ffe2be83d..b78c58c67 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1558,6 +1558,30 @@ ASTPointer Parser::parsePrimaryExpression() case Token::IllegalHex: fatalParserError("Expected even number of hex-nibbles within double-quotes."); break; + case Token::IllegalCommentTerminator: + fatalParserError("Expected multi-line comment-terminator."); + break; + case Token::IllegalStringEscape: + fatalParserError("Invalid String Escape."); + break; + case Token::IllegalStringEndQuote: + fatalParserError("Expected String end-quote."); + break; + case Token::IllegalNumberSeparator: + fatalParserError("Invalid use of Number Separator '_'."); + break; + case Token::IllegalHexDigit: + fatalParserError("Hex Digit missing or invalid."); + break; + case Token::IllegalOctalNotAllowed: + fatalParserError("Octal Numbers not allowed."); + break; + case Token::IllegalExponent: + fatalParserError("Invalid Exponent."); + break; + case Token::IllegalNumberEnd: + fatalParserError("Digit or Identifier-Start not allowed at end of Number."); + break; default: if (TokenTraits::isElementaryTypeName(token)) { diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 2d164ae34..9d1383db2 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -59,6 +59,8 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } +// STRING ESCAPES + BOOST_AUTO_TEST_CASE(string_escapes) { Scanner scanner(CharStream(" { \"a\\x61\"")); @@ -87,12 +89,12 @@ BOOST_AUTO_TEST_CASE(string_escape_illegal) { Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEscape); BOOST_CHECK_EQUAL(scanner.currentLiteral(), ""); // TODO recovery from illegal tokens should be improved - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalNumberEnd); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEndQuote); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -110,18 +112,19 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x1234"); scanner.reset(CharStream("0X1234"), ""); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + // @todo update underlying code to return "Expected lower-case 'x' for Hex-Numbers." or similar. + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalNumberEnd); } BOOST_AUTO_TEST_CASE(octal_numbers) { Scanner scanner(CharStream("07")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalOctalNotAllowed); scanner.reset(CharStream("007"), ""); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalOctalNotAllowed); scanner.reset(CharStream("-07"), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Sub); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalOctalNotAllowed); scanner.reset(CharStream("-.07"), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Sub); BOOST_CHECK_EQUAL(scanner.next(), Token::Number); @@ -204,7 +207,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_exp_after_e_illegal) BOOST_AUTO_TEST_CASE(leading_underscore_hex_illegal) { Scanner scanner(CharStream("0x_abc")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalHexDigit); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -469,7 +472,7 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape) { Scanner scanner(CharStream("{ \"\\uFFnicode\"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEscape); } // HEX STRING LITERAL @@ -516,7 +519,7 @@ BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) { // This used to parse as "comment", "identifier" Scanner scanner(CharStream("/** / x")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalCommentTerminator); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -524,14 +527,14 @@ BOOST_AUTO_TEST_CASE(multiline_doc_comment_at_eos) { // This used to parse as "whitespace" Scanner scanner(CharStream("/**")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalCommentTerminator); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } BOOST_AUTO_TEST_CASE(multiline_comment_at_eos) { Scanner scanner(CharStream("/*")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalCommentTerminator); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -594,10 +597,10 @@ BOOST_AUTO_TEST_CASE(regular_line_breaks_in_strings) for (auto const& nl: {"\n", "\r"}) { Scanner scanner(CharStream("\"abc " + string(nl) + " def\"")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalStringEndQuote); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEndQuote); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } } @@ -607,12 +610,12 @@ 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\"")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalStringEndQuote); for (size_t i = 0; i < string(nl).size(); i++) BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); - BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); + BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEndQuote); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } } diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol index 715913de7..99a906deb 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/parsing/invalid_fixed_conversion_leading_zeroes_check.sol b/test/libsolidity/syntaxTests/parsing/invalid_fixed_conversion_leading_zeroes_check.sol index fb267ba3f..4ac008a87 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): Digit or Identifier-Start not allowed at end of Number. diff --git a/test/libsolidity/syntaxTests/string/string_new_line.sol b/test/libsolidity/syntaxTests/string/string_new_line.sol index da2240f78..5a52534b1 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 3eaba6af0..000d3b0e3 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. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/string/string_unterminated.sol b/test/libsolidity/syntaxTests/string/string_unterminated.sol index 3291781e0..6772a3007 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. \ No newline at end of file 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 e7be50d23..734ce37f5 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. \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/unicode_escape_literals.sol b/test/libsolidity/syntaxTests/unicode_escape_literals.sol index a340487b1..ac9aa08a9 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 String Escape. From aeb66905de3f65ca7a63addb6c9d05108986dbeb Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Sat, 24 Nov 2018 12:33:36 +0100 Subject: [PATCH 080/168] Moving SourceReferenceFormatter into langutil namespace. --- .../SourceReferenceFormatter.cpp | 13 +++--------- .../SourceReferenceFormatter.h | 21 +++++++------------ libsolidity/codegen/CompilerContext.cpp | 2 +- libsolidity/interface/StandardCompiler.cpp | 2 +- solc/CommandLineInterface.cpp | 2 +- test/libsolidity/AnalysisFramework.cpp | 2 +- test/libsolidity/GasMeter.cpp | 2 +- test/libsolidity/SolidityExecutionFramework.h | 4 ++-- test/libyul/Common.cpp | 2 +- test/libyul/YulOptimizerTest.cpp | 2 +- test/tools/yulopti.cpp | 2 +- 11 files changed, 20 insertions(+), 34 deletions(-) rename {libsolidity/interface => liblangutil}/SourceReferenceFormatter.cpp (96%) rename {libsolidity/interface => liblangutil}/SourceReferenceFormatter.h (91%) diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp similarity index 96% rename from libsolidity/interface/SourceReferenceFormatter.cpp rename to liblangutil/SourceReferenceFormatter.cpp index d727afbeb..58a655215 100644 --- a/libsolidity/interface/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -20,18 +20,14 @@ * Formatting functions for errors referencing positions and locations in the source. */ -#include +#include #include #include using namespace std; +using namespace dev; using namespace langutil; -namespace dev -{ -namespace solidity -{ - void SourceReferenceFormatter::printSourceLocation(SourceLocation const* _location) { if (!_location || !_location->sourceName) @@ -103,7 +99,7 @@ void SourceReferenceFormatter::printSourceName(SourceLocation const* _location) } void SourceReferenceFormatter::printExceptionInformation( - Exception const& _exception, + dev::Exception const& _exception, string const& _name ) { @@ -131,6 +127,3 @@ void SourceReferenceFormatter::printExceptionInformation( m_stream << endl; } } - -} -} diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/liblangutil/SourceReferenceFormatter.h similarity index 91% rename from libsolidity/interface/SourceReferenceFormatter.h rename to liblangutil/SourceReferenceFormatter.h index 7dea5254e..0ef3ca001 100644 --- a/libsolidity/interface/SourceReferenceFormatter.h +++ b/liblangutil/SourceReferenceFormatter.h @@ -26,21 +26,15 @@ #include #include +namespace dev +{ +struct Exception; // forward +} + namespace langutil { struct SourceLocation; class Scanner; -} - -namespace dev -{ - -struct Exception; // forward - -namespace solidity -{ - -class CompilerStack; // forward class SourceReferenceFormatter { @@ -57,10 +51,10 @@ public: /// Prints source location if it is given. void printSourceLocation(langutil::SourceLocation const* _location); - void printExceptionInformation(Exception const& _exception, std::string const& _name); + void printExceptionInformation(dev::Exception const& _exception, std::string const& _name); static std::string formatExceptionInformation( - Exception const& _exception, + dev::Exception const& _exception, std::string const& _name, ScannerFromSourceNameFun const& _scannerFromSourceName ) @@ -80,4 +74,3 @@ private: }; } -} diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index d1bf29fc2..55a33cf51 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index bf33b7897..4a32d9f34 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -21,7 +21,7 @@ */ #include -#include +#include #include #include #include diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index b523f0521..7f64d8ac3 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 12d63cb78..bd24115cd 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 61f16c0fe..601948bc3 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include using namespace std; using namespace langutil; diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index d43e994d7..cedbf51a7 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -28,7 +28,7 @@ #include #include -#include +#include namespace dev { @@ -73,7 +73,7 @@ public: if (!m_compiler.compile()) { auto scannerFromSourceName = [&](std::string const& _sourceName) -> langutil::Scanner const& { return m_compiler.scanner(_sourceName); }; - SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); + langutil::SourceReferenceFormatter formatter(std::cerr, scannerFromSourceName); for (auto const& error: m_compiler.errors()) formatter.printExceptionInformation( diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index d7785287a..2e70d0869 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 9c2da4930..c857d8a5f 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 7a1471370..5a8a51063 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include From e4106bd06eebce9e17d51858a37bf82566b7f640 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 16:47:34 +0100 Subject: [PATCH 081/168] Change scanner error diagnostics to be non-intrusive to the token API. This also implicitly eliminates the magic-token Token::IllegalHex, and streamlines error diagnostics over a custom enum class. --- liblangutil/Scanner.cpp | 70 +++++++++++++++++++++++----------- liblangutil/Scanner.h | 33 ++++++++++++++++ liblangutil/Token.h | 14 ------- libsolidity/parsing/Parser.cpp | 28 +------------- 4 files changed, 83 insertions(+), 62 deletions(-) diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 091e9b89a..215171b3f 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include using namespace std; @@ -100,7 +101,32 @@ int hexValue(char c) } } // end anonymous namespace +std::string to_string(ScannerError _errorCode) +{ + switch (_errorCode) + { + case ScannerError::NoError: return "No error."; + case ScannerError::IllegalToken: return "Invalid token."; + case ScannerError::IllegalHexString: return "Expected even number of hex-nibbles within double-quotes."; + case ScannerError::IllegalHexDigit: return "Hexadecimal digit missing or invalid."; + case ScannerError::IllegalCommentTerminator: return "Expected multi-line comment-terminator."; + case ScannerError::IllegalEscapeSequence: return "Invalid escape sequence."; + case ScannerError::IllegalStringEndQuote: return "Expected string end-quote."; + case ScannerError::IllegalNumberSeparator: return "Invalid use of number separator '_'."; + case ScannerError::IllegalExponent: return "Invalid exponent."; + case ScannerError::IllegalNumberEnd: return "Identifier-start is not allowed at end of a number."; + case ScannerError::OctalNotAllowed: return "Octal numbers not allowed."; + default: + solAssert(false, "Unhandled case in to_string(ScannerError)"); + return ""; + } +} +std::ostream& operator<<(std::ostream& os, ScannerError _errorCode) +{ + os << to_string(_errorCode); + return os; +} /// Scoped helper for literal recording. Automatically drops the literal /// if aborting the scanning before it's complete. @@ -311,7 +337,7 @@ Token Scanner::skipMultiLineComment() } } // Unterminated multi-line comment. - return Token::IllegalCommentTerminator; + return setError(ScannerError::IllegalCommentTerminator); } Token Scanner::scanMultiLineDocComment() @@ -362,7 +388,7 @@ Token Scanner::scanMultiLineDocComment() } literal.complete(); if (!endFound) - return Token::IllegalCommentTerminator; + return setError(ScannerError::IllegalCommentTerminator); else return Token::CommentLiteral; } @@ -392,7 +418,7 @@ Token Scanner::scanSlash() { // doxygen style /** natspec comment if (!advance()) /* slash star comment before EOS */ - return Token::IllegalCommentTerminator; + return setError(ScannerError::IllegalCommentTerminator); else if (m_char == '*') { advance(); //consume the last '*' at /** @@ -409,9 +435,8 @@ Token Scanner::scanSlash() comment = scanMultiLineDocComment(); m_nextSkippedComment.location.end = sourcePos(); m_nextSkippedComment.token = comment; - // @todo possibly: if (comment.isIllegal) return comment; to pass all errors - if (comment == Token::IllegalCommentTerminator) - return Token::IllegalCommentTerminator; + if (comment == Token::Illegal) + return Token::Illegal; // error already set else return Token::Whitespace; } @@ -426,6 +451,7 @@ Token Scanner::scanSlash() void Scanner::scanToken() { + m_nextToken.error = ScannerError::NoError; m_nextToken.literal.clear(); m_nextToken.extendedTokenInfo = make_tuple(0, 0); m_nextSkippedComment.literal.clear(); @@ -611,7 +637,7 @@ void Scanner::scanToken() if (m_char == '"' || m_char == '\'') token = scanHexString(); else - token = Token::IllegalHex; + token = setError(ScannerError::IllegalToken); } } else if (isDecimalDigit(m_char)) @@ -621,8 +647,7 @@ void Scanner::scanToken() else if (isSourcePastEndOfInput()) token = Token::EOS; else - // @todo verfiy if this is actually an "IllegalUnknown" case - token = selectToken(Token::Illegal); + token = selectErrorToken(ScannerError::IllegalToken); break; } // Continue scanning for tokens as long as we're just skipping @@ -715,13 +740,13 @@ Token Scanner::scanString() if (c == '\\') { if (isSourcePastEndOfInput() || !scanEscape()) - return Token::IllegalStringEscape; + return setError(ScannerError::IllegalEscapeSequence); } else addLiteralChar(c); } if (m_char != quote) - return Token::IllegalStringEndQuote; + return setError(ScannerError::IllegalStringEndQuote); literal.complete(); advance(); // consume quote return Token::StringLiteral; @@ -736,11 +761,14 @@ Token Scanner::scanHexString() { char c = m_char; if (!scanHexByte(c)) - return Token::IllegalHex; + // can only return false if hex-byte is incomplete (only one hex digit instead of two) + return setError(ScannerError::IllegalHexString); addLiteralChar(c); } + if (m_char != quote) - return Token::IllegalHex; + return setError(ScannerError::IllegalStringEndQuote); + literal.complete(); advance(); // consume quote return Token::StringLiteral; @@ -769,8 +797,7 @@ Token Scanner::scanNumber(char _charSeen) // we have already seen a decimal point of the float addLiteralChar('.'); if (m_char == '_') - // @todo add test-case (change of return value did not break test) - return Token::IllegalNumberSeparator; + return setError(ScannerError::IllegalToken); scanDecimalDigits(); // we know we have at least one digit } else @@ -787,14 +814,14 @@ Token Scanner::scanNumber(char _charSeen) kind = HEX; addLiteralCharAndAdvance(); if (!isHexDigit(m_char)) - return Token::IllegalHexDigit; // we must have at least one hex digit after 'x' + return setError(ScannerError::IllegalHexDigit); // we must have at least one hex digit after 'x' while (isHexDigit(m_char) || m_char == '_') // We keep the underscores for later validation addLiteralCharAndAdvance(); } else if (isDecimalDigit(m_char)) // We do not allow octal numbers - return Token::IllegalOctalNotAllowed; + return setError(ScannerError::OctalNotAllowed); } // Parse decimal digits and allow trailing fractional part. if (kind == DECIMAL) @@ -826,8 +853,7 @@ Token Scanner::scanNumber(char _charSeen) { solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); if (kind != DECIMAL) - // @todo add test (change introduced no failing) - return Token::IllegalExponent; + return setError(ScannerError::IllegalExponent); else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') { // Recover from wrongly placed underscore as delimiter in literal with scientific @@ -842,8 +868,8 @@ Token Scanner::scanNumber(char _charSeen) addLiteralCharAndAdvance(); // 'e' | 'E' if (m_char == '+' || m_char == '-') addLiteralCharAndAdvance(); - if (!isDecimalDigit(m_char)) - return Token::IllegalExponent; // we must have at least one decimal digit after 'e'/'E' + if (!isDecimalDigit(m_char)) // we must have at least one decimal digit after 'e'/'E' + return setError(ScannerError::IllegalExponent); scanDecimalDigits(); } // The source character immediately following a numeric literal must @@ -851,7 +877,7 @@ Token Scanner::scanNumber(char _charSeen) // section 7.8.3, page 17 (note that we read only one decimal digit // if the value is 0). if (isDecimalDigit(m_char) || isIdentifierStart(m_char)) - return Token::IllegalNumberEnd; + return setError(ScannerError::IllegalNumberEnd); literal.complete(); return Token::Number; } diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index da5e3dfb1..d01e71e2f 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -57,6 +57,7 @@ #include #include #include +#include namespace langutil { @@ -65,6 +66,26 @@ class AstRawString; class AstValueFactory; class ParserRecorder; +enum class ScannerError +{ + NoError, + + IllegalToken, + IllegalHexString, + IllegalHexDigit, + IllegalCommentTerminator, + IllegalEscapeSequence, + IllegalStringEndQuote, + IllegalNumberSeparator, + IllegalExponent, + IllegalNumberEnd, + + OctalNotAllowed, +}; + +std::string to_string(ScannerError _errorCode); +std::ostream& operator<<(std::ostream& os, ScannerError _errorCode); + class Scanner { friend class LiteralScope; @@ -100,6 +121,10 @@ public: SourceLocation currentLocation() const { return m_currentToken.location; } std::string const& currentLiteral() const { return m_currentToken.literal; } std::tuple const& currentTokenInfo() const { return m_currentToken.extendedTokenInfo; } + + /// Retrieves the last error that occurred during lexical analysis. + /// @note If no error occurred, the value is undefined. + ScannerError currentError() const noexcept { return m_currentToken.error; } ///@} ///@{ @@ -139,12 +164,19 @@ public: ///@} private: + inline Token setError(ScannerError _error) noexcept + { + m_nextToken.error = _error; + return Token::Illegal; + } + /// Used for the current and look-ahead token and comments struct TokenDesc { Token token; SourceLocation location; std::string literal; + ScannerError error = ScannerError::NoError; std::tuple extendedTokenInfo; }; @@ -159,6 +191,7 @@ private: bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); } void rollback(int _amount) { m_char = m_source.rollback(_amount); } + inline Token selectErrorToken(ScannerError _err) { advance(); return setError(_err); } inline Token selectToken(Token _tok) { advance(); return _tok; } /// If the next character is _next, advance and return _then, otherwise return _else. inline Token selectToken(char _next, Token _then, Token _else); diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 55d474f51..f832fdf7c 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -263,17 +263,6 @@ namespace langutil \ /* Illegal token - not able to scan. */ \ T(Illegal, "ILLEGAL", 0) \ - /* Illegal hex token */ \ - T(IllegalHex, "ILLEGAL_HEX", 0) \ - T(IllegalCommentTerminator, "ILLEGAL_COMMENT_TERMINATOR", 0) \ - T(IllegalStringEscape, "ILLEGAL_STRING_ESCAPE", 0) \ - T(IllegalStringEndQuote, "ILLEGAL_STRING_END_QUOTE", 0) \ - T(IllegalNumberSeparator, "ILLEGAL_NUMER_SEPARATOR", 0) \ - T(IllegalHexDigit, "ILLEGAL_HEX_DIGIT", 0) \ - T(IllegalOctalNotAllowed, "ILLEGAL_OCTAL_NOT_ALLOWED", 0) \ - T(IllegalExponent, "ILLEGAL_EXPONENT", 0) \ - T(IllegalNumberEnd, "ILLEGAL_NUMBER_END", 0) \ - T(IllegalEnd, NULL, 0) /* used as type Illegal enum end marker */ \ \ /* Scanner-internal use only. */ \ T(Whitespace, nullptr, 0) @@ -321,9 +310,6 @@ namespace TokenTraits constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; } constexpr bool isReservedKeyword(Token op) { return (Token::Abstract <= op && op <= Token::Unchecked); } - // @returns true if token is illegal - constexpr bool isIllegal(Token tok) { return Token::Illegal <= tok && tok < Token::IllegalEnd; }; - inline Token AssignmentToBinaryOp(Token op) { solAssert(isAssignmentOp(op) && op != Token::Assign, ""); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b78c58c67..3f4a015b0 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1555,32 +1555,8 @@ ASTPointer Parser::parsePrimaryExpression() expression = nodeFactory.createNode(components, isArray); break; } - case Token::IllegalHex: - fatalParserError("Expected even number of hex-nibbles within double-quotes."); - break; - case Token::IllegalCommentTerminator: - fatalParserError("Expected multi-line comment-terminator."); - break; - case Token::IllegalStringEscape: - fatalParserError("Invalid String Escape."); - break; - case Token::IllegalStringEndQuote: - fatalParserError("Expected String end-quote."); - break; - case Token::IllegalNumberSeparator: - fatalParserError("Invalid use of Number Separator '_'."); - break; - case Token::IllegalHexDigit: - fatalParserError("Hex Digit missing or invalid."); - break; - case Token::IllegalOctalNotAllowed: - fatalParserError("Octal Numbers not allowed."); - break; - case Token::IllegalExponent: - fatalParserError("Invalid Exponent."); - break; - case Token::IllegalNumberEnd: - fatalParserError("Digit or Identifier-Start not allowed at end of Number."); + case Token::Illegal: + fatalParserError(to_string(m_scanner->currentError())); break; default: if (TokenTraits::isElementaryTypeName(token)) From 0ad56bca790fa88d3baa7f46dc47c104baedd824 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 16:49:01 +0100 Subject: [PATCH 082/168] Adapting tests to Scanner's lexical error diagnostics change. --- test/libsolidity/SolidityScanner.cpp | 48 ++++++++++--------- .../inlineAssembly/invalid/invalid_number.sol | 2 +- ..._fixed_conversion_leading_zeroes_check.sol | 2 +- .../syntaxTests/string/string_new_line.sol | 2 +- .../string/string_terminated_by_backslash.sol | 2 +- .../string/string_unterminated.sol | 2 +- .../string_unterminated_no_new_line.sol | 2 +- .../syntaxTests/unicode_escape_literals.sol | 2 +- 8 files changed, 32 insertions(+), 30 deletions(-) diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 9d1383db2..02d91d32b 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -59,8 +59,6 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } -// STRING ESCAPES - BOOST_AUTO_TEST_CASE(string_escapes) { Scanner scanner(CharStream(" { \"a\\x61\"")); @@ -89,12 +87,13 @@ BOOST_AUTO_TEST_CASE(string_escape_illegal) { Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEscape); + 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::IllegalNumberEnd); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEndQuote); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -112,19 +111,18 @@ BOOST_AUTO_TEST_CASE(hex_numbers) BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "0x1234"); scanner.reset(CharStream("0X1234"), ""); - // @todo update underlying code to return "Expected lower-case 'x' for Hex-Numbers." or similar. - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalNumberEnd); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); } BOOST_AUTO_TEST_CASE(octal_numbers) { Scanner scanner(CharStream("07")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalOctalNotAllowed); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); scanner.reset(CharStream("007"), ""); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalOctalNotAllowed); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); scanner.reset(CharStream("-07"), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Sub); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalOctalNotAllowed); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); scanner.reset(CharStream("-.07"), ""); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Sub); BOOST_CHECK_EQUAL(scanner.next(), Token::Number); @@ -207,7 +205,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_exp_after_e_illegal) BOOST_AUTO_TEST_CASE(leading_underscore_hex_illegal) { Scanner scanner(CharStream("0x_abc")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalHexDigit); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -472,7 +470,7 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape) { Scanner scanner(CharStream("{ \"\\uFFnicode\"")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEscape); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); } // HEX STRING LITERAL @@ -489,28 +487,32 @@ BOOST_AUTO_TEST_CASE(invalid_short_hex_literal) { 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 \"")); 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'")); 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\"")); 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 @@ -519,7 +521,7 @@ BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close) { // This used to parse as "comment", "identifier" Scanner scanner(CharStream("/** / x")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalCommentTerminator); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -527,14 +529,14 @@ BOOST_AUTO_TEST_CASE(multiline_doc_comment_at_eos) { // This used to parse as "whitespace" Scanner scanner(CharStream("/**")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalCommentTerminator); + 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("/*")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalCommentTerminator); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } @@ -597,10 +599,10 @@ BOOST_AUTO_TEST_CASE(regular_line_breaks_in_strings) for (auto const& nl: {"\n", "\r"}) { Scanner scanner(CharStream("\"abc " + string(nl) + " def\"")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalStringEndQuote); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEndQuote); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } } @@ -610,12 +612,12 @@ 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\"")); - BOOST_CHECK_EQUAL(scanner.currentToken(), Token::IllegalStringEndQuote); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Illegal); for (size_t i = 0; i < string(nl).size(); i++) BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "def"); - BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalStringEndQuote); + BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } } diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/invalid_number.sol index 99a906deb..b44d09e32 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): Octal Numbers not allowed. +// ParserError: (72-73): Octal numbers not allowed. 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 4ac008a87..352b5f8fe 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): Digit or Identifier-Start not allowed at end of Number. +// 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 5a52534b1..4cbc71a5b 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 String end-quote. +// 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 000d3b0e3..fba53a039 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 String end-quote. \ 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 6772a3007..e893f4b17 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 String end-quote. \ 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 734ce37f5..b100396b7 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 String end-quote. \ No newline at end of file +// ParserError: (47-53): Expected string end-quote. diff --git a/test/libsolidity/syntaxTests/unicode_escape_literals.sol b/test/libsolidity/syntaxTests/unicode_escape_literals.sol index ac9aa08a9..4415d493b 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): Invalid String Escape. +// ParserError: (678-681): Invalid escape sequence. From 56d5dd46687026d2fab80f1b38e8314b080267ab Mon Sep 17 00:00:00 2001 From: Lazaridis Date: Sun, 25 Nov 2018 02:02:32 +0200 Subject: [PATCH 083/168] decouple TestCase class from test/libsolidity --- test/{libsolidity => }/TestCase.cpp | 2 +- test/{libsolidity => }/TestCase.h | 0 test/libsolidity/ASTJSONTest.h | 2 +- test/libsolidity/SyntaxTest.h | 2 +- test/libyul/YulOptimizerTest.h | 2 +- test/tools/CMakeLists.txt | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename test/{libsolidity => }/TestCase.cpp (97%) rename test/{libsolidity => }/TestCase.h (100%) diff --git a/test/libsolidity/TestCase.cpp b/test/TestCase.cpp similarity index 97% rename from test/libsolidity/TestCase.cpp rename to test/TestCase.cpp index 179722698..e9e2c9f21 100644 --- a/test/libsolidity/TestCase.cpp +++ b/test/TestCase.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see . */ -#include +#include #include #include diff --git a/test/libsolidity/TestCase.h b/test/TestCase.h similarity index 100% rename from test/libsolidity/TestCase.h rename to test/TestCase.h diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h index 9760ef660..dcdaf2210 100644 --- a/test/libsolidity/ASTJSONTest.h +++ b/test/libsolidity/ASTJSONTest.h @@ -18,7 +18,7 @@ #pragma once #include -#include +#include #include #include diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index d286f9341..12c14087b 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 72c4299fc..90026e243 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -17,7 +17,7 @@ #pragma once -#include +#include namespace langutil { diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index a0fbe140f..736212fc7 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 ../libsolidity/SMTCheckerJSONTest.cpp ../libyul/YulOptimizerTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) From 08579818c3a69888ec206bb01854d013f0ffc8d0 Mon Sep 17 00:00:00 2001 From: David Lozano Jarque Date: Sun, 25 Nov 2018 17:39:02 +0100 Subject: [PATCH 084/168] Update introduction-to-smart-contracts.rst Fix typo --- docs/introduction-to-smart-contracts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 9245300ba..34ef012e1 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -400,7 +400,7 @@ within a word). At the time of expansion, the cost in gas must be paid. Memory i costly the larger it grows (it scales quadratically). The EVM is not a register machine but a stack machine, so all -computations are performed on an data area called the **stack**. It has a maximum size of +computations are performed on a data area called the **stack**. It has a maximum size of 1024 elements and contains words of 256 bits. Access to the stack is limited to the top end in the following way: It is possible to copy one of From 06ae2286212bac0834090db415947c4d378b6122 Mon Sep 17 00:00:00 2001 From: David Lozano Jarque Date: Sun, 25 Nov 2018 19:19:05 +0100 Subject: [PATCH 085/168] Update installing-solidity.rst Homebrow -> homebrew --- docs/installing-solidity.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index f8de0e8d9..2797d8b06 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -115,7 +115,7 @@ Arch Linux also has packages, albeit limited to the latest development version: pacman -S solidity -We distribute the Solidity compiler through Homebrow +We distribute the Solidity compiler through Homebrew as a build-from-source version. Pre-built bottles are currently not supported. From 0e08fb7469dc376ff3ffced654446ef19eefbe9b Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Nov 2018 10:53:40 +0100 Subject: [PATCH 086/168] Use "in" tag for jumps from unpacker to function. --- libsolidity/codegen/CompilerContext.h | 5 ++++- libsolidity/codegen/ContractCompiler.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 63365175a..023698136 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -167,7 +167,10 @@ public: /// the data. CompilerContext& appendConditionalRevert(bool _forwardReturnData = false); /// Appends a JUMP to a specific tag - CompilerContext& appendJumpTo(eth::AssemblyItem const& _tag) { m_asm->appendJump(_tag); return *this; } + CompilerContext& appendJumpTo( + eth::AssemblyItem const& _tag, + eth::AssemblyItem::JumpType _jumpType = eth::AssemblyItem::JumpType::Ordinary + ) { *m_asm << _tag.pushTag(); return appendJump(_jumpType); } /// Appends pushing of a new tag and @returns the new tag. eth::AssemblyItem pushNewTag() { return m_asm->append(m_asm->newPushTag()).tag(); } /// @returns a new tag without pushing any opcodes or data diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 157d5fa7f..aabdbb79c 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -344,7 +344,10 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac m_context << Instruction::DUP1 << Instruction::CALLDATASIZE << Instruction::SUB; CompilerUtils(m_context).abiDecode(functionType->parameterTypes()); } - m_context.appendJumpTo(m_context.functionEntryLabel(functionType->declaration())); + m_context.appendJumpTo( + m_context.functionEntryLabel(functionType->declaration()), + eth::AssemblyItem::JumpType::IntoFunction + ); m_context << returnTag; // Return tag and input parameters get consumed. m_context.adjustStackOffset( From 2d0326aad2a2233f58dd4c2c1cb4ef7bbbb22d87 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Nov 2018 10:58:51 +0100 Subject: [PATCH 087/168] Changelog entry. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index ff26882d8..dc3a8bbe7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Compiler Features: Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. + * Code Generator: Annotate jump from calldata decoder to function as "jump in". Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. From 58181e8df9c2cb3401e02d0533ba6c2c0a2bde6a Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Mon, 1 Oct 2018 17:53:51 +0300 Subject: [PATCH 088/168] Move FAQ point to input and output parameters and polish surrounding text Update docs/control-structures.rst Co-Authored-By: ChrisChinchilla Remove line with no further details. Fix tabs Remove FAQ item --- docs/control-structures.rst | 16 +++++++++++++++- docs/frequently-asked-questions.rst | 5 ----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 889fbdb95..720b7084e 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -30,6 +30,16 @@ with two integers, you would use something like:: Function parameters can be used as any other local variable and they can also be assigned to. +.. note:: + + An :ref:`external function` cannot accept a + multi-dimensional array as an input + parameter. This functionality is possible if you enable the new + experimental ``ABIEncoderV2`` feature by adding ``pragma experimental ABIEncoderV2;`` to your source file. + + An :ref:`internal function` can accept a + multi-dimensional array without enabling the feature. + .. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct Return Variables @@ -56,7 +66,7 @@ two integers passed as function parameters, then you use something like:: The names of return variables can be omitted. Return variables can be used as any other local variable and they -are zero-initialized. If they are not explicitly +are initialized with their :ref:`default value ` and have that value unless explicitly set. set, they stay zero value. You can either explicitly assign to return variables and @@ -122,6 +132,8 @@ the same as the number of return types. Function Calls ============== +.. _internal-function-calls: + Internal Function Calls ----------------------- @@ -143,6 +155,8 @@ contract can be called internally. You should still avoid excessive recursion, as every internal function call uses up at least one stack slot and there are at most 1024 slots available. +.. _external-function-calls: + External Function Calls ----------------------- diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index b6e5fe784..e1a0e91bd 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -307,11 +307,6 @@ to create an independent copy of the storage value in memory. On the other hand, ``h(x)`` successfully modifies ``x`` because only a reference and not a copy is passed. -Is it possible to return an array of strings (``string[]``) from a Solidity function? -===================================================================================== - -Only when ``pragma experimental "ABIEncoderV2";`` is used. - What does the following strange check do in the Custom Token contract? ====================================================================== From 95206f26c8f561b327936f8b7059a2b975c23cbe Mon Sep 17 00:00:00 2001 From: David Lozano Jarque Date: Mon, 26 Nov 2018 11:39:33 +0100 Subject: [PATCH 089/168] Update types.rst RST note with incorrect syntax --- docs/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index b84d32226..5a5780720 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -273,7 +273,7 @@ Example:: when the call returns. The regular way to interact with other contracts is to call a function on a contract object (``x.f()``). -:: note:: +.. note:: Previous versions of Solidity allowed these functions to receive arbitrary arguments and would also handle a first argument of type ``bytes4`` differently. These edge cases were removed in version 0.5.0. From 0f0e466d36a3e09c4c5873998b5dd32dbe8025d6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 15:04:43 +0100 Subject: [PATCH 090/168] Allow visibility change from external to public. --- libsolidity/analysis/TypeChecker.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index a6c23ada7..d503b9ec9 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -413,16 +413,14 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun if (_function.visibility() != _super.visibility()) { - // visibility is enforced to be external in interfaces, but a contract can override that with public - if ( - _super.inContractKind() == ContractDefinition::ContractKind::Interface && - _function.inContractKind() != ContractDefinition::ContractKind::Interface && + // Visibility change from external to public is fine. + // Any other change is disallowed. + if (!( + _super.visibility() == FunctionDefinition::Visibility::External && _function.visibility() == FunctionDefinition::Visibility::Public - ) - return; - overrideError(_function, _super, "Overriding function visibility differs."); + )) + overrideError(_function, _super, "Overriding function visibility differs."); } - else if (_function.stateMutability() != _super.stateMutability()) overrideError( _function, @@ -433,7 +431,6 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun stateMutabilityToString(_function.stateMutability()) + "\"." ); - else if (functionType != superType) overrideError(_function, _super, "Overriding function return types differ."); } From ac5803bf3e5dc43adf8bf64c1041603259e8a16f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 17:38:12 +0100 Subject: [PATCH 091/168] Changelog entry and tests. --- Changelog.md | 1 + test/libsolidity/SolidityEndToEndTest.cpp | 15 +++++++++++++++ .../override/external_turns_public_no_params.sol | 7 +++++++ .../syntaxTests/inheritance/super_on_external.sol | 10 ++++++++++ .../nameAndTypeResolution/182_equal_overload.sol | 1 - 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/super_on_external.sol diff --git a/Changelog.md b/Changelog.md index ff26882d8..e6f015537 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.5.1 (unreleased) Language Features: + * Allow public functions to override external functions. Compiler Features: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e591432a3..e9667483f 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14062,6 +14062,21 @@ 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_SUITE_END() } 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 000000000..3d0394f5e --- /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/super_on_external.sol b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol new file mode 100644 index 000000000..21f3b1c2e --- /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/nameAndTypeResolution/182_equal_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol index cb9eb3fa8..6f0c7df79 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol @@ -4,4 +4,3 @@ contract C { } // ---- // DeclarationError: (17-66): Function with same name and arguments defined twice. -// TypeError: (17-66): Overriding function visibility differs. From aaaa92012cdab9c11984dfab2d0d56a1c537a61e Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Mon, 26 Nov 2018 11:55:53 +0100 Subject: [PATCH 092/168] [SMTChecker] Unknown answer for constant condition check should not do anything --- libsolidity/formal/SMTChecker.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 5b7807f7e..477568a0a 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -889,6 +889,10 @@ void SMTChecker::checkBooleanNotConstant(Expression const& _condition, string co { // everything fine. } + else if (positiveResult == smt::CheckResult::UNKNOWN || negatedResult == smt::CheckResult::UNKNOWN) + { + // can't do anything. + } else if (positiveResult == smt::CheckResult::UNSATISFIABLE && negatedResult == smt::CheckResult::UNSATISFIABLE) m_errorReporter.warning(_condition.location(), "Condition unreachable."); else From 9a4968ba1d1db573e57befe497cedc81eb2ef587 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 14:55:06 +0100 Subject: [PATCH 093/168] Use asCallableFunction in override check (part 1). --- libsolidity/analysis/TypeChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d503b9ec9..4d874197d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -250,7 +250,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont if (function->isConstructor()) continue; auto& overloads = functions[function->name()]; - FunctionTypePointer funType = make_shared(*function); + FunctionTypePointer funType = make_shared(*function)->asCallableFunction(false); auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) { return funType->hasEqualParameterTypes(*_funAndFlag.first); From 939365a1d5bec0f4c61f18bb5744189f39734198 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 14:57:37 +0100 Subject: [PATCH 094/168] Use callable types for override check. --- libsolidity/analysis/TypeChecker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 4d874197d..f8ea357cf 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -402,10 +402,10 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super) { - FunctionType functionType(_function); - FunctionType superType(_super); + FunctionTypePointer functionType = FunctionType(_function).asCallableFunction(false); + FunctionTypePointer superType = FunctionType(_super).asCallableFunction(false); - if (!functionType.hasEqualParameterTypes(superType)) + if (!functionType->hasEqualParameterTypes(*superType)) return; if (!_function.annotation().superFunction) @@ -431,7 +431,7 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun stateMutabilityToString(_function.stateMutability()) + "\"." ); - else if (functionType != superType) + else if (*functionType != *superType) overrideError(_function, _super, "Overriding function return types differ."); } From 36a369d077490a45018cefe5b0686eb373140920 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 15:07:14 +0100 Subject: [PATCH 095/168] Use asCallableFunction for external interface clash check. --- libsolidity/analysis/TypeChecker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f8ea357cf..9f3ba95f2 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -456,7 +456,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co // under non error circumstances this should be true if (functionType->interfaceFunctionType()) externalDeclarations[functionType->externalSignature()].push_back( - make_pair(f, functionType) + make_pair(f, functionType->asCallableFunction(false)) ); } for (VariableDeclaration const* v: contract->stateVariables()) @@ -466,7 +466,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co // under non error circumstances this should be true if (functionType->interfaceFunctionType()) externalDeclarations[functionType->externalSignature()].push_back( - make_pair(v, functionType) + make_pair(v, functionType->asCallableFunction(false)) ); } } From 5ec634939e2207a264453feb1b975575a80cd545 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 15:13:43 +0100 Subject: [PATCH 096/168] Use asCallableFunction for definition clashes in the same contract. --- libsolidity/analysis/TypeChecker.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9f3ba95f2..6295e083c 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -215,7 +215,9 @@ void TypeChecker::findDuplicateDefinitions(map> const& _defini SecondarySourceLocation ssl; for (size_t j = i + 1; j < overloads.size(); ++j) - if (FunctionType(*overloads[i]).hasEqualParameterTypes(FunctionType(*overloads[j]))) + if (FunctionType(*overloads[i]).asCallableFunction(false)->hasEqualParameterTypes( + *FunctionType(*overloads[j]).asCallableFunction(false)) + ) { ssl.append("Other declaration is here:", overloads[j]->location()); reported.insert(j); From 597174119a5f8ab03286c58581e7bf5ec52c14dc Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 12 Nov 2018 15:14:13 +0100 Subject: [PATCH 097/168] Tests. --- test/libsolidity/SolidityEndToEndTest.cpp | 52 +++++++++++++++++++ .../inheritance/override/calldata_memory.sol | 13 +++++ .../override/calldata_memory_conflict.sol | 26 ++++++++++ .../override/calldata_memory_interface.sol | 13 +++++ .../calldata_memory_interface_instantiate.sol | 12 +++++ .../calldata_memory_interface_struct.sol | 17 ++++++ .../override/calldata_memory_struct.sol | 17 ++++++ .../override/internal_external.sol | 7 +++ .../internal_external_inheritance.sol | 9 ++++ 9 files changed, 166 insertions(+) create mode 100644 test/libsolidity/syntaxTests/inheritance/override/calldata_memory.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/calldata_memory_conflict.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/calldata_memory_struct.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/internal_external.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/internal_external_inheritance.sol diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e9667483f..c34a1399f 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -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; } } 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 000000000..e683ef395 --- /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 000000000..dc734d36c --- /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 000000000..7eecc0797 --- /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 000000000..4cdc39246 --- /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 000000000..49b27fd76 --- /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 000000000..42aebf304 --- /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/internal_external.sol b/test/libsolidity/syntaxTests/inheritance/override/internal_external.sol new file mode 100644 index 000000000..90973ee79 --- /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 000000000..c09a80001 --- /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. From cdd8c72c9d38a6638cd23db58079251b6a632e3b Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 23 Nov 2018 14:21:17 +0100 Subject: [PATCH 098/168] CMake: Explicitly state which files to compile instead of relying on globbing. Also remove header file lists, as there is no need to add them to add_library() or add_executable(), which should lower maintenance of the cmake files. --- libdevcore/CMakeLists.txt | 16 +++++++++-- libevmasm/CMakeLists.txt | 22 +++++++++++++-- liblangutil/CMakeLists.txt | 12 ++++++-- liblll/CMakeLists.txt | 10 +++++-- libsolidity/CMakeLists.txt | 57 ++++++++++++++++++++++++++++++++++---- 5 files changed, 100 insertions(+), 17 deletions(-) diff --git a/libdevcore/CMakeLists.txt b/libdevcore/CMakeLists.txt index fa7e3f489..01a8bcc6d 100644 --- a/libdevcore/CMakeLists.txt +++ b/libdevcore/CMakeLists.txt @@ -1,7 +1,17 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + CommonData.cpp + CommonIO.cpp + Exceptions.cpp + IndentedWriter.cpp + JSON.cpp + Keccak256.cpp + StringUtils.cpp + SwarmHash.cpp + UTF8.cpp + Whiskers.cpp +) -add_library(devcore ${sources} ${headers}) +add_library(devcore ${sources}) target_link_libraries(devcore PRIVATE jsoncpp ${Boost_FILESYSTEM_LIBRARIES} ${Boost_REGEX_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) target_include_directories(devcore PUBLIC "${CMAKE_SOURCE_DIR}") target_include_directories(devcore SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) diff --git a/libevmasm/CMakeLists.txt b/libevmasm/CMakeLists.txt index 86192c1ba..e0e3389a0 100644 --- a/libevmasm/CMakeLists.txt +++ b/libevmasm/CMakeLists.txt @@ -1,5 +1,21 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + Assembly.cpp + AssemblyItem.cpp + BlockDeduplicator.cpp + CommonSubexpressionEliminator.cpp + ConstantOptimiser.cpp + ControlFlowGraph.cpp + ExpressionClasses.cpp + GasMeter.cpp + Instruction.cpp + JumpdestRemover.cpp + KnownState.cpp + LinkerObject.cpp + PathGasMeter.cpp + PeepholeOptimiser.cpp + SemanticInformation.cpp + SimplificationRules.cpp +) -add_library(evmasm ${sources} ${headers}) +add_library(evmasm ${sources}) target_link_libraries(evmasm PUBLIC devcore) diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 722ca840e..3d8bd37ad 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -1,6 +1,12 @@ # Solidity Commons Library (Solidity related sharing bits between libsolidity and libyul) -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + CharStream.cpp + ErrorReporter.cpp + Exceptions.cpp + ParserBase.cpp + Scanner.cpp + Token.cpp +) -add_library(langutil ${sources} ${headers}) +add_library(langutil ${sources}) target_link_libraries(langutil PUBLIC devcore) diff --git a/liblll/CMakeLists.txt b/liblll/CMakeLists.txt index 4cdc073a5..9566c62f5 100644 --- a/liblll/CMakeLists.txt +++ b/liblll/CMakeLists.txt @@ -1,5 +1,9 @@ -file(GLOB sources "*.cpp") -file(GLOB headers "*.h") +set(sources + CodeFragment.cpp + Compiler.cpp + CompilerState.cpp + Parser.cpp +) -add_library(lll ${sources} ${headers}) +add_library(lll ${sources}) target_link_libraries(lll PUBLIC evmasm devcore) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index c40087f05..40996abad 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,14 +1,60 @@ # Until we have a clear separation, libyul has to be included here -file(GLOB_RECURSE sources "*.cpp") -file(GLOB_RECURSE headers "*.h") +set(sources + analysis/ConstantEvaluator.cpp + analysis/ControlFlowAnalyzer.cpp + analysis/ControlFlowBuilder.cpp + analysis/ControlFlowGraph.cpp + analysis/DeclarationContainer.cpp + analysis/DocStringAnalyser.cpp + analysis/GlobalContext.cpp + analysis/NameAndTypeResolver.cpp + analysis/PostTypeChecker.cpp + analysis/ReferencesResolver.cpp + analysis/SemVerHandler.cpp + analysis/StaticAnalyzer.cpp + analysis/SyntaxChecker.cpp + analysis/TypeChecker.cpp + analysis/ViewPureChecker.cpp + ast/AST.cpp + ast/ASTAnnotations.cpp + ast/ASTJsonConverter.cpp + ast/ASTPrinter.cpp + ast/Types.cpp + codegen/ABIFunctions.cpp + codegen/ArrayUtils.cpp + codegen/Compiler.cpp + codegen/CompilerContext.cpp + codegen/CompilerUtils.cpp + codegen/ContractCompiler.cpp + codegen/ExpressionCompiler.cpp + codegen/LValue.cpp + formal/SMTChecker.cpp + formal/SMTLib2Interface.cpp + formal/SMTPortfolio.cpp + formal/SSAVariable.cpp + formal/SymbolicTypes.cpp + formal/SymbolicVariables.cpp + formal/VariableUsage.cpp + interface/ABI.cpp + interface/AssemblyStack.cpp + interface/CompilerStack.cpp + interface/GasEstimator.cpp + interface/Natspec.cpp + interface/SourceReferenceFormatter.cpp + interface/StandardCompiler.cpp + interface/Version.cpp + parsing/DocStringParser.cpp + parsing/Parser.cpp +) find_package(Z3 QUIET) if (${Z3_FOUND}) include_directories(${Z3_INCLUDE_DIR}) add_definitions(-DHAVE_Z3) message("Z3 SMT solver found. This enables optional SMT checking with Z3.") + set(z3_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") else() - list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") + set(z3_SRCS) endif() find_package(CVC4 QUIET) @@ -16,8 +62,9 @@ if (${CVC4_FOUND}) include_directories(${CVC4_INCLUDE_DIR}) add_definitions(-DHAVE_CVC4) message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.") + set(cvc4_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp") else() - list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp") + set(cvc4_SRCS) endif() if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) @@ -25,7 +72,7 @@ if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) \nPlease install Z3 or CVC4 or remove the option disabling them (USE_Z3, USE_CVC4).") endif() -add_library(solidity ${sources} ${headers}) +add_library(solidity ${sources} ${z3_SRCS} ${cvc4_SRCS}) target_link_libraries(solidity PUBLIC yul evmasm langutil devcore ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}) if (${Z3_FOUND}) From b98a9eeb976b40f2f5a246889cadcb69e4596fc7 Mon Sep 17 00:00:00 2001 From: William Entriken Date: Wed, 14 Nov 2018 22:55:19 -0500 Subject: [PATCH 099/168] Define how inheritance affects storage --- docs/miscellaneous.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index cc2ba8012..017d5b818 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -15,6 +15,10 @@ Statically-sized variables (everything except mapping and dynamically-sized arra - If an elementary type does not fit the remaining part of a storage slot, it is moved to the next storage slot. - Structs and array data always start a new slot and occupy whole slots (but items inside a struct or array are packed tightly according to these rules). +For contracts that use inheritance, the ordering of state variables is determined by the +C3-linearized order of contracts starting with the most base-ward contract. If allowed +by the above rules, state variables from different contracts do share the same storage slot. + .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller From a46d5c65803c7e0cf814d610d8ad87f09f89f2e4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 26 Nov 2018 14:50:04 +0100 Subject: [PATCH 100/168] Fix merge problem in CMake files. --- liblangutil/CMakeLists.txt | 1 + libsolidity/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/liblangutil/CMakeLists.txt b/liblangutil/CMakeLists.txt index 3d8bd37ad..dfcccfced 100644 --- a/liblangutil/CMakeLists.txt +++ b/liblangutil/CMakeLists.txt @@ -5,6 +5,7 @@ set(sources Exceptions.cpp ParserBase.cpp Scanner.cpp + SourceReferenceFormatter.cpp Token.cpp ) diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 40996abad..d2e0c8549 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -40,7 +40,6 @@ set(sources interface/CompilerStack.cpp interface/GasEstimator.cpp interface/Natspec.cpp - interface/SourceReferenceFormatter.cpp interface/StandardCompiler.cpp interface/Version.cpp parsing/DocStringParser.cpp From 5c67821af48c307d4b3da9b0cc50b4d447e8eae2 Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Wed, 14 Nov 2018 15:05:20 -0800 Subject: [PATCH 101/168] Script that directly comments errors to the github pull request. --- scripts/check_style.sh | 10 ++++---- scripts/report_errors.sh | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) create mode 100755 scripts/report_errors.sh diff --git a/scripts/check_style.sh b/scripts/check_style.sh index 4f716d669..171867f94 100755 --- a/scripts/check_style.sh +++ b/scripts/check_style.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +. scripts/report_errors.sh + ( REPO_ROOT="$(dirname "$0")"/.. cd $REPO_ROOT @@ -8,8 +10,8 @@ WHITESPACE=$(git grep -n -I -E "^.*[[:space:]]+$" | grep -v "test/libsolidity/AS if [[ "$WHITESPACE" != "" ]] then - echo "Error: Trailing whitespace found:" >&2 - echo "$WHITESPACE" >&2 + echo "Error: Trailing whitespace found:" | tee -a $ERROR_LOG + echo "$WHITESPACE" | tee -a $ERROR_LOG exit 1 fi @@ -22,8 +24,8 @@ git grep -nIE "\\s*\(.*\)\s*\{\s*$" -- '*.h' '*.cpp' if [[ "$FORMATERROR" != "" ]] then - echo "Error: Format error for if/for:" >&2 - echo "$FORMATERROR" >&2 + echo "Error: Format error for if/for:" | tee -a $ERROR_LOG + echo "$FORMATERROR" | tee -a $ERROR_LOG exit 1 fi ) diff --git a/scripts/report_errors.sh b/scripts/report_errors.sh new file mode 100755 index 000000000..55fc2e8c6 --- /dev/null +++ b/scripts/report_errors.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +export ERROR_LOG="/tmp/error.log" + +function report_error_to_github +{ + if [ $? -eq 0 ] + then + exit 0 + fi + + if [ -z $CIRCLE_PR_NUMBER ] + then + CIRCLE_PR_NUMBER="${CIRCLE_PULL_REQUEST//[^0-9]/}" + fi + + ERROR_MSG=$(cat $ERROR_LOG) + + echo $ERROR_MSG + + if [ ! -z $CI ] + then + echo "posting error message to github" + post_error_to_github + fi +} + +function post_error_to_github +{ + if [ -z $CIRCLE_PR_NUMBER ] + then + CIRCLE_PR_NUMBER="${CIRCLE_PULL_REQUEST//[^0-9]/}" + fi + + GITHUB_API_URL="https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/issues/$CIRCLE_PR_NUMBER/comments" + + ESCAPED_ERROR_MSG=$(cat -e $ERROR_LOG | sed 's/\\/\\\\/g' | sed 's/"/\\\"/g') + + FORMATTED_ERROR_MSG=$(echo $ESCAPED_ERROR_MSG | sed 's/\$/\\n/g' | tr -d '\n') + + curl --request POST \ + --url $GITHUB_API_URL \ + --header 'accept: application/vnd.github.v3+json' \ + --header 'content-type: application/json' \ + -u stackenbotten:$GITHUB_ACCESS_TOKEN \ + --data "{\"body\": \"There was an error when running \`$CIRCLE_JOB\` for commit \`$CIRCLE_SHA1\`:\n\`\`\`\n$FORMATTED_ERROR_MSG\n\`\`\`\nPlease check that your changes are working as intended.\"}" +} + +trap report_error_to_github EXIT From 30e6f8d3fb9a16dc1e07367c9010aabe3577e2f1 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 8 Nov 2018 11:22:57 +0100 Subject: [PATCH 102/168] Allow mapping arguments for public and external library functions. --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 28 ++++--- libsolidity/codegen/ExpressionCompiler.cpp | 2 + test/libsolidity/SolidityEndToEndTest.cpp | 84 +++++++++++++++++++ .../mapping/library_argument_external.sol | 1 - .../types/mapping/library_argument_public.sol | 1 - .../types/mapping/library_return_external.sol | 3 - .../types/mapping/library_return_public.sol | 3 - ..._data_location_function_param_external.sol | 4 +- ...ng_data_location_function_param_public.sol | 3 +- .../mapping/mapping_return_public_memory.sol | 3 +- 11 files changed, 106 insertions(+), 27 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5408bb8e2..3603ebcf7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.5.1 (unreleased) Language Features: + * Allow mapping type for parameters and return variables of public and external library functions. * Allow public functions to override external functions. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d503b9ec9..aa7e344e2 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -695,20 +695,22 @@ bool TypeChecker::visit(FunctionDefinition const& _function) } for (ASTPointer const& var: _function.parameters() + _function.returnParameters()) { + if (type(*var)->category() == Type::Category::Mapping) + { + if (!type(*var)->dataStoredIn(DataLocation::Storage)) + m_errorReporter.typeError(var->location(), "Mapping types can only have a data location of \"storage\"." ); + else if (!isLibraryFunction && _function.isPublic()) + m_errorReporter.typeError(var->location(), "Mapping types for parameters or return variables can only be used in internal or library functions."); + } + else + { + if (!type(*var)->canLiveOutsideStorage() && _function.isPublic()) + m_errorReporter.typeError(var->location(), "Type is required to live outside storage."); + if (_function.isPublic() && !(type(*var)->interfaceType(isLibraryFunction))) + m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions."); + } if ( - type(*var)->category() == Type::Category::Mapping && - !type(*var)->dataStoredIn(DataLocation::Storage) - ) - m_errorReporter.typeError(var->location(), "Mapping types can only have a data location of \"storage\"."); - else if ( - !type(*var)->canLiveOutsideStorage() && - _function.visibility() > FunctionDefinition::Visibility::Internal - ) - m_errorReporter.typeError(var->location(), "Type is required to live outside storage."); - if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction))) - m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions."); - if ( - _function.visibility() > FunctionDefinition::Visibility::Internal && + _function.isPublic() && !_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) && !typeSupportedByOldABIEncoder(*type(*var)) ) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index b0d172864..c9a1e076b 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1873,6 +1873,8 @@ void ExpressionCompiler::appendExternalFunctionCall( retSize = 0; break; } + else if (retType->decodingType()) + retSize += retType->decodingType()->calldataEncodedSize(); else retSize += retType->calldataEncodedSize(); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e9667483f..145783a8a 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8658,6 +8658,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{{"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{{"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{{"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"( diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol index 1098008d4..ebd05d867 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 dedd4f685..36e833b70 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 1e7568192..6c145801c 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 357751a0f..a98458cd7 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 c050f8e91..fa3757fa6 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 b63868b89..8c73b5ae9 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 35c3abc9f..7378324a7 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. From 4d7799eed467009323e43d36134eba64bfafad34 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 17:22:12 +0100 Subject: [PATCH 103/168] Properly disallow different return types for interface overloads with different visibilities. --- libsolidity/analysis/TypeChecker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 6295e083c..1a3844ad7 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -409,6 +409,8 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun if (!functionType->hasEqualParameterTypes(*superType)) return; + if (!functionType->hasEqualReturnTypes(*superType)) + overrideError(_function, _super, "Overriding function return types differ."); if (!_function.annotation().superFunction) _function.annotation().superFunction = &_super; @@ -423,7 +425,7 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun )) overrideError(_function, _super, "Overriding function visibility differs."); } - else if (_function.stateMutability() != _super.stateMutability()) + if (_function.stateMutability() != _super.stateMutability()) overrideError( _function, _super, @@ -433,8 +435,6 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun stateMutabilityToString(_function.stateMutability()) + "\"." ); - else if (*functionType != *superType) - overrideError(_function, _super, "Overriding function return types differ."); } void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message) From 1e7a23a2051c07adbafc60e3c82b34ee307e9647 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 17:28:02 +0100 Subject: [PATCH 104/168] Changelog entry and tests. --- Changelog.md | 2 +- .../override/change_return_types_in_interface.sol | 10 ++++++++++ .../nameAndTypeResolution/182_equal_overload.sol | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol diff --git a/Changelog.md b/Changelog.md index 5408bb8e2..b899fa30b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,7 +3,6 @@ Language Features: * Allow public functions to override external functions. - Compiler Features: * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. @@ -16,6 +15,7 @@ Compiler Features: Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. * Code Generator: Annotate jump from calldata decoder to function as "jump in". + * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. 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 000000000..804a18108 --- /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/nameAndTypeResolution/182_equal_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol index 6f0c7df79..865855184 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol @@ -4,3 +4,4 @@ contract C { } // ---- // DeclarationError: (17-66): Function with same name and arguments defined twice. +// TypeError: (17-66): Overriding function return types differ. From 2d5516b28dd17ed222c07ca14acfef49032796d1 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Sun, 30 Sep 2018 16:32:33 +0300 Subject: [PATCH 105/168] Review contributing docs for language and ease --- docs/contributing.rst | 64 +++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 11f952069..4ac93565a 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -70,16 +70,15 @@ Thank you for your help! Running the compiler tests ========================== -There is a script at ``scripts/tests.sh`` which executes most of the tests and +The ``./scripts/tests.sh`` script executes most Solidity tests and runs ``aleth`` automatically if it is in the path, but does not download it, -so it most likely will not work right away. Please read on for the details. +so you need to install it first. Please read on for the details. -Solidity includes different types of tests. Most of them are bundled in the application -called ``soltest``. Some of them require the ``aleth`` client in testing mode, -some others require ``libz3`` to be installed. +Solidity includes different types of tests, most of them bundled into the ``soltest`` +application. Some of them require the ``aleth`` client in testing mode, others require ``libz3``. -To run a basic set of tests that neither require ``aleth`` nor ``libz3``, run -``./scripts/soltest.sh --no-ipc --no-smt``. This script will run ``build/test/soltest`` +To run a basic set of tests that require neither ``aleth`` nor ``libz3``, run +``./scripts/soltest.sh --no-ipc --no-smt``. This script runs ``./build/test/soltest`` internally. .. note :: @@ -90,23 +89,24 @@ internally. The option ``--no-smt`` disables the tests that require ``libz3`` and ``--no-ipc`` disables those that require ``aleth``. -If you want to run the ipc tests (those test the semantics of the generated code), +If you want to run the ipc tests (that test the semantics of the generated code), you need to install `aleth `_ and run it in testing mode: ``aleth --test -d /tmp/testeth`` (make sure to rename it). -Then you run the actual tests: ``./scripts/soltest.sh --ipcpath /tmp/testeth/geth.ipc``. +To run the actual tests, use: ``./scripts/soltest.sh --ipcpath /tmp/testeth/geth.ipc``. -To run a subset of tests, filters can be used: +To run a subset of tests, you can use filters: ``./scripts/soltest.sh -t TestSuite/TestName --ipcpath /tmp/testeth/geth.ipc``, where ``TestName`` can be a wildcard ``*``. -The script ``scripts/tests.sh`` also runs commandline tests and compilation tests +The script ``./scripts/tests.sh`` also runs commandline tests and compilation tests in addition to those found in ``soltest``. -The CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. +The CI runs additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. .. note :: - Some versions of ``aleth`` cannot be used for testing. We suggest using the same version that is used by the Solidity continuous integration tests. + You can not use some versions of ``aleth`` for testing. We suggest using + the same version that the Solidity continuous integration tests use. Currently the CI uses ``d661ac4fec0aeffbedcdc195f67f5ded0c798278`` of ``aleth``. Writing and running syntax tests @@ -114,11 +114,11 @@ Writing and running syntax tests Syntax tests check that the compiler generates the correct error messages for invalid code and properly accepts valid code. -They are stored in individual files inside ``tests/libsolidity/syntaxTests``. +They are stored in individual files inside the ``tests/libsolidity/syntaxTests`` folder. These files must contain annotations, stating the expected result(s) of the respective test. -The test suite will compile and check them against the given expectations. +The test suite compiles and checks them against the given expectations. -Example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` +For example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` :: @@ -129,14 +129,14 @@ Example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` // ---- // DeclarationError: (36-52): Identifier already declared. -A syntax test must contain at least the contract under test itself, followed by the separator ``// ----``. The following comments are used to describe the +A syntax test must contain at least the contract under test itself, followed by the separator ``// ----``. The comments that follow the separator are used to describe the expected compiler errors or warnings. The number range denotes the location in the source where the error occurred. -In case the contract should compile without any errors or warning, the section after the separator has to be empty -and the separator can be left out completely. +If you want the contract to compile without any errors or warning you can leave +out the separator and the comments that follow it. -In the above example, the state variable ``variable`` was declared twice, which is not allowed. This will result in a ``DeclarationError`` stating that the identifier was already declared. +In the above example, the state variable ``variable`` was declared twice, which is not allowed. This results in a ``DeclarationError`` stating that the identifier was already declared. -The tool that is being used for those tests is called ``isoltest`` and can be found under ``./test/tools/``. It is an interactive tool which allows +The ``isoltest`` tool is used for these tests and you can find it under ``./build/test/tools/``. It is an interactive tool which allows editing of failing contracts using your preferred text editor. Let's try to break this test by removing the second declaration of ``variable``: :: @@ -147,7 +147,7 @@ editing of failing contracts using your preferred text editor. Let's try to brea // ---- // DeclarationError: (36-52): Identifier already declared. -Running ``./test/isoltest`` again will result in a test failure: +Running ``./build/test/isoltest`` again results in a test failure: :: @@ -163,15 +163,19 @@ Running ``./test/isoltest`` again will result in a test failure: Success -``isoltest`` prints the expected result next to the obtained result, but also provides a way to change edit / update / skip the current contract or to even quit. +``isoltest`` prints the expected result next to the obtained result, and also +provides a way to edit, update or skip the current contract file, or quit the application. + It offers several options for failing tests: -- edit: ``isoltest`` tries to open the contract in an editor so you can adjust it. It either uses the editor given on the command line (as ``isoltest --editor /path/to/editor``), in the environment variable ``EDITOR`` or just ``/usr/bin/editor`` (in this order). -- update: Updates the contract under test. This either removes the annotation which contains the exception not met or adds missing expectations. The test will then be run again. -- skip: Skips the execution of this particular test. -- quit: Quits ``isoltest``. +- ``edit``: ``isoltest`` tries to open the contract in an editor so you can adjust it. It either uses the editor given on the command line (as ``isoltest --editor /path/to/editor``), in the environment variable ``EDITOR`` or just ``/usr/bin/editor`` (in that order). +- ``update``: Updates the expectations for contract under test. This updates the annotations by removing unmet expectations and adding missing expectations. The test is then run again. +- ``skip``: Skips the execution of this particular test. +- ``quit``: Quits ``isoltest``. -Automatically updating the test above will change it to +All of these options apply to the current contract, expect ``quit`` which stops the entire testing process. + +Automatically updating the test above changes it to :: @@ -180,7 +184,7 @@ Automatically updating the test above will change it to } // ---- -and re-run the test. It will now pass again: +and re-run the test. It now passes again: :: @@ -190,7 +194,7 @@ and re-run the test. It will now pass again: .. note:: - Please choose a name for the contract file that explains what it tests, e.g. ``double_variable_declaration.sol``. + Choose a name for the contract file that explains what it tests, e.g. ``double_variable_declaration.sol``. Do not put more than one contract into a single file, unless you are testing inheritance or cross-contract calls. Each file should test one aspect of your new feature. From 12daec3535f75de3eb44cd988d58844e996b2de2 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Mon, 26 Nov 2018 15:44:02 +0100 Subject: [PATCH 106/168] Move function related content to contracts doc --- docs/contracts.rst | 102 +++++++++++++++++++++++++++++++++++ docs/control-structures.rst | 103 ------------------------------------ 2 files changed, 102 insertions(+), 103 deletions(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index c1c51e568..9913cfb3f 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -485,6 +485,108 @@ value types and strings. Functions ********* +Function Parameters and Return Variables +======================================== + +As in JavaScript, functions may take parameters as input. Unlike in JavaScript +and C, functions may also return an arbitrary number of values as output. + +Function Parameters +------------------- + +Function parameters are declared the same way as variables, and the name of +unused parameters can be omitted. + +For example, if you want your contract to accept one kind of external call +with two integers, you would use something like:: + + pragma solidity >=0.4.16 <0.6.0; + + contract Simple { + uint sum; + function taker(uint _a, uint _b) public { + sum = _a + _b; + } + } + +Function parameters can be used as any other local variable and they can also be assigned to. + +.. note:: + + An :ref:`external function` cannot accept a + multi-dimensional array as an input + parameter. This functionality is possible if you enable the new + experimental ``ABIEncoderV2`` feature by adding ``pragma experimental ABIEncoderV2;`` to your source file. + + An :ref:`internal function` can accept a + multi-dimensional array without enabling the feature. + +.. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct + +Return Variables +---------------- + +Function return variables are declared with the same syntax after the +``returns`` keyword. + +For example, suppose you want to return two results: the sum and the product of +two integers passed as function parameters, then you use something like:: + + pragma solidity >=0.4.16 <0.6.0; + + contract Simple { + function arithmetic(uint _a, uint _b) + public + pure + returns (uint o_sum, uint o_product) + { + o_sum = _a + _b; + o_product = _a * _b; + } + } + +The names of return variables can be omitted. +Return variables can be used as any other local variable and they +are initialized with their :ref:`default value ` and have that value unless explicitly set. + +You can either explicitly assign to return variables and +then leave the function using ``return;``, +or you can provide return values +(either a single or :ref:`multiple ones`) directly with the ``return`` +statement:: + + pragma solidity >=0.4.16 <0.6.0; + + contract Simple { + function arithmetic(uint _a, uint _b) + public + pure + returns (uint o_sum, uint o_product) + { + return (_a + _b, _a * _b); + } + } + +This form is equivalent to first assigning values to the +return variables and then using ``return;`` to leave the function. + +.. note:: + You cannot return some types from non-internal functions, notably + multi-dimensional dynamic arrays and structs. If you enable the + new experimental ``ABIEncoderV2`` feature by adding ``pragma experimental + ABIEncoderV2;`` to your source file then more types are available, but + ``mapping`` types are still limited to inside a single contract and you + cannot transfer them. + +.. _multi-return: + +Returning Multiple Values +------------------------- + +When a function has multiple return types, the statement ``return (v0, v1, ..., vn) can be used to return multiple values. +vn)`` can return multiple values. The number of components must be +the same as the number of return types. + .. index:: ! view function, function;view .. _view-functions: diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 720b7084e..f80168060 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -4,100 +4,6 @@ Expressions and Control Structures .. index:: ! parameter, parameter;input, parameter;output, function parameter, parameter;function, return variable, variable;return, return -Function Parameters and Return Variables -======================================== - -As in JavaScript, functions may take parameters as input. Unlike in JavaScript -and C, functions may also return an arbitrary number of values as output. - -Function Parameters -------------------- - -Function parameters are declared the same way as variables, and the name of -unused parameters can be omitted. - -For example, if you want your contract to accept one kind of external call -with two integers, you would use something like:: - - pragma solidity >=0.4.16 <0.6.0; - - contract Simple { - uint sum; - function taker(uint _a, uint _b) public { - sum = _a + _b; - } - } - -Function parameters can be used as any other local variable and they can also be assigned to. - -.. note:: - - An :ref:`external function` cannot accept a - multi-dimensional array as an input - parameter. This functionality is possible if you enable the new - experimental ``ABIEncoderV2`` feature by adding ``pragma experimental ABIEncoderV2;`` to your source file. - - An :ref:`internal function` can accept a - multi-dimensional array without enabling the feature. - -.. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct - -Return Variables ----------------- - -Function return variables are declared with the same syntax after the -``returns`` keyword. - -For example, suppose you want to return two results: the sum and the product of -two integers passed as function parameters, then you use something like:: - - pragma solidity >=0.4.16 <0.6.0; - - contract Simple { - function arithmetic(uint _a, uint _b) - public - pure - returns (uint o_sum, uint o_product) - { - o_sum = _a + _b; - o_product = _a * _b; - } - } - -The names of return variables can be omitted. -Return variables can be used as any other local variable and they -are initialized with their :ref:`default value ` and have that value unless explicitly set. -set, they stay zero value. - -You can either explicitly assign to return variables and -then leave the function using ``return;``, -or you can provide return values -(either a single or :ref:`multiple ones`) directly with the ``return`` -statement:: - - pragma solidity >=0.4.16 <0.6.0; - - contract Simple { - function arithmetic(uint _a, uint _b) - public - pure - returns (uint o_sum, uint o_product) - { - return (_a + _b, _a * _b); - } - } - -This form is equivalent to first assigning values to the -return variables and then using ``return;`` to leave the function. - - -.. note:: - You cannot return some types from non-internal functions, notably - multi-dimensional dynamic arrays and structs. If you enable the - new experimental ``ABIEncoderV2`` feature by adding ``pragma experimental - ABIEncoderV2;`` to your source file then more types are available, but - ``mapping`` types are still limited to inside a single contract and you - cannot transfer them. .. index:: if, else, while, do/while, for, break, continue, return, switch, goto @@ -116,15 +22,6 @@ Note that there is no type conversion from non-boolean to boolean types as there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid Solidity. -.. _multi-return: - -Returning Multiple Variables ----------------------------- - -When a function has multiple return types, ``return (v0, v1, ..., -vn)`` can return multiple values. The number of components must be -the same as the number of return types. - .. index:: ! function;call, function;internal, function;external .. _function-calls: From ae542176e3a8490cb83a42a309208fa6c5fd1589 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Fri, 19 Oct 2018 12:59:21 +0200 Subject: [PATCH 107/168] Add that pure functions can use revert and require --- docs/contracts.rst | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index c1c51e568..68c7bea36 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -569,6 +569,20 @@ In addition to the list of state modifying statements explained above, the follo } } +Pure functions are able to use the `revert()` and `require()` functions to revert +potential state changes when an :ref:`error occurs `. + +Reverting a state change is not considered a "state modification", as only changes to the +state made previously in code that did not have the ``view`` or ``pure`` restriction +are reverted and that code has the option to catch the ``revert`` and not pass it on. + +This behaviour is also in line with the ``STATICCALL`` opcode. + +.. warning:: + It is not possible to prevent functions from reading the state at the level + of the EVM, it is only possible to prevent them from writing to the state + (i.e. only ``view`` can be enforced at the EVM level, ``pure`` can not). + .. note:: Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode for ``pure`` functions. @@ -577,13 +591,8 @@ In addition to the list of state modifying statements explained above, the follo By using ``STATICCALL`` for ``pure`` functions, modifications to the state are prevented on the level of the EVM. -.. warning:: - It is not possible to prevent functions from reading the state at the level - of the EVM, it is only possible to prevent them from writing to the state - (i.e. only ``view`` can be enforced at the EVM level, ``pure`` can not). - -.. warning:: - Before version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. +.. note:: + Prior to version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. It is a compile-time type check, which can be circumvented doing invalid explicit conversions between contract types, because the compiler can verify that the type of the contract does not do state-changing operations, but it cannot check that the contract that will be called From e016cb99e679c53708ca7294442e04f80df477cc Mon Sep 17 00:00:00 2001 From: chriseth Date: Sun, 4 Nov 2018 09:34:21 +0100 Subject: [PATCH 108/168] Yul objects. --- libsolidity/interface/AssemblyStack.cpp | 14 +-- libsolidity/interface/AssemblyStack.h | 10 +- libyul/CMakeLists.txt | 2 + libyul/Object.cpp | 61 ++++++++++ libyul/Object.h | 72 ++++++++++++ libyul/ObjectParser.cpp | 146 ++++++++++++++++++++++++ libyul/ObjectParser.h | 72 ++++++++++++ 7 files changed, 359 insertions(+), 18 deletions(-) create mode 100644 libyul/Object.cpp create mode 100644 libyul/Object.h create mode 100644 libyul/ObjectParser.cpp create mode 100644 libyul/ObjectParser.h diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 31959d930..ef4e32b06 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -69,7 +70,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string m_errors.clear(); m_analysisSuccessful = false; m_scanner = make_shared(CharStream(_source), _sourceName); - m_parserResult = yul::Parser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); + m_parserResult = yul::YulObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; solAssert(m_parserResult, ""); @@ -77,17 +78,6 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string return analyzeParsed(); } -bool AssemblyStack::analyze(yul::Block const& _block, Scanner const* _scanner) -{ - m_errors.clear(); - m_analysisSuccessful = false; - if (_scanner) - m_scanner = make_shared(*_scanner); - m_parserResult = make_shared(_block); - - return analyzeParsed(); -} - bool AssemblyStack::analyzeParsed() { m_analysisInfo = make_shared(); diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index 03b811db0..b89faca00 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -24,6 +24,9 @@ #include #include +#include +#include + #include #include @@ -72,10 +75,6 @@ public: /// Multiple calls overwrite the previous state. bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source); - /// Runs analysis step on the supplied block, returns false if input cannot be assembled. - /// Multiple calls overwrite the previous state. - bool analyze(yul::Block const& _block, langutil::Scanner const* _scanner = nullptr); - /// Run the assembly step (should only be called after parseAndAnalyze). MachineAssemblyObject assemble(Machine _machine) const; @@ -94,8 +93,7 @@ private: std::shared_ptr m_scanner; bool m_analysisSuccessful = false; - std::shared_ptr m_parserResult; - std::shared_ptr m_analysisInfo; + std::shared_ptr m_parserResult; langutil::ErrorList m_errors; langutil::ErrorReporter m_errorReporter; }; diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 8fbea6899..7ed84ff5c 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -6,6 +6,8 @@ add_library(yul AsmPrinter.cpp AsmScope.cpp AsmScopeFiller.cpp + Object.cpp + ObjectParser.cpp backends/evm/EVMAssembly.cpp backends/evm/EVMCodeTransform.cpp optimiser/ASTCopier.cpp diff --git a/libyul/Object.cpp b/libyul/Object.cpp new file mode 100644 index 000000000..a52287934 --- /dev/null +++ b/libyul/Object.cpp @@ -0,0 +1,61 @@ +/* + 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 . +*/ +/** + * Yul code and data object container. + */ + +#include + +#include +#include + +#include +#include + +#include + +using namespace dev; +using namespace yul; +using namespace std; + +namespace +{ + +string indent(std::string const& _input) +{ + if (_input.empty()) + return _input; + return boost::replace_all_copy(" " + _input, "\n", "\n "); +} + +} + +string Data::toString(bool) const +{ + return "data \"" + name.str() + "\" hex\"" + dev::toHex(data) + "\""; +} + +string Object::toString(bool _yul) const +{ + yulAssert(code, "No code"); + string inner = "code " + AsmPrinter{_yul}(*code); + + for (auto const& obj: subObjects) + inner += "\n" + obj->toString(_yul); + + return "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; +} diff --git a/libyul/Object.h b/libyul/Object.h new file mode 100644 index 000000000..cfd8d02d2 --- /dev/null +++ b/libyul/Object.h @@ -0,0 +1,72 @@ +/* + 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 . +*/ +/** + * Yul code and data object container. + */ + +#pragma once + +#include +#include + +#include + +#include + +namespace yul +{ +struct AsmAnalysisInfo; + + +/** + * Generic base class for both Yul objects and Yul data. + */ +struct ObjectNode +{ + virtual ~ObjectNode() {} + virtual std::string toString(bool _yul) const = 0; + + YulString name; +}; + +/** + * Named data in Yul objects. + */ +struct Data: ObjectNode +{ + Data(YulString _name, dev::bytes _data): data(std::move(_data)) { name = _name; } + std::string toString(bool _yul) const override; + + dev::bytes data; +}; + +/** + * Yul code and data object container. + */ +struct Object: ObjectNode +{ +public: + /// @returns a (parseable) string representation. Includes types if @a _yul is set. + std::string toString(bool _yul) const override; + + std::shared_ptr code; + std::vector> subObjects; + std::map subIndexByName; + std::shared_ptr analysisInfo; +}; + +} diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp new file mode 100644 index 000000000..43dd4be96 --- /dev/null +++ b/libyul/ObjectParser.cpp @@ -0,0 +1,146 @@ +/* + 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 . +*/ +/** + * Parser for Yul code and data object container. + */ + +#include + +#include +#include + +#include + +using namespace dev; +using namespace langutil; +using namespace yul; +using namespace std; + + +shared_ptr ObjectParser::parse(shared_ptr const& _scanner, bool _reuseScanner) +{ + m_recursionDepth = 0; + try + { + shared_ptr object; + m_scanner = _scanner; + if (currentToken() == Token::LBrace) + { + // Special case: Code-only form. + object = make_shared(); + object->name = YulString{"object"}; + object->code = parseBlock(); + if (!object->code) + return nullptr; + } + else + object = parseObject(); + if (object && !_reuseScanner) + expectToken(Token::EOS); + return object; + } + catch (FatalError const&) + { + if (m_errorReporter.errors().empty()) + throw; // Something is weird here, rather throw again. + } + return nullptr; +} + +shared_ptr ObjectParser::parseObject(Object* _containingObject) +{ + RecursionGuard guard(*this); + + if (currentToken() != Token::Identifier || currentLiteral() != "object") + fatalParserError("Expected keyword \"object\"."); + advance(); + + shared_ptr ret = make_shared(); + ret->name = parseUniqueName(_containingObject); + + expectToken(Token::LBrace); + + ret->code = parseCode(); + + while (currentToken() != Token::RBrace) + { + if (currentToken() == Token::Identifier && currentLiteral() == "object") + parseObject(ret.get()); + else if (currentToken() == Token::Identifier && currentLiteral() == "data") + parseData(*ret); + else + fatalParserError("Expected keyword \"data\" or \"object\" or \"}\"."); + } + if (_containingObject) + addNamedSubObject(*_containingObject, ret->name, ret); + + expectToken(Token::RBrace); + + return ret; +} + +shared_ptr ObjectParser::parseCode() +{ + if (currentToken() != Token::Identifier || currentLiteral() != "code") + fatalParserError("Expected keyword \"code\"."); + advance(); + + return parseBlock(); +} + +shared_ptr ObjectParser::parseBlock() +{ + Parser parser(m_errorReporter, m_flavour); + shared_ptr block = parser.parse(m_scanner, true); + yulAssert(block || m_errorReporter.hasErrors(), "Invalid block but no error!"); + return block; +} + +void ObjectParser::parseData(Object& _containingObject) +{ + solAssert( + currentToken() == Token::Identifier && currentLiteral() == "data", + "parseData called on wrong input." + ); + advance(); + + YulString name = parseUniqueName(&_containingObject); + + expectToken(Token::StringLiteral, false); + addNamedSubObject(_containingObject, name, make_shared(name, asBytes(currentLiteral()))); + advance(); +} + +YulString ObjectParser::parseUniqueName(Object const* _containingObject) +{ + expectToken(Token::StringLiteral, false); + YulString name{currentLiteral()}; + if (name.empty()) + parserError("Object name cannot be empty."); + else if (_containingObject && _containingObject->name == name) + parserError("Object name cannot be the same as the name of the containing object."); + else if (_containingObject && _containingObject->subIndexByName.count(name)) + parserError("Object name \"" + name.str() + "\" already exists inside the containing object."); + advance(); + return name; +} + +void ObjectParser::addNamedSubObject(Object& _container, YulString _name, shared_ptr _subObject) +{ + _container.subIndexByName[_name] = _container.subObjects.size(); + _container.subObjects.emplace_back(std::move(_subObject)); +} diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h new file mode 100644 index 000000000..1d88a1196 --- /dev/null +++ b/libyul/ObjectParser.h @@ -0,0 +1,72 @@ +/* + 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 . +*/ +/** + * Parser for Yul code and data object container. + */ + +#pragma once + +#include +#include + +#include +#include + +#include + +#include + +namespace langutil +{ +class Scanner; +} + +namespace yul +{ + +/** + * Yul object parser. Invokes the inline assembly parser. + */ +class ObjectParser: public langutil::ParserBase +{ +public: + explicit ObjectParser( + langutil::ErrorReporter& _errorReporter, + yul::AsmFlavour _flavour = yul::AsmFlavour::Loose + ): + ParserBase(_errorReporter), m_flavour(_flavour) {} + + /// Parses a Yul object. + /// Falls back to code-only parsing if the source starts with `{`. + /// @param _reuseScanner if true, do check for end of input after the last `}`. + /// @returns an empty shared pointer on error. + std::shared_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); + +private: + std::shared_ptr parseObject(Object* _containingObject = nullptr); + std::shared_ptr parseCode(); + std::shared_ptr parseBlock(); + void parseData(Object& _containingObject); + + /// Tries to parse a name that is non-empty and unique inside the containing object. + YulString parseUniqueName(Object const* _containingObject); + void addNamedSubObject(Object& _container, YulString _name, std::shared_ptr _subObject); + + yul::AsmFlavour m_flavour; +}; + +} From 728119bb110b68be3df80b827f73e1d4f36d6bc5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 7 Nov 2018 12:01:43 +0100 Subject: [PATCH 109/168] Use yul parser in assembly stack. --- libsolidity/interface/AssemblyStack.cpp | 23 ++++++++++++++--------- libsolidity/interface/AssemblyStack.h | 12 +++--------- test/libsolidity/InlineAssembly.cpp | 9 ++++++--- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index ef4e32b06..24e190b3b 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include @@ -70,19 +70,22 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string m_errors.clear(); m_analysisSuccessful = false; m_scanner = make_shared(CharStream(_source), _sourceName); - m_parserResult = yul::YulObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); + m_parserResult = yul::ObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; solAssert(m_parserResult, ""); + solAssert(m_parserResult->code, ""); return analyzeParsed(); } bool AssemblyStack::analyzeParsed() { - m_analysisInfo = make_shared(); - yul::AsmAnalyzer analyzer(*m_analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language)); - m_analysisSuccessful = analyzer.analyze(*m_parserResult); + solAssert(m_parserResult, ""); + solAssert(m_parserResult->code, ""); + m_parserResult->analysisInfo = make_shared(); + yul::AsmAnalyzer analyzer(*m_parserResult->analysisInfo, m_errorReporter, m_evmVersion, boost::none, languageToAsmFlavour(m_language)); + m_analysisSuccessful = analyzer.analyze(*m_parserResult->code); return m_analysisSuccessful; } @@ -90,7 +93,8 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const { solAssert(m_analysisSuccessful, ""); solAssert(m_parserResult, ""); - solAssert(m_analysisInfo, ""); + solAssert(m_parserResult->code, ""); + solAssert(m_parserResult->analysisInfo, ""); switch (_machine) { @@ -98,7 +102,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const { MachineAssemblyObject object; eth::Assembly assembly; - yul::CodeGenerator::assemble(*m_parserResult, *m_analysisInfo, assembly); + yul::CodeGenerator::assemble(*m_parserResult->code, *m_parserResult->analysisInfo, assembly); object.bytecode = make_shared(assembly.assemble()); object.assembly = assembly.assemblyString(); return object; @@ -107,7 +111,7 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const { MachineAssemblyObject object; yul::EVMAssembly assembly(true); - yul::CodeTransform(assembly, *m_analysisInfo, m_language == Language::Yul, true)(*m_parserResult); + yul::CodeTransform(assembly, *m_parserResult->analysisInfo, m_language == Language::Yul, true)(*m_parserResult->code); object.bytecode = make_shared(assembly.finalize()); /// TODO: fill out text representation return object; @@ -122,5 +126,6 @@ MachineAssemblyObject AssemblyStack::assemble(Machine _machine) const string AssemblyStack::print() const { solAssert(m_parserResult, ""); - return yul::AsmPrinter(m_language == Language::Yul)(*m_parserResult); + solAssert(m_parserResult->code, ""); + return m_parserResult->toString(m_language == Language::Yul) + "\n"; } diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index b89faca00..7ae0592e1 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -24,8 +24,8 @@ #include #include -#include -#include +#include +#include #include @@ -37,12 +37,6 @@ namespace langutil class Scanner; } -namespace yul -{ -struct AsmAnalysisInfo; -struct Block; -} - namespace dev { namespace solidity @@ -93,7 +87,7 @@ private: std::shared_ptr m_scanner; bool m_analysisSuccessful = false; - std::shared_ptr m_parserResult; + std::shared_ptr m_parserResult; langutil::ErrorList m_errors; langutil::ErrorReporter m_errorReporter; }; diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 31d21490c..11d4c59fb 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -124,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); } } @@ -567,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) From 105898b81b54a19335b81239f99a7c5b5d909be5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 7 Nov 2018 12:02:11 +0100 Subject: [PATCH 110/168] Tests. --- test/libyul/ObjectParser.cpp | 257 +++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 test/libyul/ObjectParser.cpp diff --git a/test/libyul/ObjectParser.cpp b/test/libyul/ObjectParser.cpp new file mode 100644 index 000000000..bb88e4da0 --- /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 . +*/ +/** + * @date 2018 + * Unit tests for the Yul object parser. + */ + +#include + +#include + +#include + +#include +#include + +#include +#include + +using namespace std; +using namespace langutil; + +namespace dev +{ +namespace yul +{ +namespace test +{ + +namespace +{ + +std::pair 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 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 From fb2e471d00d41dece0152b14ef209aa4e4b2d60d Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 27 Nov 2018 15:28:20 +0100 Subject: [PATCH 111/168] Fix nondeterminism bug related to boost version. --- Changelog.md | 1 + libevmasm/ConstantOptimiser.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 876182cc2..bed3ab369 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,7 @@ Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. * Code Generator: Annotate jump from calldata decoder to function as "jump in". * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. + * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 9844ba3a3..ae1a56437 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -193,7 +193,7 @@ AssemblyItems ComputeMethod::findRepresentation(u256 const& _value) bigint bestGas = gasNeeded(routine); for (unsigned bits = 255; bits > 8 && m_maxSteps > 0; --bits) { - unsigned gapDetector = unsigned(_value >> (bits - 8)) & 0x1ff; + unsigned gapDetector = unsigned((_value >> (bits - 8)) & 0x1ff); if (gapDetector != 0xff && gapDetector != 0x100) continue; From 16d1bf33357a48167298f1961124a50cd54172e1 Mon Sep 17 00:00:00 2001 From: Justin Wilson Date: Tue, 27 Nov 2018 13:45:59 -0700 Subject: [PATCH 112/168] Builds both scratch & Alpine Docker images - Adds `Dockerfile_alpine`, which copies the complier from the scratch step into an Alpine image - Updates `docker_build.sh` to build the Alpine image - Updates `docker_deploy.sh` to tag and push the Alpine images - Updates `docker_deploy_manual.sh` to tag and push the Alpine images The tags that are pushed follow: - Scratch - ethereum/solc:stable - ethereum/solc:0.5.1 - ethereum/solc:nightly - ethereum/solc:nightly-0.5.1-bc7cb301e3d71756c8fbefe888aca53433302117 - ethereum/solc:nightly-0.5.1-bc7cb301e3d71756c8fbefe888aca53433302117 - Alpine - ethereum/solc:stable-alpine - ethereum/solc:0.5.1-alpine - ethereum/solc:nightly-alpine - ethereum/solc:nightly-alpine-0.5.1-bc7cb301e3d71756c8fbefe888aca53433302117 - ethereum/solc:nightly-alpine-0.5.1-bc7cb301e3d71756c8fbefe888aca53433302117 --- scripts/Dockerfile_alpine | 5 +++++ scripts/docker_build.sh | 4 ++++ scripts/docker_deploy.sh | 24 ++++++++++++++++-------- scripts/docker_deploy_manual.sh | 27 +++++++++++++++++---------- 4 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 scripts/Dockerfile_alpine diff --git a/scripts/Dockerfile_alpine b/scripts/Dockerfile_alpine new file mode 100644 index 000000000..21bba4566 --- /dev/null +++ b/scripts/Dockerfile_alpine @@ -0,0 +1,5 @@ +FROM alpine +MAINTAINER chriseth + +COPY upload/solc-static-linux /usr/local/bin/solc +ENTRYPOINT ["/usr/local/bin/solc"] diff --git a/scripts/docker_build.sh b/scripts/docker_build.sh index 22657a8ca..9eedec344 100755 --- a/scripts/docker_build.sh +++ b/scripts/docker_build.sh @@ -2,7 +2,11 @@ set -e +# Scratch image docker build -t ethereum/solc:build -f scripts/Dockerfile . tmp_container=$(docker create ethereum/solc:build sh) mkdir -p upload docker cp ${tmp_container}:/usr/bin/solc upload/solc-static-linux + +# Alpine image +docker build -t ethereum/solc:build-alpine -f scripts/Dockerfile_alpine . diff --git a/scripts/docker_deploy.sh b/scripts/docker_deploy.sh index 007057256..36e918cf8 100755 --- a/scripts/docker_deploy.sh +++ b/scripts/docker_deploy.sh @@ -2,20 +2,28 @@ set -e +image="ethereum/solc" + +tag_and_push() +{ + docker tag "$image:$1" "$image:$2" + docker push "$image:$2" +} + docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; version=$($(dirname "$0")/get_version.sh) if [ "$TRAVIS_BRANCH" = "develop" ] then - docker tag ethereum/solc:build ethereum/solc:nightly; - docker tag ethereum/solc:build ethereum/solc:nightly-"$version"-"$TRAVIS_COMMIT" - docker push ethereum/solc:nightly-"$version"-"$TRAVIS_COMMIT"; - docker push ethereum/solc:nightly; + tag_and_push build nightly + tag_and_push build nightly-"$version"-"$TRAVIS_COMMIT" + tag_and_push build-alpine nightly-alpine + tag_and_push build-alpine nightly-alpine-"$version"-"$TRAVIS_COMMIT" elif [ "$TRAVIS_TAG" = v"$version" ] then - docker tag ethereum/solc:build ethereum/solc:stable; - docker tag ethereum/solc:build ethereum/solc:"$version"; - docker push ethereum/solc:stable; - docker push ethereum/solc:"$version"; + tag_and_push build stable + tag_and_push build "$version" + tag_and_push build-alpine stable-alpine + tag_and_push build-alpine "$version"-alpine else echo "Not publishing docker image from branch $TRAVIS_BRANCH or tag $TRAVIS_TAG" fi diff --git a/scripts/docker_deploy_manual.sh b/scripts/docker_deploy_manual.sh index c098f4eec..0393d22de 100755 --- a/scripts/docker_deploy_manual.sh +++ b/scripts/docker_deploy_manual.sh @@ -7,6 +7,7 @@ then echo "Usage: $0 " exit 1 fi +image="ethereum/solc" branch="$1" #docker login @@ -27,21 +28,27 @@ else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt fi +tag_and_push() +{ + docker tag "$image:$1" "$image:$2" + docker push "$image:$2" +} + rm -rf .git -docker build -t ethereum/solc:build -f scripts/Dockerfile . -tmp_container=$(docker create ethereum/solc:build sh) +docker build -t "$image":build -f scripts/Dockerfile . +tmp_container=$(docker create "$image":build sh) if [ "$branch" = "develop" ] then - docker tag ethereum/solc:build ethereum/solc:nightly; - docker tag ethereum/solc:build ethereum/solc:nightly-"$version"-"$commithash" - docker push ethereum/solc:nightly-"$version"-"$commithash"; - docker push ethereum/solc:nightly; + tag_and_push build nightly + tag_and_push build nightly-"$version"-"$commithash" + tag_and_push build-alpine nightly-alpine + tag_and_push build-alpine nightly-alpine-"$version"-"$commithash" elif [ "$branch" = v"$version" ] then - docker tag ethereum/solc:build ethereum/solc:stable; - docker tag ethereum/solc:build ethereum/solc:"$version"; - docker push ethereum/solc:stable; - docker push ethereum/solc:"$version"; + tag_and_push build stable + tag_and_push build "$version" + tag_and_push build-alpine stable-alpine + tag_and_push build-alpine "$version"-alpine else echo "Not publishing docker image from branch or tag $branch" fi From 9a2cb7bbc11faa7ae051f80ff4425746711a7b95 Mon Sep 17 00:00:00 2001 From: Justin Wilson Date: Tue, 27 Nov 2018 13:50:00 -0700 Subject: [PATCH 113/168] Added Docker updates to changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index bed3ab369..bec10c173 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,6 +21,7 @@ Bugfixes: Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. + * Docker: Includes both Scratch and Alpine images. From 69dcf1a5f78ce6caf1c78012e599d7a1f08a6877 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 11:30:00 +0100 Subject: [PATCH 114/168] Changelog entry. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 876182cc2..f20d1d9c2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Compiler Features: * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. * SMTChecker: Support internal bound function calls. + * Yul: Support Yul objects in ``--assemble`` and ``--yul`` commandline options. Bugfixes: From cb9816f7d69a8b0f877cb60a0201279e9d50135b Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 11:32:05 +0100 Subject: [PATCH 115/168] Yul grammar changes. - also the top level object needs to be named - code is not optional --- docs/yul.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/yul.rst b/docs/yul.rst index 2784078c5..9e50f126f 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -559,8 +559,7 @@ regular strings in native encoding. For code, Grammar:: - TopLevelObject = 'object' '{' Code? ( Object | Data )* '}' - Object = 'object' StringLiteral '{' Code? ( Object | Data )* '}' + Object = 'object' StringLiteral '{' Code ( Object | Data )* '}' Code = 'code' Block Data = 'data' StringLiteral ( HexLiteral | StringLiteral ) HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') From 4fa47322f9d6d66c551caa6cfd72c0838dda3dc3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 11:48:51 +0100 Subject: [PATCH 116/168] Remove obsolete comment. --- libsolidity/analysis/TypeChecker.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9d536a3ab..c41c372b5 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -777,15 +777,10 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) ) m_errorReporter.typeError(_variable.location(), "Variables cannot be declared in interfaces."); - // Variables can be declared without type (with "var"), in which case the first assignment - // sets the type. - // Note that assignments before the first declaration are legal because of the special scoping - // rules inherited from JavaScript. - // type is filled either by ReferencesResolver directly from the type name or by // TypeChecker at the VariableDeclarationStatement level. TypePointer varType = _variable.annotation().type; - solAssert(!!varType, "Failed to infer variable type."); + solAssert(!!varType, "Variable type not provided."); if (_variable.value()) expectType(*_variable.value(), *varType); From 46f3da0b87f1244deb0ac3e3f964c53eb88e4a25 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 12:17:30 +0100 Subject: [PATCH 117/168] Properly check getter types to be old-abi-coder-compatible. --- libsolidity/analysis/TypeChecker.cpp | 45 ++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9d536a3ab..6d5d5cb71 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -21,17 +21,24 @@ */ #include -#include +#include + +#include +#include +#include + +#include + +#include +#include + #include #include #include #include -#include -#include -#include -#include -#include -#include + +#include +#include using namespace std; using namespace dev; @@ -814,11 +821,25 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) if (!varType->canLiveOutsideStorage()) m_errorReporter.typeError(_variable.location(), "Type " + varType->toString() + " is only valid in storage."); } - else if ( - _variable.visibility() >= VariableDeclaration::Visibility::Public && - !FunctionType(_variable).interfaceFunctionType() - ) - m_errorReporter.typeError(_variable.location(), "Internal or recursive type is not allowed for public state variables."); + else if (_variable.visibility() >= VariableDeclaration::Visibility::Public) + { + FunctionType getter(_variable); + if (!_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2)) + { + vector unsupportedTypes; + for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes()) + if (!typeSupportedByOldABIEncoder(*param)) + unsupportedTypes.emplace_back(param->toString()); + if (!unsupportedTypes.empty()) + m_errorReporter.typeError(_variable.location(), + "The following types are only supported for getters in the new experimental ABI encoder: " + + joinHumanReadable(unsupportedTypes) + + ". Either remove \"public\" or use \"pragma experimental ABIEncoderV2;\" to enable the feature." + ); + } + if (!getter.interfaceFunctionType()) + m_errorReporter.typeError(_variable.location(), "Internal or recursive type is not allowed for public state variables."); + } switch (varType->category()) { From c54814b47bbc77e6754218ab1bdd479e87711b55 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 12:18:32 +0100 Subject: [PATCH 118/168] Tests. --- .../libsolidity/syntaxTests/getter/complex_struct.sol | 7 +++++++ .../libsolidity/syntaxTests/getter/nested_structs.sol | 11 +++++++++++ .../syntaxTests/getter/recursive_struct.sol | 8 ++++++++ test/libsolidity/syntaxTests/getter/simple_struct.sol | 6 ++++++ 4 files changed, 32 insertions(+) create mode 100644 test/libsolidity/syntaxTests/getter/complex_struct.sol create mode 100644 test/libsolidity/syntaxTests/getter/nested_structs.sol create mode 100644 test/libsolidity/syntaxTests/getter/recursive_struct.sol create mode 100644 test/libsolidity/syntaxTests/getter/simple_struct.sol diff --git a/test/libsolidity/syntaxTests/getter/complex_struct.sol b/test/libsolidity/syntaxTests/getter/complex_struct.sol new file mode 100644 index 000000000..3fa8111cd --- /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 000000000..1068f2871 --- /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 000000000..d81cac60e --- /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 000000000..c7a23ae93 --- /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; +} From 9ba3532eac1ad2a647a327c19509b409a2cfb6f2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 12:19:03 +0100 Subject: [PATCH 119/168] Changelog entry. --- Changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index a90580bc3..f5817771a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,8 +17,9 @@ Compiler Features: Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. * Code Generator: Annotate jump from calldata decoder to function as "jump in". - * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. + * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. + * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. From c51e6a545a29851947eb011b44031e0318a388ca Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 28 Nov 2018 13:03:51 +0100 Subject: [PATCH 120/168] Remove boost test checks from SMTCheckerJSONTest --- test/libsolidity/SMTCheckerJSONTest.cpp | 87 ++++++++++++++++--------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/test/libsolidity/SMTCheckerJSONTest.cpp b/test/libsolidity/SMTCheckerJSONTest.cpp index 6e1329a96..e9204cc4e 100644 --- a/test/libsolidity/SMTCheckerJSONTest.cpp +++ b/test/libsolidity/SMTCheckerJSONTest.cpp @@ -38,11 +38,15 @@ using namespace boost::unit_test; SMTCheckerTest::SMTCheckerTest(string const& _filename) : SyntaxTest(_filename) { - BOOST_REQUIRE_MESSAGE(boost::algorithm::ends_with(_filename, ".sol"), "Invalid test contract file name: \"" + _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"; - BOOST_CHECK(jsonParseFile(jsonFilename, m_smtResponses)); - BOOST_CHECK(m_smtResponses.isObject()); + 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) @@ -59,42 +63,62 @@ bool SMTCheckerTest::run(ostream& _stream, string const& _linePrefix, bool const // This is the list of responses provided in the test string auxInput("auxiliaryInput"); - BOOST_CHECK(m_smtResponses.isMember(auxInput)); + if (!m_smtResponses.isMember(auxInput)) + BOOST_THROW_EXCEPTION(runtime_error("JSON file does not contain field \"auxiliaryInput\".")); + vector inHashes = hashesFromJson(m_smtResponses, auxInput, "smtlib2responses"); // Ensure that the provided list matches the requested one - BOOST_CHECK_MESSAGE( - outHashes == inHashes, - "SMT query hashes differ: " + boost::algorithm::join(outHashes, ", ") + " x " + boost::algorithm::join(inHashes, ", ") - ); + 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); - BOOST_CHECK(endResult.isMember("errors")); - Json::Value const& errors = endResult["errors"]; - for (auto const& error: errors) + if (endResult.isMember("errors") && endResult["errors"].isArray()) { - BOOST_CHECK(error.isMember("type") && error["type"].isString()); - BOOST_CHECK(error.isMember("message") && error["message"].isString()); - if (!error.isMember("sourceLocation")) - continue; - Json::Value const& location = error["sourceLocation"]; - BOOST_CHECK(location.isMember("start") && location["start"].isInt()); - BOOST_CHECK(location.isMember("end") && location["end"].isInt()); - int start = location["start"].asInt(); - int end = location["end"].asInt(); - if (start >= static_cast(versionPragma.size())) - start -= versionPragma.size(); - if (end >= static_cast(versionPragma.size())) - end -= versionPragma.size(); - m_errorList.emplace_back(SyntaxTestError{ - error["type"].asString(), - error["message"].asString(), - start, - end - }); + 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(versionPragma.size())) + start -= versionPragma.size(); + if (end >= static_cast(versionPragma.size())) + end -= versionPragma.size(); + m_errorList.emplace_back(SyntaxTestError{ + error["type"].asString(), + error["message"].asString(), + start, + end + }); + } } return printExpectationAndError(_stream, _linePrefix, _formatted); @@ -123,6 +147,7 @@ Json::Value SMTCheckerTest::buildJson(string const& _extra) string sources = " \"sources\": { " + sourceName + ": " + sourceObj + "}"; string input = "{" + language + ", " + sources + "}"; Json::Value source; - BOOST_REQUIRE(jsonParse(input, source)); + if (!jsonParse(input, source)) + BOOST_THROW_EXCEPTION(runtime_error("Could not build JSON from string.")); return source; } From 50351fb8e2f318998d73f8e7043a8a56c3a6c06a Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Wed, 28 Nov 2018 14:32:26 +0100 Subject: [PATCH 121/168] Fixes crash on empty runtime code. --- Changelog.md | 1 + solc/CommandLineInterface.cpp | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index a90580bc3..6c5c8c71c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Compiler Features: Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. + * Commandline interface: Fix crash when using ``--ast`` on empty runtime code. * Code Generator: Annotate jump from calldata decoder to function as "jump in". * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 7f64d8ac3..e2baca7f5 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -1022,12 +1022,16 @@ void CommandLineInterface::handleAst(string const& _argStr) map gasCosts; for (auto const& contract : m_compiler->contractNames()) { - auto ret = GasEstimator::breakToStatementLevel( - GasEstimator(m_evmVersion).structuralEstimation(*m_compiler->runtimeAssemblyItems(contract), asts), - asts - ); - for (auto const& it: ret) - gasCosts[it.first] += it.second; + if (auto const* assemblyItems = m_compiler->runtimeAssemblyItems(contract)) + { + auto ret = GasEstimator::breakToStatementLevel( + GasEstimator(m_evmVersion).structuralEstimation(*assemblyItems, asts), + asts + ); + for (auto const& it: ret) + gasCosts[it.first] += it.second; + } + } bool legacyFormat = !m_args.count(g_argAstCompactJson); From b75859ff150200e83d74f5cef2504ab805d2bf35 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Mon, 17 Sep 2018 17:16:05 +0200 Subject: [PATCH 122/168] Begin overhaul of documentation index --- docs/index.rst | 64 ++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 17abf4b24..ed9311630 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -19,26 +19,43 @@ user-defined types among other features. With Solidity you can create contracts for uses such as voting, crowdfunding, blind auctions, and multi-signature wallets. -.. note:: - The best way to try out Solidity right now is using - `Remix `_ - (it can take a while to load, please be patient). Remix is a web browser - based IDE that allows you to write Solidity smart contracts, then deploy - and run the smart contracts. +Language Documentation +---------------------- + +If you are new to the concept of smart contracts we recommend you start with +:ref:`an example smart contract ` written +in Solidity. When you are ready for more detail, we recommend you read the +:doc:`"Solidity by Example" ` and :doc:`"Solidity in Depth" ` sections to learn the core concepts of the language. + +For further reading, try :ref:`the basics of blockchains ` +and details of the :ref:`Ethereum Virtual Machine `. + +.. hint:: + You can always try out code examples in your browser with the + `Remix IDE `_. Remix is a web browser based IDE + that allows you to write Solidity smart contracts, then deploy and run the + smart contracts. It can take a while to load, so please be patient. .. warning:: - Since software is written by humans, it can have bugs. Thus, also - smart contracts should be created following well-known best-practices in - software development. This includes code review, testing, audits and correctness proofs. - Also note that users are sometimes more confident in code than its authors. - Finally, blockchains have their own things to watch out for, so please take - a look at the section :ref:`security_considerations`. + As humans write software, it can have bugs. You should follow established + software development best-practices when writing your smart contracts, this + includes code review, testing, audits, and correctness proofs. Smart contract + users are sometimes more confident with code than their authors, and + blockchains and smart contracts have their own unique issues to + watch out for, so before working on production code, make sure you read the + :ref:`security_considerations` section. + +If you have any questions, you can try searching for answers or asking on the +`Ethereum Stackexchange `_, or our `gitter channel `_. + +Ideas for improving Solidity or this documentation are always welcome, read our :doc:`contributors guide ` for more details. Translations ------------ -This documentation is translated into several languages by community volunteers -with varying degrees of completeness and up-to-dateness. The English version stands as a reference. +Community volunteers help translate this documentation into several languages. +They have varying degrees of completeness and up-to-dateness. The English +version stands as a reference. * `Simplified Chinese `_ (in progress) * `Spanish `_ @@ -46,25 +63,6 @@ with varying degrees of completeness and up-to-dateness. The English version sta * `Korean `_ (in progress) * `French `_ (in progress) -Language Documentation ----------------------- - -On the next pages, we will first see a :ref:`simple smart contract ` written -in Solidity followed by the basics about :ref:`blockchains ` -and the :ref:`Ethereum Virtual Machine `. - -The next section will explain several *features* of Solidity by giving -useful :ref:`example contracts `. -Remember that you can always try out the contracts -`in your browser `_! - -The fourth and most extensive section will cover all aspects of Solidity in depth. - -If you still have questions, you can try searching or asking on the -`Ethereum Stackexchange `_ -site, or come to our `gitter channel `_. -Ideas for improving Solidity or this documentation are always welcome! - Contents ======== From 8ec66bcab65bd764a3923f5866d0d5c930a99e74 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 28 Nov 2018 14:24:02 +0100 Subject: [PATCH 123/168] Disable coverage generation for release branch. --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 975d1c7a3..6c5f3e857 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,6 +14,7 @@ defaults: command: | mkdir -p build cd build + [ -n "$COVERAGE" -a "$CIRCLE_BRANCH" != release -a -z "$CIRCLE_TAG" ] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo $CMAKE_OPTIONS make -j4 - run_tests: &run_tests @@ -122,7 +123,7 @@ jobs: - image: buildpack-deps:artful environment: TERM: xterm - CMAKE_OPTIONS: -DCOVERAGE=ON + COVERAGE: "ON" steps: - checkout - run: From 87f98343811a559e424de1f2dc3122ae87298ded Mon Sep 17 00:00:00 2001 From: Albert Date: Tue, 27 Nov 2018 04:43:06 +0100 Subject: [PATCH 124/168] Fix #5512 Make the double quotes around the distro name optional so it matches properly in Fedora (`NAME=Fedora`) --- scripts/install_deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index b107f7c9b..09d5a2492 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -55,7 +55,7 @@ detect_linux_distro() { DISTRO=$(lsb_release -is) elif [ -f /etc/os-release ]; then # extract 'foo' from NAME=foo, only on the line with NAME=foo - DISTRO=$(sed -n -e 's/^NAME="\(.*\)\"/\1/p' /etc/os-release) + DISTRO=$(sed -n -e 's/^NAME="\?\([^"]*\)"\?$/\1/p' /etc/os-release) elif [ -f /etc/centos-release ]; then DISTRO=CentOS else From 5ec67ee477f021b25355c546e4ba9b69b79040ce Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 28 Nov 2018 16:15:45 +0100 Subject: [PATCH 125/168] liblangutil: adds ParserBase::charStream() accessor --- liblangutil/ParserBase.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 3ecabed5c..0007da63d 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include @@ -38,6 +39,7 @@ public: explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {} std::shared_ptr const& sourceName() const; + CharStream const* charStream() const { return &m_scanner->charStream(); } protected: /// Utility class that creates an error and throws an exception if the From 9326adc3db513353da51d9732d1c92b33ecd4d16 Mon Sep 17 00:00:00 2001 From: hydai Date: Thu, 29 Nov 2018 16:34:17 +0800 Subject: [PATCH 126/168] Replace IntegerType(256) with static function IntegerType::uint256() --- libsolidity/analysis/TypeChecker.cpp | 6 +++--- libsolidity/ast/Types.h | 2 ++ libsolidity/codegen/ABIFunctions.cpp | 2 +- libsolidity/codegen/CompilerUtils.cpp | 18 +++++++++--------- libsolidity/codegen/CompilerUtils.h | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 16 ++++++++-------- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e1a89dd40..fcc6746fd 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2506,7 +2506,7 @@ bool TypeChecker::visit(IndexAccess const& _access) } else { - expectType(*index, IntegerType(256)); + expectType(*index, IntegerType::uint256()); if (!m_errorReporter.hasErrors()) if (auto numberType = dynamic_cast(type(*index).get())) { @@ -2537,7 +2537,7 @@ bool TypeChecker::visit(IndexAccess const& _access) resultType = make_shared(make_shared(DataLocation::Memory, typeType.actualType())); else { - expectType(*index, IntegerType(256)); + expectType(*index, IntegerType::uint256()); if (auto length = dynamic_cast(type(*index).get())) resultType = make_shared(make_shared( DataLocation::Memory, @@ -2556,7 +2556,7 @@ bool TypeChecker::visit(IndexAccess const& _access) m_errorReporter.typeError(_access.location(), "Index expression cannot be omitted."); else { - if (!expectType(*index, IntegerType(256))) + if (!expectType(*index, IntegerType::uint256())) m_errorReporter.fatalTypeError(_access.location(), "Index expression cannot be represented as an unsigned integer."); if (auto integerType = dynamic_cast(type(*index).get())) if (bytesType.numBytes() <= integerType->literalValue(nullptr)) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 953aa557d..0f0548d3b 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -374,6 +374,8 @@ public: Unsigned, Signed }; + static IntegerType& uint256() { static std::shared_ptr uint256(std::make_shared(256)); return *uint256; } + Category category() const override { return Category::Integer; } explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned); diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index bd29b3820..b02623de6 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -558,7 +558,7 @@ string ABIFunctions::abiEncodingFunction( // special case: convert storage reference type to value type - this is only // possible for library calls where we just forward the storage reference solAssert(_encodeAsLibraryTypes, ""); - solAssert(to == IntegerType(256), ""); + solAssert(to == IntegerType::uint256(), ""); templ("cleanupConvert", "value"); } else diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 93c8cc778..7d2ad9d2b 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -136,7 +136,7 @@ void CompilerUtils::loadFromMemoryDynamic( void CompilerUtils::storeInMemory(unsigned _offset) { - unsigned numBytes = prepareMemoryStore(IntegerType(256), true); + unsigned numBytes = prepareMemoryStore(IntegerType::uint256(), true); if (numBytes > 0) m_context << u256(_offset) << Instruction::MSTORE; } @@ -150,7 +150,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound ref->location() == DataLocation::Memory, "Only in-memory reference type can be stored." ); - storeInMemoryDynamic(IntegerType(256), _padToWordBoundaries); + storeInMemoryDynamic(IntegerType::uint256(), _padToWordBoundaries); } else if (auto str = dynamic_cast(&_type)) { @@ -266,7 +266,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem if (calldataType->isDynamicallySized()) { // put on stack: data_pointer length - loadFromMemoryDynamic(IntegerType(256), !_fromMemory); + loadFromMemoryDynamic(IntegerType::uint256(), !_fromMemory); m_context << Instruction::SWAP1; // stack: input_end base_offset next_pointer data_offset m_context.appendInlineAssembly("{ if gt(data_offset, 0x100000000) { revert(0, 0) } }", {"data_offset"}); @@ -277,7 +277,7 @@ void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMem {"input_end", "base_offset", "next_ptr", "array_head_ptr"} ); // retrieve length - loadFromMemoryDynamic(IntegerType(256), !_fromMemory, true); + loadFromMemoryDynamic(IntegerType::uint256(), !_fromMemory, true); // stack: input_end base_offset next_pointer array_length data_pointer m_context << Instruction::SWAP2; // stack: input_end base_offset data_pointer array_length next_pointer @@ -430,7 +430,7 @@ void CompilerUtils::encodeToMemory( { auto const& strType = dynamic_cast(*_givenTypes[i]); m_context << u256(strType.value().size()); - storeInMemoryDynamic(IntegerType(256), true); + storeInMemoryDynamic(IntegerType::uint256(), true); // stack: ... storeInMemoryDynamic(strType, _padToWordBoundaries); } @@ -445,7 +445,7 @@ void CompilerUtils::encodeToMemory( m_context << dupInstruction(1 + arrayType.sizeOnStack()); ArrayUtils(m_context).retrieveLength(arrayType, 1); // stack: ... - storeInMemoryDynamic(IntegerType(256), true); + storeInMemoryDynamic(IntegerType::uint256(), true); // stack: ... // copy the new memory pointer m_context << swapInstruction(arrayType.sizeOnStack() + 1) << Instruction::POP; @@ -807,7 +807,7 @@ void CompilerUtils::convertType( allocateMemory(); // stack: mempos m_context << Instruction::DUP1 << u256(data.size()); - storeInMemoryDynamic(IntegerType(256)); + storeInMemoryDynamic(IntegerType::uint256()); // stack: mempos datapos storeStringData(data); } @@ -856,7 +856,7 @@ void CompilerUtils::convertType( if (targetType.isDynamicallySized()) { m_context << Instruction::DUP2; - storeInMemoryDynamic(IntegerType(256)); + storeInMemoryDynamic(IntegerType::uint256()); } // stack: (variably sized) if (targetType.baseType()->isValueType()) @@ -1210,7 +1210,7 @@ void CompilerUtils::storeStringData(bytesConstRef _data) for (unsigned i = 0; i < _data.size(); i += 32) { m_context << h256::Arith(h256(_data.cropped(i), h256::AlignLeft)); - storeInMemoryDynamic(IntegerType(256)); + storeInMemoryDynamic(IntegerType::uint256()); } m_context << Instruction::POP; } diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index bd8170ad1..5f7dce226 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -69,7 +69,7 @@ public: /// @returns the number of bytes consumed in memory. unsigned loadFromMemory( unsigned _offset, - Type const& _type = IntegerType(256), + Type const& _type = IntegerType::uint256(), bool _fromCalldata = false, bool _padToWords = false ); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c9a1e076b..87eecd2e3 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -631,7 +631,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) _functionCall.expression().accept(*this); arguments.front()->accept(*this); - utils().convertType(*arguments.front()->annotation().type, IntegerType(256), true); + utils().convertType(*arguments.front()->annotation().type, IntegerType::uint256(), true); // Note that function is not the original function, but the ".gas" function. // Its values of gasSet and valueSet is equal to the original function's though. unsigned stackDepth = (function.gasSet() ? 1 : 0) + (function.valueSet() ? 1 : 0); @@ -814,13 +814,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) case FunctionType::Kind::MulMod: { arguments[2]->accept(*this); - utils().convertType(*arguments[2]->annotation().type, IntegerType(256)); + utils().convertType(*arguments[2]->annotation().type, IntegerType::uint256()); m_context << Instruction::DUP1 << Instruction::ISZERO; m_context.appendConditionalInvalid(); for (unsigned i = 1; i < 3; i ++) { arguments[2 - i]->accept(*this); - utils().convertType(*arguments[2 - i]->annotation().type, IntegerType(256)); + utils().convertType(*arguments[2 - i]->annotation().type, IntegerType::uint256()); } if (function.kind() == FunctionType::Kind::AddMod) m_context << Instruction::ADDMOD; @@ -904,7 +904,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // Fetch requested length. arguments[0]->accept(*this); - utils().convertType(*arguments[0]->annotation().type, IntegerType(256)); + utils().convertType(*arguments[0]->annotation().type, IntegerType::uint256()); // Stack: requested_length utils().fetchFreeMemoryPointer(); @@ -1452,7 +1452,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) TypePointers{keyType} ); m_context << Instruction::SWAP1; - utils().storeInMemoryDynamic(IntegerType(256)); + utils().storeInMemoryDynamic(IntegerType::uint256()); utils().toSizeAfterFreeMemoryPointer(); } else @@ -1461,7 +1461,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) appendExpressionCopyToMemory(*keyType, *_indexAccess.indexExpression()); m_context << Instruction::SWAP1; solAssert(CompilerUtils::freeMemoryPointer >= 0x40, ""); - utils().storeInMemoryDynamic(IntegerType(256)); + utils().storeInMemoryDynamic(IntegerType::uint256()); m_context << u256(0); } m_context << Instruction::KECCAK256; @@ -1474,7 +1474,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) solAssert(_indexAccess.indexExpression(), "Index expression expected."); _indexAccess.indexExpression()->accept(*this); - utils().convertType(*_indexAccess.indexExpression()->annotation().type, IntegerType(256), true); + utils().convertType(*_indexAccess.indexExpression()->annotation().type, IntegerType::uint256(), true); // stack layout: [] ArrayUtils(m_context).accessIndex(arrayType); switch (arrayType.location()) @@ -1510,7 +1510,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) solAssert(_indexAccess.indexExpression(), "Index expression expected."); _indexAccess.indexExpression()->accept(*this); - utils().convertType(*_indexAccess.indexExpression()->annotation().type, IntegerType(256), true); + utils().convertType(*_indexAccess.indexExpression()->annotation().type, IntegerType::uint256(), true); // stack layout: // check out-of-bounds access m_context << u256(fixedBytesType.numBytes()); From 1d47919c0c77f23542f62f3e4cab83b264d06fa4 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 28 Nov 2018 16:16:02 +0100 Subject: [PATCH 127/168] Fix ICE when function type struct parameter has field of non-existent type --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 8 +++++++- .../functionTypes/function_type_struct.sol | 8 ++++++++ .../function_type_struct_undefined_member.sol | 11 +++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/functionTypes/function_type_struct.sol create mode 100644 test/libsolidity/syntaxTests/functionTypes/function_type_struct_undefined_member.sol diff --git a/Changelog.md b/Changelog.md index b67bc5928..f64ae1845 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,6 +21,7 @@ Bugfixes: * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. + * Type Checker: Fix internal compiler error when a field of a struct used as a parameter in a function type has a non-existent type. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 102e43e9a..16e9cf892 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2124,9 +2124,15 @@ bool StructType::canBeUsedExternally(bool _inLibrary) const // We pass "false" to canBeUsedExternally (_inLibrary), because this struct will be // passed by value and thus the encoding does not differ, but it will disallow // mappings. + // Also return false if at least one struct member does not have a type. + // This might happen, for example, if the type of the member does not exist, + // which is reported as an error. for (auto const& var: m_struct.members()) { - solAssert(var->annotation().type, ""); + // If the struct member does not have a type return false. + // A TypeError is expected in this case. + if (!var->annotation().type) + return false; if (!var->annotation().type->canBeUsedExternally(false)) return false; } 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 000000000..a367996e5 --- /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 000000000..ca08afe5b --- /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. From 6060a3682c077d7b329ec9171abdacbf1b383ec7 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Thu, 29 Nov 2018 00:56:25 +0100 Subject: [PATCH 128/168] liblangutil: adds Scanner.charStream() accessor --- liblangutil/Scanner.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index d01e71e2f..9c29edfd4 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -94,6 +94,8 @@ public: std::string source() const { return m_source.source(); } + CharStream const& charStream() const noexcept { return m_source; } + /// Resets the scanner as if newly constructed with _source and _sourceName as input. void reset(CharStream _source, std::string _sourceName); /// Resets scanner to the start of input. From 22eff22492b2d569fe56b59763ddc1cd1cf9ccf4 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 28 Nov 2018 16:13:36 +0100 Subject: [PATCH 129/168] liblangutil: extends CharStream to know about the respective (file-)name (and adapt codebase to it) --- liblangutil/CharStream.h | 5 +- libsolidity/codegen/CompilerContext.cpp | 2 +- libsolidity/interface/AssemblyStack.cpp | 2 +- libsolidity/interface/CompilerStack.cpp | 4 +- test/libsolidity/Assembly.cpp | 2 +- test/libsolidity/SemVerMatcher.cpp | 2 +- .../SolidityExpressionCompiler.cpp | 2 +- test/libsolidity/SolidityParser.cpp | 2 +- test/libsolidity/SolidityScanner.cpp | 134 +++++++++--------- test/libyul/Common.cpp | 2 +- test/libyul/Parser.cpp | 2 +- test/libyul/YulOptimizerTest.cpp | 2 +- test/tools/yulopti.cpp | 2 +- 13 files changed, 83 insertions(+), 80 deletions(-) diff --git a/liblangutil/CharStream.h b/liblangutil/CharStream.h index 72aacacf5..6f2da3bbe 100644 --- a/liblangutil/CharStream.h +++ b/liblangutil/CharStream.h @@ -68,7 +68,8 @@ class CharStream { public: CharStream(): m_position(0) {} - explicit CharStream(std::string const& _source): m_source(_source), m_position(0) {} + explicit CharStream(std::string const& _source, std::string const& name): + m_source(_source), m_name(name), m_position(0) {} int position() const { return m_position; } bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); } @@ -80,6 +81,7 @@ public: void reset() { m_position = 0; } std::string const& source() const { return m_source; } + std::string const& name() const noexcept { return m_name; } ///@{ ///@name Error printing helper functions @@ -91,6 +93,7 @@ public: private: std::string m_source; + std::string m_name; size_t m_position; }; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 2fd62de20..16bc42254 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -360,7 +360,7 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared(langutil::CharStream(_assembly), "--CODEGEN--"); + auto scanner = make_shared(langutil::CharStream(_assembly, "--CODEGEN--"), "--CODEGEN--"); auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter()(*parserResult) << endl; diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 24e190b3b..5268c5aaa 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -69,7 +69,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string { m_errors.clear(); m_analysisSuccessful = false; - m_scanner = make_shared(CharStream(_source), _sourceName); + m_scanner = make_shared(CharStream(_source, _sourceName), _sourceName); m_parserResult = yul::ObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index de4a7ec20..cc5a2102a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -125,7 +125,7 @@ bool CompilerStack::addSource(string const& _name, string const& _content, bool { bool existed = m_sources.count(_name) != 0; reset(true); - m_sources[_name].scanner = make_shared(CharStream(_content), _name); + m_sources[_name].scanner = make_shared(CharStream(_content, _name), _name); m_sources[_name].isLibrary = _isLibrary; m_stackState = SourcesSet; return existed; @@ -160,7 +160,7 @@ bool CompilerStack::parse() { string const& newPath = newSource.first; string const& newContents = newSource.second; - m_sources[newPath].scanner = make_shared(CharStream(newContents), newPath); + m_sources[newPath].scanner = make_shared(CharStream(newContents, newPath), newPath); sourcesToParse.push_back(newPath); } } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 926e29fed..620f9661a 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -58,7 +58,7 @@ eth::AssemblyItems compileContract(string const& _sourceCode) ErrorReporter errorReporter(errors); Parser parser(errorReporter); ASTPointer sourceUnit; - BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode)))); + BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode, "")))); BOOST_CHECK(!!sourceUnit); map> scopes; diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 2e147847c..2980acd1b 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -41,7 +41,7 @@ BOOST_AUTO_TEST_SUITE(SemVerMatcher) SemVerMatchExpression parseExpression(string const& _input) { - Scanner scanner{CharStream(_input)}; + Scanner scanner{CharStream(_input, "")}; vector literals; vector tokens; while (scanner.currentToken() != Token::EOS) diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index a68eb3df3..8bce26c11 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -101,7 +101,7 @@ bytes compileFirstExpression( { ErrorList errors; ErrorReporter errorReporter(errors); - sourceUnit = Parser(errorReporter).parse(make_shared(CharStream(_sourceCode))); + sourceUnit = Parser(errorReporter).parse(make_shared(CharStream(_sourceCode, ""))); if (!sourceUnit) return bytes(); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 3534dd5ba..d86d3d397 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -43,7 +43,7 @@ namespace ASTPointer parseText(std::string const& _source, ErrorList& _errors) { ErrorReporter errorReporter(_errors); - ASTPointer sourceUnit = Parser(errorReporter).parse(std::make_shared(CharStream(_source))); + ASTPointer sourceUnit = Parser(errorReporter).parse(std::make_shared(CharStream(_source, ""))); if (!sourceUnit) return ASTPointer(); for (ASTPointer const& node: sourceUnit->nodes()) diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 02d91d32b..95d565683 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -37,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); @@ -61,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"); @@ -69,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"); @@ -77,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)); @@ -85,7 +85,7 @@ 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); @@ -99,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); @@ -107,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); @@ -146,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); @@ -167,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); @@ -176,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); } @@ -188,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); } @@ -196,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); @@ -204,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); @@ -213,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); } @@ -221,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); @@ -263,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); @@ -286,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); @@ -308,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); @@ -334,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); @@ -346,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); @@ -358,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); @@ -368,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(), ""); } @@ -398,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 "); @@ -406,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); @@ -415,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); @@ -426,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); @@ -436,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)); @@ -444,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)); @@ -452,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)); @@ -460,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)); @@ -468,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); } @@ -477,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)); @@ -485,7 +485,7 @@ 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::Illegal); BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); @@ -493,7 +493,7 @@ BOOST_AUTO_TEST_CASE(invalid_short_hex_literal) 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::Illegal); BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); @@ -501,7 +501,7 @@ BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space) 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::Illegal); BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); @@ -509,7 +509,7 @@ BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes) 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::Illegal); BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalHexString); @@ -520,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); } @@ -528,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); } @@ -544,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"); @@ -556,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++) @@ -571,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"); @@ -583,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++) @@ -598,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"); @@ -611,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/libyul/Common.cpp b/test/libyul/Common.cpp index 2e70d0869..36065db79 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -57,7 +57,7 @@ pair, shared_ptr> yul::test::parse(strin auto flavour = _yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared(CharStream(_source), ""); + auto scanner = make_shared(CharStream(_source, ""), ""); auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false); if (parserResult) { diff --git a/test/libyul/Parser.cpp b/test/libyul/Parser.cpp index 6f9463627..caaf27196 100644 --- a/test/libyul/Parser.cpp +++ b/test/libyul/Parser.cpp @@ -51,7 +51,7 @@ bool parse(string const& _source, ErrorReporter& errorReporter) { try { - auto scanner = make_shared(CharStream(_source)); + auto scanner = make_shared(CharStream(_source, "")); auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Yul).parse(scanner, false); if (parserResult) { diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index c857d8a5f..8f282aaca 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -259,7 +259,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c yul::AsmFlavour flavour = m_yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); - shared_ptr scanner = make_shared(CharStream(m_source), ""); + shared_ptr scanner = make_shared(CharStream(m_source, ""), ""); m_ast = yul::Parser(errorReporter, flavour).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 5a8a51063..8ecafb29a 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -81,7 +81,7 @@ public: bool parse(string const& _input) { ErrorReporter errorReporter(m_errors); - shared_ptr scanner = make_shared(CharStream(_input), ""); + shared_ptr scanner = make_shared(CharStream(_input, ""), ""); m_ast = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { From 2867c2b4dd616aa181c4d06ed6179f2030b6a934 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 13:32:52 +0100 Subject: [PATCH 130/168] Clarify "copying bytecode" in inheritance. --- docs/contracts.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index df95883f9..d6337d9a0 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1043,14 +1043,15 @@ Additional Resources for Understanding Events Inheritance *********** -Solidity supports multiple inheritance by copying code including polymorphism. +Solidity supports multiple inheritance including polymorphism. All function calls are virtual, which means that the most derived function -is called, except when the contract name is explicitly given. +is called, except when the contract name is explicitly given or the +``super`` keyword is used. When a contract inherits from other contracts, only a single contract is created on the blockchain, and the code from all the base contracts -is copied into the created contract. +is compiled into the created contract. The general inheritance system is very similar to `Python's `_, From 67bbcefe6c104d60b42d35c61d42fb979f69fe89 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Thu, 29 Nov 2018 10:05:52 +0100 Subject: [PATCH 131/168] Report deprecation error on functions sha3 and suicide also without call. --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 37 +++++++++---------- .../syntaxTests/deprecated_functions.sol | 4 +- .../globalFunctions/sha3_no_call.sol | 8 ++++ .../globalFunctions/sha3_override.sol | 11 ++++++ .../syntaxTests/globalFunctions/sha3_var.sol | 9 +++++ .../globalFunctions/suicide_no_call.sol | 8 ++++ .../globalFunctions/suicide_override.sol | 11 ++++++ .../globalFunctions/suicide_var.sol | 9 +++++ 9 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 test/libsolidity/syntaxTests/globalFunctions/sha3_no_call.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/sha3_override.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/sha3_var.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/suicide_no_call.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/suicide_override.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/suicide_var.sol diff --git a/Changelog.md b/Changelog.md index f64ae1845..99c1ead87 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Bugfixes: * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. * Type Checker: Fix internal compiler error when a field of a struct used as a parameter in a function type has a non-existent type. + * Type Checker: Disallow functions ``sha3`` and ``suicide`` also without a function call. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index fcc6746fd..16b6a55e7 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1824,26 +1824,6 @@ void TypeChecker::typeCheckFunctionCall( "\"staticcall\" is not supported by the VM version." ); - // Check for deprecated function names - if (_functionType->kind() == FunctionType::Kind::KECCAK256) - { - if (auto functionName = dynamic_cast(&_functionCall.expression())) - if (functionName->name() == "sha3") - m_errorReporter.typeError( - _functionCall.location(), - "\"sha3\" has been deprecated in favour of \"keccak256\"" - ); - } - else if (_functionType->kind() == FunctionType::Kind::Selfdestruct) - { - if (auto functionName = dynamic_cast(&_functionCall.expression())) - if (functionName->name() == "suicide") - m_errorReporter.typeError( - _functionCall.location(), - "\"suicide\" has been deprecated in favour of \"selfdestruct\"" - ); - } - // Check for event outside of emit statement if (!m_insideEmitStatement && _functionType->kind() == FunctionType::Kind::Event) m_errorReporter.typeError( @@ -2639,6 +2619,23 @@ bool TypeChecker::visit(Identifier const& _identifier) else if (dynamic_cast(annotation.referencedDeclaration)) if (dynamic_cast(annotation.type.get())) annotation.isPure = true; + + // Check for deprecated function names. + // The check is done here for the case without an actual function call. + if (FunctionType const* fType = dynamic_cast(_identifier.annotation().type.get())) + { + if (_identifier.name() == "sha3" && fType->kind() == FunctionType::Kind::KECCAK256) + m_errorReporter.typeError( + _identifier.location(), + "\"sha3\" has been deprecated in favour of \"keccak256\"" + ); + else if (_identifier.name() == "suicide" && fType->kind() == FunctionType::Kind::Selfdestruct) + m_errorReporter.typeError( + _identifier.location(), + "\"suicide\" has been deprecated in favour of \"selfdestruct\"" + ); + } + return false; } diff --git a/test/libsolidity/syntaxTests/deprecated_functions.sol b/test/libsolidity/syntaxTests/deprecated_functions.sol index 62dfcff95..c5764e96c 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/globalFunctions/sha3_no_call.sol b/test/libsolidity/syntaxTests/globalFunctions/sha3_no_call.sol new file mode 100644 index 000000000..37b60e5e4 --- /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 000000000..909c2dc34 --- /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 000000000..19ee72d94 --- /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 000000000..bf3f5ebc8 --- /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 000000000..7350da39f --- /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 000000000..3549a5633 --- /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. From 9e9250c961b8510c581fa8e46712ab02beb4f6e8 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 15:32:38 +0100 Subject: [PATCH 132/168] Fix move bug. --- libsolidity/formal/SolverInterface.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index cc8214de8..7f20876e5 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -136,9 +136,10 @@ public: static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue) { solAssert(*_trueValue.sort == *_falseValue.sort, ""); + SortPointer sort = _trueValue.sort; return Expression("ite", std::vector{ std::move(_condition), std::move(_trueValue), std::move(_falseValue) - }, _trueValue.sort); + }, std::move(sort)); } static Expression implies(Expression _a, Expression _b) From 73a64da041efb2b64b1c89ed6012161cb278e24e Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 19:30:27 +0100 Subject: [PATCH 133/168] Fix bug related to state variables of function type accessed via base contract. --- Changelog.md | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 6 +++--- test/libsolidity/SolidityEndToEndTest.cpp | 20 +++++++++++++++++++ .../memberLookup/internal_function_type.sol | 7 +++++++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol diff --git a/Changelog.md b/Changelog.md index 99c1ead87..a54b999f9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,6 +18,7 @@ Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. * Commandline interface: Fix crash when using ``--ast`` on empty runtime code. * Code Generator: Annotate jump from calldata decoder to function as "jump in". + * Code Generator: Fix internal error related to state variables of function type access via base contract name. * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 87eecd2e3..121585d99 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1153,7 +1153,9 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) if (dynamic_cast(type->actualType().get())) { solAssert(_memberAccess.annotation().type, "_memberAccess has no type"); - if (auto funType = dynamic_cast(_memberAccess.annotation().type.get())) + if (auto variable = dynamic_cast(_memberAccess.annotation().referencedDeclaration)) + appendVariable(*variable, static_cast(_memberAccess)); + else if (auto funType = dynamic_cast(_memberAccess.annotation().type.get())) { switch (funType->kind()) { @@ -1199,8 +1201,6 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) { // no-op } - else if (auto variable = dynamic_cast(_memberAccess.annotation().referencedDeclaration)) - appendVariable(*variable, static_cast(_memberAccess)); else _memberAccess.expression().accept(*this); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 05bb74464..c6135a720 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14213,6 +14213,26 @@ BOOST_AUTO_TEST_CASE(external_public_override) 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/syntaxTests/memberLookup/internal_function_type.sol b/test/libsolidity/syntaxTests/memberLookup/internal_function_type.sol new file mode 100644 index 000000000..560a6c2ae --- /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) {} +} From c445e7dfa4505ba5d914f2d4b29b18107b7e6e97 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 19:44:33 +0100 Subject: [PATCH 134/168] Disallow inline arrays of mapping type. --- Changelog.md | 1 + libsolidity/analysis/TypeChecker.cpp | 3 +++ .../inline_arrays/inline_array_of_mapping_type.sol | 8 ++++++++ 3 files changed, 12 insertions(+) create mode 100644 test/libsolidity/syntaxTests/inline_arrays/inline_array_of_mapping_type.sol diff --git a/Changelog.md b/Changelog.md index 99c1ead87..2835a14e5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,6 +23,7 @@ Bugfixes: * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. * Type Checker: Fix internal compiler error when a field of a struct used as a parameter in a function type has a non-existent type. * Type Checker: Disallow functions ``sha3`` and ``suicide`` also without a function call. + * Type Checker: Disallow inline arrays of mapping type. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 16b6a55e7..a80ca7d60 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1608,6 +1608,9 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { if (!inlineArrayType) m_errorReporter.fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); + else if (!inlineArrayType->canLiveOutsideStorage()) + m_errorReporter.fatalTypeError(_tuple.location(), "Type " + inlineArrayType->toString() + " is only valid in storage."); + _tuple.annotation().type = make_shared(DataLocation::Memory, inlineArrayType, types.size()); } else 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 000000000..59a88130c --- /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. From f46dd91c208e99bf0eba240d34e976a46888ee4d Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 19:47:44 +0100 Subject: [PATCH 135/168] Move inline array tests. --- .../dynamic_inline_array.sol} | 0 .../inline_array_declaration_and_passing_implicit_conversion.sol} | 0 ...array_declaration_and_passing_implicit_conversion_strings.sol} | 0 .../inline_array_declaration_const_int_conversion.sol} | 0 .../inline_array_declaration_const_string_conversion.sol} | 0 .../inline_array_declaration_no_type.sol} | 0 .../inline_array_declaration_no_type_strings.sol} | 0 .../inline_array_fixed_types.sol} | 0 .../inline_array_rationals.sol} | 0 .../invalid_types_in_inline_array.sol} | 0 .../lvalues_as_inline_array.sol} | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/277_dynamic_inline_array.sol => inline_arrays/dynamic_inline_array.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol => inline_arrays/inline_array_declaration_and_passing_implicit_conversion.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol => inline_arrays/inline_array_declaration_and_passing_implicit_conversion_strings.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol => inline_arrays/inline_array_declaration_const_int_conversion.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol => inline_arrays/inline_array_declaration_const_string_conversion.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/273_inline_array_declaration_no_type.sol => inline_arrays/inline_array_declaration_no_type.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol => inline_arrays/inline_array_declaration_no_type_strings.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/325_inline_array_fixed_types.sol => inline_arrays/inline_array_fixed_types.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/326_inline_array_rationals.sol => inline_arrays/inline_array_rationals.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/276_invalid_types_in_inline_array.sol => inline_arrays/invalid_types_in_inline_array.sol} (100%) rename test/libsolidity/syntaxTests/{nameAndTypeResolution/278_lvalues_as_inline_array.sol => inline_arrays/lvalues_as_inline_array.sol} (100%) diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol b/test/libsolidity/syntaxTests/inline_arrays/dynamic_inline_array.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/277_dynamic_inline_array.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/269_inline_array_declaration_and_passing_implicit_conversion.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/270_inline_array_declaration_and_passing_implicit_conversion_strings.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/271_inline_array_declaration_const_int_conversion.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/272_inline_array_declaration_const_string_conversion.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/273_inline_array_declaration_no_type.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/274_inline_array_declaration_no_type_strings.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/325_inline_array_fixed_types.sol rename to test/libsolidity/syntaxTests/inline_arrays/inline_array_fixed_types.sol diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol b/test/libsolidity/syntaxTests/inline_arrays/inline_array_rationals.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/326_inline_array_rationals.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/276_invalid_types_in_inline_array.sol rename to 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 similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/278_lvalues_as_inline_array.sol rename to test/libsolidity/syntaxTests/inline_arrays/lvalues_as_inline_array.sol From 2f6de12e8ca98c92ee708081c3a3be05c2c30c6c Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Wed, 28 Nov 2018 13:16:35 +0100 Subject: [PATCH 136/168] [SMTChecker] Make smt::Sort::operator== virtual --- libsolidity/formal/SolverInterface.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index 7f20876e5..4a4b3fb1a 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -55,7 +55,7 @@ struct Sort Sort(Kind _kind): kind(_kind) {} virtual ~Sort() = default; - bool operator==(Sort const& _other) const { return kind == _other.kind; } + virtual bool operator==(Sort const& _other) const { return kind == _other.kind; } Kind const kind; }; @@ -65,16 +65,22 @@ struct FunctionSort: public Sort { FunctionSort(std::vector _domain, SortPointer _codomain): Sort(Kind::Function), domain(std::move(_domain)), codomain(std::move(_codomain)) {} - bool operator==(FunctionSort const& _other) const + bool operator==(Sort const& _other) const override { + if (!Sort::operator==(_other)) + return false; + auto _otherFunction = dynamic_cast(&_other); + solAssert(_otherFunction, ""); + if (domain.size() != _otherFunction->domain.size()) + return false; if (!std::equal( domain.begin(), domain.end(), - _other.domain.begin(), + _otherFunction->domain.begin(), [&](SortPointer _a, SortPointer _b) { return *_a == *_b; } )) return false; - return Sort::operator==(_other) && *codomain == *_other.codomain; + return *codomain == *_otherFunction->codomain; } std::vector domain; @@ -87,9 +93,13 @@ struct ArraySort: public Sort /// _range is the sort of the values ArraySort(SortPointer _domain, SortPointer _range): Sort(Kind::Array), domain(std::move(_domain)), range(std::move(_range)) {} - bool operator==(ArraySort const& _other) const + bool operator==(Sort const& _other) const override { - return Sort::operator==(_other) && *domain == *_other.domain && *range == *_other.range; + if (!Sort::operator==(_other)) + return false; + auto _otherArray = dynamic_cast(&_other); + solAssert(_otherArray, ""); + return *domain == *_otherArray->domain && *range == *_otherArray->range; } SortPointer domain; From 0bd9db480f54d846abbdb4218e000f08ead4fbd5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 17:35:14 +0100 Subject: [PATCH 137/168] Add skeleton for contract level checker. --- libsolidity/CMakeLists.txt | 1 + libsolidity/analysis/ContractLevelChecker.cpp | 37 ++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 59 +++++++++++++++++++ libsolidity/interface/CompilerStack.cpp | 18 +++++- 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 libsolidity/analysis/ContractLevelChecker.cpp create mode 100644 libsolidity/analysis/ContractLevelChecker.h diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index d2e0c8549..dc4c6d156 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,6 +1,7 @@ # Until we have a clear separation, libyul has to be included here set(sources analysis/ConstantEvaluator.cpp + analysis/ContractLevelChecker.cpp analysis/ControlFlowAnalyzer.cpp analysis/ControlFlowBuilder.cpp analysis/ControlFlowGraph.cpp diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp new file mode 100644 index 000000000..4f32eb626 --- /dev/null +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -0,0 +1,37 @@ +/* + 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 . +*/ +/** + * Component that verifies overloads, abstract contracts, function clashes and others + * checks at contract or function level. + */ + +#include +#include + +#include + + +using namespace std; +using namespace dev; +using namespace langutil; +using namespace dev::solidity; + + +bool ContractLevelChecker::check(ContractDefinition const&) +{ + return Error::containsOnlyWarnings(m_errorReporter.errors()); +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h new file mode 100644 index 000000000..f89cf5048 --- /dev/null +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -0,0 +1,59 @@ +/* + 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 . +*/ +/** + * Component that verifies overloads, abstract contracts, function clashes and others + * checks at contract or function level. + */ + +#pragma once + +#include + +#include + +namespace langutil +{ +class ErrorReporter; +} + +namespace dev +{ +namespace solidity +{ + +/** + * Component that verifies overloads, abstract contracts, function clashes and others + * checks at contract or function level. + */ +class ContractLevelChecker +{ +public: + /// @param _errorReporter provides the error logging functionality. + explicit ContractLevelChecker(langutil::ErrorReporter& _errorReporter): + m_errorReporter(_errorReporter) + {} + + /// Performs checks on the given contract. + /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings + bool check(ContractDefinition const& _contract); + +private: + langutil::ErrorReporter& m_errorReporter; +}; + +} +} diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index de4a7ec20..623ccca82 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -225,8 +226,21 @@ bool CompilerStack::analyze() m_contracts[contract->fullyQualifiedName()].contract = contract; } - // This cannot be done in the above loop, because cross-contract types couldn't be resolved. - // A good example is `LibraryName.TypeName x;`. + // Next, we check inheritance, overrides, function collisions and other things at + // contract or function level. + // This also calculates whether a contract is abstract, which is needed by the + // type checker. + ContractLevelChecker contractLevelChecker(m_errorReporter); + for (Source const* source: m_sourceOrder) + for (ASTPointer const& node: source->ast->nodes()) + if (ContractDefinition* contract = dynamic_cast(node.get())) + if (!contractLevelChecker.check(*contract)) + noErrors = false; + + // New we run full type checks that go down to the expression level. This + // cannot be done earlier, because we need cross-contract types and information + // about whether a contract is abstract for the `new` expression. + // This populates the `type` annotation for all expressions. // // Note: this does not resolve overloaded functions. In order to do that, types of arguments are needed, // which is only done one step later. From d054a3b85d70508611c4f8a1e093610ab95cfa37 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 17:39:57 +0100 Subject: [PATCH 138/168] Move duplication checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 87 ++++++++++++++++++- libsolidity/analysis/ContractLevelChecker.h | 7 ++ libsolidity/analysis/TypeChecker.cpp | 84 ------------------ libsolidity/analysis/TypeChecker.h | 7 -- 4 files changed, 93 insertions(+), 92 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 4f32eb626..a2e76edfc 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -31,7 +31,92 @@ using namespace langutil; using namespace dev::solidity; -bool ContractLevelChecker::check(ContractDefinition const&) +bool ContractLevelChecker::check(ContractDefinition const& _contract) { + checkContractDuplicateFunctions(_contract); + checkContractDuplicateEvents(_contract); + return Error::containsOnlyWarnings(m_errorReporter.errors()); } + +void ContractLevelChecker::checkContractDuplicateFunctions(ContractDefinition const& _contract) +{ + /// Checks that two functions with the same name defined in this contract have different + /// argument types and that there is at most one constructor. + map> functions; + FunctionDefinition const* constructor = nullptr; + FunctionDefinition const* fallback = nullptr; + for (FunctionDefinition const* function: _contract.definedFunctions()) + if (function->isConstructor()) + { + if (constructor) + m_errorReporter.declarationError( + function->location(), + SecondarySourceLocation().append("Another declaration is here:", constructor->location()), + "More than one constructor defined." + ); + constructor = function; + } + else if (function->isFallback()) + { + if (fallback) + m_errorReporter.declarationError( + function->location(), + SecondarySourceLocation().append("Another declaration is here:", fallback->location()), + "Only one fallback function is allowed." + ); + fallback = function; + } + else + { + solAssert(!function->name().empty(), ""); + functions[function->name()].push_back(function); + } + + findDuplicateDefinitions(functions, "Function with same name and arguments defined twice."); +} + +void ContractLevelChecker::checkContractDuplicateEvents(ContractDefinition const& _contract) +{ + /// Checks that two events with the same name defined in this contract have different + /// argument types + map> events; + for (EventDefinition const* event: _contract.events()) + events[event->name()].push_back(event); + + findDuplicateDefinitions(events, "Event with same name and arguments defined twice."); +} + +template +void ContractLevelChecker::findDuplicateDefinitions(map> const& _definitions, string _message) +{ + for (auto const& it: _definitions) + { + vector const& overloads = it.second; + set reported; + for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i) + { + SecondarySourceLocation ssl; + + for (size_t j = i + 1; j < overloads.size(); ++j) + if (FunctionType(*overloads[i]).asCallableFunction(false)->hasEqualParameterTypes( + *FunctionType(*overloads[j]).asCallableFunction(false)) + ) + { + ssl.append("Other declaration is here:", overloads[j]->location()); + reported.insert(j); + } + + if (ssl.infos.size() > 0) + { + ssl.limitSize(_message); + + m_errorReporter.declarationError( + overloads[i]->location(), + ssl, + _message + ); + } + } + } +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index f89cf5048..b1632b787 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -52,6 +52,13 @@ public: bool check(ContractDefinition const& _contract); private: + /// Checks that two functions defined in this contract with the same name have different + /// arguments and that there is at most one constructor. + void checkContractDuplicateFunctions(ContractDefinition const& _contract); + void checkContractDuplicateEvents(ContractDefinition const& _contract); + template + void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); + langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index a80ca7d60..3ffa81018 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -96,8 +96,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.definedStructs(), *this); ASTNode::listAccept(_contract.baseContracts(), *this); - checkContractDuplicateFunctions(_contract); - checkContractDuplicateEvents(_contract); checkContractIllegalOverrides(_contract); checkContractAbstractFunctions(_contract); checkContractBaseConstructorArguments(_contract); @@ -162,88 +160,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) return false; } -void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _contract) -{ - /// Checks that two functions with the same name defined in this contract have different - /// argument types and that there is at most one constructor. - map> functions; - FunctionDefinition const* constructor = nullptr; - FunctionDefinition const* fallback = nullptr; - for (FunctionDefinition const* function: _contract.definedFunctions()) - if (function->isConstructor()) - { - if (constructor) - m_errorReporter.declarationError( - function->location(), - SecondarySourceLocation().append("Another declaration is here:", constructor->location()), - "More than one constructor defined." - ); - constructor = function; - } - else if (function->isFallback()) - { - if (fallback) - m_errorReporter.declarationError( - function->location(), - SecondarySourceLocation().append("Another declaration is here:", fallback->location()), - "Only one fallback function is allowed." - ); - fallback = function; - } - else - { - solAssert(!function->name().empty(), ""); - functions[function->name()].push_back(function); - } - - findDuplicateDefinitions(functions, "Function with same name and arguments defined twice."); -} - -void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract) -{ - /// Checks that two events with the same name defined in this contract have different - /// argument types - map> events; - for (EventDefinition const* event: _contract.events()) - events[event->name()].push_back(event); - - findDuplicateDefinitions(events, "Event with same name and arguments defined twice."); -} - -template -void TypeChecker::findDuplicateDefinitions(map> const& _definitions, string _message) -{ - for (auto const& it: _definitions) - { - vector const& overloads = it.second; - set reported; - for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i) - { - SecondarySourceLocation ssl; - - for (size_t j = i + 1; j < overloads.size(); ++j) - if (FunctionType(*overloads[i]).asCallableFunction(false)->hasEqualParameterTypes( - *FunctionType(*overloads[j]).asCallableFunction(false)) - ) - { - ssl.append("Other declaration is here:", overloads[j]->location()); - reported.insert(j); - } - - if (ssl.infos.size() > 0) - { - ssl.limitSize(_message); - - m_errorReporter.declarationError( - overloads[i]->location(), - ssl, - _message - ); - } - } - } -} - void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) { // Mapping from name to function definition (exactly one per argument type equality class) and diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index c98a4c7f2..69fbbb3ed 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,10 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - /// Checks that two functions defined in this contract with the same name have different - /// arguments and that there is at most one constructor. - void checkContractDuplicateFunctions(ContractDefinition const& _contract); - void checkContractDuplicateEvents(ContractDefinition const& _contract); void checkContractIllegalOverrides(ContractDefinition const& _contract); /// Reports a type error with an appropriate message if overridden function signature differs. /// Also stores the direct super function in the AST annotations. @@ -157,9 +153,6 @@ private: void endVisit(ElementaryTypeNameExpression const& _expr) override; void endVisit(Literal const& _literal) override; - template - void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); - bool contractDependenciesAreCyclic( ContractDefinition const& _contract, std::set const& _seenContracts = std::set() From 89cf6a5a38b02c3da1377279fcd98d690a58a978 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 17:44:38 +0100 Subject: [PATCH 139/168] Move override checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 83 +++++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 5 ++ libsolidity/analysis/TypeChecker.cpp | 82 ------------------ libsolidity/analysis/TypeChecker.h | 5 -- 4 files changed, 88 insertions(+), 87 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index a2e76edfc..bf132d63b 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -35,6 +35,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) { checkContractDuplicateFunctions(_contract); checkContractDuplicateEvents(_contract); + checkContractIllegalOverrides(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -120,3 +121,85 @@ void ContractLevelChecker::findDuplicateDefinitions(map> const } } } + +void ContractLevelChecker::checkContractIllegalOverrides(ContractDefinition const& _contract) +{ + // TODO unify this at a later point. for this we need to put the constness and the access specifier + // into the types + map> functions; + map modifiers; + + // We search from derived to base, so the stored item causes the error. + for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) + { + for (FunctionDefinition const* function: contract->definedFunctions()) + { + if (function->isConstructor()) + continue; // constructors can neither be overridden nor override anything + string const& name = function->name(); + if (modifiers.count(name)) + m_errorReporter.typeError(modifiers[name]->location(), "Override changes function to modifier."); + + for (FunctionDefinition const* overriding: functions[name]) + checkFunctionOverride(*overriding, *function); + + functions[name].push_back(function); + } + for (ModifierDefinition const* modifier: contract->functionModifiers()) + { + string const& name = modifier->name(); + ModifierDefinition const*& override = modifiers[name]; + if (!override) + override = modifier; + else if (ModifierType(*override) != ModifierType(*modifier)) + m_errorReporter.typeError(override->location(), "Override changes modifier signature."); + if (!functions[name].empty()) + m_errorReporter.typeError(override->location(), "Override changes modifier to function."); + } + } +} + +void ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super) +{ + FunctionTypePointer functionType = FunctionType(_function).asCallableFunction(false); + FunctionTypePointer superType = FunctionType(_super).asCallableFunction(false); + + if (!functionType->hasEqualParameterTypes(*superType)) + return; + if (!functionType->hasEqualReturnTypes(*superType)) + overrideError(_function, _super, "Overriding function return types differ."); + + if (!_function.annotation().superFunction) + _function.annotation().superFunction = &_super; + + if (_function.visibility() != _super.visibility()) + { + // Visibility change from external to public is fine. + // Any other change is disallowed. + if (!( + _super.visibility() == FunctionDefinition::Visibility::External && + _function.visibility() == FunctionDefinition::Visibility::Public + )) + overrideError(_function, _super, "Overriding function visibility differs."); + } + if (_function.stateMutability() != _super.stateMutability()) + overrideError( + _function, + _super, + "Overriding function changes state mutability from \"" + + stateMutabilityToString(_super.stateMutability()) + + "\" to \"" + + stateMutabilityToString(_function.stateMutability()) + + "\"." + ); +} + +void ContractLevelChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message) +{ + m_errorReporter.typeError( + function.location(), + SecondarySourceLocation().append("Overridden function is here:", super.location()), + message + ); +} + diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index b1632b787..400979c05 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -58,6 +58,11 @@ private: void checkContractDuplicateEvents(ContractDefinition const& _contract); template void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); + void checkContractIllegalOverrides(ContractDefinition const& _contract); + /// Reports a type error with an appropriate message if overridden function signature differs. + /// Also stores the direct super function in the AST annotations. + void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super); + void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3ffa81018..07d32563d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -96,7 +96,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.definedStructs(), *this); ASTNode::listAccept(_contract.baseContracts(), *this); - checkContractIllegalOverrides(_contract); checkContractAbstractFunctions(_contract); checkContractBaseConstructorArguments(_contract); @@ -288,87 +287,6 @@ void TypeChecker::annotateBaseConstructorArguments( } -void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contract) -{ - // TODO unify this at a later point. for this we need to put the constness and the access specifier - // into the types - map> functions; - map modifiers; - - // We search from derived to base, so the stored item causes the error. - for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) - { - for (FunctionDefinition const* function: contract->definedFunctions()) - { - if (function->isConstructor()) - continue; // constructors can neither be overridden nor override anything - string const& name = function->name(); - if (modifiers.count(name)) - m_errorReporter.typeError(modifiers[name]->location(), "Override changes function to modifier."); - - for (FunctionDefinition const* overriding: functions[name]) - checkFunctionOverride(*overriding, *function); - - functions[name].push_back(function); - } - for (ModifierDefinition const* modifier: contract->functionModifiers()) - { - string const& name = modifier->name(); - ModifierDefinition const*& override = modifiers[name]; - if (!override) - override = modifier; - else if (ModifierType(*override) != ModifierType(*modifier)) - m_errorReporter.typeError(override->location(), "Override changes modifier signature."); - if (!functions[name].empty()) - m_errorReporter.typeError(override->location(), "Override changes modifier to function."); - } - } -} - -void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super) -{ - FunctionTypePointer functionType = FunctionType(_function).asCallableFunction(false); - FunctionTypePointer superType = FunctionType(_super).asCallableFunction(false); - - if (!functionType->hasEqualParameterTypes(*superType)) - return; - if (!functionType->hasEqualReturnTypes(*superType)) - overrideError(_function, _super, "Overriding function return types differ."); - - if (!_function.annotation().superFunction) - _function.annotation().superFunction = &_super; - - if (_function.visibility() != _super.visibility()) - { - // Visibility change from external to public is fine. - // Any other change is disallowed. - if (!( - _super.visibility() == FunctionDefinition::Visibility::External && - _function.visibility() == FunctionDefinition::Visibility::Public - )) - overrideError(_function, _super, "Overriding function visibility differs."); - } - if (_function.stateMutability() != _super.stateMutability()) - overrideError( - _function, - _super, - "Overriding function changes state mutability from \"" + - stateMutabilityToString(_super.stateMutability()) + - "\" to \"" + - stateMutabilityToString(_function.stateMutability()) + - "\"." - ); -} - -void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message) -{ - m_errorReporter.typeError( - function.location(), - SecondarySourceLocation().append("Overridden function is here:", super.location()), - message - ); -} - void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _contract) { map>> externalDeclarations; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 69fbbb3ed..7d718ff90 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,11 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - void checkContractIllegalOverrides(ContractDefinition const& _contract); - /// Reports a type error with an appropriate message if overridden function signature differs. - /// Also stores the direct super function in the AST annotations. - void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super); - void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message); void checkContractAbstractFunctions(ContractDefinition const& _contract); void checkContractBaseConstructorArguments(ContractDefinition const& _contract); void annotateBaseConstructorArguments( From 57a62429c9d0be4b3a8a9cc98fa7eb46a6015165 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 17:51:57 +0100 Subject: [PATCH 140/168] Move abstract function check. --- libsolidity/analysis/ContractLevelChecker.cpp | 45 +++++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 1 + libsolidity/analysis/TypeChecker.cpp | 45 ------------------- libsolidity/analysis/TypeChecker.h | 1 - 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index bf132d63b..74ac665f7 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -24,6 +24,8 @@ #include +#include + using namespace std; using namespace dev; @@ -36,6 +38,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkContractDuplicateFunctions(_contract); checkContractDuplicateEvents(_contract); checkContractIllegalOverrides(_contract); + checkContractAbstractFunctions(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -203,3 +206,45 @@ void ContractLevelChecker::overrideError(FunctionDefinition const& function, Fun ); } +void ContractLevelChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) +{ + // Mapping from name to function definition (exactly one per argument type equality class) and + // flag to indicate whether it is fully implemented. + using FunTypeAndFlag = std::pair; + map> functions; + + // Search from base to derived + for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) + for (FunctionDefinition const* function: contract->definedFunctions()) + { + // Take constructors out of overload hierarchy + if (function->isConstructor()) + continue; + auto& overloads = functions[function->name()]; + FunctionTypePointer funType = make_shared(*function)->asCallableFunction(false); + auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) + { + return funType->hasEqualParameterTypes(*_funAndFlag.first); + }); + if (it == overloads.end()) + overloads.push_back(make_pair(funType, function->isImplemented())); + else if (it->second) + { + if (!function->isImplemented()) + m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract"); + } + else if (function->isImplemented()) + it->second = true; + } + + // Set to not fully implemented if at least one flag is false. + for (auto const& it: functions) + for (auto const& funAndFlag: it.second) + if (!funAndFlag.second) + { + FunctionDefinition const* function = dynamic_cast(&funAndFlag.first->declaration()); + solAssert(function, ""); + _contract.annotation().unimplementedFunctions.push_back(function); + break; + } +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 400979c05..1746153b4 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -63,6 +63,7 @@ private: /// Also stores the direct super function in the AST annotations. void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super); void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message); + void checkContractAbstractFunctions(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 07d32563d..2b79e29bc 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -96,7 +95,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.definedStructs(), *this); ASTNode::listAccept(_contract.baseContracts(), *this); - checkContractAbstractFunctions(_contract); checkContractBaseConstructorArguments(_contract); FunctionDefinition const* function = _contract.constructor(); @@ -159,49 +157,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) return false; } -void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) -{ - // Mapping from name to function definition (exactly one per argument type equality class) and - // flag to indicate whether it is fully implemented. - using FunTypeAndFlag = std::pair; - map> functions; - - // Search from base to derived - for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) - for (FunctionDefinition const* function: contract->definedFunctions()) - { - // Take constructors out of overload hierarchy - if (function->isConstructor()) - continue; - auto& overloads = functions[function->name()]; - FunctionTypePointer funType = make_shared(*function)->asCallableFunction(false); - auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) - { - return funType->hasEqualParameterTypes(*_funAndFlag.first); - }); - if (it == overloads.end()) - overloads.push_back(make_pair(funType, function->isImplemented())); - else if (it->second) - { - if (!function->isImplemented()) - m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract"); - } - else if (function->isImplemented()) - it->second = true; - } - - // Set to not fully implemented if at least one flag is false. - for (auto const& it: functions) - for (auto const& funAndFlag: it.second) - if (!funAndFlag.second) - { - FunctionDefinition const* function = dynamic_cast(&funAndFlag.first->declaration()); - solAssert(function, ""); - _contract.annotation().unimplementedFunctions.push_back(function); - break; - } -} - void TypeChecker::checkContractBaseConstructorArguments(ContractDefinition const& _contract) { vector const& bases = _contract.annotation().linearizedBaseContracts; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 7d718ff90..61eee386d 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,7 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - void checkContractAbstractFunctions(ContractDefinition const& _contract); void checkContractBaseConstructorArguments(ContractDefinition const& _contract); void annotateBaseConstructorArguments( ContractDefinition const& _currentContract, From 2c2c976697d22400d37f3b26064b6b1f6fc91dba Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 17:58:15 +0100 Subject: [PATCH 141/168] Move base constructor argument checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 91 +++++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 6 ++ libsolidity/analysis/TypeChecker.cpp | 87 ------------------ libsolidity/analysis/TypeChecker.h | 6 -- 4 files changed, 97 insertions(+), 93 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 74ac665f7..f41e569fe 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -39,6 +39,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkContractDuplicateEvents(_contract); checkContractIllegalOverrides(_contract); checkContractAbstractFunctions(_contract); + checkContractBaseConstructorArguments(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -248,3 +249,93 @@ void ContractLevelChecker::checkContractAbstractFunctions(ContractDefinition con break; } } + + +void ContractLevelChecker::checkContractBaseConstructorArguments(ContractDefinition const& _contract) +{ + vector const& bases = _contract.annotation().linearizedBaseContracts; + + // Determine the arguments that are used for the base constructors. + for (ContractDefinition const* contract: bases) + { + if (FunctionDefinition const* constructor = contract->constructor()) + for (auto const& modifier: constructor->modifiers()) + if (auto baseContract = dynamic_cast( + modifier->name()->annotation().referencedDeclaration + )) + { + if (modifier->arguments()) + { + if (baseContract->constructor()) + annotateBaseConstructorArguments(_contract, baseContract->constructor(), modifier.get()); + } + else + m_errorReporter.declarationError( + modifier->location(), + "Modifier-style base constructor call without arguments." + ); + } + + for (ASTPointer const& base: contract->baseContracts()) + { + ContractDefinition const* baseContract = dynamic_cast( + base->name().annotation().referencedDeclaration + ); + solAssert(baseContract, ""); + + if (baseContract->constructor() && base->arguments() && !base->arguments()->empty()) + annotateBaseConstructorArguments(_contract, baseContract->constructor(), base.get()); + } + } + + // check that we get arguments for all base constructors that need it. + // If not mark the contract as abstract (not fully implemented) + for (ContractDefinition const* contract: bases) + if (FunctionDefinition const* constructor = contract->constructor()) + if (contract != &_contract && !constructor->parameters().empty()) + if (!_contract.annotation().baseConstructorArguments.count(constructor)) + _contract.annotation().unimplementedFunctions.push_back(constructor); +} + +void ContractLevelChecker::annotateBaseConstructorArguments( + ContractDefinition const& _currentContract, + FunctionDefinition const* _baseConstructor, + ASTNode const* _argumentNode +) +{ + solAssert(_baseConstructor, ""); + solAssert(_argumentNode, ""); + + auto insertionResult = _currentContract.annotation().baseConstructorArguments.insert( + std::make_pair(_baseConstructor, _argumentNode) + ); + if (!insertionResult.second) + { + ASTNode const* previousNode = insertionResult.first->second; + + SourceLocation const* mainLocation = nullptr; + SecondarySourceLocation ssl; + + if ( + _currentContract.location().contains(previousNode->location()) || + _currentContract.location().contains(_argumentNode->location()) + ) + { + mainLocation = &previousNode->location(); + ssl.append("Second constructor call is here:", _argumentNode->location()); + } + else + { + mainLocation = &_currentContract.location(); + ssl.append("First constructor call is here: ", _argumentNode->location()); + ssl.append("Second constructor call is here: ", previousNode->location()); + } + + m_errorReporter.declarationError( + *mainLocation, + ssl, + "Base constructor arguments given twice." + ); + } + +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 1746153b4..fc0d69729 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -64,6 +64,12 @@ private: void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super); void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message); void checkContractAbstractFunctions(ContractDefinition const& _contract); + void checkContractBaseConstructorArguments(ContractDefinition const& _contract); + void annotateBaseConstructorArguments( + ContractDefinition const& _currentContract, + FunctionDefinition const* _baseConstructor, + ASTNode const* _argumentNode + ); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 2b79e29bc..0ae7ee7ad 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -95,8 +95,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.definedStructs(), *this); ASTNode::listAccept(_contract.baseContracts(), *this); - checkContractBaseConstructorArguments(_contract); - FunctionDefinition const* function = _contract.constructor(); if (function) { @@ -157,91 +155,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) return false; } -void TypeChecker::checkContractBaseConstructorArguments(ContractDefinition const& _contract) -{ - vector const& bases = _contract.annotation().linearizedBaseContracts; - - // Determine the arguments that are used for the base constructors. - for (ContractDefinition const* contract: bases) - { - if (FunctionDefinition const* constructor = contract->constructor()) - for (auto const& modifier: constructor->modifiers()) - if (auto baseContract = dynamic_cast(&dereference(*modifier->name()))) - { - if (modifier->arguments()) - { - if (baseContract->constructor()) - annotateBaseConstructorArguments(_contract, baseContract->constructor(), modifier.get()); - } - else - m_errorReporter.declarationError( - modifier->location(), - "Modifier-style base constructor call without arguments." - ); - } - - for (ASTPointer const& base: contract->baseContracts()) - { - auto baseContract = dynamic_cast(&dereference(base->name())); - solAssert(baseContract, ""); - - if (baseContract->constructor() && base->arguments() && !base->arguments()->empty()) - annotateBaseConstructorArguments(_contract, baseContract->constructor(), base.get()); - } - } - - // check that we get arguments for all base constructors that need it. - // If not mark the contract as abstract (not fully implemented) - for (ContractDefinition const* contract: bases) - if (FunctionDefinition const* constructor = contract->constructor()) - if (contract != &_contract && !constructor->parameters().empty()) - if (!_contract.annotation().baseConstructorArguments.count(constructor)) - _contract.annotation().unimplementedFunctions.push_back(constructor); -} - -void TypeChecker::annotateBaseConstructorArguments( - ContractDefinition const& _currentContract, - FunctionDefinition const* _baseConstructor, - ASTNode const* _argumentNode -) -{ - solAssert(_baseConstructor, ""); - solAssert(_argumentNode, ""); - - auto insertionResult = _currentContract.annotation().baseConstructorArguments.insert( - std::make_pair(_baseConstructor, _argumentNode) - ); - if (!insertionResult.second) - { - ASTNode const* previousNode = insertionResult.first->second; - - SourceLocation const* mainLocation = nullptr; - SecondarySourceLocation ssl; - - if ( - _currentContract.location().contains(previousNode->location()) || - _currentContract.location().contains(_argumentNode->location()) - ) - { - mainLocation = &previousNode->location(); - ssl.append("Second constructor call is here:", _argumentNode->location()); - } - else - { - mainLocation = &_currentContract.location(); - ssl.append("First constructor call is here: ", _argumentNode->location()); - ssl.append("Second constructor call is here: ", previousNode->location()); - } - - m_errorReporter.declarationError( - *mainLocation, - ssl, - "Base constructor arguments given twice." - ); - } - -} - void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _contract) { map>> externalDeclarations; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 61eee386d..d5ccb2631 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,12 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - void checkContractBaseConstructorArguments(ContractDefinition const& _contract); - void annotateBaseConstructorArguments( - ContractDefinition const& _currentContract, - FunctionDefinition const* _baseConstructor, - ASTNode const* _argumentNode - ); /// Checks that different functions with external visibility end up having different /// external argument types (i.e. different signature). void checkContractExternalTypeClashes(ContractDefinition const& _contract); From 621ce3df20ad019cf3e86cc2bbae22a59610847f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 17:59:34 +0100 Subject: [PATCH 142/168] Test. --- .../abstract_creation_forward_reference.sol | 15 +++++++++++++++ .../recursive_struct_forward_reference.sol | 11 +++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol create mode 100644 test/libsolidity/syntaxTests/structs/recursion/recursive_struct_forward_reference.sol 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 000000000..2e6aeaa5e --- /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/structs/recursion/recursive_struct_forward_reference.sol b/test/libsolidity/syntaxTests/structs/recursion/recursive_struct_forward_reference.sol new file mode 100644 index 000000000..d2a411ec8 --- /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. From d1cc731843507f81451ea8d898799d2d1659e128 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:18:17 +0100 Subject: [PATCH 143/168] No need to visit structs early. --- libsolidity/analysis/TypeChecker.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 0ae7ee7ad..3572943b5 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -88,11 +88,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) { m_scope = &_contract; - // We force our own visiting order here. The structs have to be excluded below. - set visited; - for (auto const& s: _contract.definedStructs()) - visited.insert(s); - ASTNode::listAccept(_contract.definedStructs(), *this); ASTNode::listAccept(_contract.baseContracts(), *this); FunctionDefinition const* function = _contract.constructor(); @@ -132,8 +127,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract) } for (auto const& n: _contract.subNodes()) - if (!visited.count(n.get())) - n->accept(*this); + n->accept(*this); checkContractExternalTypeClashes(_contract); // check for hash collisions in function signatures From b610be4882ca77defb73e35eda93996ca790f9f4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:23:58 +0100 Subject: [PATCH 144/168] Rename functions. --- libsolidity/analysis/ContractLevelChecker.cpp | 20 +++++++++---------- libsolidity/analysis/ContractLevelChecker.h | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index f41e569fe..0ddb198f5 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -35,16 +35,16 @@ using namespace dev::solidity; bool ContractLevelChecker::check(ContractDefinition const& _contract) { - checkContractDuplicateFunctions(_contract); - checkContractDuplicateEvents(_contract); - checkContractIllegalOverrides(_contract); - checkContractAbstractFunctions(_contract); - checkContractBaseConstructorArguments(_contract); + checkDuplicateFunctions(_contract); + checkDuplicateEvents(_contract); + checkIllegalOverrides(_contract); + checkAbstractFunctions(_contract); + checkBaseConstructorArguments(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } -void ContractLevelChecker::checkContractDuplicateFunctions(ContractDefinition const& _contract) +void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract) { /// Checks that two functions with the same name defined in this contract have different /// argument types and that there is at most one constructor. @@ -81,7 +81,7 @@ void ContractLevelChecker::checkContractDuplicateFunctions(ContractDefinition co findDuplicateDefinitions(functions, "Function with same name and arguments defined twice."); } -void ContractLevelChecker::checkContractDuplicateEvents(ContractDefinition const& _contract) +void ContractLevelChecker::checkDuplicateEvents(ContractDefinition const& _contract) { /// Checks that two events with the same name defined in this contract have different /// argument types @@ -126,7 +126,7 @@ void ContractLevelChecker::findDuplicateDefinitions(map> const } } -void ContractLevelChecker::checkContractIllegalOverrides(ContractDefinition const& _contract) +void ContractLevelChecker::checkIllegalOverrides(ContractDefinition const& _contract) { // TODO unify this at a later point. for this we need to put the constness and the access specifier // into the types @@ -207,7 +207,7 @@ void ContractLevelChecker::overrideError(FunctionDefinition const& function, Fun ); } -void ContractLevelChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) +void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _contract) { // Mapping from name to function definition (exactly one per argument type equality class) and // flag to indicate whether it is fully implemented. @@ -251,7 +251,7 @@ void ContractLevelChecker::checkContractAbstractFunctions(ContractDefinition con } -void ContractLevelChecker::checkContractBaseConstructorArguments(ContractDefinition const& _contract) +void ContractLevelChecker::checkBaseConstructorArguments(ContractDefinition const& _contract) { vector const& bases = _contract.annotation().linearizedBaseContracts; diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index fc0d69729..eb8807e96 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -54,17 +54,17 @@ public: private: /// Checks that two functions defined in this contract with the same name have different /// arguments and that there is at most one constructor. - void checkContractDuplicateFunctions(ContractDefinition const& _contract); - void checkContractDuplicateEvents(ContractDefinition const& _contract); + void checkDuplicateFunctions(ContractDefinition const& _contract); + void checkDuplicateEvents(ContractDefinition const& _contract); template void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); - void checkContractIllegalOverrides(ContractDefinition const& _contract); + void checkIllegalOverrides(ContractDefinition const& _contract); /// Reports a type error with an appropriate message if overridden function signature differs. /// Also stores the direct super function in the AST annotations. void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super); void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message); - void checkContractAbstractFunctions(ContractDefinition const& _contract); - void checkContractBaseConstructorArguments(ContractDefinition const& _contract); + void checkAbstractFunctions(ContractDefinition const& _contract); + void checkBaseConstructorArguments(ContractDefinition const& _contract); void annotateBaseConstructorArguments( ContractDefinition const& _currentContract, FunctionDefinition const* _baseConstructor, From 2a85152463e3990d4695978613efddbcebe29b5b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:26:53 +0100 Subject: [PATCH 145/168] Move constructor checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 20 +++++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 1 + libsolidity/analysis/TypeChecker.cpp | 16 --------------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 0ddb198f5..879903de1 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -40,6 +40,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkIllegalOverrides(_contract); checkAbstractFunctions(_contract); checkBaseConstructorArguments(_contract); + checkConstructor(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -339,3 +340,22 @@ void ContractLevelChecker::annotateBaseConstructorArguments( } } + +void ContractLevelChecker::checkConstructor(ContractDefinition const& _contract) +{ + FunctionDefinition const* constructor = _contract.constructor(); + if (!constructor) + return; + + if (!constructor->returnParameters().empty()) + m_errorReporter.typeError(constructor->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor."); + if (constructor->stateMutability() != StateMutability::NonPayable && constructor->stateMutability() != StateMutability::Payable) + m_errorReporter.typeError( + constructor->location(), + "Constructor must be payable or non-payable, but is \"" + + stateMutabilityToString(constructor->stateMutability()) + + "\"." + ); + if (constructor->visibility() != FunctionDefinition::Visibility::Public && constructor->visibility() != FunctionDefinition::Visibility::Internal) + m_errorReporter.typeError(constructor->location(), "Constructor must be public or internal."); +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index eb8807e96..003cfbfd9 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -70,6 +70,7 @@ private: FunctionDefinition const* _baseConstructor, ASTNode const* _argumentNode ); + void checkConstructor(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3572943b5..1f88c8ab4 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -90,22 +90,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.baseContracts(), *this); - FunctionDefinition const* function = _contract.constructor(); - if (function) - { - if (!function->returnParameters().empty()) - m_errorReporter.typeError(function->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor."); - if (function->stateMutability() != StateMutability::NonPayable && function->stateMutability() != StateMutability::Payable) - m_errorReporter.typeError( - function->location(), - "Constructor must be payable or non-payable, but is \"" + - stateMutabilityToString(function->stateMutability()) + - "\"." - ); - if (function->visibility() != FunctionDefinition::Visibility::Public && function->visibility() != FunctionDefinition::Visibility::Internal) - m_errorReporter.typeError(function->location(), "Constructor must be public or internal."); - } - for (FunctionDefinition const* function: _contract.definedFunctions()) if (function->isFallback()) { From 4f4f623273052de6ede71bae2696f2388f1aa713 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:29:51 +0100 Subject: [PATCH 146/168] Move fallback function checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 24 +++++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 1 + libsolidity/analysis/TypeChecker.cpp | 20 ---------------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 879903de1..dd08e1814 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -41,6 +41,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkAbstractFunctions(_contract); checkBaseConstructorArguments(_contract); checkConstructor(_contract); + checkFallbackFunction(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -359,3 +360,26 @@ void ContractLevelChecker::checkConstructor(ContractDefinition const& _contract) if (constructor->visibility() != FunctionDefinition::Visibility::Public && constructor->visibility() != FunctionDefinition::Visibility::Internal) m_errorReporter.typeError(constructor->location(), "Constructor must be public or internal."); } + +void ContractLevelChecker::checkFallbackFunction(ContractDefinition const& _contract) +{ + FunctionDefinition const* fallback = _contract.fallbackFunction(); + if (!fallback) + return; + + if (_contract.isLibrary()) + m_errorReporter.typeError(fallback->location(), "Libraries cannot have fallback functions."); + if (fallback->stateMutability() != StateMutability::NonPayable && fallback->stateMutability() != StateMutability::Payable) + m_errorReporter.typeError( + fallback->location(), + "Fallback function must be payable or non-payable, but is \"" + + stateMutabilityToString(fallback->stateMutability()) + + "\"." + ); + if (!fallback->parameters().empty()) + m_errorReporter.typeError(fallback->parameterList().location(), "Fallback function cannot take parameters."); + if (!fallback->returnParameters().empty()) + m_errorReporter.typeError(fallback->returnParameterList()->location(), "Fallback function cannot return values."); + if (fallback->visibility() != FunctionDefinition::Visibility::External) + m_errorReporter.typeError(fallback->location(), "Fallback function must be defined as \"external\"."); +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 003cfbfd9..d6b2808bc 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -71,6 +71,7 @@ private: ASTNode const* _argumentNode ); void checkConstructor(ContractDefinition const& _contract); + void checkFallbackFunction(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1f88c8ab4..1dcb6e65d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -90,26 +90,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.baseContracts(), *this); - for (FunctionDefinition const* function: _contract.definedFunctions()) - if (function->isFallback()) - { - if (_contract.isLibrary()) - m_errorReporter.typeError(function->location(), "Libraries cannot have fallback functions."); - if (function->stateMutability() != StateMutability::NonPayable && function->stateMutability() != StateMutability::Payable) - m_errorReporter.typeError( - function->location(), - "Fallback function must be payable or non-payable, but is \"" + - stateMutabilityToString(function->stateMutability()) + - "\"." - ); - if (!function->parameters().empty()) - m_errorReporter.typeError(function->parameterList().location(), "Fallback function cannot take parameters."); - if (!function->returnParameters().empty()) - m_errorReporter.typeError(function->returnParameterList()->location(), "Fallback function cannot return values."); - if (function->visibility() != FunctionDefinition::Visibility::External) - m_errorReporter.typeError(function->location(), "Fallback function must be defined as \"external\"."); - } - for (auto const& n: _contract.subNodes()) n->accept(*this); From 6d1644e55c03850341e6bfcc4ae46f8de264a039 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:32:06 +0100 Subject: [PATCH 147/168] Move external type clash check. --- libsolidity/analysis/ContractLevelChecker.cpp | 37 +++++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 3 ++ libsolidity/analysis/TypeChecker.cpp | 37 ------------------- libsolidity/analysis/TypeChecker.h | 3 -- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index dd08e1814..e2208f3fb 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -42,6 +42,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkBaseConstructorArguments(_contract); checkConstructor(_contract); checkFallbackFunction(_contract); + checkExternalTypeClashes(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -383,3 +384,39 @@ void ContractLevelChecker::checkFallbackFunction(ContractDefinition const& _cont if (fallback->visibility() != FunctionDefinition::Visibility::External) m_errorReporter.typeError(fallback->location(), "Fallback function must be defined as \"external\"."); } + +void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _contract) +{ + map>> externalDeclarations; + for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) + { + for (FunctionDefinition const* f: contract->definedFunctions()) + if (f->isPartOfExternalInterface()) + { + auto functionType = make_shared(*f); + // under non error circumstances this should be true + if (functionType->interfaceFunctionType()) + externalDeclarations[functionType->externalSignature()].push_back( + make_pair(f, functionType->asCallableFunction(false)) + ); + } + for (VariableDeclaration const* v: contract->stateVariables()) + if (v->isPartOfExternalInterface()) + { + auto functionType = make_shared(*v); + // under non error circumstances this should be true + if (functionType->interfaceFunctionType()) + externalDeclarations[functionType->externalSignature()].push_back( + make_pair(v, functionType->asCallableFunction(false)) + ); + } + } + for (auto const& it: externalDeclarations) + for (size_t i = 0; i < it.second.size(); ++i) + for (size_t j = i + 1; j < it.second.size(); ++j) + if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second)) + m_errorReporter.typeError( + it.second[j].first->location(), + "Function overload clash during conversion to external types for arguments." + ); +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index d6b2808bc..ef1486171 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -72,6 +72,9 @@ private: ); void checkConstructor(ContractDefinition const& _contract); void checkFallbackFunction(ContractDefinition const& _contract); + /// Checks that different functions with external visibility end up having different + /// external argument types (i.e. different signature). + void checkExternalTypeClashes(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1dcb6e65d..d107d2dcc 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -93,7 +93,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) for (auto const& n: _contract.subNodes()) n->accept(*this); - checkContractExternalTypeClashes(_contract); // check for hash collisions in function signatures set> hashes; for (auto const& it: _contract.interfaceFunctionList()) @@ -113,42 +112,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) return false; } -void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _contract) -{ - map>> externalDeclarations; - for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts) - { - for (FunctionDefinition const* f: contract->definedFunctions()) - if (f->isPartOfExternalInterface()) - { - auto functionType = make_shared(*f); - // under non error circumstances this should be true - if (functionType->interfaceFunctionType()) - externalDeclarations[functionType->externalSignature()].push_back( - make_pair(f, functionType->asCallableFunction(false)) - ); - } - for (VariableDeclaration const* v: contract->stateVariables()) - if (v->isPartOfExternalInterface()) - { - auto functionType = make_shared(*v); - // under non error circumstances this should be true - if (functionType->interfaceFunctionType()) - externalDeclarations[functionType->externalSignature()].push_back( - make_pair(v, functionType->asCallableFunction(false)) - ); - } - } - for (auto const& it: externalDeclarations) - for (size_t i = 0; i < it.second.size(); ++i) - for (size_t j = i + 1; j < it.second.size(); ++j) - if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second)) - m_errorReporter.typeError( - it.second[j].first->location(), - "Function overload clash during conversion to external types for arguments." - ); -} - void TypeChecker::checkLibraryRequirements(ContractDefinition const& _contract) { solAssert(_contract.isLibrary(), ""); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index d5ccb2631..aabda33cb 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,9 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - /// Checks that different functions with external visibility end up having different - /// external argument types (i.e. different signature). - void checkContractExternalTypeClashes(ContractDefinition const& _contract); /// Checks that all requirements for a library are fulfilled if this is a library. void checkLibraryRequirements(ContractDefinition const& _contract); /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. From 4f992298c6381b3c7ea41462bce749850b5846e5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:33:54 +0100 Subject: [PATCH 148/168] Move hash collisions checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 16 ++++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 2 ++ libsolidity/analysis/TypeChecker.cpp | 13 ------------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index e2208f3fb..419ebe93f 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -43,6 +43,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkConstructor(_contract); checkFallbackFunction(_contract); checkExternalTypeClashes(_contract); + checkHashCollisions(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -420,3 +421,18 @@ void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _c "Function overload clash during conversion to external types for arguments." ); } + +void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contract) +{ + set> hashes; + for (auto const& it: _contract.interfaceFunctionList()) + { + FixedHash<4> const& hash = it.first; + if (hashes.count(hash)) + m_errorReporter.typeError( + _contract.location(), + string("Function signature hash collision for ") + it.second->externalSignature() + ); + hashes.insert(hash); + } +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index ef1486171..f930fb60d 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -75,6 +75,8 @@ private: /// Checks that different functions with external visibility end up having different /// external argument types (i.e. different signature). void checkExternalTypeClashes(ContractDefinition const& _contract); + /// Checks for hash collisions in external function signatures. + void checkHashCollisions(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d107d2dcc..e411609cd 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -93,19 +93,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) for (auto const& n: _contract.subNodes()) n->accept(*this); - // check for hash collisions in function signatures - set> hashes; - for (auto const& it: _contract.interfaceFunctionList()) - { - FixedHash<4> const& hash = it.first; - if (hashes.count(hash)) - m_errorReporter.typeError( - _contract.location(), - string("Function signature hash collision for ") + it.second->externalSignature() - ); - hashes.insert(hash); - } - if (_contract.isLibrary()) checkLibraryRequirements(_contract); From 33d6a24c47f4cfd95e8bb880d5254fb7dd6ea21a Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:36:26 +0100 Subject: [PATCH 149/168] Move library related checks. --- libsolidity/analysis/ContractLevelChecker.cpp | 14 ++++++++++++++ libsolidity/analysis/ContractLevelChecker.h | 2 ++ libsolidity/analysis/TypeChecker.cpp | 14 -------------- libsolidity/analysis/TypeChecker.h | 2 -- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 419ebe93f..58dcfe4d6 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -44,6 +44,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkFallbackFunction(_contract); checkExternalTypeClashes(_contract); checkHashCollisions(_contract); + checkLibraryRequirements(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -436,3 +437,16 @@ void ContractLevelChecker::checkHashCollisions(ContractDefinition const& _contra hashes.insert(hash); } } + +void ContractLevelChecker::checkLibraryRequirements(ContractDefinition const& _contract) +{ + if (!_contract.isLibrary()) + return; + + if (!_contract.baseContracts().empty()) + m_errorReporter.typeError(_contract.location(), "Library is not allowed to inherit."); + + for (auto const& var: _contract.stateVariables()) + if (!var->isConstant()) + m_errorReporter.typeError(var->location(), "Library cannot have non-constant state variables"); +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index f930fb60d..15cbf45dc 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -77,6 +77,8 @@ private: void checkExternalTypeClashes(ContractDefinition const& _contract); /// Checks for hash collisions in external function signatures. void checkHashCollisions(ContractDefinition const& _contract); + /// Checks that all requirements for a library are fulfilled if this is a library. + void checkLibraryRequirements(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e411609cd..9350df059 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -93,23 +93,9 @@ bool TypeChecker::visit(ContractDefinition const& _contract) for (auto const& n: _contract.subNodes()) n->accept(*this); - if (_contract.isLibrary()) - checkLibraryRequirements(_contract); - return false; } -void TypeChecker::checkLibraryRequirements(ContractDefinition const& _contract) -{ - solAssert(_contract.isLibrary(), ""); - if (!_contract.baseContracts().empty()) - m_errorReporter.typeError(_contract.location(), "Library is not allowed to inherit."); - - for (auto const& var: _contract.stateVariables()) - if (!var->isConstant()) - m_errorReporter.typeError(var->location(), "Library cannot have non-constant state variables"); -} - void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment) { TupleType const& lhs = dynamic_cast(*type(_assignment.leftHandSide())); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index aabda33cb..ebfcdadce 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,8 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - /// Checks that all requirements for a library are fulfilled if this is a library. - void checkLibraryRequirements(ContractDefinition const& _contract); /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. /// Should only be called if the left hand side is tuple-typed. void checkDoubleStorageAssignment(Assignment const& _assignment); From 17a703f71ac842253e9948dff488cd675e568c1b Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 30 Nov 2018 16:29:44 +0100 Subject: [PATCH 150/168] Changelog entry. --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 1c3fcde46..630801e48 100644 --- a/Changelog.md +++ b/Changelog.md @@ -24,6 +24,8 @@ Bugfixes: * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. * Type Checker: Fix internal compiler error when a field of a struct used as a parameter in a function type has a non-existent type. * Type Checker: Disallow functions ``sha3`` and ``suicide`` also without a function call. + * Type Checker: Fixed internal error when trying to create abstract contract in some cases. + * Type Checker: Fixed internal error related to double declaration of events. * Type Checker: Disallow inline arrays of mapping type. Build System: From c48a5264be4221873fe02cac57f6a41a32010fea Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 28 Nov 2018 16:19:22 +0100 Subject: [PATCH 151/168] liblangutil: SourceLocation: adds (shared) pointer to underlying CharStream source, eliminating sourceName Also, adapted affecting code to those changes. --- libevmasm/Assembly.cpp | 10 ++-- liblangutil/ParserBase.cpp | 4 +- liblangutil/ParserBase.h | 2 +- liblangutil/Scanner.cpp | 51 +++++++++++--------- liblangutil/Scanner.h | 25 +++++----- liblangutil/SourceLocation.h | 34 ++++++++----- liblangutil/SourceReferenceFormatter.cpp | 10 ++-- libsolidity/analysis/NameAndTypeResolver.cpp | 6 +-- libsolidity/ast/ASTJsonConverter.cpp | 4 +- libsolidity/interface/CompilerStack.cpp | 8 +-- libsolidity/interface/StandardCompiler.cpp | 4 +- libsolidity/parsing/Parser.cpp | 4 +- libyul/AsmParser.h | 6 +-- test/libevmasm/Assembler.cpp | 6 ++- test/libevmasm/Optimiser.cpp | 2 +- test/liblangutil/SourceLocation.cpp | 14 ++++-- test/libsolidity/Assembly.cpp | 39 ++++++++------- 17 files changed, 127 insertions(+), 102 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index d80f97c43..29d9846d4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -114,10 +114,10 @@ namespace string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) { - if (_location.isEmpty() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0) + if (_location.isEmpty() || !_location.source.get() || _sourceCodes.empty() || _location.start >= _location.end || _location.start < 0) return ""; - auto it = _sourceCodes.find(*_location.sourceName); + auto it = _sourceCodes.find(_location.source->name()); if (it == _sourceCodes.end()) return ""; @@ -186,11 +186,11 @@ public: void printLocation() { - if (!m_location.sourceName && m_location.isEmpty()) + if (!m_location.source && m_location.isEmpty()) return; m_out << m_prefix << " /*"; - if (m_location.sourceName) - m_out << " \"" + *m_location.sourceName + "\""; + if (m_location.source) + m_out << " \"" + m_location.source->name() + "\""; if (!m_location.isEmpty()) m_out << ":" << to_string(m_location.start) + ":" + to_string(m_location.end); m_out << " " << locationFromSources(m_sourceCodes, m_location); diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index 8156f9b9a..c103475a7 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -105,10 +105,10 @@ void ParserBase::decreaseRecursionDepth() void ParserBase::parserError(string const& _description) { - m_errorReporter.parserError(SourceLocation(position(), endPosition(), sourceName()), _description); + m_errorReporter.parserError(SourceLocation(position(), endPosition(), source()), _description); } void ParserBase::fatalParserError(string const& _description) { - m_errorReporter.fatalParserError(SourceLocation(position(), endPosition(), sourceName()), _description); + m_errorReporter.fatalParserError(SourceLocation(position(), endPosition(), source()), _description); } diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 0007da63d..f6315351e 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -39,7 +39,7 @@ public: explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {} std::shared_ptr const& sourceName() const; - CharStream const* charStream() const { return &m_scanner->charStream(); } + std::shared_ptr source() const { return m_scanner->charStream(); } protected: /// Utility class that creates an error and throws an exception if the diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 215171b3f..5c0f356e5 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -169,15 +169,22 @@ private: void Scanner::reset(CharStream _source, string _sourceName) { - m_source = std::move(_source); + m_source = make_shared(std::move(_source)); m_sourceName = make_shared(std::move(_sourceName)); reset(); } +void Scanner::reset(std::shared_ptr _source) +{ + solAssert(_source.get() != nullptr, "You MUST provide a CharStream when resetting."); + m_source = _source; + reset(); +} + void Scanner::reset() { - m_source.reset(); - m_char = m_source.get(); + m_source->reset(); + m_char = m_source->get(); skipWhitespace(); scanToken(); next(); @@ -296,13 +303,13 @@ Token Scanner::scanSingleLineDocComment() { // check if next line is also a documentation comment skipWhitespace(); - if (!m_source.isPastEndOfInput(3) && - m_source.get(0) == '/' && - m_source.get(1) == '/' && - m_source.get(2) == '/') + if (!m_source->isPastEndOfInput(3) && + m_source->get(0) == '/' && + m_source->get(1) == '/' && + m_source->get(2) == '/') { addCommentLiteralChar('\n'); - m_char = m_source.advanceAndGet(3); + m_char = m_source->advanceAndGet(3); } else break; // next line is not a documentation comment, we are done @@ -355,20 +362,20 @@ Token Scanner::scanMultiLineDocComment() if (isLineTerminator(m_char)) { skipWhitespace(); - if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '*') + if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) == '*') { // it is unknown if this leads to the end of the comment addCommentLiteralChar('*'); advance(); } - else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/') + else if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) != '/') { // skip first '*' in subsequent lines if (charsAdded) addCommentLiteralChar('\n'); - m_char = m_source.advanceAndGet(2); + m_char = m_source->advanceAndGet(2); } - else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') + else if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) == '/') { // if after newline the comment ends, don't insert the newline - m_char = m_source.advanceAndGet(2); + m_char = m_source->advanceAndGet(2); endFound = true; break; } @@ -376,9 +383,9 @@ Token Scanner::scanMultiLineDocComment() addCommentLiteralChar('\n'); } - if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/') + if (!m_source->isPastEndOfInput(1) && m_source->get(0) == '*' && m_source->get(1) == '/') { - m_char = m_source.advanceAndGet(2); + m_char = m_source->advanceAndGet(2); endFound = true; break; } @@ -715,11 +722,11 @@ bool Scanner::isUnicodeLinebreak() if (0x0a <= m_char && m_char <= 0x0d) // line feed, vertical tab, form feed, carriage return return true; - else if (!m_source.isPastEndOfInput(1) && uint8_t(m_source.get(0)) == 0xc2 && uint8_t(m_source.get(1)) == 0x85) + else if (!m_source->isPastEndOfInput(1) && uint8_t(m_source->get(0)) == 0xc2 && uint8_t(m_source->get(1)) == 0x85) // NEL - U+0085, C2 85 in utf8 return true; - else if (!m_source.isPastEndOfInput(2) && uint8_t(m_source.get(0)) == 0xe2 && uint8_t(m_source.get(1)) == 0x80 && ( - uint8_t(m_source.get(2)) == 0xa8 || uint8_t(m_source.get(2)) == 0xa9 + else if (!m_source->isPastEndOfInput(2) && uint8_t(m_source->get(0)) == 0xe2 && uint8_t(m_source->get(1)) == 0x80 && ( + uint8_t(m_source->get(2)) == 0xa8 || uint8_t(m_source->get(2)) == 0xa9 )) // LS - U+2028, E2 80 A8 in utf8 // PS - U+2029, E2 80 A9 in utf8 @@ -783,7 +790,7 @@ void Scanner::scanDecimalDigits() // May continue with decimal digit or underscore for grouping. do addLiteralCharAndAdvance(); - while (!m_source.isPastEndOfInput() && (isDecimalDigit(m_char) || m_char == '_')); + while (!m_source->isPastEndOfInput() && (isDecimalDigit(m_char) || m_char == '_')); // Defer further validation of underscore to SyntaxChecker. } @@ -829,7 +836,7 @@ Token Scanner::scanNumber(char _charSeen) scanDecimalDigits(); // optional if (m_char == '.') { - if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') + if (!m_source->isPastEndOfInput(1) && m_source->get(1) == '_') { // Assume the input may be a floating point number with leading '_' in fraction part. // Recover by consuming it all but returning `Illegal` right away. @@ -837,7 +844,7 @@ Token Scanner::scanNumber(char _charSeen) addLiteralCharAndAdvance(); // '_' scanDecimalDigits(); } - if (m_source.isPastEndOfInput() || !isDecimalDigit(m_source.get(1))) + if (m_source->isPastEndOfInput() || !isDecimalDigit(m_source->get(1))) { // A '.' has to be followed by a number. literal.complete(); @@ -854,7 +861,7 @@ Token Scanner::scanNumber(char _charSeen) solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number"); if (kind != DECIMAL) return setError(ScannerError::IllegalExponent); - else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_') + else if (!m_source->isPastEndOfInput(1) && m_source->get(1) == '_') { // Recover from wrongly placed underscore as delimiter in literal with scientific // notation by consuming until the end. diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index 9c29edfd4..dc37745fc 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -90,14 +90,16 @@ class Scanner { friend class LiteralScope; public: + explicit Scanner(std::shared_ptr _source) { reset(std::move(_source)); } explicit Scanner(CharStream _source = CharStream(), std::string _sourceName = "") { reset(std::move(_source), std::move(_sourceName)); } - std::string source() const { return m_source.source(); } + std::string source() const { return m_source->source(); } - CharStream const& charStream() const noexcept { return m_source; } + std::shared_ptr charStream() noexcept { return m_source; } /// Resets the scanner as if newly constructed with _source and _sourceName as input. void reset(CharStream _source, std::string _sourceName); + void reset(std::shared_ptr _source); /// Resets scanner to the start of input. void reset(); @@ -154,14 +156,13 @@ public: ///@name Error printing helper functions /// Functions that help pretty-printing parse errors /// Do only use in error cases, they are quite expensive. - std::string lineAtPosition(int _position) const { return m_source.lineAtPosition(_position); } - std::tuple translatePositionToLineColumn(int _position) const { return m_source.translatePositionToLineColumn(_position); } + std::string lineAtPosition(int _position) const { return m_source->lineAtPosition(_position); } + std::tuple translatePositionToLineColumn(int _position) const { return m_source->translatePositionToLineColumn(_position); } std::string sourceAt(SourceLocation const& _location) const { solAssert(!_location.isEmpty(), ""); - solAssert(m_sourceName && _location.sourceName, ""); - solAssert(*m_sourceName == *_location.sourceName, ""); - return m_source.source().substr(_location.start, _location.end - _location.start); + solAssert(m_source.get() == _location.source.get(), "CharStream memory locations must match."); + return m_source->source().substr(_location.start, _location.end - _location.start); } ///@} @@ -190,8 +191,8 @@ private: void addUnicodeAsUTF8(unsigned codepoint); ///@} - bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); } - void rollback(int _amount) { m_char = m_source.rollback(_amount); } + bool advance() { m_char = m_source->advanceAndGet(); return !m_source->isPastEndOfInput(); } + void rollback(int _amount) { m_char = m_source->rollback(_amount); } inline Token selectErrorToken(ScannerError _err) { advance(); return setError(_err); } inline Token selectToken(Token _tok) { advance(); return _tok; } @@ -231,8 +232,8 @@ private: bool isUnicodeLinebreak(); /// Return the current source position. - int sourcePos() const { return m_source.position(); } - bool isSourcePastEndOfInput() const { return m_source.isPastEndOfInput(); } + int sourcePos() const { return m_source->position(); } + bool isSourcePastEndOfInput() const { return m_source->isPastEndOfInput(); } TokenDesc m_skippedComment; // desc for current skipped comment TokenDesc m_nextSkippedComment; // desc for next skipped comment @@ -240,7 +241,7 @@ private: TokenDesc m_currentToken; // desc for current token (as returned by Next()) TokenDesc m_nextToken; // desc for next token (one token look-ahead) - CharStream m_source; + std::shared_ptr m_source; std::shared_ptr m_sourceName; /// one character look-ahead, equals 0 at end of input diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index eeb81e946..2dfd7123c 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -23,6 +23,7 @@ #pragma once #include // defines noexcept macro for MSVC +#include #include #include #include @@ -37,13 +38,13 @@ namespace langutil */ struct SourceLocation { - SourceLocation(): start(-1), end(-1) { } - SourceLocation(int _start, int _end, std::shared_ptr _sourceName): - start(_start), end(_end), sourceName(_sourceName) { } + SourceLocation(): start(-1), end(-1), source{nullptr} { } + SourceLocation(int _start, int _end, std::shared_ptr _source): + start(_start), end(_end), source{std::move(_source)} { } SourceLocation(SourceLocation&& _other) noexcept: start(_other.start), end(_other.end), - sourceName(std::move(_other.sourceName)) + source{std::move(_other.source)} {} SourceLocation(SourceLocation const&) = default; SourceLocation& operator=(SourceLocation const&) = default; @@ -51,14 +52,15 @@ struct SourceLocation { start = _other.start; end = _other.end; - sourceName = std::move(_other.sourceName); + source = std::move(_other.source); return *this; } bool operator==(SourceLocation const& _other) const { return start == _other.start && end == _other.end && - ((!sourceName && !_other.sourceName) || (sourceName && _other.sourceName && *sourceName == *_other.sourceName)); + ((!source.get() && !_other.source.get()) || + (source.get() && _other.source.get() && source->name() == _other.source->name())); } bool operator!=(SourceLocation const& _other) const { return !operator==(_other); } inline bool operator<(SourceLocation const& _other) const; @@ -69,7 +71,7 @@ struct SourceLocation int start; int end; - std::shared_ptr sourceName; + std::shared_ptr source; }; /// Stream output for Location (used e.g. in boost exceptions). @@ -77,27 +79,33 @@ inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _locat { if (_location.isEmpty()) return _out << "NO_LOCATION_SPECIFIED"; - return _out << *_location.sourceName << "[" << _location.start << "," << _location.end << ")"; + + if (_location.source) + _out << _location.source->name(); + + _out << "[" << _location.start << "," << _location.end << ")"; + + return _out; } bool SourceLocation::operator<(SourceLocation const& _other) const { - if (!sourceName || !_other.sourceName) - return std::make_tuple(int(!!sourceName), start, end) < std::make_tuple(int(!!_other.sourceName), _other.start, _other.end); + if (!source|| !_other.source) + return std::make_tuple(int(!!source), start, end) < std::make_tuple(int(!!_other.source), _other.start, _other.end); else - return std::make_tuple(*sourceName, start, end) < std::make_tuple(*_other.sourceName, _other.start, _other.end); + return std::make_tuple(source->name(), start, end) < std::make_tuple(_other.source->name(), _other.start, _other.end); } bool SourceLocation::contains(SourceLocation const& _other) const { - if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) + if (isEmpty() || _other.isEmpty() || ((!source || !_other.source || source->name() != _other.source->name()) && (source || _other.source))) return false; return start <= _other.start && _other.end <= end; } bool SourceLocation::intersects(SourceLocation const& _other) const { - if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName))) + if (isEmpty() || _other.isEmpty() || ((!source || !_other.source || source->name() != _other.source->name()) && (source || _other.source))) return false; return _other.start < end && start < _other.end; } diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index 58a655215..8ac05b4e9 100644 --- a/liblangutil/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -30,9 +30,9 @@ using namespace langutil; void SourceReferenceFormatter::printSourceLocation(SourceLocation const* _location) { - if (!_location || !_location->sourceName) + if (!_location || !_location->source) return; // Nothing we can print here - auto const& scanner = m_scannerFromSourceName(*_location->sourceName); + auto const& scanner = m_scannerFromSourceName(_location->source->name()); int startLine; int startColumn; tie(startLine, startColumn) = scanner.translatePositionToLineColumn(_location->start); @@ -89,13 +89,13 @@ void SourceReferenceFormatter::printSourceLocation(SourceLocation const* _locati void SourceReferenceFormatter::printSourceName(SourceLocation const* _location) { - if (!_location || !_location->sourceName) + if (!_location || !_location->source) return; // Nothing we can print here - auto const& scanner = m_scannerFromSourceName(*_location->sourceName); + auto const& scanner = m_scannerFromSourceName(_location->source->name()); int startLine; int startColumn; tie(startLine, startColumn) = scanner.translatePositionToLineColumn(_location->start); - m_stream << *_location->sourceName << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": "; + m_stream << _location->source->name() << ":" << (startLine + 1) << ":" << (startColumn + 1) << ": "; } void SourceReferenceFormatter::printExceptionInformation( diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index e40a2c973..0528a2005 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -492,9 +492,9 @@ bool DeclarationRegistrationHelper::registerDeclaration( Declaration const* conflictingDeclaration = _container.conflictingDeclaration(_declaration, _name); solAssert(conflictingDeclaration, ""); bool const comparable = - _errorLocation->sourceName && - conflictingDeclaration->location().sourceName && - *_errorLocation->sourceName == *conflictingDeclaration->location().sourceName; + _errorLocation->source && + conflictingDeclaration->location().source && + _errorLocation->source->name() == conflictingDeclaration->location().source->name(); if (comparable && _errorLocation->start < conflictingDeclaration->location().start) { firstDeclarationLocation = *_errorLocation; diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index b9054692d..cfb13271a 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -122,8 +122,8 @@ void ASTJsonConverter::setJsonNode( string ASTJsonConverter::sourceLocationToString(SourceLocation const& _location) const { int sourceIndex{-1}; - if (_location.sourceName && m_sourceIndices.count(*_location.sourceName)) - sourceIndex = m_sourceIndices.at(*_location.sourceName); + if (_location.source && m_sourceIndices.count(_location.source->name())) + sourceIndex = m_sourceIndices.at(_location.source->name()); int length = -1; if (_location.start >= 0 && _location.end >= 0) length = _location.end - _location.start; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index cc5a2102a..58229379e 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -598,8 +598,8 @@ tuple CompilerStack::positionFromSourceLocation(SourceLocati int startColumn; int endLine; int endColumn; - tie(startLine, startColumn) = scanner(*_sourceLocation.sourceName).translatePositionToLineColumn(_sourceLocation.start); - tie(endLine, endColumn) = scanner(*_sourceLocation.sourceName).translatePositionToLineColumn(_sourceLocation.end); + tie(startLine, startColumn) = scanner(_sourceLocation.source->name()).translatePositionToLineColumn(_sourceLocation.start); + tie(endLine, endColumn) = scanner(_sourceLocation.source->name()).translatePositionToLineColumn(_sourceLocation.end); return make_tuple(++startLine, ++startColumn, ++endLine, ++endColumn); } @@ -922,8 +922,8 @@ string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) con SourceLocation const& location = item.location(); int length = location.start != -1 && location.end != -1 ? location.end - location.start : -1; int sourceIndex = - location.sourceName && sourceIndicesMap.count(*location.sourceName) ? - sourceIndicesMap.at(*location.sourceName) : + location.source && sourceIndicesMap.count(location.source->name()) ? + sourceIndicesMap.at(location.source->name()) : -1; char jump = '-'; if (item.getJumpType() == eth::AssemblyItem::JumpType::IntoFunction) diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 4a32d9f34..0eef50d2f 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -85,9 +85,9 @@ Json::Value formatErrorWithException( message = _message; Json::Value sourceLocation; - if (location && location->sourceName) + if (location && location->source && location->source->name() != "") { - sourceLocation["file"] = *location->sourceName; + sourceLocation["file"] = location->source->name(); sourceLocation["start"] = location->start; sourceLocation["end"] = location->end; } diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 3f4a015b0..6cab7be3e 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -42,7 +42,7 @@ class Parser::ASTNodeFactory { public: explicit ASTNodeFactory(Parser const& _parser): - m_parser(_parser), m_location(_parser.position(), -1, _parser.sourceName()) {} + m_parser(_parser), m_location(_parser.position(), -1, _parser.source()) {} ASTNodeFactory(Parser const& _parser, ASTPointer const& _childNode): m_parser(_parser), m_location(_childNode->location()) {} @@ -55,7 +55,7 @@ public: template ASTPointer createNode(Args&& ... _args) { - solAssert(m_location.sourceName, ""); + solAssert(m_location.source, ""); if (m_location.end < 0) markEndPosition(); return make_shared(m_location, std::forward(_args)...); diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index cea3b6679..52166a200 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -56,11 +56,11 @@ protected: r.location.start = position(); r.location.end = endPosition(); } - if (!r.location.sourceName) - r.location.sourceName = sourceName(); + if (!r.location.source) + r.location.source = m_scanner->charStream(); return r; } - langutil::SourceLocation location() const { return {position(), endPosition(), sourceName()}; } + langutil::SourceLocation location() const { return {position(), endPosition(), m_scanner->charStream()}; } Block parseBlock(); Statement parseStatement(); diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index 5ad015949..bece2be47 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -55,10 +55,12 @@ BOOST_AUTO_TEST_SUITE(Assembler) BOOST_AUTO_TEST_CASE(all_assembly_items) { Assembly _assembly; - _assembly.setSourceLocation(SourceLocation(1, 3, make_shared("root.asm"))); + auto root_asm = make_shared("", "root.asm"); + _assembly.setSourceLocation(SourceLocation(1, 3, root_asm)); Assembly _subAsm; - _subAsm.setSourceLocation(SourceLocation(6, 8, make_shared("sub.asm"))); + auto sub_asm = make_shared("", "sub.asm"); + _subAsm.setSourceLocation(SourceLocation(6, 8, sub_asm)); _subAsm.append(Instruction::INVALID); shared_ptr _subAsmPtr = make_shared(_subAsm); diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index c061b7835..7d1029484 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -53,7 +53,7 @@ namespace // add dummy locations to each item so that we can check that they are not deleted AssemblyItems input = _input; for (AssemblyItem& item: input) - item.setLocation(SourceLocation(1, 3, make_shared(""))); + item.setLocation(SourceLocation(1, 3, nullptr)); return input; } diff --git a/test/liblangutil/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp index ac7a21736..ef4103daf 100644 --- a/test/liblangutil/SourceLocation.cpp +++ b/test/liblangutil/SourceLocation.cpp @@ -33,12 +33,16 @@ BOOST_AUTO_TEST_SUITE(SourceLocationTest) BOOST_AUTO_TEST_CASE(test_fail) { + auto const source = std::make_shared("", "source"); + auto const sourceA = std::make_shared("", "sourceA"); + auto const sourceB = std::make_shared("", "sourceB"); + BOOST_CHECK(SourceLocation() == SourceLocation()); - BOOST_CHECK(SourceLocation(0, 3, std::make_shared("sourceA")) != SourceLocation(0, 3, std::make_shared("sourceB"))); - BOOST_CHECK(SourceLocation(0, 3, std::make_shared("source")) == SourceLocation(0, 3, std::make_shared("source"))); - BOOST_CHECK(SourceLocation(3, 7, std::make_shared("source")).contains(SourceLocation(4, 6, std::make_shared("source")))); - BOOST_CHECK(!SourceLocation(3, 7, std::make_shared("sourceA")).contains(SourceLocation(4, 6, std::make_shared("sourceB")))); - BOOST_CHECK(SourceLocation(3, 7, std::make_shared("sourceA")) < SourceLocation(4, 6, std::make_shared("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() diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 620f9661a..004917d46 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -52,13 +52,13 @@ namespace test namespace { -eth::AssemblyItems compileContract(string const& _sourceCode) +eth::AssemblyItems compileContract(std::shared_ptr _sourceCode) { ErrorList errors; ErrorReporter errorReporter(errors); Parser parser(errorReporter); ASTPointer sourceUnit; - BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode, "")))); + BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(_sourceCode))); BOOST_CHECK(!!sourceUnit); map> scopes; @@ -104,7 +104,7 @@ void printAssemblyLocations(AssemblyItems const& _items) ", " << _loc.end << ", make_shared(\"" << - *_loc.sourceName << + _loc.source->name() << "\"))) +" << endl; }; @@ -151,29 +151,32 @@ BOOST_AUTO_TEST_SUITE(Assembly) BOOST_AUTO_TEST_CASE(location_test) { - char const* sourceCode = R"( + auto sourceCode = make_shared(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("", "--CODEGEN--"); + vector locations = - vector(hasShifts ? 21 : 22, SourceLocation(2, 82, make_shared(""))) + - vector(2, SourceLocation(20, 79, make_shared(""))) + - vector(1, SourceLocation(8, 17, make_shared("--CODEGEN--"))) + - vector(3, SourceLocation(5, 7, make_shared("--CODEGEN--"))) + - vector(1, SourceLocation(30, 31, make_shared("--CODEGEN--"))) + - vector(1, SourceLocation(27, 28, make_shared("--CODEGEN--"))) + - vector(1, SourceLocation(20, 32, make_shared("--CODEGEN--"))) + - vector(1, SourceLocation(5, 7, make_shared("--CODEGEN--"))) + - vector(24, SourceLocation(20, 79, make_shared(""))) + - vector(1, SourceLocation(49, 58, make_shared(""))) + - vector(1, SourceLocation(72, 74, make_shared(""))) + - vector(2, SourceLocation(65, 74, make_shared(""))) + - vector(2, SourceLocation(20, 79, make_shared(""))); + vector(hasShifts ? 21 : 22, SourceLocation(2, 82, sourceCode)) + + vector(2, SourceLocation(20, 79, sourceCode)) + + vector(1, SourceLocation(8, 17, codegenCharStream)) + + vector(3, SourceLocation(5, 7, codegenCharStream)) + + vector(1, SourceLocation(30, 31, codegenCharStream)) + + vector(1, SourceLocation(27, 28, codegenCharStream)) + + vector(1, SourceLocation(20, 32, codegenCharStream)) + + vector(1, SourceLocation(5, 7, codegenCharStream)) + + vector(24, SourceLocation(20, 79, sourceCode)) + + vector(1, SourceLocation(49, 58, sourceCode)) + + vector(1, SourceLocation(72, 74, sourceCode)) + + vector(2, SourceLocation(65, 74, sourceCode)) + + vector(2, SourceLocation(20, 79, sourceCode)); checkAssemblyLocations(items, locations); } From 435f7b3b72157e884344adbc7b62033bd08bb51c Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Thu, 29 Nov 2018 01:58:15 +0100 Subject: [PATCH 152/168] liblangutil: Scanner: remove superfluous sourceName field (it's in CharStream already) Also, ParserBase::sourceName() was dead code. Eliminating it should increase test coverage (how sneaky) :-) --- liblangutil/ParserBase.cpp | 5 ----- liblangutil/ParserBase.h | 1 - liblangutil/Scanner.cpp | 3 +-- liblangutil/Scanner.h | 9 +++----- libsolidity/codegen/CompilerContext.cpp | 2 +- libsolidity/interface/AssemblyStack.cpp | 2 +- libsolidity/interface/CompilerStack.cpp | 4 ++-- test/libsolidity/SolidityScanner.cpp | 28 ++++++++++++------------- test/libyul/Common.cpp | 2 +- test/libyul/YulOptimizerTest.cpp | 2 +- test/tools/yulopti.cpp | 2 +- 11 files changed, 25 insertions(+), 35 deletions(-) diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index c103475a7..391af2911 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -27,11 +27,6 @@ using namespace std; using namespace langutil; -std::shared_ptr const& ParserBase::sourceName() const -{ - return m_scanner->sourceName(); -} - int ParserBase::position() const { return m_scanner->currentLocation().start; diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index f6315351e..855201e22 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -38,7 +38,6 @@ class ParserBase public: explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {} - std::shared_ptr const& sourceName() const; std::shared_ptr source() const { return m_scanner->charStream(); } protected: diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 5c0f356e5..ac298bd5d 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -167,10 +167,9 @@ private: }; // end of LiteralScope class -void Scanner::reset(CharStream _source, string _sourceName) +void Scanner::reset(CharStream _source) { m_source = make_shared(std::move(_source)); - m_sourceName = make_shared(std::move(_sourceName)); reset(); } diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index dc37745fc..a11853690 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -91,14 +91,14 @@ class Scanner friend class LiteralScope; public: explicit Scanner(std::shared_ptr _source) { reset(std::move(_source)); } - explicit Scanner(CharStream _source = CharStream(), std::string _sourceName = "") { reset(std::move(_source), std::move(_sourceName)); } + explicit Scanner(CharStream _source = CharStream()) { reset(std::move(_source)); } std::string source() const { return m_source->source(); } std::shared_ptr charStream() noexcept { return m_source; } - /// Resets the scanner as if newly constructed with _source and _sourceName as input. - void reset(CharStream _source, std::string _sourceName); + /// Resets the scanner as if newly constructed with _source as input. + void reset(CharStream _source); void reset(std::shared_ptr _source); /// Resets scanner to the start of input. void reset(); @@ -150,8 +150,6 @@ public: std::string const& peekLiteral() const { return m_nextToken.literal; } ///@} - std::shared_ptr const& sourceName() const { return m_sourceName; } - ///@{ ///@name Error printing helper functions /// Functions that help pretty-printing parse errors @@ -242,7 +240,6 @@ private: TokenDesc m_nextToken; // desc for next token (one token look-ahead) std::shared_ptr m_source; - std::shared_ptr m_sourceName; /// one character look-ahead, equals 0 at end of input char m_char; diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 16bc42254..5a3a233ca 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -360,7 +360,7 @@ void CompilerContext::appendInlineAssembly( ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared(langutil::CharStream(_assembly, "--CODEGEN--"), "--CODEGEN--"); + auto scanner = make_shared(langutil::CharStream(_assembly, "--CODEGEN--")); auto parserResult = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); #ifdef SOL_OUTPUT_ASM cout << yul::AsmPrinter()(*parserResult) << endl; diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 5268c5aaa..66ba42ee2 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -69,7 +69,7 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string { m_errors.clear(); m_analysisSuccessful = false; - m_scanner = make_shared(CharStream(_source, _sourceName), _sourceName); + m_scanner = make_shared(CharStream(_source, _sourceName)); m_parserResult = yul::ObjectParser(m_errorReporter, languageToAsmFlavour(m_language)).parse(m_scanner, false); if (!m_errorReporter.errors().empty()) return false; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 58229379e..534073f1c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -125,7 +125,7 @@ bool CompilerStack::addSource(string const& _name, string const& _content, bool { bool existed = m_sources.count(_name) != 0; reset(true); - m_sources[_name].scanner = make_shared(CharStream(_content, _name), _name); + m_sources[_name].scanner = make_shared(CharStream(_content, _name)); m_sources[_name].isLibrary = _isLibrary; m_stackState = SourcesSet; return existed; @@ -160,7 +160,7 @@ bool CompilerStack::parse() { string const& newPath = newSource.first; string const& newContents = newSource.second; - m_sources[newPath].scanner = make_shared(CharStream(newContents, newPath), newPath); + m_sources[newPath].scanner = make_shared(CharStream(newContents, newPath)); sourcesToParse.push_back(newPath); } } diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 95d565683..5ce4eda2a 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -107,10 +107,10 @@ 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); } @@ -118,17 +118,17 @@ BOOST_AUTO_TEST_CASE(octal_numbers) { 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); } @@ -149,16 +149,16 @@ BOOST_AUTO_TEST_CASE(trailing_dot) 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); @@ -180,7 +180,7 @@ BOOST_AUTO_TEST_CASE(leading_underscore_decimal_after_dot_illegal) 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); } @@ -225,11 +225,11 @@ BOOST_AUTO_TEST_CASE(number_literals_with_trailing_underscore_at_eos) 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); } diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 36065db79..a247a1698 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -57,7 +57,7 @@ pair, shared_ptr> yul::test::parse(strin auto flavour = _yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); - auto scanner = make_shared(CharStream(_source, ""), ""); + auto scanner = make_shared(CharStream(_source, "")); auto parserResult = yul::Parser(errorReporter, flavour).parse(scanner, false); if (parserResult) { diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 8f282aaca..15d70faaf 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -259,7 +259,7 @@ bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool c yul::AsmFlavour flavour = m_yul ? yul::AsmFlavour::Yul : yul::AsmFlavour::Strict; ErrorList errors; ErrorReporter errorReporter(errors); - shared_ptr scanner = make_shared(CharStream(m_source, ""), ""); + shared_ptr scanner = make_shared(CharStream(m_source, "")); m_ast = yul::Parser(errorReporter, flavour).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 8ecafb29a..5273bbb94 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -81,7 +81,7 @@ public: bool parse(string const& _input) { ErrorReporter errorReporter(m_errors); - shared_ptr scanner = make_shared(CharStream(_input, ""), ""); + shared_ptr scanner = make_shared(CharStream(_input, "")); m_ast = yul::Parser(errorReporter, yul::AsmFlavour::Strict).parse(scanner, false); if (!m_ast || !errorReporter.errors().empty()) { From 18e3d6dbca1250cdc36119c3da8328338fe9f1f6 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 30 Nov 2018 13:34:44 +0100 Subject: [PATCH 153/168] liblangutil: small refactors wrt. API cleanups Especially also remove SourceLocation ctor's that the compiler can default-implement. --- liblangutil/CharStream.h | 2 +- liblangutil/Scanner.h | 2 +- liblangutil/SourceLocation.h | 14 -------------- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/liblangutil/CharStream.h b/liblangutil/CharStream.h index 6f2da3bbe..f92beb30a 100644 --- a/liblangutil/CharStream.h +++ b/liblangutil/CharStream.h @@ -80,7 +80,7 @@ public: void reset() { m_position = 0; } - std::string const& source() const { return m_source; } + std::string const& source() const noexcept { return m_source; } std::string const& name() const noexcept { return m_name; } ///@{ diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index a11853690..72d0072f5 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -93,7 +93,7 @@ public: explicit Scanner(std::shared_ptr _source) { reset(std::move(_source)); } explicit Scanner(CharStream _source = CharStream()) { reset(std::move(_source)); } - std::string source() const { return m_source->source(); } + std::string const& source() const noexcept { return m_source->source(); } std::shared_ptr charStream() noexcept { return m_source; } diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index 2dfd7123c..732a32e1c 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -41,20 +41,6 @@ struct SourceLocation SourceLocation(): start(-1), end(-1), source{nullptr} { } SourceLocation(int _start, int _end, std::shared_ptr _source): start(_start), end(_end), source{std::move(_source)} { } - SourceLocation(SourceLocation&& _other) noexcept: - start(_other.start), - end(_other.end), - source{std::move(_other.source)} - {} - SourceLocation(SourceLocation const&) = default; - SourceLocation& operator=(SourceLocation const&) = default; - SourceLocation& operator=(SourceLocation&& _other) noexcept - { - start = _other.start; - end = _other.end; - source = std::move(_other.source); - return *this; - } bool operator==(SourceLocation const& _other) const { From 757623e381aba24b81a2365cf19037d3d96bf945 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Fri, 30 Nov 2018 17:34:54 +0100 Subject: [PATCH 154/168] liblangutil: SourceLocation: Retricts == and != operator --- liblangutil/SourceLocation.h | 8 +++----- test/libsolidity/Assembly.cpp | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index 732a32e1c..2d18a7d1b 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -44,9 +44,7 @@ struct SourceLocation bool operator==(SourceLocation const& _other) const { - return start == _other.start && end == _other.end && - ((!source.get() && !_other.source.get()) || - (source.get() && _other.source.get() && source->name() == _other.source->name())); + return source.get() == _other.source.get() && start == _other.start && end == _other.end; } bool operator!=(SourceLocation const& _other) const { return !operator==(_other); } inline bool operator<(SourceLocation const& _other) const; @@ -84,14 +82,14 @@ bool SourceLocation::operator<(SourceLocation const& _other) const bool SourceLocation::contains(SourceLocation const& _other) const { - if (isEmpty() || _other.isEmpty() || ((!source || !_other.source || source->name() != _other.source->name()) && (source || _other.source))) + if (isEmpty() || _other.isEmpty() || source.get() != _other.source.get()) return false; return start <= _other.start && _other.end <= end; } bool SourceLocation::intersects(SourceLocation const& _other) const { - if (isEmpty() || _other.isEmpty() || ((!source || !_other.source || source->name() != _other.source->name()) && (source || _other.source))) + if (isEmpty() || _other.isEmpty() || source.get() != _other.source.get()) return false; return _other.start < end && start < _other.end; } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 004917d46..aa10147cb 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -135,7 +135,8 @@ void checkAssemblyLocations(AssemblyItems const& _items, vector 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); From 436696d3b647ccf1b7fed4edbf86c7cd37950839 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 29 Nov 2018 18:55:27 +0100 Subject: [PATCH 155/168] Update assembly grammar part. --- docs/grammar.txt | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/docs/grammar.txt b/docs/grammar.txt index b9c8ddb9b..3d2c9bc37 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -72,7 +72,7 @@ WhileStatement = 'while' '(' Expression ')' Statement PlaceholderStatement = '_' SimpleStatement = VariableDefinition | ExpressionStatement ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement -InlineAssemblyStatement = 'assembly' StringLiteral? InlineAssemblyBlock +InlineAssemblyStatement = 'assembly' StringLiteral? AssemblyBlock DoWhileStatement = 'do' Statement 'while' '(' Expression ')' Continue = 'continue' Break = 'break' @@ -152,11 +152,30 @@ Fixed = 'fixed' | ( 'fixed' [0-9]+ 'x' [0-9]+ ) Ufixed = 'ufixed' | ( 'ufixed' [0-9]+ 'x' [0-9]+ ) -InlineAssemblyBlock = '{' AssemblyItem* '}' -AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyVariableDeclaration | AssemblyAssignment | AssemblyLabel | NumberLiteral | StringLiteral | HexLiteral -AssemblyExpression = Identifier | FunctionalAssemblyExpression | NumberLiteral | StringLiteral | HexLiteral -AssemblyVariableDeclaration = 'let' Identifier ':=' AssemblyExpression -AssemblyAssignment = ( Identifier ':=' AssemblyExpression ) | ( '=:' Identifier ) -AssemblyLabel = Identifier ':' -FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')' +AssemblyBlock = '{' AssemblyStatement* '}' + +AssemblyStatement = AssemblyBlock + | AssemblyFunctionDefinition + | AssemblyVariableDeclaration + | AssemblyAssignment + | AssemblyIf + | AssemblyExpression + | AssemblySwitch + | AssemblyForLoop + | AssemblyBreakContinue +AssemblyFunctionDefinition = + 'function' Identifier '(' AssemblyIdentifierList? ')' + ( '->' AssemblyIdentifierList )? AssemblyBlock +AssemblyVariableDeclaration = 'let' AssemblyIdentifierList ( ':=' AssemblyExpression )? +AssemblyAssignment = AssemblyIdentifierList ':=' AssemblyExpression +AssemblyExpression = AssemblyFunctionCall | Identifier | Literal +AssemblyIf = 'if' AssemblyExpression AssemblyBlock +AssemblySwitch = 'switch' AssemblyExpression ( Case+ AssemblyDefault? | AssemblyDefault ) +AssemblyCase = 'case' Literal AssemblyBlock +AssemblyDefault = 'default' AssemblyBlock +AssemblyForLoop = 'for' AssemblyBlock AssemblyExpression AssemblyBlock AssemblyBlock +AssemblyBreakContinue = 'break' | 'continue' +AssemblyFunctionCall = Identifier '(' ( AssemblyExpression ( ',' AssemblyExpression )* )? ')' + +AssemblyIdentifierList = Identifier ( ',' Identifier )* From 6c44c5f0c93d6ce623bec773cc151a73d4b12bff Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 3 Nov 2018 16:05:08 +0100 Subject: [PATCH 156/168] Apply the optimize commandline parameter to assembly mode. --- Changelog.md | 1 + libsolidity/interface/AssemblyStack.cpp | 9 +++++++++ libsolidity/interface/AssemblyStack.h | 3 +++ solc/CommandLineInterface.cpp | 25 ++++++++++++++++++++----- solc/CommandLineInterface.h | 2 +- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/Changelog.md b/Changelog.md index 630801e48..a80bb1c95 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Language Features: Compiler Features: * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. + * Commandline interface: Experimental ``--optimize`` option for assembly mode. * SMTChecker: SMTLib2 queries and responses passed via standard JSON compiler interface. * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index 24e190b3b..f361c5da6 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -34,6 +34,8 @@ #include +#include + using namespace std; using namespace dev; using namespace langutil; @@ -79,6 +81,13 @@ bool AssemblyStack::parseAndAnalyze(std::string const& _sourceName, std::string return analyzeParsed(); } +void AssemblyStack::optimize() +{ + solAssert(m_language != Language::Assembly, "Optimization requested for loose assembly."); + yul::OptimiserSuite::run(*m_parserResult->code, *m_parserResult->analysisInfo); + solAssert(analyzeParsed(), "Invalid source code after optimization."); +} + bool AssemblyStack::analyzeParsed() { solAssert(m_parserResult, ""); diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index 7ae0592e1..0d04ffec9 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -69,6 +69,9 @@ public: /// Multiple calls overwrite the previous state. bool parseAndAnalyze(std::string const& _sourceName, std::string const& _source); + /// Run the optimizer suite. Can only be used with Yul or strict assembly. + void optimize(); + /// Run the assembly step (should only be called after parseAndAnalyze). MachineAssemblyObject assemble(Machine _machine) const; diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index e2baca7f5..38e778c63 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -626,15 +626,15 @@ Allowed options)", ) ( g_argAssemble.c_str(), - "Switch to assembly mode, ignoring all options except --machine and assumes input is assembly." + "Switch to assembly mode, ignoring all options except --machine and --optimize and assumes input is assembly." ) ( g_argYul.c_str(), - "Switch to Yul mode, ignoring all options except --machine and assumes input is Yul." + "Switch to Yul mode, ignoring all options except --machine and --optimize and assumes input is Yul." ) ( g_argStrictAssembly.c_str(), - "Switch to strict assembly mode, ignoring all options except --machine and assumes input is strict assembly." + "Switch to strict assembly mode, ignoring all options except --machine and --optimize and assumes input is strict assembly." ) ( g_argMachine.c_str(), @@ -820,6 +820,7 @@ bool CommandLineInterface::processInput() using Machine = AssemblyStack::Machine; Input inputLanguage = m_args.count(g_argYul) ? Input::Yul : (m_args.count(g_argStrictAssembly) ? Input::StrictAssembly : Input::Assembly); Machine targetMachine = Machine::EVM; + bool optimize = m_args.count(g_argOptimize); if (m_args.count(g_argMachine)) { string machine = m_args[g_argMachine].as(); @@ -835,7 +836,18 @@ bool CommandLineInterface::processInput() return false; } } - return assemble(inputLanguage, targetMachine); + if (optimize && inputLanguage == Input::Assembly) + { + serr() << + "Optimizer cannot be used for loose assembly. Use --" << + g_strStrictAssembly << + " or --" << + g_strYul << + "." << + endl; + return false; + } + return assemble(inputLanguage, targetMachine, optimize); } if (m_args.count(g_argLink)) { @@ -1179,7 +1191,8 @@ string CommandLineInterface::objectWithLinkRefsHex(eth::LinkerObject const& _obj bool CommandLineInterface::assemble( AssemblyStack::Language _language, - AssemblyStack::Machine _targetMachine + AssemblyStack::Machine _targetMachine, + bool _optimize ) { bool successful = true; @@ -1191,6 +1204,8 @@ bool CommandLineInterface::assemble( { if (!stack.parseAndAnalyze(src.first, src.second)) successful = false; + else if (_optimize) + stack.optimize(); } catch (Exception const& _exception) { diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 8dc003709..0b22ca298 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -59,7 +59,7 @@ private: /// @returns the full object with library placeholder hints in hex. static std::string objectWithLinkRefsHex(eth::LinkerObject const& _obj); - bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine); + bool assemble(AssemblyStack::Language _language, AssemblyStack::Machine _targetMachine, bool _optimize); void outputCompilationResults(); From 0d1b9c3b1bbfcc4ca61d35049f1c3624681dbb13 Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Wed, 21 Nov 2018 18:10:56 +0100 Subject: [PATCH 157/168] Adds tests for --optimize in assembly mode. --- test/cmdlineTests.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 4838d088b..9dfbe409b 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -262,10 +262,19 @@ 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 +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 + echo '{}' | "$SOLC" - --yul --optimize &>/dev/null + echo '{}' | "$SOLC" - --strict-assembly --optimize &>/dev/null +) + printTask "Testing standard input..." SOLTMPDIR=$(mktemp -d) From 1cdcdcee656c080b8c6f9e2631bcc2a3c35fb13b Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Thu, 29 Nov 2018 15:56:51 +0100 Subject: [PATCH 158/168] Improves assembly output commandline tests. --- test/cmdlineTests.sh | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 9dfbe409b..fdc9fbe30 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -262,6 +262,25 @@ SOLTMPDIR=$(mktemp -d) ) rm -rf "$SOLTMPDIR" +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 @@ -271,8 +290,15 @@ printTask "Testing assemble, yul, strict-assembly and optimize..." # Test options above in conjunction with --optimize. # Using both, --assemble and --optimize should fail. ! echo '{}' | "$SOLC" - --assemble --optimize &>/dev/null - echo '{}' | "$SOLC" - --yul --optimize &>/dev/null - echo '{}' | "$SOLC" - --strict-assembly --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" ) From 4a907faf44b5ca899a316c4646df97b351060423 Mon Sep 17 00:00:00 2001 From: Robert Chung Date: Sat, 1 Dec 2018 21:32:13 -0800 Subject: [PATCH 159/168] Added information about debugging and examples on how to run subsets of tests. --- docs/contributing.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index 4ac93565a..f9c4d9d98 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -98,6 +98,20 @@ To run a subset of tests, you can use filters: ``./scripts/soltest.sh -t TestSuite/TestName --ipcpath /tmp/testeth/geth.ipc``, where ``TestName`` can be a wildcard ``*``. +For example, here's an example test you might run; +``./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-ipc --no-smt``. +This will test all the tests for the disambiguator. + +If you want to debug using GDB, make sure you build differently than the "usual". +For example, you could run the following command in your ``build`` folder: +:: + + cmake -DCMAKE_BUILD_TYPE=Debug .. + make + +This will create symbols such that when you debug a test using the ``--debug`` flag, you will have acecess to functions and varialbes in which you can break or print with. + + The script ``./scripts/tests.sh`` also runs commandline tests and compilation tests in addition to those found in ``soltest``. From 98a07797713d4eaa2141827a4e26ada0493482a5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 3 Dec 2018 08:26:56 +0100 Subject: [PATCH 160/168] Explain how to get a list of all tests. --- docs/contributing.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index f9c4d9d98..43b2fd38d 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -102,6 +102,9 @@ For example, here's an example test you might run; ``./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-ipc --no-smt``. This will test all the tests for the disambiguator. +To get a list of all tests, use +``./build/test/soltest --list_content=HRF -- --ipcpath /tmp/irrelevant``. + If you want to debug using GDB, make sure you build differently than the "usual". For example, you could run the following command in your ``build`` folder: :: From 32c3f6c817b864907fb758b0615c2659c33919f9 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Fri, 30 Nov 2018 10:27:18 +0100 Subject: [PATCH 161/168] Add link between functions in contract structure and more details Fix missing label --- docs/contracts.rst | 2 ++ docs/structure-of-a-contract.rst | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index d6337d9a0..984194302 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -485,6 +485,8 @@ value types and strings. Functions ********* +.. _function-parameters-return-variables: + Function Parameters and Return Variables ======================================== diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 582e53381..569639e0b 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -56,7 +56,8 @@ Functions are the executable units of code within a contract. :ref:`function-calls` can happen internally or externally and have different levels of :ref:`visibility` -towards other contracts. +towards other contracts. :ref:`Functions` accept :ref:`parameters and return variables` to pass parameters +and values between them. .. _structure-function-modifiers: From 6d41ffb4a5e9f08ac63bd0303eacfb5351d1fb84 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Mon, 3 Dec 2018 10:35:38 +0100 Subject: [PATCH 162/168] [SMTChecker] Remove unary plus operator --- libsolidity/formal/SMTChecker.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 477568a0a..ebb09f0a9 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -323,9 +323,6 @@ void SMTChecker::endVisit(UnaryOperation const& _op) ); break; } - case Token::Add: // + - defineExpr(_op, expr(_op.subExpression())); - break; case Token::Sub: // - { defineExpr(_op, 0 - expr(_op.subExpression())); From bbe0268163b95c147df1cc894ea8f9e8211a7930 Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Mon, 12 Nov 2018 12:06:59 +0100 Subject: [PATCH 163/168] Add mapping guide to style docs thanks to @aupiff --- docs/style-guide.rst | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 7b48ccada..68fee871e 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -809,7 +809,23 @@ possible permutations for function declarations. Mappings ======== -TODO +In variable declarations, do not separate the keyword ``mapping`` from its +type by a space. Do not separate any nested ``mapping`` keyword from its type by +whitespace. + +Yes:: + + mapping(uint => uint) map; + mapping(address => bool) registeredAddresses; + mapping(uint => mapping(bool => Data[])) public data; + mapping(uint => mapping(uint => s)) data; + +No:: + + mapping (uint => uint) map; + mapping( address => bool ) registeredAddresses; + mapping (uint => mapping (bool => Data[])) public data; + mapping(uint => mapping (uint => s)) data; Variable Declarations ===================== From 0668a9ecfb60ab0e00bfb2c4a4a97ce523860832 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sat, 1 Dec 2018 00:08:42 +0100 Subject: [PATCH 164/168] Public state variables are implementing external functions. --- Changelog.md | 1 + libsolidity/analysis/ContractLevelChecker.cpp | 53 +++++++++++-------- ...implement_interface_by_public_variable.sol | 7 +++ ...t_internal_function_by_public_variable.sol | 9 ++++ ...nt_private_function_by_public_variable.sol | 7 +++ ...ent_public_function_by_public_variable.sol | 9 ++++ .../override/state_variable_function.sol | 1 + 7 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol diff --git a/Changelog.md b/Changelog.md index 630801e48..7aa5a6be6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -27,6 +27,7 @@ Bugfixes: * Type Checker: Fixed internal error when trying to create abstract contract in some cases. * Type Checker: Fixed internal error related to double declaration of events. * Type Checker: Disallow inline arrays of mapping type. + * Type Checker: Consider abstract function to be implemented by public state variable. Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 58dcfe4d6..6dc564de0 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -219,29 +219,40 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con using FunTypeAndFlag = std::pair; map> functions; - // Search from base to derived - for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) - for (FunctionDefinition const* function: contract->definedFunctions()) + auto registerFunction = [&](Declaration const& _declaration, FunctionTypePointer const& _type, bool _implemented) + { + auto& overloads = functions[_declaration.name()]; + auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) { - // Take constructors out of overload hierarchy - if (function->isConstructor()) - continue; - auto& overloads = functions[function->name()]; - FunctionTypePointer funType = make_shared(*function)->asCallableFunction(false); - auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) - { - return funType->hasEqualParameterTypes(*_funAndFlag.first); - }); - if (it == overloads.end()) - overloads.push_back(make_pair(funType, function->isImplemented())); - else if (it->second) - { - if (!function->isImplemented()) - m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract"); - } - else if (function->isImplemented()) - it->second = true; + return _type->hasEqualParameterTypes(*_funAndFlag.first); + }); + if (it == overloads.end()) + overloads.push_back(make_pair(_type, _implemented)); + else if (it->second) + { + if (!_implemented) + m_errorReporter.typeError(_declaration.location(), "Redeclaring an already implemented function as abstract"); } + else if (_implemented) + it->second = true; + }; + + // Search from base to derived, collect all functions and update + // the 'implemented' flag. + for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) + { + for (VariableDeclaration const* v: contract->stateVariables()) + if (v->isPartOfExternalInterface()) + registerFunction(*v, make_shared(*v), true); + + for (FunctionDefinition const* function: contract->definedFunctions()) + if (!function->isConstructor()) + registerFunction( + *function, + make_shared(*function)->asCallableFunction(false), + function->isImplemented() + ); + } // Set to not fully implemented if at least one flag is false. for (auto const& it: functions) 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 000000000..49f7c33b2 --- /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 000000000..32fac25c8 --- /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 000000000..c58e24b68 --- /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 000000000..7a59c1371 --- /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/state_variable_function.sol b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol index 0f05cc8eb..fb7f3fbdd 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 From 78ca2801d8a63769bbd8cff5948c4b92d693d11c Mon Sep 17 00:00:00 2001 From: Chris Ward Date: Thu, 15 Nov 2018 11:59:37 +0100 Subject: [PATCH 165/168] Move String literal and inline array FAQ items Fix tab Update docs/types.rst Co-Authored-By: ChrisChinchilla Update docs/types.rst Co-Authored-By: ChrisChinchilla --- docs/frequently-asked-questions.rst | 40 ----------------------------- docs/types.rst | 35 +++++++++++++------------ 2 files changed, 19 insertions(+), 56 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index bcdfdcd83..f3c5b1f79 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -38,24 +38,6 @@ has it (which includes `Remix `_), then ``contractname.kill.sendTransaction({from:eth.coinbase})``, just the same as my examples. -Is it possible to in-line initialize an array like so: ``string[] myarray = ["a", "b"];`` -========================================================================================= - -Yes. However it should be noted that this currently only works with statically sized memory arrays. You can even create an inline memory -array in the return statement. - -Example:: - - pragma solidity >=0.4.16 <0.6.0; - - contract C { - function f() public pure returns (uint8[5] memory) { - string[4] memory adaArr = ["This", "is", "an", "array"]; - adaArr[0] = "That"; - return [1, 2, 3, 4, 5]; - } - } - If I return an ``enum``, I only get integer values in web3.js. How to get the named values? =========================================================================================== @@ -217,28 +199,6 @@ In this example:: } } -What is the relationship between ``bytes32`` and ``string``? Why is it that ``bytes32 somevar = "stringliteral";`` works and what does the saved 32-byte hex value mean? -======================================================================================================================================================================== - -The type ``bytes32`` can hold 32 (raw) bytes. In the assignment ``bytes32 samevar = "stringliteral";``, -the string literal is interpreted in its raw byte form and if you inspect ``somevar`` and -see a 32-byte hex value, this is just ``"stringliteral"`` in hex. - -The type ``bytes`` is similar, only that it can change its length. - -Finally, ``string`` is basically identical to ``bytes`` only that it is assumed -to hold the UTF-8 encoding of a real string. Since ``string`` stores the -data in UTF-8 encoding it is quite expensive to compute the number of -characters in the string (the encoding of some characters takes more -than a single byte). Because of that, ``string s; s.length`` is not yet -supported and not even index access ``s[2]``. But if you want to access -the low-level byte encoding of the string, you can use -``bytes(s).length`` and ``bytes(s)[2]`` which will result in the number -of bytes in the UTF-8 encoding of the string (not the number of -characters) and the second byte (not character) of the UTF-8 encoded -string, respectively. - - Can a contract pass an array (static size) or string or ``bytes`` (dynamic size) to another contract? ===================================================================================================== diff --git a/docs/types.rst b/docs/types.rst index 69c846a66..f67a6d1a2 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -465,11 +465,13 @@ a non-rational number). .. index:: literal, literal;string, string .. _string_literals: -String Literals ---------------- +String Literals and Types +------------------------- String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; ``"foo"`` represents three bytes, not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``. +For example, with ``bytes32 samevar = "stringliteral"`` the string literal is interpreted in its raw byte form when assigned to a ``bytes32`` type. + String literals support the following escape characters: - ``\`` (escapes an actual newline) @@ -862,13 +864,20 @@ or create a new memory array and copy every element. } } -.. index:: ! array;literals, !inline;arrays +.. index:: ! array;literals, ! inline;arrays -Array Literals / Inline Arrays -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Array Literals +^^^^^^^^^^^^^^ -Array literals are arrays that are written as an expression and are not -assigned to a variable right away. +An array literal is a comma-separated list of one or more expressions, enclosed +in square brackets (``[...]``). For example ``[1, a, f(3)]``. There must be a +common type all elements can be implicitly converted to. This is the elementary +type of the array. + +Array literals are always statically-sized memory arrays. + +In the example below, the type of ``[1, 2, 3]`` is +``uint8[3] memory``. Because the type of each of these constants is ``uint8``, if you want the result to be a ``uint[3] memory`` type, you need to convert the first element to ``uint``. :: @@ -883,13 +892,7 @@ assigned to a variable right away. } } -The type of an array literal is a memory array of fixed size whose base -type is the common type of the given elements. The type of ``[1, 2, 3]`` is -``uint8[3] memory``, because the type of each of these constants is ``uint8``. -Because of that, it is necessary to convert the first element in the example -above to ``uint``. Note that currently, fixed size memory arrays cannot -be assigned to dynamically-sized memory arrays, i.e. the following is not -possible: +Fixed size memory arrays cannot be assigned to dynamically-sized memory arrays, i.e. the following is not possible: :: @@ -904,8 +907,8 @@ possible: } } -It is planned to remove this restriction in the future but currently creates -some complications because of how arrays are passed in the ABI. +It is planned to remove this restriction in the future, but it creates some +complications because of how arrays are passed in the ABI. .. index:: ! array;length, length, push, pop, !array;push, !array;pop From 82f5763e7afa498f891e9d41b30278c4482ddb8b Mon Sep 17 00:00:00 2001 From: Anurag Dashputre Date: Sat, 1 Dec 2018 22:50:56 +0530 Subject: [PATCH 166/168] Fix internal compiler error for unimplemented base contract function. --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 3 ++- .../syntaxTests/unimplemented_super_function.sol | 8 ++++++++ .../unimplemented_super_function_derived.sol | 12 ++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/unimplemented_super_function.sol create mode 100644 test/libsolidity/syntaxTests/unimplemented_super_function_derived.sol diff --git a/Changelog.md b/Changelog.md index 72d51bff9..5df412ca8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -25,6 +25,7 @@ Bugfixes: * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. * Type Checker: Fix internal compiler error when a field of a struct used as a parameter in a function type has a non-existent type. * Type Checker: Disallow functions ``sha3`` and ``suicide`` also without a function call. + * Type Checker: Fix internal compiler error with ``super`` when base contract function is not implemented. * Type Checker: Fixed internal error when trying to create abstract contract in some cases. * Type Checker: Fixed internal error related to double declaration of events. * Type Checker: Disallow inline arrays of mapping type. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 16e9cf892..6cadb5f33 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1943,8 +1943,9 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con for (ContractDefinition const* base: bases | boost::adaptors::sliced(1, bases.size())) for (FunctionDefinition const* function: base->definedFunctions()) { - if (!function->isVisibleInDerivedContracts()) + if (!function->isVisibleInDerivedContracts() || !function->isImplemented()) continue; + auto functionType = make_shared(*function, true); bool functionWithEqualArgumentsFound = false; for (auto const& member: members) diff --git a/test/libsolidity/syntaxTests/unimplemented_super_function.sol b/test/libsolidity/syntaxTests/unimplemented_super_function.sol new file mode 100644 index 000000000..356727ae4 --- /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 000000000..88acbdf0d --- /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. From 1502449b85ebbdfa169932d4bb3ad1aae5133ee0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 3 Dec 2018 12:30:08 +0100 Subject: [PATCH 167/168] Add solc-js changes. --- Changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 72d51bff9..6c28a204d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,7 +14,6 @@ Compiler Features: * SMTChecker: Support internal bound function calls. * Yul: Support Yul objects in ``--assemble`` and ``--yul`` commandline options. - Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. * Commandline interface: Fix crash when using ``--ast`` on empty runtime code. @@ -34,6 +33,9 @@ Build System: * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. * Docker: Includes both Scratch and Alpine images. +Solc-Js: + * Fix handling of standard-json in the commandline executable. + * Remove support of nodejs 4. ### 0.5.0 (2018-11-13) From 8d623dcca1c6806adbe4fba9de9e790eaba8c4a4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 3 Dec 2018 12:50:40 +0100 Subject: [PATCH 168/168] Massage changelog for 0.5.1 --- Changelog.md | 10 +++++----- docs/bugs_by_version.json | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 1f60ece7d..a53cca7e4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,18 +1,17 @@ -### 0.5.1 (unreleased) +### 0.5.1 (2018-12-03) Language Features: * Allow mapping type for parameters and return variables of public and external library functions. * Allow public functions to override external functions. Compiler Features: - * Build System: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. - * Commandline interface: Experimental ``--optimize`` option for assembly mode. + * Commandline interface: Experimental ``--optimize`` option for assembly mode (``--strict-assembly`` and ``--yul``). * SMTChecker: SMTLib2 queries and responses passed via standard JSON compiler interface. * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. * SMTChecker: Support internal bound function calls. - * Yul: Support Yul objects in ``--assemble`` and ``--yul`` commandline options. + * Yul: Support Yul objects in ``--assemble``, ``--strict-assembly`` and ``--yul`` commandline options. Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. @@ -31,8 +30,9 @@ Bugfixes: * Type Checker: Consider abstract function to be implemented by public state variable. Build System: - * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. + * CMake: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Docker: Includes both Scratch and Alpine images. + * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. Solc-Js: * Fix handling of standard-json in the commandline executable. diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 2631b2867..658aab9c1 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -612,5 +612,9 @@ "0.5.0": { "bugs": [], "released": "2018-11-13" + }, + "0.5.1": { + "bugs": [], + "released": "2018-12-03" } } \ No newline at end of file