diff --git a/.circleci/config.yml b/.circleci/config.yml index 5157f06615f0..4a48caf546b3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,18 +7,21 @@ # - ems: Emscripten version: 2.1 parameters: - ubuntu-1804-docker-image-rev: + ubuntu-1804-docker-image: type: string - default: "4" - ubuntu-2004-docker-image-rev: + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:4484ac3da8fdc337cc77a7a7be1af71cd0f28f9c890d934f1d6ae7532beb66b1" + ubuntu-2004-docker-image: type: string - default: "2" - ubuntu-2004-clang-docker-image-rev: + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:48b5bb6b91ac7dddfe9345c88876ebed126c652258800f114caed69db73b29bf" + ubuntu-2004-clang-docker-image: type: string - default: "2" - ubuntu-1604-clang-ossfuzz-docker-image-rev: + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:d8775de58167db5a11690fdb6ef639317fe1e579ec5d46e9732d2d903b55d135" + ubuntu-1604-clang-ossfuzz-docker-image: type: string - default: "2" + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:db52f3257396814215744a19904e42c07e040ab36b68be72a27ba71ad2f1083c" + emscripten-docker-image: + type: string + default: "solbuildpackpusher/solidity-buildpack-deps@sha256:d557d015918c3cf68b0d22839bab41013f0757b651a7fef21595f89721dbebcc" defaults: @@ -33,26 +36,11 @@ defaults: - run_build: &run_build name: Build - command: | - set -ex - if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" -o -n "$FORCE_RELEASE" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi - echo -n "$CIRCLE_SHA1" > commit_hash.txt - 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=${CMAKE_BUILD_TYPE:-Release} $CMAKE_OPTIONS -G "Unix Makefiles" - make -j4 + command: scripts/ci/build.sh - run_build_ossfuzz: &run_build_ossfuzz name: Build_ossfuzz - command: | - mkdir -p build - cd build - protoc --proto_path=../test/tools/ossfuzz yulProto.proto --cpp_out=../test/tools/ossfuzz - protoc --proto_path=../test/tools/ossfuzz abiV2Proto.proto --cpp_out=../test/tools/ossfuzz - protoc --proto_path=../test/tools/ossfuzz solProto.proto --cpp_out=../test/tools/ossfuzz - cmake .. -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} $CMAKE_OPTIONS - make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j4 + command: scripts/ci/build_ossfuzz.sh - run_proofs: &run_proofs name: Correctness proofs for optimization rules @@ -97,6 +85,7 @@ defaults: - test/tools/ossfuzz/strictasm_diff_ossfuzz - test/tools/ossfuzz/strictasm_opt_ossfuzz - test/tools/ossfuzz/yul_proto_diff_ossfuzz + - test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz - test/tools/ossfuzz/yul_proto_ossfuzz - test/tools/ossfuzz/sol_proto_ossfuzz @@ -130,7 +119,7 @@ defaults: - test_ubuntu1604_clang: &test_ubuntu1604_clang docker: - - image: ethereum/solidity-buildpack-deps:ubuntu1604-clang-ossfuzz-<< pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >> steps: - checkout - attach_workspace: @@ -141,7 +130,7 @@ defaults: - test_ubuntu2004_clang: &test_ubuntu2004_clang docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-clang-<< pipeline.parameters.ubuntu-2004-clang-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >> steps: - checkout - attach_workspace: @@ -152,7 +141,8 @@ defaults: - test_ubuntu2004: &test_ubuntu2004 docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-<< pipeline.parameters.ubuntu-2004-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-docker-image >> + parallelism: 6 steps: - checkout - attach_workspace: @@ -387,7 +377,7 @@ jobs: chk_docs_pragma_min_version: docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-<< pipeline.parameters.ubuntu-2004-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-docker-image >> environment: TERM: xterm steps: @@ -396,7 +386,7 @@ jobs: b_ubu_clang: &build_ubuntu2004_clang docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-clang-<< pipeline.parameters.ubuntu-2004-clang-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >> environment: CC: clang CXX: clang++ @@ -409,7 +399,7 @@ jobs: b_ubu_asan_clang: &build_ubuntu2004_clang docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-clang-<< pipeline.parameters.ubuntu-2004-clang-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-clang-docker-image >> environment: CC: clang CXX: clang++ @@ -421,8 +411,11 @@ jobs: - persist_to_workspace: *artifacts_executables b_ubu: &build_ubuntu2004 + resource_class: xlarge docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-<< pipeline.parameters.ubuntu-2004-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-docker-image >> + environment: + MAKEFLAGS: -j 10 steps: - checkout - run: *run_build @@ -437,7 +430,7 @@ jobs: b_ubu18: &build_ubuntu1804 docker: - - image: ethereum/solidity-buildpack-deps:ubuntu1804-<< pipeline.parameters.ubuntu-1804-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-1804-docker-image >> environment: CMAKE_OPTIONS: -DCMAKE_CXX_FLAGS=-O2 CMAKE_BUILD_TYPE: RelWithDebugInfo @@ -491,7 +484,7 @@ jobs: b_ubu_ossfuzz: &build_ubuntu1604_clang docker: - - image: ethereum/solidity-buildpack-deps:ubuntu1604-clang-ossfuzz-<< pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-1604-clang-ossfuzz-docker-image >> environment: CC: clang CXX: clang++ @@ -597,9 +590,11 @@ jobs: - store_artifacts: *artifacts_test_results b_ems: + resource_class: xlarge docker: - - image: ethereum/solidity-buildpack-deps:emsdk-1.39.15-2 + - image: << pipeline.parameters.emscripten-docker-image >> environment: + MAKEFLAGS: -j 10 TERM: xterm steps: - checkout @@ -633,7 +628,7 @@ jobs: b_docs: docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-<< pipeline.parameters.ubuntu-2004-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-docker-image >> steps: - checkout - run: *setup_prerelease_commit_hash @@ -649,7 +644,7 @@ jobs: t_ubu_soltest_enforce_yul: &t_ubu_soltest_enforce_yul docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-<< pipeline.parameters.ubuntu-2004-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-docker-image >> environment: EVM: constantinople SOLTEST_FLAGS: --enforce-via-yul @@ -675,7 +670,7 @@ jobs: t_ubu_cli: &t_ubu_cli docker: - - image: ethereum/solidity-buildpack-deps:ubuntu2004-<< pipeline.parameters.ubuntu-2004-docker-image-rev >> + - image: << pipeline.parameters.ubuntu-2004-docker-image >> environment: TERM: xterm steps: diff --git a/.circleci/soltest.sh b/.circleci/soltest.sh index f55239e60362..41ab71875026 100755 --- a/.circleci/soltest.sh +++ b/.circleci/soltest.sh @@ -54,7 +54,7 @@ get_logfile_basename() { echo -ne "${filename}" } -BOOST_TEST_ARGS="--color_output=no --show_progress=yes --logger=JUNIT,error,test_results/`get_logfile_basename`.xml" +BOOST_TEST_ARGS="--color_output=no --show_progress=yes --logger=JUNIT,error,test_results/`get_logfile_basename`.xml ${BOOST_TEST_ARGS}" SOLTEST_ARGS="--evm-version=$EVM $SOLTEST_FLAGS" test "${OPTIMIZE}" = "1" && SOLTEST_ARGS="${SOLTEST_ARGS} --optimize" test "${ABI_ENCODER_V2}" = "1" && SOLTEST_ARGS="${SOLTEST_ARGS} --abiencoderv2" diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 74b3f1197935..7b1fb053bd69 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -28,10 +28,49 @@ set -e REPODIR="$(realpath $(dirname $0)/..)" -for OPTIMIZE in 0 1; do - for EVM in homestead byzantium constantinople petersburg istanbul; do - EVM=$EVM OPTIMIZE=$OPTIMIZE ${REPODIR}/.circleci/soltest.sh +EVM_VALUES=(homestead byzantium constantinople petersburg istanbul) +OPTIMIZE_VALUES=(0 1) +STEPS=$(( 1 + ${#EVM_VALUES[@]} * ${#OPTIMIZE_VALUES[@]} )) + +if (( $CIRCLE_NODE_TOTAL )) && (( $CIRCLE_NODE_TOTAL > 1 )) +then + # Run step 1 as the only step on the first executor + # and evenly distribute the other steps among + # the other executors. + # The first step takes much longer than the other steps. + if (( $CIRCLE_NODE_INDEX == 0 )) + then + RUN_STEPS="1" + else + export CIRCLE_NODE_INDEX=$(($CIRCLE_NODE_INDEX - 1)) + export CIRCLE_NODE_TOTAL=$(($CIRCLE_NODE_TOTAL - 1)) + RUN_STEPS=$(seq 2 "$STEPS" | circleci tests split) + fi +else + RUN_STEPS=$(seq "$STEPS") +fi + +# turn newlines into spaces +RUN_STEPS=$(echo $RUN_STEPS) + +echo "Running steps $RUN_STEPS..." + +STEP=1 + +[[ " $RUN_STEPS " =~ " $STEP " ]] && EVM=istanbul OPTIMIZE=1 ABI_ENCODER_V2=1 "${REPODIR}/.circleci/soltest.sh" +STEP=$(($STEP + 1)) + +for OPTIMIZE in ${OPTIMIZE_VALUES[@]} +do + for EVM in ${EVM_VALUES[@]} + do + [[ " $RUN_STEPS " =~ " $STEP " ]] && EVM="$EVM" OPTIMIZE="$OPTIMIZE" BOOST_TEST_ARGS="-t !@nooptions" "${REPODIR}/.circleci/soltest.sh" + STEP=$(($STEP + 1)) done done -EVM=istanbul OPTIMIZE=1 ABI_ENCODER_V2=1 ${REPODIR}/.circleci/soltest.sh +if (($STEP != $STEPS + 1)) +then + echo "Step counter not properly adjusted!" >2 + exit 1 +fi diff --git a/.github/workflows/buildpack-deps.yml b/.github/workflows/buildpack-deps.yml new file mode 100644 index 000000000000..2e2ea547fc54 --- /dev/null +++ b/.github/workflows/buildpack-deps.yml @@ -0,0 +1,43 @@ +name: buildpack-deps + +on: + pull_request: + branches: [ develop ] + paths: + - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu1804' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang' + - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2004' + +jobs: + buildpack-deps: + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKER_REPOSITORY: solbuildpackpusher/solidity-buildpack-deps + IMAGE_NAME: buildpack-deps + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + image_variant: [emscripten, ubuntu1604.clang.ossfuzz, ubuntu1804, ubuntu2004.clang, ubuntu2004] + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Upgrade ${{ env.IMAGE_NAME }}-${{ matrix.image_variant }} + run: | + echo ${DOCKERHUB_TOKEN} | docker login -u solbuildpackpusher --password-stdin + scripts/ci/docker_upgrade.sh ${{ env.IMAGE_NAME }} ${{ matrix.image_variant }} ${{ env.DOCKER_REPOSITORY }} + docker logout + + - name: comment PR + if: "env.DOCKER_IMAGE" + uses: aarlt/comment-on-pr@v1.2.0 + with: + msg: "`${{ env.DOCKER_IMAGE }} ${{ env.DOCKER_REPO_DIGEST }}`." \ No newline at end of file diff --git a/.gitignore b/.gitignore index f6eeba75fffa..749860301975 100644 --- a/.gitignore +++ b/.gitignore @@ -32,10 +32,10 @@ prerelease.txt # Build directory build/ -build*/ +/build*/ emscripten_build/ docs/_build -docs/utils/__pycache__ +__pycache__ docs/utils/*.pyc /deps/downloads/ deps/install diff --git a/.travis.yml b/.travis.yml index ef7832777448..3d00a974de7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,7 @@ env: - SOLC_TESTS=On - SOLC_STOREBYTECODE=Off - SOLC_DOCKER=Off + - MAKEFLAGS="-j 4" matrix: include: @@ -112,7 +113,7 @@ matrix: before_install: - nvm install 10 - nvm use 10 - - docker pull ethereum/solidity-buildpack-deps:emsdk-1.39.15-2 + - docker pull solbuildpackpusher/solidity-buildpack-deps@sha256:d557d015918c3cf68b0d22839bab41013f0757b651a7fef21595f89721dbebcc env: - SOLC_EMSCRIPTEN=On - SOLC_INSTALL_DEPS_TRAVIS=Off diff --git a/CMakeLists.txt b/CMakeLists.txt index 3374ff09d57f..18949721e62b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.6.11") +set(PROJECT_VERSION "0.6.12") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/Changelog.md b/Changelog.md index 5c52d5e65e90..79cbf3e109cc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,32 @@ +### 0.6.12 (2020-07-22) + +Language Features: + * NatSpec: Implement tag ``@inheritdoc`` to copy documentation from a specific base contract. + * Wasm backend: Add ``i32.ctz``, ``i64.ctz``, ``i32.popcnt``, and ``i64.popcnt``. + + +Compiler Features: + * Code Generator: Avoid double cleanup when copying to memory. + * Code Generator: Evaluate ``keccak256`` of string literals at compile-time. + * Optimizer: Add rule to remove shifts inside the byte opcode. + * Peephole Optimizer: Add rule to remove swap after dup. + * Peephole Optimizer: Remove unnecessary masking of tags. + * Yul EVM Code Transform: Free stack slots directly after visiting the right-hand-side of variable declarations instead of at the end of the statement only. + + +Bugfixes: + * SMTChecker: Fix error in events with indices of type static array. + * SMTChecker: Fix internal error in sequential storage array pushes (``push().push()``). + * SMTChecker: Fix internal error when using bitwise operators on fixed bytes type. + * SMTChecker: Fix internal error when using compound bitwise operator assignments on array indices inside branches. + * Type Checker: Fix internal compiler error related to oversized types. + * Type Checker: Fix overload resolution in combination with ``{value: ...}``. + + +Build System: + * Update internal dependency of jsoncpp to 1.9.3. + + ### 0.6.11 (2020-07-07) Language Features: diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index 1f7600d9b141..3bcdad47bec7 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -50,6 +50,7 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA add_compile_options(-pedantic) add_compile_options(-Wno-unknown-pragmas) add_compile_options(-Wimplicit-fallthrough) + add_compile_options(-Wsign-conversion) # Configuration-specific compiler settings. set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -DETH_DEBUG") diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index 1377041b9a69..80a16f8d57c8 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -37,15 +37,16 @@ endif() ExternalProject_Add(jsoncpp-project PREFIX "${prefix}" DOWNLOAD_DIR "${CMAKE_SOURCE_DIR}/deps/downloads" - DOWNLOAD_NAME jsoncpp-1.9.2.tar.gz - URL https://github.com/open-source-parsers/jsoncpp/archive/1.9.2.tar.gz - URL_HASH SHA256=77a402fb577b2e0e5d0bdc1cf9c65278915cdb25171e3452c68b6da8a561f8f0 + DOWNLOAD_NAME jsoncpp-1.9.3.tar.gz + URL https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz + URL_HASH SHA256=8593c1d69e703563d94d8c12244e2e18893eeb9a8a9f8aa3d09a327aa45c8f7d CMAKE_COMMAND ${JSONCPP_CMAKE_COMMAND} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_INSTALL_LIBDIR=lib # Build static lib but suitable to be included in a shared lib. -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} + -DJSONCPP_WITH_EXAMPLE=OFF -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF -DCMAKE_CXX_FLAGS=${JSONCPP_CXX_FLAGS} diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 000ab3ef8c13..fc9782c47177 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1113,6 +1113,10 @@ "bugs": [], "released": "2020-07-07" }, + "0.6.12": { + "bugs": [], + "released": "2020-07-22" + }, "0.6.2": { "bugs": [ "MissingEscapingInFormatting", diff --git a/docs/index.rst b/docs/index.rst index 89976a8d4e91..d616d6e881c2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -77,7 +77,7 @@ version stands as a reference. * `Japanese `_ * `Korean `_ (in progress) * `Russian `_ (rather outdated) -* `Simplified Chinese `_ (in progress) +* `Simplified Chinese `_ (in progress) * `Spanish `_ * `Turkish `_ (partial) diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index ec774014bb6b..c566d54078b3 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -49,7 +49,7 @@ The following example shows a contract and a function using all available tags. .. code:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.5.0 <0.7.0; + pragma solidity >0.6.10 <0.7.0; /// @title A simulator for trees /// @author Larry A. Gardner @@ -60,9 +60,33 @@ The following example shows a contract and a function using all available tags. /// @dev The Alexandr N. Tetearing algorithm could increase precision /// @param rings The number of rings from dendrochronological sample /// @return age in years, rounded up for partial years - function age(uint256 rings) external pure returns (uint256) { + function age(uint256 rings) external virtual pure returns (uint256) { return rings + 1; } + + /// @notice Returns the amount of leaves the tree has. + /// @dev Returns only a fixed number. + function leaves() external virtual pure returns(uint256) { + return 2; + } + } + + contract Plant { + function leaves() external virtual pure returns(uint256) { + return 3; + } + } + + contract KumquatTree is Tree, Plant { + function age(uint256 rings) external override pure returns (uint256) { + return rings + 2; + } + + /// Return the amount of leaves that this specific kind of tree has + /// @inheritdoc Tree + function leaves() external override(Tree, Plant) pure returns(uint256) { + return 3; + } } .. _header-tags: @@ -75,16 +99,17 @@ NatSpec tag and where it may be used. As a special case, if no tags are used then the Solidity compiler will interpret a ``///`` or ``/**`` comment in the same way as if it were tagged with ``@notice``. -=========== =============================================================================== ============================= -Tag Context -=========== =============================================================================== ============================= -``@title`` A title that should describe the contract/interface contract, interface -``@author`` The name of the author contract, interface -``@notice`` Explain to an end user what this does contract, interface, function, public state variable, event -``@dev`` Explain to a developer any extra details contract, interface, function, state variable, event -``@param`` Documents a parameter just like in doxygen (must be followed by parameter name) function, event -``@return`` Documents the return variables of a contract's function function, public state variable -=========== =============================================================================== ============================= +=============== ====================================================================================== ============================= +Tag Context +=============== ====================================================================================== ============================= +``@title`` A title that should describe the contract/interface contract, interface +``@author`` The name of the author contract, interface +``@notice`` Explain to an end user what this does contract, interface, function, public state variable, event +``@dev`` Explain to a developer any extra details contract, interface, function, state variable, event +``@param`` Documents a parameter just like in doxygen (must be followed by parameter name) function, event +``@return`` Documents the return variables of a contract's function function, public state variable +``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, public state variable +=============== ====================================================================================== ============================= If your function returns multiple values, like ``(int quotient, int remainder)`` then use multiple ``@return`` statements in the same format as the @@ -127,6 +152,7 @@ base function. Exceptions to this are: * When the parameter names are different. * When there is more than one base function. + * When there is an explicit ``@inheritdoc`` tag which specifies which contract should be used to inherit. .. _header-output: diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 5bd242f06b99..17a52f43b616 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -237,6 +237,23 @@ memory arrays, i.e. the following is not possible: It is planned to remove this restriction in the future, but it creates some complications because of how arrays are passed in the ABI. +If you want to initialize dynamically-sized arrays, you have to assign the +individual elements: + +:: + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.4.0 <0.7.0; + + contract C { + function f() public pure { + uint[] memory x = new uint[](3); + x[0] = 1; + x[1] = 3; + x[2] = 4; + } + } + .. index:: ! array;length, length, push, pop, !array;push, !array;pop .. _array-members: diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 8588832fe429..b1de71e3b488 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Assembly.cpp * @author Gav Wood * @date 2014 @@ -91,8 +92,8 @@ string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& class Functionalizer { public: - Functionalizer (ostream& _out, string const& _prefix, StringMap const& _sourceCodes): - m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes) + Functionalizer (ostream& _out, string const& _prefix, StringMap const& _sourceCodes, Assembly const& _assembly): + m_out(_out), m_prefix(_prefix), m_sourceCodes(_sourceCodes), m_assembly(_assembly) {} void feed(AssemblyItem const& _item) @@ -103,6 +104,9 @@ class Functionalizer m_location = _item.location(); printLocation(); } + + string expression = _item.toAssemblyText(m_assembly); + if (!( _item.canBeFunctional() && _item.returnValues() <= 1 && @@ -110,10 +114,9 @@ class Functionalizer )) { flush(); - m_out << m_prefix << (_item.type() == Tag ? "" : " ") << _item.toAssemblyText() << endl; + m_out << m_prefix << (_item.type() == Tag ? "" : " ") << expression << endl; return; } - string expression = _item.toAssemblyText(); if (_item.arguments() > 0) { expression += "("; @@ -159,13 +162,14 @@ class Functionalizer ostream& m_out; string const& m_prefix; StringMap const& m_sourceCodes; + Assembly const& m_assembly; }; } void Assembly::assemblyStream(ostream& _out, string const& _prefix, StringMap const& _sourceCodes) const { - Functionalizer f(_out, _prefix, _sourceCodes); + Functionalizer f(_out, _prefix, _sourceCodes, *this); for (auto const& i: m_items) f.feed(i); @@ -521,6 +525,7 @@ map Assembly::optimiseInternal( LinkerObject const& Assembly::assemble() const { + assertThrow(!m_invalid, AssemblyException, "Attempted to assemble invalid Assembly object."); // Return the already assembled object, if present. if (!m_assembledObject.bytecode.empty()) return m_assembledObject; @@ -637,7 +642,7 @@ LinkerObject const& Assembly::assemble() const case PushSubSize: { assertThrow(i.data() <= numeric_limits::max(), AssemblyException, ""); - auto s = m_subs.at(static_cast(i.data()))->assemble().bytecode.size(); + auto s = subAssemblyById(static_cast(i.data()))->assemble().bytecode.size(); i.setPushedValue(u256(s)); uint8_t b = max(1, util::bytesRequired(s)); ret.bytecode.push_back((uint8_t)Instruction::PUSH1 - 1 + b); @@ -705,25 +710,20 @@ LinkerObject const& Assembly::assemble() const // Append an INVALID here to help tests find miscompilation. ret.bytecode.push_back(uint8_t(Instruction::INVALID)); - for (size_t i = 0; i < m_subs.size(); ++i) + for (auto const& [subIdPath, bytecodeOffset]: subRef) { - auto references = subRef.equal_range(i); - if (references.first == references.second) - continue; - for (auto ref = references.first; ref != references.second; ++ref) - { - bytesRef r(ret.bytecode.data() + ref->second, bytesPerDataRef); - toBigEndian(ret.bytecode.size(), r); - } - ret.append(m_subs[i]->assemble()); + bytesRef r(ret.bytecode.data() + bytecodeOffset, bytesPerDataRef); + toBigEndian(ret.bytecode.size(), r); + ret.append(subAssemblyById(subIdPath)->assemble()); } + for (auto const& i: tagRef) { size_t subId; size_t tagId; tie(subId, tagId) = i.second; assertThrow(subId == numeric_limits::max() || subId < m_subs.size(), AssemblyException, "Invalid sub id"); - std::vector const& tagPositions = + vector const& tagPositions = subId == numeric_limits::max() ? m_tagPositionsInBytecode : m_subs[subId]->m_tagPositionsInBytecode; @@ -756,3 +756,51 @@ LinkerObject const& Assembly::assemble() const } return ret; } + +vector Assembly::decodeSubPath(size_t _subObjectId) const +{ + if (_subObjectId < m_subs.size()) + return {_subObjectId}; + + auto subIdPathIt = find_if( + m_subPaths.begin(), + m_subPaths.end(), + [_subObjectId](auto const& subId) { return subId.second == _subObjectId; } + ); + + assertThrow(subIdPathIt != m_subPaths.end(), AssemblyException, ""); + return subIdPathIt->first; +} + +size_t Assembly::encodeSubPath(vector const& _subPath) +{ + assertThrow(!_subPath.empty(), AssemblyException, ""); + if (_subPath.size() == 1) + { + assertThrow(_subPath[0] < m_subs.size(), AssemblyException, ""); + return _subPath[0]; + } + + if (m_subPaths.find(_subPath) == m_subPaths.end()) + { + size_t objectId = numeric_limits::max() - m_subPaths.size(); + assertThrow(objectId >= m_subs.size(), AssemblyException, ""); + m_subPaths[_subPath] = objectId; + } + + return m_subPaths[_subPath]; +} + +Assembly const* Assembly::subAssemblyById(size_t _subId) const +{ + vector subIds = decodeSubPath(_subId); + Assembly const* currentAssembly = this; + for (size_t currentSubId: subIds) + { + currentAssembly = currentAssembly->m_subs.at(currentSubId).get(); + assertThrow(currentAssembly, AssemblyException, ""); + } + + assertThrow(currentAssembly != this, AssemblyException, ""); + return currentAssembly; +} diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index e82fee7ddda4..354304dcbafd 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once @@ -142,6 +143,12 @@ class Assembly std::map const& _sourceIndices = std::map() ) const; + /// Mark this assembly as invalid. Calling ``assemble`` on it will throw. + void markAsInvalid() { m_invalid = true; } + + std::vector decodeSubPath(size_t _subObjectId) const; + size_t encodeSubPath(std::vector const& _subPath); + protected: /// Does the same operations as @a optimise, but should only be applied to a sub and /// returns the replaced tags. Also takes an argument containing the tags of this assembly @@ -161,6 +168,10 @@ class Assembly ); static std::string toStringInHex(u256 _value); + bool m_invalid = false; + + Assembly const* subAssemblyById(size_t _subId) const; + protected: /// 0 is reserved for exception unsigned m_usedTags = 1; @@ -174,6 +185,10 @@ class Assembly std::map m_libraries; ///< Identifiers of libraries to be linked. std::map m_immutables; ///< Identifiers of immutables. + /// Map from a vector representing a path to a particular sub assembly to sub assembly id. + /// This map is used only for sub-assemblies which are not direct sub-assemblies (where path is having more than one value). + std::map, size_t> m_subPaths; + mutable LinkerObject m_assembledObject; mutable std::vector m_tagPositionsInBytecode; diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index b78c0e60c718..e70e844d6d63 100644 --- a/libevmasm/AssemblyItem.cpp +++ b/libevmasm/AssemblyItem.cpp @@ -14,10 +14,14 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include +#include + #include +#include #include #include @@ -169,7 +173,7 @@ string AssemblyItem::getJumpTypeAsString() const } } -string AssemblyItem::toAssemblyText() const +string AssemblyItem::toAssemblyText(Assembly const& _assembly) const { string text; switch (type()) @@ -207,11 +211,18 @@ string AssemblyItem::toAssemblyText() const text = string("data_") + util::toHex(data()); break; case PushSub: - text = string("dataOffset(sub_") + to_string(static_cast(data())) + ")"; - break; case PushSubSize: - text = string("dataSize(sub_") + to_string(static_cast(data())) + ")"; + { + vector subPathComponents; + for (size_t subPathComponentId: _assembly.decodeSubPath(static_cast(data()))) + subPathComponents.emplace_back("sub_" + to_string(subPathComponentId)); + text = + (type() == PushSub ? "dataOffset"s : "dataSize"s) + + "(" + + solidity::util::joinHumanReadable(subPathComponents, ".") + + ")"; break; + } case PushProgramSize: text = string("bytecodeSize"); break; diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 4b0b7ca722e5..ac3a2c9d81a1 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file AssemblyItem.h * @author Gav Wood * @date 2014 @@ -151,7 +152,7 @@ class AssemblyItem void setPushedValue(u256 const& _value) const { m_pushedValue = std::make_shared(_value); } u256 const* pushedValue() const { return m_pushedValue.get(); } - std::string toAssemblyText() const; + std::string toAssemblyText(Assembly const& _assembly) const; size_t m_modifierDepth = 0; diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index 95aba2a01d86..5f9fa768ffde 100644 --- a/libevmasm/BlockDeduplicator.cpp +++ b/libevmasm/BlockDeduplicator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file BlockDeduplicator.cpp * @author Christian diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h index ce12b4bfb951..ef131ae52afc 100644 --- a/libevmasm/BlockDeduplicator.h +++ b/libevmasm/BlockDeduplicator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file BlockDeduplicator.h * @author Christian diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 7fa5c938bbc5..9d07e47caf0b 100644 --- a/libevmasm/CommonSubexpressionEliminator.cpp +++ b/libevmasm/CommonSubexpressionEliminator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file CommonSubexpressionEliminator.cpp * @author Christian diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index ce9c898ee4e0..88e559719320 100644 --- a/libevmasm/CommonSubexpressionEliminator.h +++ b/libevmasm/CommonSubexpressionEliminator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file CommonSubexpressionEliminator.h * @author Christian diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 018be38ea43d..87ef57089126 100644 --- a/libevmasm/ConstantOptimiser.cpp +++ b/libevmasm/ConstantOptimiser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file ConstantOptimiser.cpp * @author Christian * @date 2015 diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index a9db47ab1d19..aad0fd169bef 100644 --- a/libevmasm/ConstantOptimiser.h +++ b/libevmasm/ConstantOptimiser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file ConstantOptimiser.cpp * @author Christian * @date 2015 diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index 4c9d59c8b0a9..8431fb51c0af 100644 --- a/libevmasm/ControlFlowGraph.cpp +++ b/libevmasm/ControlFlowGraph.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file ControlFlowGraph.cpp * @author Christian diff --git a/libevmasm/ControlFlowGraph.h b/libevmasm/ControlFlowGraph.h index 5fceb6388440..d27702c2ac0b 100644 --- a/libevmasm/ControlFlowGraph.h +++ b/libevmasm/ControlFlowGraph.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file ControlFlowGraph.h * @author Christian diff --git a/libevmasm/Exceptions.h b/libevmasm/Exceptions.h index e4fadb53ce9c..02757757602e 100644 --- a/libevmasm/Exceptions.h +++ b/libevmasm/Exceptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Exceptions.h * @author Christian * @date 2014 diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index a208fabe7dae..55a3a04c79c1 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file ExpressionClasses.cpp * @author Christian diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index f9eebabd086f..bfab317dcb80 100644 --- a/libevmasm/ExpressionClasses.h +++ b/libevmasm/ExpressionClasses.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file ExpressionClasses.h * @author Christian diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index 6a07e9905e3c..eb259ba6286d 100644 --- a/libevmasm/GasMeter.cpp +++ b/libevmasm/GasMeter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index a6c0f29d9137..ddba491aad52 100644 --- a/libevmasm/GasMeter.h +++ b/libevmasm/GasMeter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file GasMeter.cpp * @author Christian * @date 2015 diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 0a61fbea041f..55af2340a386 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Instruction.cpp * @author Gav Wood * @date 2014 diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 511e3cf1b096..5c8eeb3ee5ff 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Instruction.h * @author Gav Wood * @date 2014 @@ -174,16 +175,16 @@ enum class Instruction: uint8_t LOG3, ///< Makes a log entry; 3 topics. LOG4, ///< Makes a log entry; 4 topics. - JUMPTO = 0xb0, ///< alter the program counter to a jumpdest -- not part of Instructions.cpp - JUMPIF, ///< conditionally alter the program counter -- not part of Instructions.cpp - JUMPV, ///< alter the program counter to a jumpdest -- not part of Instructions.cpp - JUMPSUB, ///< alter the program counter to a beginsub -- not part of Instructions.cpp - JUMPSUBV, ///< alter the program counter to a beginsub -- not part of Instructions.cpp - BEGINSUB, ///< set a potential jumpsub destination -- not part of Instructions.cpp - BEGINDATA, ///< begin the data section -- not part of Instructions.cpp - RETURNSUB, ///< return to subroutine jumped from -- not part of Instructions.cpp - PUTLOCAL, ///< pop top of stack to local variable -- not part of Instructions.cpp - GETLOCAL, ///< push local variable to top of stack -- not part of Instructions.cpp + EIP615_JUMPTO = 0xb0, ///< alter the program counter to a jumpdest -- not part of Instructions.cpp + EIP615_JUMPIF, ///< conditionally alter the program counter -- not part of Instructions.cpp + EIP615_JUMPV, ///< alter the program counter to a jumpdest -- not part of Instructions.cpp + EIP615_JUMPSUB, ///< alter the program counter to a beginsub -- not part of Instructions.cpp + EIP615_JUMPSUBV, ///< alter the program counter to a beginsub -- not part of Instructions.cpp + EIP615_BEGINSUB, ///< set a potential jumpsub destination -- not part of Instructions.cpp + EIP615_BEGINDATA, ///< begin the data section -- not part of Instructions.cpp + EIP615_RETURNSUB, ///< return to subroutine jumped from -- not part of Instructions.cpp + EIP615_PUTLOCAL, ///< pop top of stack to local variable -- not part of Instructions.cpp + EIP615_GETLOCAL, ///< push local variable to top of stack -- not part of Instructions.cpp CREATE = 0xf0, ///< create a new account with associated code CALL, ///< message-call into an account diff --git a/libevmasm/JumpdestRemover.cpp b/libevmasm/JumpdestRemover.cpp index cbb498c01d85..c4901700fa5b 100644 --- a/libevmasm/JumpdestRemover.cpp +++ b/libevmasm/JumpdestRemover.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * Removes unused JUMPDESTs. diff --git a/libevmasm/JumpdestRemover.h b/libevmasm/JumpdestRemover.h index 80b546d79dd7..e07550e2dd40 100644 --- a/libevmasm/JumpdestRemover.h +++ b/libevmasm/JumpdestRemover.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * Removes unused JUMPDESTs. diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 10e4a4f10fc3..ec6c50702014 100644 --- a/libevmasm/KnownState.cpp +++ b/libevmasm/KnownState.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file KnownState.cpp * @author Christian diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index b19585036aac..458a48b3efcb 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file KnownState.h * @author Christian diff --git a/libevmasm/LinkerObject.cpp b/libevmasm/LinkerObject.cpp index b7ffaac6682f..fdb9a460f2d0 100644 --- a/libevmasm/LinkerObject.cpp +++ b/libevmasm/LinkerObject.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file LinkerObject.cpp * @author Christian R * @date 2015 diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index ab0e26507261..03d01cc2c916 100644 --- a/libevmasm/LinkerObject.h +++ b/libevmasm/LinkerObject.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Assembly.h * @author Gav Wood * @date 2014 diff --git a/libevmasm/PathGasMeter.cpp b/libevmasm/PathGasMeter.cpp index 749cc7bb166d..b7c985f1bc80 100644 --- a/libevmasm/PathGasMeter.cpp +++ b/libevmasm/PathGasMeter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file PathGasMeter.cpp * @author Christian * @date 2015 diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h index 38a1979734ac..ecac17cac2f8 100644 --- a/libevmasm/PathGasMeter.h +++ b/libevmasm/PathGasMeter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file PathGasMeter.cpp * @author Christian * @date 2015 diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 861cae0f2bdf..6df80dac86a2 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file PeepholeOptimiser.cpp * Performs local optimising code changes to assembly. @@ -205,6 +206,30 @@ struct SwapComparison: SimplePeepholeOptimizerMethod } }; +/// Remove swapN after dupN +struct DupSwap: SimplePeepholeOptimizerMethod +{ + static size_t applySimple( + AssemblyItem const& _dupN, + AssemblyItem const& _swapN, + std::back_insert_iterator _out + ) + { + if ( + SemanticInformation::isDupInstruction(_dupN) && + SemanticInformation::isSwapInstruction(_swapN) && + getDupNumber(_dupN.instruction()) == getSwapNumber(_swapN.instruction()) + ) + { + *_out = _dupN; + return true; + } + else + return false; + } +}; + + struct IsZeroIsZeroJumpI: SimplePeepholeOptimizerMethod { static size_t applySimple( @@ -266,9 +291,10 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod std::back_insert_iterator _out ) { + if (_and != Instruction::AND) + return false; if ( _pushTag.type() == PushTag && - _and == Instruction::AND && _pushConstant.type() == Push && (_pushConstant.data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF) ) @@ -276,6 +302,16 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod *_out = _pushTag; return true; } + else if ( + // tag and constant are swapped + _pushConstant.type() == PushTag && + _pushTag.type() == Push && + (_pushTag.data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF) + ) + { + *_out = _pushConstant; + return true; + } else return false; } @@ -357,7 +393,7 @@ bool PeepholeOptimiser::optimise() applyMethods( state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), - IsZeroIsZeroJumpI(), JumpToNext(), UnreachableCode(), + DupSwap(), IsZeroIsZeroJumpI(), JumpToNext(), UnreachableCode(), TagConjunctions(), TruthyAnd(), Identity() ); if (m_optimisedItems.size() < m_items.size() || ( diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h index a260d31481eb..64ad5227fae1 100644 --- a/libevmasm/PeepholeOptimiser.h +++ b/libevmasm/PeepholeOptimiser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file PeepholeOptimiser.h * Performs local optimising code changes to assembly. diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index e29141b494ad..93ccdcaf96e0 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2018 * Templatized list of simplification rules. @@ -571,6 +572,20 @@ std::vector> simplificationRuleListPart7( feasibilityFunction }); + rules.push_back({ + Builtins::BYTE(A, Builtins::SHL(B, X)), + [=]() -> Pattern { return Builtins::BYTE(A.d() + B.d() / 8, X); }, + false, + [=] { return B.d() % 8 == 0 && A.d() <= 32 && B.d() <= 256; } + }); + + rules.push_back({ + Builtins::BYTE(A, Builtins::SHR(B, X)), + [=]() -> Pattern { return A.d() < B.d() / 8 ? Word(0) : Builtins::BYTE(A.d() - B.d() / 8, X); }, + false, + [=] { return B.d() % 8 == 0 && A.d() < Pattern::WordSize / 8 && B.d() <= Pattern::WordSize; } + }); + return rules; } diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index 76eeb59566f3..3d4ead64f384 100644 --- a/libevmasm/SemanticInformation.cpp +++ b/libevmasm/SemanticInformation.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file SemanticInformation.cpp * @author Christian diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 39a1b2439418..f919b4207b4c 100644 --- a/libevmasm/SemanticInformation.h +++ b/libevmasm/SemanticInformation.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file SemanticInformation.h * @author Christian diff --git a/libevmasm/SimplificationRule.h b/libevmasm/SimplificationRule.h index 1fa1d8ea8182..6ce9a9e7c08b 100644 --- a/libevmasm/SimplificationRule.h +++ b/libevmasm/SimplificationRule.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Expression simplification pattern. */ diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index c4cc598639b1..d2f30c22e4ff 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file ExpressionClasses.cpp * @author Christian diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index 72884d32ab12..f548f501d87d 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file SimplificationRules * @author Christian diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp index fa100c091fad..c953eda0f8e0 100644 --- a/liblangutil/EVMVersion.cpp +++ b/liblangutil/EVMVersion.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * EVM versioning. */ diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index 2c9e87ef3d3d..b34426c928cb 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * EVM versioning. */ diff --git a/liblangutil/ErrorReporter.cpp b/liblangutil/ErrorReporter.cpp index a8dccd55761b..29a20a8d8ce0 100644 --- a/liblangutil/ErrorReporter.cpp +++ b/liblangutil/ErrorReporter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Rhett * @date 2017 diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 3dc8c59c7845..e533d7f6cbda 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Rhett * @date 2017 diff --git a/liblangutil/Exceptions.cpp b/liblangutil/Exceptions.cpp index fa65031cd66e..2e9d22b418cf 100644 --- a/liblangutil/Exceptions.cpp +++ b/liblangutil/Exceptions.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Liana * @date 2015 diff --git a/liblangutil/Exceptions.h b/liblangutil/Exceptions.h index 0dd7568481b0..69745a2fc0df 100644 --- a/liblangutil/Exceptions.h +++ b/liblangutil/Exceptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/liblangutil/ParserBase.cpp b/liblangutil/ParserBase.cpp index c2162044a082..19c4d187cc58 100644 --- a/liblangutil/ParserBase.cpp +++ b/liblangutil/ParserBase.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/liblangutil/ParserBase.h b/liblangutil/ParserBase.h index 0f61460059f6..475b08456a6b 100644 --- a/liblangutil/ParserBase.h +++ b/liblangutil/ParserBase.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/liblangutil/SemVerHandler.cpp b/liblangutil/SemVerHandler.cpp index a626c5aa708b..ee5490f55ac8 100644 --- a/liblangutil/SemVerHandler.cpp +++ b/liblangutil/SemVerHandler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 @@ -245,14 +246,14 @@ unsigned SemVerMatchExpressionParser::parseVersionPart() return 0; else if ('1' <= c && c <= '9') { - unsigned v(c - '0'); + auto v = static_cast(c - '0'); // If we skip to the next token, the current number is terminated. while (m_pos == startPos && '0' <= currentChar() && currentChar() <= '9') { c = currentChar(); - if (v * 10 < v || v * 10 + unsigned(c - '0') < v * 10) + if (v * 10 < v || v * 10 + static_cast(c - '0') < v * 10) throw SemVerError(); - v = v * 10 + unsigned(c - '0'); + v = v * 10 + static_cast(c - '0'); nextChar(); } return v; diff --git a/liblangutil/SemVerHandler.h b/liblangutil/SemVerHandler.h index d3dfd5a5b0a3..0a291224e0db 100644 --- a/liblangutil/SemVerHandler.h +++ b/liblangutil/SemVerHandler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/liblangutil/SourceLocation.cpp b/liblangutil/SourceLocation.cpp index 8c531c6255b5..160a3616bd35 100644 --- a/liblangutil/SourceLocation.cpp +++ b/liblangutil/SourceLocation.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/liblangutil/SourceLocation.h b/liblangutil/SourceLocation.h index 283c8a52420e..4b7122de33f8 100644 --- a/liblangutil/SourceLocation.h +++ b/liblangutil/SourceLocation.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris Karapetsas * @date 2015 diff --git a/liblangutil/SourceReferenceExtractor.cpp b/liblangutil/SourceReferenceExtractor.cpp index 89f84011db71..2faefc9b0a97 100644 --- a/liblangutil/SourceReferenceExtractor.cpp +++ b/liblangutil/SourceReferenceExtractor.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/liblangutil/SourceReferenceExtractor.h b/liblangutil/SourceReferenceExtractor.h index b9dababb9671..7eb54845c7f9 100644 --- a/liblangutil/SourceReferenceExtractor.h +++ b/liblangutil/SourceReferenceExtractor.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/liblangutil/SourceReferenceFormatter.cpp b/liblangutil/SourceReferenceFormatter.cpp index e10f251d5b21..d7a0a21690ff 100644 --- a/liblangutil/SourceReferenceFormatter.cpp +++ b/liblangutil/SourceReferenceFormatter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/liblangutil/SourceReferenceFormatter.h b/liblangutil/SourceReferenceFormatter.h index 439fe177c26c..636ddfcb03b4 100644 --- a/liblangutil/SourceReferenceFormatter.h +++ b/liblangutil/SourceReferenceFormatter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/liblangutil/SourceReferenceFormatterHuman.cpp b/liblangutil/SourceReferenceFormatterHuman.cpp index 998ca7bf59b6..96bef2ed7753 100644 --- a/liblangutil/SourceReferenceFormatterHuman.cpp +++ b/liblangutil/SourceReferenceFormatterHuman.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Formatting functions for errors referencing positions and locations in the source. */ diff --git a/liblangutil/SourceReferenceFormatterHuman.h b/liblangutil/SourceReferenceFormatterHuman.h index b468f375651b..21816ce67004 100644 --- a/liblangutil/SourceReferenceFormatterHuman.h +++ b/liblangutil/SourceReferenceFormatterHuman.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Formatting functions for errors referencing positions and locations in the source. */ diff --git a/liblangutil/UndefMacros.h b/liblangutil/UndefMacros.h index d96e242ec8a4..e3dde6d31514 100644 --- a/liblangutil/UndefMacros.h +++ b/liblangutil/UndefMacros.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file UndefMacros.h * @author Lefteris * @date 2015 diff --git a/libsmtutil/CHCSmtLib2Interface.cpp b/libsmtutil/CHCSmtLib2Interface.cpp index 8116ea2a26ce..c6c5a4cac1aa 100644 --- a/libsmtutil/CHCSmtLib2Interface.cpp +++ b/libsmtutil/CHCSmtLib2Interface.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsmtutil/CHCSmtLib2Interface.h b/libsmtutil/CHCSmtLib2Interface.h index 8ec3f8dd263f..5a74bacbe997 100644 --- a/libsmtutil/CHCSmtLib2Interface.h +++ b/libsmtutil/CHCSmtLib2Interface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Interface for solving Horn systems via smtlib2. diff --git a/libsmtutil/CHCSolverInterface.h b/libsmtutil/CHCSolverInterface.h index f2d14cbcfa41..bf8b6a4ccce7 100644 --- a/libsmtutil/CHCSolverInterface.h +++ b/libsmtutil/CHCSolverInterface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Interface for constrained Horn solvers. diff --git a/libsmtutil/CVC4Interface.cpp b/libsmtutil/CVC4Interface.cpp index 7735d5a16daa..2a795d827586 100644 --- a/libsmtutil/CVC4Interface.cpp +++ b/libsmtutil/CVC4Interface.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -191,7 +192,7 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr) return m_context.mkExpr(CVC4::kind::BITVECTOR_AND, arguments[0], arguments[1]); else if (n == "int2bv") { - size_t size = std::stoi(_expr.arguments[1].name); + size_t size = std::stoul(_expr.arguments[1].name); auto i2bvOp = m_context.mkConst(CVC4::IntToBitVector(size)); // CVC4 treats all BVs as unsigned, so we need to manually apply 2's complement if needed. return m_context.mkExpr( diff --git a/libsmtutil/CVC4Interface.h b/libsmtutil/CVC4Interface.h index 99059035182e..16f9f1f81860 100644 --- a/libsmtutil/CVC4Interface.h +++ b/libsmtutil/CVC4Interface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsmtutil/Exceptions.h b/libsmtutil/Exceptions.h index 6321c4f6a647..29011dab97a4 100644 --- a/libsmtutil/Exceptions.h +++ b/libsmtutil/Exceptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsmtutil/SMTLib2Interface.cpp b/libsmtutil/SMTLib2Interface.cpp index ce1efb5f6805..f1d21c2cc668 100644 --- a/libsmtutil/SMTLib2Interface.cpp +++ b/libsmtutil/SMTLib2Interface.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -139,7 +140,7 @@ string SMTLib2Interface::toSExpr(Expression const& _expr) std::string sexpr = "("; if (_expr.name == "int2bv") { - size_t size = std::stoi(_expr.arguments[1].name); + size_t size = std::stoul(_expr.arguments[1].name); auto arg = toSExpr(_expr.arguments.front()); auto int2bv = "(_ int2bv " + to_string(size) + ")"; // Some solvers treat all BVs as unsigned, so we need to manually apply 2's complement if needed. diff --git a/libsmtutil/SMTLib2Interface.h b/libsmtutil/SMTLib2Interface.h index dfb32a959bc4..2a43c04418b5 100644 --- a/libsmtutil/SMTLib2Interface.h +++ b/libsmtutil/SMTLib2Interface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsmtutil/SMTPortfolio.cpp b/libsmtutil/SMTPortfolio.cpp index 80c1a47506bb..334d91dd73b6 100644 --- a/libsmtutil/SMTPortfolio.cpp +++ b/libsmtutil/SMTPortfolio.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsmtutil/SMTPortfolio.h b/libsmtutil/SMTPortfolio.h index 0399ac033f3e..3e933df5d133 100644 --- a/libsmtutil/SMTPortfolio.h +++ b/libsmtutil/SMTPortfolio.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsmtutil/SolverInterface.h b/libsmtutil/SolverInterface.h index be12c3a80811..d4c4d7fefa8a 100644 --- a/libsmtutil/SolverInterface.h +++ b/libsmtutil/SolverInterface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once @@ -59,10 +60,10 @@ class Expression public: explicit Expression(bool _v): Expression(_v ? "true" : "false", Kind::Bool) {} explicit Expression(std::shared_ptr _sort, std::string _name = ""): Expression(std::move(_name), {}, _sort) {} - Expression(size_t _number): Expression(std::to_string(_number), Kind::Int) {} - Expression(u256 const& _number): Expression(_number.str(), Kind::Int) {} - Expression(s256 const& _number): Expression(_number.str(), Kind::Int) {} - Expression(bigint const& _number): Expression(_number.str(), Kind::Int) {} + Expression(size_t _number): Expression(std::to_string(_number), {}, SortProvider::sintSort) {} + Expression(u256 const& _number): Expression(_number.str(), {}, SortProvider::sintSort) {} + Expression(s256 const& _number): Expression(_number.str(), {}, SortProvider::sintSort) {} + Expression(bigint const& _number): Expression(_number.str(), {}, SortProvider::sintSort) {} Expression(Expression const&) = default; Expression(Expression&&) = default; @@ -262,23 +263,28 @@ class Expression } friend Expression operator+(Expression _a, Expression _b) { - return Expression("+", std::move(_a), std::move(_b), Kind::Int); + auto intSort = _a.sort; + return Expression("+", {std::move(_a), std::move(_b)}, intSort); } friend Expression operator-(Expression _a, Expression _b) { - return Expression("-", std::move(_a), std::move(_b), Kind::Int); + auto intSort = _a.sort; + return Expression("-", {std::move(_a), std::move(_b)}, intSort); } friend Expression operator*(Expression _a, Expression _b) { - return Expression("*", std::move(_a), std::move(_b), Kind::Int); + auto intSort = _a.sort; + return Expression("*", {std::move(_a), std::move(_b)}, intSort); } friend Expression operator/(Expression _a, Expression _b) { - return Expression("/", std::move(_a), std::move(_b), Kind::Int); + auto intSort = _a.sort; + return Expression("/", {std::move(_a), std::move(_b)}, intSort); } friend Expression operator%(Expression _a, Expression _b) { - return Expression("mod", std::move(_a), std::move(_b), Kind::Int); + auto intSort = _a.sort; + return Expression("mod", {std::move(_a), std::move(_b)}, intSort); } friend Expression operator&(Expression _a, Expression _b) { diff --git a/libsmtutil/Sorts.cpp b/libsmtutil/Sorts.cpp index 7624cbb5b57a..303e8bb8448a 100644 --- a/libsmtutil/Sorts.cpp +++ b/libsmtutil/Sorts.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsmtutil/Sorts.h b/libsmtutil/Sorts.h index 20cbf2be5af8..de94e8fff6bc 100644 --- a/libsmtutil/Sorts.h +++ b/libsmtutil/Sorts.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsmtutil/Z3CHCInterface.cpp b/libsmtutil/Z3CHCInterface.cpp index d2bce2f1c6dd..262e72e1a947 100644 --- a/libsmtutil/Z3CHCInterface.cpp +++ b/libsmtutil/Z3CHCInterface.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsmtutil/Z3CHCInterface.h b/libsmtutil/Z3CHCInterface.h index f36ee2caae46..7fe9e66537f6 100644 --- a/libsmtutil/Z3CHCInterface.h +++ b/libsmtutil/Z3CHCInterface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Z3 specific Horn solver interface. diff --git a/libsmtutil/Z3Interface.cpp b/libsmtutil/Z3Interface.cpp index a71d008aba89..501446553bf5 100644 --- a/libsmtutil/Z3Interface.cpp +++ b/libsmtutil/Z3Interface.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -184,7 +185,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr) return arguments[0] & arguments[1]; else if (n == "int2bv") { - size_t size = std::stoi(_expr.arguments[1].name); + size_t size = std::stoul(_expr.arguments[1].name); return z3::int2bv(size, arguments[0]); } else if (n == "bv2int") diff --git a/libsmtutil/Z3Interface.h b/libsmtutil/Z3Interface.h index d1fdce0f8d03..22f79333785a 100644 --- a/libsmtutil/Z3Interface.h +++ b/libsmtutil/Z3Interface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolc/libsolc.cpp b/libsolc/libsolc.cpp index d216ae8a22a2..f87f075d6465 100644 --- a/libsolc/libsolc.cpp +++ b/libsolc/libsolc.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolc/libsolc.h b/libsolc/libsolc.h index 655c9e7b54a6..c5b3b3db732b 100644 --- a/libsolc/libsolc.h +++ b/libsolc/libsolc.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index 8e930b6ab9b5..74f4a9a21e02 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -16,6 +16,8 @@ set(sources analysis/DeclarationTypeChecker.h analysis/DocStringAnalyser.cpp analysis/DocStringAnalyser.h + analysis/DocStringTagParser.cpp + analysis/DocStringTagParser.h analysis/ImmutableValidator.cpp analysis/ImmutableValidator.h analysis/GlobalContext.cpp diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 4bd8b1389865..d00affb91a9b 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index f07e6783d342..521f463384ad 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index c0da545644a0..8d40ace0e746 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that verifies overloads, abstract contracts, function clashes and others * checks at contract or function level. @@ -60,6 +61,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkLibraryRequirements(_contract); checkBaseABICompatibility(_contract); checkPayableFallbackWithoutReceive(_contract); + checkStorageSize(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -458,3 +460,20 @@ void ContractLevelChecker::checkPayableFallbackWithoutReceive(ContractDefinition SecondarySourceLocation{}.append("The payable fallback function is defined here.", fallback->location()) ); } + +void ContractLevelChecker::checkStorageSize(ContractDefinition const& _contract) +{ + bigint size = 0; + vector variables; + for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) + for (VariableDeclaration const* variable: contract->stateVariables()) + if (!(variable->isConstant() || variable->immutable())) + { + size += variable->annotation().type->storageSizeUpperBound(); + if (size >= bigint(1) << 256) + { + m_errorReporter.typeError(7676_error, _contract.location(), "Contract too large for storage."); + break; + } + } +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index e40cb8b0d5b8..2af0963d7d60 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that verifies overloads, abstract contracts, function clashes and others * checks at contract or function level. @@ -83,6 +84,8 @@ class ContractLevelChecker /// Warns if the contract has a payable fallback, but no receive ether function. void checkPayableFallbackWithoutReceive(ContractDefinition const& _contract); + /// Error if the contract requires too much storage + void checkStorageSize(ContractDefinition const& _contract); OverrideChecker m_overrideChecker; langutil::ErrorReporter& m_errorReporter; diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index 4937ee1d4269..1ed66f72b6db 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/analysis/ControlFlowAnalyzer.h b/libsolidity/analysis/ControlFlowAnalyzer.h index a839c5679f96..c731cc31fc92 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.h +++ b/libsolidity/analysis/ControlFlowAnalyzer.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index a0c557a3ef14..4eb4658e1d50 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libsolidity/analysis/ControlFlowBuilder.h b/libsolidity/analysis/ControlFlowBuilder.h index 2d0910d6a741..0efd55d77bcb 100644 --- a/libsolidity/analysis/ControlFlowBuilder.h +++ b/libsolidity/analysis/ControlFlowBuilder.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/ControlFlowGraph.cpp b/libsolidity/analysis/ControlFlowGraph.cpp index fb5fc1be0221..f7344e7fc94e 100644 --- a/libsolidity/analysis/ControlFlowGraph.cpp +++ b/libsolidity/analysis/ControlFlowGraph.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/analysis/ControlFlowGraph.h b/libsolidity/analysis/ControlFlowGraph.h index 4d11ef8f6bb2..7d51f2196a8d 100644 --- a/libsolidity/analysis/ControlFlowGraph.h +++ b/libsolidity/analysis/ControlFlowGraph.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/DeclarationContainer.cpp b/libsolidity/analysis/DeclarationContainer.cpp index 2450778cd918..b514c2c3973f 100644 --- a/libsolidity/analysis/DeclarationContainer.cpp +++ b/libsolidity/analysis/DeclarationContainer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/analysis/DeclarationContainer.h b/libsolidity/analysis/DeclarationContainer.h index 4b4df9339a41..8036a5a58e81 100644 --- a/libsolidity/analysis/DeclarationContainer.h +++ b/libsolidity/analysis/DeclarationContainer.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index 07e8f606675f..0027b3045ba4 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/analysis/DeclarationTypeChecker.h b/libsolidity/analysis/DeclarationTypeChecker.h index 0edd97bd94ed..6ba9d1aad6c2 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.h +++ b/libsolidity/analysis/DeclarationTypeChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index 92989ddac413..94a841e00e81 100644 --- a/libsolidity/analysis/DocStringAnalyser.cpp +++ b/libsolidity/analysis/DocStringAnalyser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 @@ -52,6 +53,17 @@ void copyMissingTags(StructurallyDocumentedAnnotation& _target, set const& _baseFunctions, int64_t _contractId) +{ + for (CallableDeclaration const* baseFuncCandidate: _baseFunctions) + if (baseFuncCandidate->annotation().contract->id() == _contractId) + return baseFuncCandidate; + else if (auto callable = findBaseCallable(baseFuncCandidate->annotation().baseFunctions, _contractId)) + return callable; + + return nullptr; +} + bool parameterNamesEqual(CallableDeclaration const& _a, CallableDeclaration const& _b) { return boost::range::equal(_a.parameters(), _b.parameters(), [](auto const& pa, auto const& pb) { return pa->name() == pb->name(); }); @@ -66,50 +78,23 @@ bool DocStringAnalyser::analyseDocStrings(SourceUnit const& _sourceUnit) return errorWatcher.ok(); } -bool DocStringAnalyser::visit(ContractDefinition const& _contract) -{ - static set const validTags = set{"author", "title", "dev", "notice"}; - parseDocStrings(_contract, _contract.annotation(), validTags, "contracts"); - - return true; -} - bool DocStringAnalyser::visit(FunctionDefinition const& _function) { - if (_function.isConstructor()) - handleConstructor(_function, _function, _function.annotation()); - else + if (!_function.isConstructor()) handleCallable(_function, _function, _function.annotation()); return true; } bool DocStringAnalyser::visit(VariableDeclaration const& _variable) { - if (_variable.isStateVariable()) - { - static set const validPublicTags = set{"dev", "notice", "return", "title", "author"}; - if (_variable.isPublic()) - parseDocStrings(_variable, _variable.annotation(), validPublicTags, "public state variables"); - else - { - parseDocStrings(_variable, _variable.annotation(), validPublicTags, "non-public state variables"); - if (_variable.annotation().docTags.count("notice") > 0) - m_errorReporter.warning( - 7816_error, _variable.documentation()->location(), - "Documentation tag on non-public state variables will be disallowed in 0.7.0. " - "You will need to use the @dev tag explicitly." - ); - } - if (_variable.annotation().docTags.count("title") > 0 || _variable.annotation().docTags.count("author") > 0) - m_errorReporter.warning( - 8532_error, _variable.documentation()->location(), - "Documentation tag @title and @author is only allowed on contract definitions. " - "It will be disallowed in 0.7.0." - ); + if (!_variable.isStateVariable()) + return false; + + if (CallableDeclaration const* baseFunction = resolveInheritDoc(_variable.annotation().baseFunctions, _variable, _variable.annotation())) + copyMissingTags(_variable.annotation(), {baseFunction}); + else if (_variable.annotation().docTags.empty()) + copyMissingTags(_variable.annotation(), _variable.annotation().baseFunctions); - if (_variable.annotation().docTags.empty()) - copyMissingTags(_variable.annotation(), _variable.annotation().baseFunctions); - } return false; } @@ -127,133 +112,41 @@ bool DocStringAnalyser::visit(EventDefinition const& _event) return true; } -void DocStringAnalyser::checkParameters( - CallableDeclaration const& _callable, - StructurallyDocumented const& _node, - StructurallyDocumentedAnnotation& _annotation -) -{ - set validParams; - for (auto const& p: _callable.parameters()) - validParams.insert(p->name()); - if (_callable.returnParameterList()) - for (auto const& p: _callable.returnParameterList()->parameters()) - validParams.insert(p->name()); - auto paramRange = _annotation.docTags.equal_range("param"); - for (auto i = paramRange.first; i != paramRange.second; ++i) - if (!validParams.count(i->second.paramName)) - m_errorReporter.docstringParsingError( - 3881_error, - _node.documentation()->location(), - "Documented parameter \"" + - i->second.paramName + - "\" not found in the parameter list of the function." - ); - -} - -void DocStringAnalyser::handleConstructor( - CallableDeclaration const& _callable, - StructurallyDocumented const& _node, - StructurallyDocumentedAnnotation& _annotation -) -{ - static set const validTags = set{"author", "dev", "notice", "param"}; - parseDocStrings(_node, _annotation, validTags, "constructor"); - checkParameters(_callable, _node, _annotation); -} - void DocStringAnalyser::handleCallable( CallableDeclaration const& _callable, StructurallyDocumented const& _node, StructurallyDocumentedAnnotation& _annotation ) { - static set const validTags = set{"author", "dev", "notice", "return", "param"}; - parseDocStrings(_node, _annotation, validTags, "functions"); - checkParameters(_callable, _node, _annotation); - - if ( + if (CallableDeclaration const* baseFunction = resolveInheritDoc(_callable.annotation().baseFunctions, _node, _annotation)) + copyMissingTags(_annotation, {baseFunction}); + else if ( _annotation.docTags.empty() && _callable.annotation().baseFunctions.size() == 1 && parameterNamesEqual(_callable, **_callable.annotation().baseFunctions.begin()) ) copyMissingTags(_annotation, _callable.annotation().baseFunctions); - - if (_node.documentation() && _annotation.docTags.count("author") > 0) - m_errorReporter.warning( - 9843_error, _node.documentation()->location(), - "Documentation tag @author is only allowed on contract definitions. " - "It will be disallowed in 0.7.0." - ); } -void DocStringAnalyser::parseDocStrings( +CallableDeclaration const* DocStringAnalyser::resolveInheritDoc( + set const& _baseFuncs, StructurallyDocumented const& _node, - StructurallyDocumentedAnnotation& _annotation, - set const& _validTags, - string const& _nodeName + StructurallyDocumentedAnnotation& _annotation ) { - DocStringParser parser; - if (_node.documentation() && !_node.documentation()->text()->empty()) - { - parser.parse(*_node.documentation()->text(), m_errorReporter); - _annotation.docTags = parser.tags(); - } + if (_annotation.inheritdocReference == nullptr) + return nullptr; + + if (auto const callable = findBaseCallable(_baseFuncs, _annotation.inheritdocReference->id())) + return callable; - size_t returnTagsVisited = 0; - for (auto const& docTag: _annotation.docTags) - { - if (!_validTags.count(docTag.first)) - m_errorReporter.docstringParsingError( - 6546_error, - _node.documentation()->location(), - "Documentation tag @" + docTag.first + " not valid for " + _nodeName + "." - ); - else - if (docTag.first == "return") - { - returnTagsVisited++; - if (auto* varDecl = dynamic_cast(&_node)) - { - if (!varDecl->isPublic()) - m_errorReporter.docstringParsingError( - 9440_error, - _node.documentation()->location(), - "Documentation tag \"@" + docTag.first + "\" is only allowed on public state-variables." - ); - if (returnTagsVisited > 1) - m_errorReporter.docstringParsingError( - 5256_error, - _node.documentation()->location(), - "Documentation tag \"@" + docTag.first + "\" is only allowed once on state-variables." - ); - } - else if (auto* function = dynamic_cast(&_node)) - { - string content = docTag.second.content; - string firstWord = content.substr(0, content.find_first_of(" \t")); + m_errorReporter.docstringParsingError( + 4682_error, + _node.documentation()->location(), + "Documentation tag @inheritdoc references contract \"" + + _annotation.inheritdocReference->name() + + "\", but the contract does not contain a function that is overridden by this function." + ); - if (returnTagsVisited > function->returnParameters().size()) - m_errorReporter.docstringParsingError( - 2604_error, - _node.documentation()->location(), - "Documentation tag \"@" + docTag.first + " " + docTag.second.content + "\"" + - " exceeds the number of return parameters." - ); - else - { - auto parameter = function->returnParameters().at(returnTagsVisited - 1); - if (!parameter->name().empty() && parameter->name() != firstWord) - m_errorReporter.docstringParsingError( - 5856_error, - _node.documentation()->location(), - "Documentation tag \"@" + docTag.first + " " + docTag.second.content + "\"" + - " does not contain the name of its return parameter." - ); - } - } - } - } + return nullptr; } diff --git a/libsolidity/analysis/DocStringAnalyser.h b/libsolidity/analysis/DocStringAnalyser.h index 9bc8ec5782a4..e13cab8985a4 100644 --- a/libsolidity/analysis/DocStringAnalyser.h +++ b/libsolidity/analysis/DocStringAnalyser.h @@ -14,12 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ -/** - * @author Christian - * @date 2015 - * Parses and analyses the doc strings. - * Stores the parsing results in the AST annotations and reports errors. - */ +// SPDX-License-Identifier: GPL-3.0 #pragma once @@ -34,7 +29,7 @@ namespace solidity::frontend { /** - * Parses and analyses the doc strings. + * Analyses and validates the doc strings. * Stores the parsing results in the AST annotations and reports errors. */ class DocStringAnalyser: private ASTConstVisitor @@ -44,20 +39,13 @@ class DocStringAnalyser: private ASTConstVisitor bool analyseDocStrings(SourceUnit const& _sourceUnit); private: - bool visit(ContractDefinition const& _contract) override; bool visit(FunctionDefinition const& _function) override; bool visit(VariableDeclaration const& _variable) override; bool visit(ModifierDefinition const& _modifier) override; bool visit(EventDefinition const& _event) override; - void checkParameters( - CallableDeclaration const& _callable, - StructurallyDocumented const& _node, - StructurallyDocumentedAnnotation& _annotation - ); - - void handleConstructor( - CallableDeclaration const& _callable, + CallableDeclaration const* resolveInheritDoc( + std::set const& _baseFunctions, StructurallyDocumented const& _node, StructurallyDocumentedAnnotation& _annotation ); @@ -68,19 +56,6 @@ class DocStringAnalyser: private ASTConstVisitor StructurallyDocumentedAnnotation& _annotation ); - void handleDeclaration( - Declaration const& _declaration, - StructurallyDocumented const& _node, - StructurallyDocumentedAnnotation& _annotation - ); - - void parseDocStrings( - StructurallyDocumented const& _node, - StructurallyDocumentedAnnotation& _annotation, - std::set const& _validTags, - std::string const& _nodeName - ); - langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/DocStringTagParser.cpp b/libsolidity/analysis/DocStringTagParser.cpp new file mode 100644 index 000000000000..36fec2f2cabc --- /dev/null +++ b/libsolidity/analysis/DocStringTagParser.cpp @@ -0,0 +1,227 @@ +/* + 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 . +*/ +/** + * @author Christian + * @date 2015 + * Parses and analyses the doc strings. + * Stores the parsing results in the AST annotations and reports errors. + */ + +#include + +#include +#include +#include +#include + +using namespace std; +using namespace solidity; +using namespace solidity::langutil; +using namespace solidity::frontend; + +bool DocStringTagParser::parseDocStrings(SourceUnit const& _sourceUnit) +{ + auto errorWatcher = m_errorReporter.errorWatcher(); + _sourceUnit.accept(*this); + return errorWatcher.ok(); +} + +bool DocStringTagParser::visit(ContractDefinition const& _contract) +{ + static set const validTags = set{"author", "title", "dev", "notice"}; + parseDocStrings(_contract, _contract.annotation(), validTags, "contracts"); + + return true; +} + +bool DocStringTagParser::visit(FunctionDefinition const& _function) +{ + if (_function.isConstructor()) + handleConstructor(_function, _function, _function.annotation()); + else + handleCallable(_function, _function, _function.annotation()); + return true; +} + +bool DocStringTagParser::visit(VariableDeclaration const& _variable) +{ + if (_variable.isStateVariable()) + { + static set const validPublicTags = set{"dev", "notice", "return", "title", "author", "inheritdoc"}; + if (_variable.isPublic()) + parseDocStrings(_variable, _variable.annotation(), validPublicTags, "public state variables"); + else + { + parseDocStrings(_variable, _variable.annotation(), validPublicTags, "non-public state variables"); + if (_variable.annotation().docTags.count("notice") > 0) + m_errorReporter.warning( + 7816_error, _variable.documentation()->location(), + "Documentation tag on non-public state variables will be disallowed in 0.7.0. " + "You will need to use the @dev tag explicitly." + ); + } + if (_variable.annotation().docTags.count("title") > 0 || _variable.annotation().docTags.count("author") > 0) + m_errorReporter.warning( + 8532_error, _variable.documentation()->location(), + "Documentation tag @title and @author is only allowed on contract definitions. " + "It will be disallowed in 0.7.0." + ); + } + return false; +} + +bool DocStringTagParser::visit(ModifierDefinition const& _modifier) +{ + handleCallable(_modifier, _modifier, _modifier.annotation()); + + return true; +} + +bool DocStringTagParser::visit(EventDefinition const& _event) +{ + handleCallable(_event, _event, _event.annotation()); + + return true; +} + +void DocStringTagParser::checkParameters( + CallableDeclaration const& _callable, + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation +) +{ + set validParams; + for (auto const& p: _callable.parameters()) + validParams.insert(p->name()); + if (_callable.returnParameterList()) + for (auto const& p: _callable.returnParameterList()->parameters()) + validParams.insert(p->name()); + auto paramRange = _annotation.docTags.equal_range("param"); + for (auto i = paramRange.first; i != paramRange.second; ++i) + if (!validParams.count(i->second.paramName)) + m_errorReporter.docstringParsingError( + 3881_error, + _node.documentation()->location(), + "Documented parameter \"" + + i->second.paramName + + "\" not found in the parameter list of the function." + ); +} + +void DocStringTagParser::handleConstructor( + CallableDeclaration const& _callable, + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation +) +{ + static set const validTags = set{"author", "dev", "notice", "param"}; + parseDocStrings(_node, _annotation, validTags, "constructor"); + checkParameters(_callable, _node, _annotation); +} + +void DocStringTagParser::handleCallable( + CallableDeclaration const& _callable, + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation +) +{ + static set const validEventTags = set{"author", "dev", "notice", "return", "param"}; + static set const validTags = set{"author", "dev", "notice", "return", "param", "inheritdoc"}; + + if (dynamic_cast(&_callable)) + parseDocStrings(_node, _annotation, validEventTags, "events"); + else + parseDocStrings(_node, _annotation, validTags, "functions"); + + checkParameters(_callable, _node, _annotation); + + if (_node.documentation() && _annotation.docTags.count("author") > 0) + m_errorReporter.warning( + 9843_error, _node.documentation()->location(), + "Documentation tag @author is only allowed on contract definitions. " + "It will be disallowed in 0.7.0." + ); +} + +void DocStringTagParser::parseDocStrings( + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation, + set const& _validTags, + string const& _nodeName +) +{ + DocStringParser parser; + if (_node.documentation() && !_node.documentation()->text()->empty()) + { + parser.parse(*_node.documentation()->text(), m_errorReporter); + _annotation.docTags = parser.tags(); + } + + size_t returnTagsVisited = 0; + for (auto const& docTag: _annotation.docTags) + { + if (!_validTags.count(docTag.first)) + m_errorReporter.docstringParsingError( + 6546_error, + _node.documentation()->location(), + "Documentation tag @" + docTag.first + " not valid for " + _nodeName + "." + ); + else if (docTag.first == "return") + { + returnTagsVisited++; + if (auto const* varDecl = dynamic_cast(&_node)) + { + if (!varDecl->isPublic()) + m_errorReporter.docstringParsingError( + 9440_error, + _node.documentation()->location(), + "Documentation tag \"@" + docTag.first + "\" is only allowed on public state-variables." + ); + if (returnTagsVisited > 1) + m_errorReporter.docstringParsingError( + 5256_error, + _node.documentation()->location(), + "Documentation tag \"@" + docTag.first + "\" is only allowed once on state-variables." + ); + } + else if (auto const* function = dynamic_cast(&_node)) + { + string content = docTag.second.content; + string firstWord = content.substr(0, content.find_first_of(" \t")); + + if (returnTagsVisited > function->returnParameters().size()) + m_errorReporter.docstringParsingError( + 2604_error, + _node.documentation()->location(), + "Documentation tag \"@" + docTag.first + " " + docTag.second.content + "\"" + + " exceeds the number of return parameters." + ); + else + { + auto parameter = function->returnParameters().at(returnTagsVisited - 1); + if (!parameter->name().empty() && parameter->name() != firstWord) + m_errorReporter.docstringParsingError( + 5856_error, + _node.documentation()->location(), + "Documentation tag \"@" + docTag.first + " " + docTag.second.content + "\"" + + " does not contain the name of its return parameter." + ); + } + } + } + } +} diff --git a/libsolidity/analysis/DocStringTagParser.h b/libsolidity/analysis/DocStringTagParser.h new file mode 100644 index 000000000000..41dcca5dfcd1 --- /dev/null +++ b/libsolidity/analysis/DocStringTagParser.h @@ -0,0 +1,76 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include + +namespace solidity::langutil +{ +class ErrorReporter; +} + +namespace solidity::frontend +{ + +/** + * Parses the doc tags and does basic validity checks. + * Stores the parsing results in the AST annotations and reports errors. + */ +class DocStringTagParser: private ASTConstVisitor +{ +public: + explicit DocStringTagParser(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} + bool parseDocStrings(SourceUnit const& _sourceUnit); + +private: + bool visit(ContractDefinition const& _contract) override; + bool visit(FunctionDefinition const& _function) override; + bool visit(VariableDeclaration const& _variable) override; + bool visit(ModifierDefinition const& _modifier) override; + bool visit(EventDefinition const& _event) override; + + void checkParameters( + CallableDeclaration const& _callable, + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation + ); + + void handleConstructor( + CallableDeclaration const& _callable, + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation + ); + + void handleCallable( + CallableDeclaration const& _callable, + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation + ); + + void parseDocStrings( + StructurallyDocumented const& _node, + StructurallyDocumentedAnnotation& _annotation, + std::set const& _validTags, + std::string const& _nodeName + ); + + langutil::ErrorReporter& m_errorReporter; +}; + +} diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 53020afce97d..885ae49a7e00 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @author Gav Wood diff --git a/libsolidity/analysis/GlobalContext.h b/libsolidity/analysis/GlobalContext.h index 81ffa2109d45..b84e3a026229 100644 --- a/libsolidity/analysis/GlobalContext.h +++ b/libsolidity/analysis/GlobalContext.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/analysis/ImmutableValidator.cpp b/libsolidity/analysis/ImmutableValidator.cpp index e4fcfadcf366..5af640e58537 100644 --- a/libsolidity/analysis/ImmutableValidator.cpp +++ b/libsolidity/analysis/ImmutableValidator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/analysis/ImmutableValidator.h b/libsolidity/analysis/ImmutableValidator.h index 5845ba011afd..ffa45e74cb51 100644 --- a/libsolidity/analysis/ImmutableValidator.h +++ b/libsolidity/analysis/ImmutableValidator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 9fbd219f91b9..c7be364a3e0c 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index efb4040380e0..d72822653044 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/analysis/OverrideChecker.cpp b/libsolidity/analysis/OverrideChecker.cpp index 6a2ccc83aa41..42a6230a221e 100644 --- a/libsolidity/analysis/OverrideChecker.cpp +++ b/libsolidity/analysis/OverrideChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that verifies overloads, abstract contracts, function clashes and others * checks at contract or function level. diff --git a/libsolidity/analysis/OverrideChecker.h b/libsolidity/analysis/OverrideChecker.h index d47b89f3dd4f..564100453cb6 100644 --- a/libsolidity/analysis/OverrideChecker.h +++ b/libsolidity/analysis/OverrideChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that verifies override properties. */ diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 1b5b5b7c351c..cb04eec6f825 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h index 0a335855393d..d3f23918c6db 100644 --- a/libsolidity/analysis/PostTypeChecker.h +++ b/libsolidity/analysis/PostTypeChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 408a7ff83782..4d26f1888326 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 @@ -35,6 +36,7 @@ #include #include +#include using namespace std; using namespace solidity::langutil; @@ -105,6 +107,14 @@ void ReferencesResolver::endVisit(VariableDeclarationStatement const& _varDeclSt m_resolver.activateVariable(var->name()); } +bool ReferencesResolver::visit(VariableDeclaration const& _varDecl) +{ + if (_varDecl.documentation()) + resolveInheritDoc(*_varDecl.documentation(), _varDecl.annotation()); + + return true; +} + bool ReferencesResolver::visit(Identifier const& _identifier) { auto declarations = m_resolver.nameFromCurrentScope(_identifier.name()); @@ -131,6 +141,10 @@ bool ReferencesResolver::visit(Identifier const& _identifier) bool ReferencesResolver::visit(FunctionDefinition const& _functionDefinition) { m_returnParameters.push_back(_functionDefinition.returnParameterList().get()); + + if (_functionDefinition.documentation()) + resolveInheritDoc(*_functionDefinition.documentation(), _functionDefinition.annotation()); + return true; } @@ -140,9 +154,13 @@ void ReferencesResolver::endVisit(FunctionDefinition const&) m_returnParameters.pop_back(); } -bool ReferencesResolver::visit(ModifierDefinition const&) +bool ReferencesResolver::visit(ModifierDefinition const& _modifierDefinition) { m_returnParameters.push_back(nullptr); + + if (_modifierDefinition.documentation()) + resolveInheritDoc(*_modifierDefinition.documentation(), _modifierDefinition.annotation()); + return true; } @@ -283,4 +301,53 @@ void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl) visit(*_varDecl.value); } +void ReferencesResolver::resolveInheritDoc(StructuredDocumentation const& _documentation, StructurallyDocumentedAnnotation& _annotation) +{ + switch (_annotation.docTags.count("inheritdoc")) + { + case 0: + break; + case 1: + { + string const& name = _annotation.docTags.find("inheritdoc")->second.content; + vector path; + boost::split(path, name, boost::is_any_of(".")); + Declaration const* result = m_resolver.pathFromCurrentScope(path); + + if (result == nullptr) + { + m_errorReporter.docstringParsingError( + 9397_error, + _documentation.location(), + "Documentation tag @inheritdoc references inexistent contract \"" + + name + + "\"." + ); + return; + } + else + { + _annotation.inheritdocReference = dynamic_cast(result); + + if (!_annotation.inheritdocReference) + m_errorReporter.docstringParsingError( + 1430_error, + _documentation.location(), + "Documentation tag @inheritdoc reference \"" + + name + + "\" is not a contract." + ); + } + break; + } + default: + m_errorReporter.docstringParsingError( + 5142_error, + _documentation.location(), + "Documentation tag @inheritdoc can only be given once." + ); + break; + } +} + } diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 7da745cc5e4c..fc71b4d4edac 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -75,6 +76,7 @@ class ReferencesResolver: private ASTConstVisitor, private yul::ASTWalker bool visit(ForStatement const& _for) override; void endVisit(ForStatement const& _for) override; void endVisit(VariableDeclarationStatement const& _varDeclStatement) override; + bool visit(VariableDeclaration const& _varDecl) override; bool visit(Identifier const& _identifier) override; bool visit(FunctionDefinition const& _functionDefinition) override; void endVisit(FunctionDefinition const& _functionDefinition) override; @@ -88,6 +90,8 @@ class ReferencesResolver: private ASTConstVisitor, private yul::ASTWalker void operator()(yul::Identifier const& _identifier) override; void operator()(yul::VariableDeclaration const& _varDecl) override; + void resolveInheritDoc(StructuredDocumentation const& _documentation, StructurallyDocumentedAnnotation& _annotation); + langutil::ErrorReporter& m_errorReporter; NameAndTypeResolver& m_resolver; langutil::EVMVersion m_evmVersion; diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index b650f1fc1cbe..68f52ac26b6c 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Federico Bond * @date 2016 @@ -155,29 +156,6 @@ bool StaticAnalyzer::visit(VariableDeclaration const& _variable) // This is not a no-op, the entry might pre-exist. m_localVarUseCount[make_pair(_variable.id(), &_variable)] += 0; } - else if (_variable.isStateVariable()) - { - set structsSeen; - TypeSet oversizedSubTypes; - if (structureSizeEstimate(*_variable.type(), structsSeen, oversizedSubTypes) >= bigint(1) << 64) - m_errorReporter.warning( - 3408_error, - _variable.location(), - "Variable " + util::escapeAndQuoteString(_variable.name()) + - " covers a large part of storage and thus makes collisions likely. " - "Either use mappings or dynamic arrays and allow their size to be increased only " - "in small quantities per transaction." - ); - for (Type const* type: oversizedSubTypes) - m_errorReporter.warning( - 7325_error, - _variable.location(), - "Type " + util::escapeAndQuoteString(type->canonicalName()) + - " has large size and thus makes collisions likely. " - "Either use mappings or dynamic arrays and allow their size to be increased only " - "in small quantities per transaction." - ); - } return true; } @@ -349,47 +327,3 @@ bool StaticAnalyzer::visit(FunctionCall const& _functionCall) } return true; } - -bigint StaticAnalyzer::structureSizeEstimate( - Type const& _type, - set& _structsSeen, - TypeSet& _oversizedSubTypes -) -{ - switch (_type.category()) - { - case Type::Category::Array: - { - auto const& t = dynamic_cast(_type); - bigint baseTypeSize = structureSizeEstimate(*t.baseType(), _structsSeen, _oversizedSubTypes); - if (baseTypeSize >= bigint(1) << 64) - _oversizedSubTypes.insert(t.baseType()); - if (!t.isDynamicallySized()) - return structureSizeEstimate(*t.baseType(), _structsSeen, _oversizedSubTypes) * t.length(); - break; - } - case Type::Category::Struct: - { - auto const& t = dynamic_cast(_type); - bigint size = 1; - if (_structsSeen.count(&t.structDefinition())) - return size; - _structsSeen.insert(&t.structDefinition()); - for (auto const& m: t.members(nullptr)) - size += structureSizeEstimate(*m.type, _structsSeen, _oversizedSubTypes); - _structsSeen.erase(&t.structDefinition()); - return size; - } - case Type::Category::Mapping: - { - auto const* valueType = dynamic_cast(_type).valueType(); - bigint valueTypeSize = structureSizeEstimate(*valueType, _structsSeen, _oversizedSubTypes); - if (valueTypeSize >= bigint(1) << 64) - _oversizedSubTypes.insert(valueType); - break; - } - default: - break; - } - return bigint(1); -} diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h index 8f7fbc59712b..dc6263d7e583 100644 --- a/libsolidity/analysis/StaticAnalyzer.h +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Federico Bond * @date 2016 @@ -73,23 +74,6 @@ class StaticAnalyzer: private ASTConstVisitor bool visit(BinaryOperation const& _operation) override; bool visit(FunctionCall const& _functionCall) override; - struct TypeComp - { - bool operator()(Type const* lhs, Type const* rhs) const - { - solAssert(lhs && rhs, ""); - return lhs->richIdentifier() < rhs->richIdentifier(); - } - }; - using TypeSet = std::set; - - /// @returns the size of this type in storage, including all sub-types. - static bigint structureSizeEstimate( - Type const& _type, - std::set& _structsSeen, - TypeSet& _oversizedSubTypes - ); - langutil::ErrorReporter& m_errorReporter; /// Flag that indicates whether the current contract definition is a library. diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 267d5764fd66..26d90f4f1dda 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 78aa6b82f55e..1ace2f36a0b7 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5c49bf1dc50c..0a14d5cc9a6f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 @@ -36,6 +37,7 @@ #include #include +#include #include #include @@ -91,6 +93,8 @@ bool TypeChecker::visit(ContractDefinition const& _contract) for (auto const& n: _contract.subNodes()) n->accept(*this); + m_currentContract = nullptr; + return false; } @@ -334,7 +338,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function) if (_function.libraryFunction()) m_errorReporter.typeError(7708_error, _function.location(), "Library functions cannot be payable."); if (_function.isOrdinary() && !_function.isPartOfExternalInterface()) - m_errorReporter.typeError(5587_error, _function.location(), "Internal functions cannot be payable."); + m_errorReporter.typeError(5587_error, _function.location(), "\"internal\" and \"private\" functions cannot be payable."); } auto checkArgumentAndReturnParameter = [&](VariableDeclaration const& var) { if (type(var)->category() == Type::Category::Mapping) @@ -523,6 +527,10 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) m_errorReporter.typeError(6744_error, _variable.location(), "Internal or recursive type is not allowed for public state variables."); } + bool isStructMemberDeclaration = dynamic_cast(_variable.scope()) != nullptr; + if (isStructMemberDeclaration) + return false; + if (auto referenceType = dynamic_cast(varType)) { auto result = referenceType->validForLocation(referenceType->location()); @@ -532,7 +540,35 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) { solAssert(!result.message().empty(), "Expected detailed error message"); m_errorReporter.typeError(1534_error, _variable.location(), result.message()); + return false; + } + } + + if (varType->dataStoredIn(DataLocation::Storage)) + { + auto collisionMessage = [&](string const& variableOrType, bool isVariable) -> string { + return + (isVariable ? "Variable " : "Type ") + + util::escapeAndQuoteString(variableOrType) + + " covers a large part of storage and thus makes collisions likely." + " Either use mappings or dynamic arrays and allow their size to be increased only" + " in small quantities per transaction."; + }; + + if (varType->storageSizeUpperBound() >= bigint(1) << 64) + { + if (_variable.isStateVariable()) + m_errorReporter.warning(3408_error, _variable.location(), collisionMessage(_variable.name(), true)); + else + m_errorReporter.warning( + 2332_error, + _variable.typeName() ? _variable.typeName()->location() : _variable.location(), + collisionMessage(varType->canonicalName(), false) + ); } + vector oversizedSubtypes = frontend::oversizedSubtypes(*varType); + for (Type const* subtype: oversizedSubtypes) + m_errorReporter.warning(7325_error, _variable.typeName()->location(), collisionMessage(subtype->canonicalName(), false)); } return false; @@ -629,7 +665,7 @@ bool TypeChecker::visit(EventDefinition const& _eventDef) m_errorReporter.typeError(8598_error, _eventDef.location(), "More than 4 indexed arguments for anonymous event."); else if (!_eventDef.isAnonymous() && numIndexed > 3) m_errorReporter.typeError(7249_error, _eventDef.location(), "More than 3 indexed arguments for event."); - return false; + return true; } void TypeChecker::endVisit(FunctionTypeName const& _funType) @@ -1270,7 +1306,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) 1719_error, _statement.location(), "Use of the \"var\" keyword is disallowed. " - "Use explicit declaration `" + createTupleDecl(variables) + " = ...´ instead." + "Use explicit declaration `" + createTupleDecl(variables) + " = ...` instead." ); } @@ -2354,6 +2390,8 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions) { solAssert(_functionCallOptions.options().size() == _functionCallOptions.names().size(), "Lengths of name & value arrays differ!"); + _functionCallOptions.expression().annotation().arguments = _functionCallOptions.annotation().arguments; + _functionCallOptions.expression().accept(*this); auto expressionFunctionType = dynamic_cast(type(_functionCallOptions.expression())); diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 9e5f9470f556..e34c9e9d06a0 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 09c8a34b3c59..d2e1b3e43d72 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libsolidity/analysis/ViewPureChecker.h b/libsolidity/analysis/ViewPureChecker.h index 10e60f05183c..87135b4f762c 100644 --- a/libsolidity/analysis/ViewPureChecker.h +++ b/libsolidity/analysis/ViewPureChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index cba5bccc39e4..7c1ed2aa8b32 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 34fefeb0a042..eb2b4f87d2b1 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/ast/ASTAnnotations.cpp b/libsolidity/ast/ASTAnnotations.cpp index eb3caf721fbe..3556041d849c 100644 --- a/libsolidity/ast/ASTAnnotations.cpp +++ b/libsolidity/ast/ASTAnnotations.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 507559ca6ceb..272bf6440e15 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 @@ -78,6 +79,8 @@ struct StructurallyDocumentedAnnotation /// Mapping docstring tag name -> content. std::multimap docTags; + /// contract that @inheritdoc references if it exists + ContractDefinition const* inheritdocReference = nullptr; }; struct SourceUnitAnnotation: ASTAnnotation diff --git a/libsolidity/ast/ASTEnums.h b/libsolidity/ast/ASTEnums.h index 19279c6b7947..e167e7d49069 100644 --- a/libsolidity/ast/ASTEnums.h +++ b/libsolidity/ast/ASTEnums.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Enums for AST classes. diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index 38da35218ebe..3f082d975bf0 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 219151f89286..39b92bbb45db 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Converts the AST into json format diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index a1d3cd4ad843..bb5d9651c199 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris * @date 2015 diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index ccf9af5a74df..33975d8caca1 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author julius * @date 2019 diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index ebcbd660c108..0bfb111bf4ea 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author julius * @date 2019 diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index 483b75301ac3..54db7002e59a 100644 --- a/libsolidity/ast/ASTUtils.cpp +++ b/libsolidity/ast/ASTUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index af77b60f11a6..38465d8d53d5 100644 --- a/libsolidity/ast/ASTUtils.h +++ b/libsolidity/ast/ASTUtils.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index 52e90b0d75b1..c5aeba402f30 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h index e597ce46b305..2105e369da4d 100644 --- a/libsolidity/ast/AST_accept.h +++ b/libsolidity/ast/AST_accept.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/ast/AsmJsonImporter.cpp b/libsolidity/ast/AsmJsonImporter.cpp index 3023888414ac..3ff280f5455f 100644 --- a/libsolidity/ast/AsmJsonImporter.cpp +++ b/libsolidity/ast/AsmJsonImporter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author julius * @date 2019 diff --git a/libsolidity/ast/AsmJsonImporter.h b/libsolidity/ast/AsmJsonImporter.h index 498b4e489bc8..b4e8cfe7b7f5 100644 --- a/libsolidity/ast/AsmJsonImporter.h +++ b/libsolidity/ast/AsmJsonImporter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author julius * @date 2019 diff --git a/libsolidity/ast/ExperimentalFeatures.h b/libsolidity/ast/ExperimentalFeatures.h index 6fdc6897b04b..772bc4e083a8 100644 --- a/libsolidity/ast/ExperimentalFeatures.h +++ b/libsolidity/ast/ExperimentalFeatures.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * List of experimental features. */ diff --git a/libsolidity/ast/TypeProvider.cpp b/libsolidity/ast/TypeProvider.cpp index 6fd7784031f3..c7ef3cfbd93b 100644 --- a/libsolidity/ast/TypeProvider.cpp +++ b/libsolidity/ast/TypeProvider.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libsolidity/ast/TypeProvider.h b/libsolidity/ast/TypeProvider.h index a86542d1688a..1f9ba4329f07 100644 --- a/libsolidity/ast/TypeProvider.h +++ b/libsolidity/ast/TypeProvider.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 992f0343d953..b382e9803103 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -53,6 +54,57 @@ using namespace solidity::frontend; namespace { +struct TypeComp +{ + bool operator()(Type const* lhs, Type const* rhs) const + { + solAssert(lhs && rhs, ""); + return lhs->richIdentifier() < rhs->richIdentifier(); + } +}; +using TypeSet = std::set; + +void oversizedSubtypesInner( + Type const& _type, + bool _includeType, + set& _structsSeen, + TypeSet& _oversizedSubtypes +) +{ + switch (_type.category()) + { + case Type::Category::Array: + { + auto const& t = dynamic_cast(_type); + if (_includeType && t.storageSizeUpperBound() >= bigint(1) << 64) + _oversizedSubtypes.insert(&t); + oversizedSubtypesInner(*t.baseType(), t.isDynamicallySized(), _structsSeen, _oversizedSubtypes); + break; + } + case Type::Category::Struct: + { + auto const& t = dynamic_cast(_type); + if (_structsSeen.count(&t.structDefinition())) + return; + if (_includeType && t.storageSizeUpperBound() >= bigint(1) << 64) + _oversizedSubtypes.insert(&t); + _structsSeen.insert(&t.structDefinition()); + for (auto const& m: t.members(nullptr)) + oversizedSubtypesInner(*m.type, false, _structsSeen, _oversizedSubtypes); + _structsSeen.erase(&t.structDefinition()); + break; + } + case Type::Category::Mapping: + { + auto const* valueType = dynamic_cast(_type).valueType(); + oversizedSubtypesInner(*valueType, true, _structsSeen, _oversizedSubtypes); + break; + } + default: + break; + } +} + /// Check whether (_base ** _exp) fits into 4096 bits. bool fitsPrecisionExp(bigint const& _base, bigint const& _exp) { @@ -149,6 +201,16 @@ util::Result transformParametersToExternal(TypePointers const& _pa } +vector solidity::frontend::oversizedSubtypes(frontend::Type const& _type) +{ + set structsSeen; + TypeSet oversized; + oversizedSubtypesInner(_type, false, structsSeen, oversized); + vector res; + copy(oversized.cbegin(), oversized.cend(), back_inserter(res)); + return res; +} + void Type::clearCache() const { m_members.clear(); @@ -1749,6 +1811,8 @@ BoolResult ArrayType::validForLocation(DataLocation _loc) const break; } case DataLocation::Storage: + if (storageSizeUpperBound() >= bigint(1) << 256) + return BoolResult::err("Type too large for storage."); break; } return true; @@ -1788,6 +1852,14 @@ bool ArrayType::isDynamicallyEncoded() const return isDynamicallySized() || baseType()->isDynamicallyEncoded(); } +bigint ArrayType::storageSizeUpperBound() const +{ + if (isDynamicallySized()) + return 1; + else + return length() * baseType()->storageSizeUpperBound(); +} + u256 ArrayType::storageSize() const { if (isDynamicallySized()) @@ -2247,6 +2319,14 @@ u256 StructType::memoryDataSize() const return size; } +bigint StructType::storageSizeUpperBound() const +{ + bigint size = 1; + for (auto const& member: members(nullptr)) + size += member.type->storageSizeUpperBound(); + return size; +} + u256 StructType::storageSize() const { return max(1, members(nullptr).storageSize()); @@ -2388,6 +2468,13 @@ BoolResult StructType::validForLocation(DataLocation _loc) const if (!result) return result; } + + if ( + _loc == DataLocation::Storage && + storageSizeUpperBound() >= bigint(1) << 256 + ) + return BoolResult::err("Type too large for storage."); + return true; } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index b902a1c77de1..02f5c9f5f1a9 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -54,6 +55,13 @@ using rational = boost::rational; using TypeResult = util::Result; using BoolResult = util::Result; +} + +namespace solidity::frontend +{ + +std::vector oversizedSubtypes(frontend::Type const& _type); + inline rational makeRational(bigint const& _numerator, bigint const& _denominator) { solAssert(_denominator != 0, "division by zero"); @@ -243,6 +251,10 @@ class Type /// @returns the number of storage slots required to hold this value in storage. /// For dynamically "allocated" types, it returns the size of the statically allocated head, virtual u256 storageSize() const { return 1; } + /// @returns an upper bound on the total storage size required by this type, descending + /// into structs and statically-sized arrays. This is mainly to ensure that the storage + /// slot allocation algorithm does not overflow, it is not a protection against collisions. + virtual bigint storageSizeUpperBound() const { return 1; } /// Multiple small types can be packed into a single storage slot. If such a packing is possible /// this function @returns the size in bytes smaller than 32. Data is moved to the next slot if /// it does not fit. @@ -780,6 +792,7 @@ class ArrayType: public ReferenceType unsigned calldataEncodedTailSize() const override; bool isDynamicallySized() const override { return m_hasDynamicLength; } bool isDynamicallyEncoded() const override; + bigint storageSizeUpperBound() const override; u256 storageSize() const override; bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); } bool nameable() const override { return true; } @@ -944,6 +957,7 @@ class StructType: public ReferenceType unsigned calldataEncodedTailSize() const override; bool isDynamicallyEncoded() const override; u256 memoryDataSize() const override; + bigint storageSizeUpperBound() const override; u256 storageSize() const override; bool canLiveOutsideStorage() const override { return true; } bool nameable() const override { return true; } diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 9f244fdb15dd..ef5948069c5b 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2017 diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index a66b1284e931..e3a7e6f187d7 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2017 diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index eebe03e53849..ef94b6bf241f 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 @@ -935,11 +936,6 @@ void ArrayUtils::clearStorageLoop(TypePointer _type) const } // stack: end_pos pos - // jump to and return from the loop to allow for duplicate code removal - evmasm::AssemblyItem returnTag = _context.pushNewTag(); - _context << Instruction::SWAP2 << Instruction::SWAP1; - - // stack: end_pos pos evmasm::AssemblyItem loopStart = _context.appendJumpToNew(); _context << loopStart; // check for loop condition @@ -959,11 +955,8 @@ void ArrayUtils::clearStorageLoop(TypePointer _type) const _context.appendJumpTo(loopStart); // cleanup _context << zeroLoopEnd; - _context << Instruction::POP << Instruction::SWAP1; - // "return" - _context << Instruction::JUMP; + _context << Instruction::POP; - _context << returnTag; solAssert(_context.stackHeight() == stackHeightStart - 1, ""); } ); diff --git a/libsolidity/codegen/ArrayUtils.h b/libsolidity/codegen/ArrayUtils.h index 2ee0879741e3..7cc01dd26c62 100644 --- a/libsolidity/codegen/ArrayUtils.h +++ b/libsolidity/codegen/ArrayUtils.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index f343f2377596..a64a3400986c 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index e12332015ff1..11d5c2abd9d8 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 2f3659010a51..9fde94e8a40a 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index c32b5140627f..f82c705d8847 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index b3fc9da2efa2..f2db905691ca 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -180,7 +181,7 @@ void CompilerUtils::storeInMemory(unsigned _offset) m_context << u256(_offset) << Instruction::MSTORE; } -void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries) +void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries, bool _cleanup) { // process special types (Reference, StringLiteral, Function) if (auto ref = dynamic_cast(&_type)) @@ -189,7 +190,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound ref->location() == DataLocation::Memory, "Only in-memory reference type can be stored." ); - storeInMemoryDynamic(*TypeProvider::uint256(), _padToWordBoundaries); + storeInMemoryDynamic(*TypeProvider::uint256(), _padToWordBoundaries, _cleanup); } else if (auto str = dynamic_cast(&_type)) { @@ -212,7 +213,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound } else if (_type.isValueType()) { - unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries); + unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries, _cleanup); m_context << Instruction::DUP2 << Instruction::MSTORE; m_context << u256(numBytes) << Instruction::ADD; } @@ -463,6 +464,7 @@ void CompilerUtils::encodeToMemory( } else { + bool needCleanup = true; copyToStackTop(argSize - stackPos + dynPointers + 2, _givenTypes[i]->sizeOnStack()); solAssert(!!targetType, "Externalable type expected."); TypePointer type = targetType; @@ -481,7 +483,11 @@ void CompilerUtils::encodeToMemory( ) type = _givenTypes[i]; // delay conversion else + { convertType(*_givenTypes[i], *targetType, true); + needCleanup = false; + } + if (auto arrayType = dynamic_cast(type)) ArrayUtils(m_context).copyArrayToMemory(*arrayType, _padToWordBoundaries); else if (auto arraySliceType = dynamic_cast(type)) @@ -495,7 +501,7 @@ void CompilerUtils::encodeToMemory( ArrayUtils(m_context).copyArrayToMemory(arraySliceType->arrayType(), _padToWordBoundaries); } else - storeInMemoryDynamic(*type, _padToWordBoundaries); + storeInMemoryDynamic(*type, _padToWordBoundaries, needCleanup); } stackPos += _givenTypes[i]->sizeOnStack(); } @@ -1499,7 +1505,7 @@ void CompilerUtils::rightShiftNumberOnStack(unsigned _bits) m_context << (u256(1) << _bits) << Instruction::SWAP1 << Instruction::DIV; } -unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords) +unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords, bool _cleanup) { solAssert( _type.sizeOnStack() == 1, @@ -1522,7 +1528,9 @@ unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords) bool leftAligned = _type.category() == Type::Category::FixedBytes; - convertType(_type, _type, true); + if (_cleanup) + convertType(_type, _type, true); + if (numBytes != 32 && !leftAligned && !_padToWords) // shift the value accordingly before storing leftShiftNumberOnStack((32 - numBytes) * 8); diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index a3c266bdee35..64ab84fe78f9 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -107,10 +108,11 @@ class CompilerUtils /// and also updates that. For reference types, only copies the data pointer. Fails for /// non-memory-references. /// @param _padToWords if true, adds zeros to pad to multiple of 32 bytes. Array elements + /// @param _cleanup if true, adds code to cleanup the value before storing it. /// are always padded (except for byte arrays), regardless of this parameter. /// Stack pre: memory_offset value... /// Stack post: (memory_offset+length) - void storeInMemoryDynamic(Type const& _type, bool _padToWords = true); + void storeInMemoryDynamic(Type const& _type, bool _padToWords = true, bool _cleanup = true); /// Creates code that unpacks the arguments according to their types specified by a vector of TypePointers. /// From memory if @a _fromMemory is true, otherwise from call data. @@ -309,7 +311,8 @@ class CompilerUtils void cleanHigherOrderBits(IntegerType const& _typeOnStack); /// Prepares the given type for storing in memory by shifting it if necessary. - unsigned prepareMemoryStore(Type const& _type, bool _padToWords); + /// @param _cleanup if true, also cleanup the value when preparing to store it in memory + unsigned prepareMemoryStore(Type const& _type, bool _padToWords, bool _cleanup = true); /// Loads type from memory assuming memory offset is on stack top. unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWords); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 3d1b41e41ff7..225628a6cf5c 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -646,7 +647,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function) } else { - m_context << swapInstruction(stackLayout.size() - static_cast(stackLayout.back()) - 1); + m_context << swapInstruction(stackLayout.size() - static_cast(stackLayout.back()) - 1u); swap(stackLayout[static_cast(stackLayout.back())], stackLayout.back()); } for (size_t i = 0; i < stackLayout.size(); ++i) diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h index 0916da281a2b..d4badc1974a2 100644 --- a/libsolidity/codegen/ContractCompiler.h +++ b/libsolidity/codegen/ContractCompiler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index ffa8ced4c426..566db8517eab 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -792,20 +793,24 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) TypePointer const& argType = arguments.front()->annotation().type; solAssert(argType, ""); arguments.front()->accept(*this); - // Optimization: If type is bytes or string, then do not encode, - // but directly compute keccak256 on memory. - if (*argType == *TypeProvider::bytesMemory() || *argType == *TypeProvider::stringMemory()) + if (auto const* stringLiteral = dynamic_cast(argType)) + // Optimization: Compute keccak256 on string literals at compile-time. + m_context << u256(keccak256(stringLiteral->value())); + else if (*argType == *TypeProvider::bytesMemory() || *argType == *TypeProvider::stringMemory()) { + // Optimization: If type is bytes or string, then do not encode, + // but directly compute keccak256 on memory. ArrayUtils(m_context).retrieveLength(*TypeProvider::bytesMemory()); m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD; + m_context << Instruction::KECCAK256; } else { utils().fetchFreeMemoryPointer(); utils().packedEncode({argType}, TypePointers()); utils().toSizeAfterFreeMemoryPointer(); + m_context << Instruction::KECCAK256; } - m_context << Instruction::KECCAK256; break; } case FunctionType::Kind::Log0: diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index 0216b260bfed..c0a703d783f2 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @author Gav Wood diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 798428098a1c..77719676759d 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index cd72f37e00a3..9bf0d1c05c0c 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/codegen/MultiUseYulFunctionCollector.cpp b/libsolidity/codegen/MultiUseYulFunctionCollector.cpp index f49f3083d37a..0049deb780f8 100644 --- a/libsolidity/codegen/MultiUseYulFunctionCollector.cpp +++ b/libsolidity/codegen/MultiUseYulFunctionCollector.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Container of (unparsed) Yul functions identified by name which are meant to be generated * only once. diff --git a/libsolidity/codegen/MultiUseYulFunctionCollector.h b/libsolidity/codegen/MultiUseYulFunctionCollector.h index 031d08bdef36..428a0c9a3cc2 100644 --- a/libsolidity/codegen/MultiUseYulFunctionCollector.h +++ b/libsolidity/codegen/MultiUseYulFunctionCollector.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Container of (unparsed) Yul functions identified by name which are meant to be generated * only once. diff --git a/libsolidity/codegen/ReturnInfo.cpp b/libsolidity/codegen/ReturnInfo.cpp index b522addd4d25..f0828befd9a8 100644 --- a/libsolidity/codegen/ReturnInfo.cpp +++ b/libsolidity/codegen/ReturnInfo.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/codegen/ReturnInfo.h b/libsolidity/codegen/ReturnInfo.h index 01aa308620ff..e1e5719ef461 100644 --- a/libsolidity/codegen/ReturnInfo.h +++ b/libsolidity/codegen/ReturnInfo.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that computes information relevant during decoding an external function * call's return values. diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 7678a0befe92..0bd6b0d3a37b 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that can generate various useful Yul functions. */ @@ -1619,26 +1620,45 @@ string YulUtilFunctions::zeroComplexMemoryArrayFunction(ArrayType const& _type) }); } -string YulUtilFunctions::allocateAndInitializeMemoryArrayFunction(ArrayType const& _type) +string YulUtilFunctions::allocateMemoryArrayFunction(ArrayType const& _type) { - string functionName = "allocate_and_zero_memory_array_" + _type.identifier(); + string functionName = "allocate_memory_array_" + _type.identifier(); return m_functionCollector.createFunction(functionName, [&]() { return Whiskers(R"( function (length) -> memPtr { let allocSize := (length) memPtr := (allocSize) + + mstore(memPtr, length) + + } + )") + ("functionName", functionName) + ("alloc", allocationFunction()) + ("allocSize", arrayAllocationSizeFunction(_type)) + ("dynamic", _type.isDynamicallySized()) + .render(); + }); +} + +string YulUtilFunctions::allocateAndInitializeMemoryArrayFunction(ArrayType const& _type) +{ + string functionName = "allocate_and_zero_memory_array_" + _type.identifier(); + return m_functionCollector.createFunction(functionName, [&]() { + return Whiskers(R"( + function (length) -> memPtr { + memPtr := (length) let dataStart := memPtr - let dataSize := allocSize + let dataSize := (length) dataStart := add(dataStart, 32) dataSize := sub(dataSize, 32) - mstore(memPtr, length) (dataStart, dataSize) } )") ("functionName", functionName) - ("alloc", allocationFunction()) + ("allocArray", allocateMemoryArrayFunction(_type)) ("allocSize", arrayAllocationSizeFunction(_type)) ("zeroArrayFunction", zeroMemoryArrayFunction(_type)) ("dynamic", _type.isDynamicallySized()) diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index c1d98cfe48ec..19ca72dd0073 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that can generate various useful Yul functions. */ @@ -281,6 +282,12 @@ class YulUtilFunctions /// signature: (dataStart, dataSizeInBytes) -> std::string zeroComplexMemoryArrayFunction(ArrayType const& _type); + /// @returns the name of a function that allocates a memory array. + /// For dynamic arrays it adds space for length and stores it. + /// The contents of the data area are unspecified. + /// signature: (length) -> memPtr + std::string allocateMemoryArrayFunction(ArrayType const& _type); + /// @returns the name of a function that allocates and zeroes a memory array. /// For dynamic arrays it adds space for length and stores it. /// signature: (length) -> memPtr diff --git a/libsolidity/codegen/ir/Common.cpp b/libsolidity/codegen/ir/Common.cpp index 2bf4a36cfabf..42a4650dbbf3 100644 --- a/libsolidity/codegen/ir/Common.cpp +++ b/libsolidity/codegen/ir/Common.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libsolidity/codegen/ir/Common.h b/libsolidity/codegen/ir/Common.h index 3f4ea64f4f67..da6c61a7f1b6 100644 --- a/libsolidity/codegen/ir/Common.h +++ b/libsolidity/codegen/ir/Common.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Miscellaneous utilities for use in IR generator. */ diff --git a/libsolidity/codegen/ir/IRGenerationContext.cpp b/libsolidity/codegen/ir/IRGenerationContext.cpp index b85e2f7d3ed1..7476dd90e6f9 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.cpp +++ b/libsolidity/codegen/ir/IRGenerationContext.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Class that contains contextual information during IR generation. */ diff --git a/libsolidity/codegen/ir/IRGenerationContext.h b/libsolidity/codegen/ir/IRGenerationContext.h index d6d8022dfbe7..469beea2fe92 100644 --- a/libsolidity/codegen/ir/IRGenerationContext.h +++ b/libsolidity/codegen/ir/IRGenerationContext.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Class that contains contextual information during IR generation. */ diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 92df1ba83e73..f7f66b4f58a1 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * @date 2017 diff --git a/libsolidity/codegen/ir/IRGenerator.h b/libsolidity/codegen/ir/IRGenerator.h index 6bf94e575b1d..e57b8535e6eb 100644 --- a/libsolidity/codegen/ir/IRGenerator.h +++ b/libsolidity/codegen/ir/IRGenerator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * @date 2017 diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index c14d6512120e..d28ee2e9c396 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that translates Solidity code into Yul at statement level and below. */ @@ -310,7 +311,31 @@ bool IRGeneratorForStatements::visit(Assignment const& _assignment) bool IRGeneratorForStatements::visit(TupleExpression const& _tuple) { if (_tuple.isInlineArray()) - solUnimplementedAssert(false, ""); + { + auto const& arrayType = dynamic_cast(*_tuple.annotation().type); + solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); + define(_tuple) << + m_utils.allocateMemoryArrayFunction(arrayType) << + "(" << + _tuple.components().size() << + ")\n"; + + string mpos = IRVariable(_tuple).part("mpos").name(); + Type const& baseType = *arrayType.baseType(); + for (size_t i = 0; i < _tuple.components().size(); i++) + { + Expression const& component = *_tuple.components()[i]; + component.accept(*this); + IRVariable converted = convert(component, baseType); + m_code << + m_utils.writeToMemoryFunction(baseType) << + "(" << + ("add(" + mpos + ", " + to_string(i * arrayType.memoryStride()) + ")") << + ", " << + converted.name() << + ")\n"; + } + } else { bool willBeWrittenTo = _tuple.annotation().willBeWrittenTo; @@ -1020,18 +1045,28 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) ArrayType const* arrayType = TypeProvider::bytesMemory(); - auto array = convert(*arguments[0], *arrayType); + if (auto const* stringLiteral = dynamic_cast(arguments.front()->annotation().type)) + { + // Optimization: Compute keccak256 on string literals at compile-time. + define(_functionCall) << + ("0x" + keccak256(stringLiteral->value()).hex()) << + "\n"; + } + else + { + auto array = convert(*arguments[0], *arrayType); - define(_functionCall) << - "keccak256(" << - m_utils.arrayDataAreaFunction(*arrayType) << - "(" << - array.commaSeparatedList() << - "), " << - m_utils.arrayLengthFunction(*arrayType) << - "(" << - array.commaSeparatedList() << - "))\n"; + define(_functionCall) << + "keccak256(" << + m_utils.arrayDataAreaFunction(*arrayType) << + "(" << + array.commaSeparatedList() << + "), " << + m_utils.arrayLengthFunction(*arrayType) << + "(" << + array.commaSeparatedList() << + "))\n"; + } break; } case FunctionType::Kind::ArrayPop: @@ -1456,7 +1491,6 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) solAssert(false, "Blockhash has been removed."); else if (member == "creationCode" || member == "runtimeCode") { - solUnimplementedAssert(member != "runtimeCode", ""); TypePointer arg = dynamic_cast(*_memberAccess.expression().annotation().type).typeArgument(); ContractDefinition const& contract = dynamic_cast(*arg).contractDefinition(); m_context.subObjectsCreated().insert(&contract); @@ -1468,7 +1502,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) )") ("allocationFunction", m_utils.allocationFunction()) ("size", m_context.newYulVariable()) - ("objectName", IRNames::creationObject(contract)) + ("objectName", IRNames::creationObject(contract) + (member == "runtimeCode" ? "." + IRNames::runtimeObject(contract) : "")) ("result", IRVariable(_memberAccess).commaSeparatedList()).render(); } else if (member == "name") diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.h b/libsolidity/codegen/ir/IRGeneratorForStatements.h index bdf21f783e0b..09c9c7d278bf 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.h +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that translates Solidity code into Yul at statement level and below. */ diff --git a/libsolidity/codegen/ir/IRLValue.h b/libsolidity/codegen/ir/IRLValue.h index c5eadc9b2753..fef390d4cb89 100644 --- a/libsolidity/codegen/ir/IRLValue.h +++ b/libsolidity/codegen/ir/IRLValue.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Classes that store locations of lvalues. */ diff --git a/libsolidity/codegen/ir/IRVariable.cpp b/libsolidity/codegen/ir/IRVariable.cpp index 8cb1896a6f12..3fce5288a159 100644 --- a/libsolidity/codegen/ir/IRVariable.cpp +++ b/libsolidity/codegen/ir/IRVariable.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libsolidity/codegen/ir/IRVariable.h b/libsolidity/codegen/ir/IRVariable.h index dbf37704c070..71413cc38907 100644 --- a/libsolidity/codegen/ir/IRVariable.h +++ b/libsolidity/codegen/ir/IRVariable.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libsolidity/formal/BMC.cpp b/libsolidity/formal/BMC.cpp index 8f74dbb3e8b3..363910edd1e5 100644 --- a/libsolidity/formal/BMC.cpp +++ b/libsolidity/formal/BMC.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -52,11 +53,11 @@ BMC::BMC( #endif } -void BMC::analyze(SourceUnit const& _source, set _safeAssertions) +void BMC::analyze(SourceUnit const& _source, map> _solvedTargets) { solAssert(_source.annotation().experimentalFeatures.count(ExperimentalFeature::SMTChecker), ""); - m_safeAssertions += move(_safeAssertions); + m_solvedTargets = move(_solvedTargets); m_context.setSolver(m_interface.get()); m_context.clear(); m_context.setAssertionAccumulation(true); @@ -684,16 +685,22 @@ void BMC::checkBalance(BMCVerificationTarget& _target) void BMC::checkAssert(BMCVerificationTarget& _target) { solAssert(_target.type == VerificationTarget::Type::Assert, ""); - if (!m_safeAssertions.count(_target.expression)) - checkCondition( - _target.constraints && !_target.value, - _target.callStack, - _target.modelExpressions, - _target.expression->location(), - 4661_error, - 7812_error, - "Assertion violation" - ); + + if ( + m_solvedTargets.count(_target.expression) && + m_solvedTargets.at(_target.expression).count(_target.type) + ) + return; + + checkCondition( + _target.constraints && !_target.value, + _target.callStack, + _target.modelExpressions, + _target.expression->location(), + 4661_error, + 7812_error, + "Assertion violation" + ); } void BMC::addVerificationTarget( diff --git a/libsolidity/formal/BMC.h b/libsolidity/formal/BMC.h index 4f0a980236d4..324595bbaf6c 100644 --- a/libsolidity/formal/BMC.h +++ b/libsolidity/formal/BMC.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Class that implements an SMT-based Bounded Model Checker (BMC). * Traverses the AST such that: @@ -63,7 +64,7 @@ class BMC: public SMTEncoder smtutil::SMTSolverChoice _enabledSolvers ); - void analyze(SourceUnit const& _sources, std::set _safeAssertions); + void analyze(SourceUnit const& _sources, std::map> _solvedTargets); /// 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 @@ -180,8 +181,8 @@ class BMC: public SMTEncoder std::vector m_verificationTargets; - /// Assertions that are known to be safe. - std::set m_safeAssertions; + /// Targets that were already proven. + std::map> m_solvedTargets; }; } diff --git a/libsolidity/formal/CHC.cpp b/libsolidity/formal/CHC.cpp index c3e9d6cb4763..f68872d5c816 100644 --- a/libsolidity/formal/CHC.cpp +++ b/libsolidity/formal/CHC.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -96,48 +97,7 @@ void CHC::analyze(SourceUnit const& _source) for (auto const* source: sources) source->accept(*this); - for (auto const& [scope, target]: m_verificationTargets) - { - if (target.type == VerificationTarget::Type::Assert) - { - auto assertions = transactionAssertions(scope); - for (auto const* assertion: assertions) - { - createErrorBlock(); - connectBlocks(target.value, error(), target.constraints && (target.errorId == static_cast(assertion->id()))); - auto [result, model] = query(error(), assertion->location()); - // This should be fine but it's a bug in the old compiler - (void)model; - if (result == smtutil::CheckResult::UNSATISFIABLE) - m_safeAssertions.insert(assertion); - } - } - else if (target.type == VerificationTarget::Type::PopEmptyArray) - { - solAssert(dynamic_cast(scope), ""); - createErrorBlock(); - connectBlocks(target.value, error(), target.constraints && (target.errorId == static_cast(scope->id()))); - auto [result, model] = query(error(), scope->location()); - // This should be fine but it's a bug in the old compiler - (void)model; - if (result != smtutil::CheckResult::UNSATISFIABLE) - { - string msg = "Empty array \"pop\" "; - if (result == smtutil::CheckResult::SATISFIABLE) - msg += "detected here."; - else - msg += "might happen here."; - m_unsafeTargets.insert(scope); - m_outerErrorReporter.warning( - 2529_error, - scope->location(), - msg - ); - } - } - else - solAssert(false, ""); - } + checkVerificationTargets(); } vector CHC::unhandledQueries() const @@ -540,7 +500,7 @@ void CHC::visitAssert(FunctionCall const& _funCall) m_currentBlock, m_currentFunction->isConstructor() ? summary(*m_currentContract) : summary(*m_currentFunction), currentPathConditions() && !m_context.expression(*args.front())->currentValue() && ( - m_error.currentValue() == static_cast(_funCall.id()) + m_error.currentValue() == newErrorId(_funCall) ) ); @@ -638,7 +598,7 @@ void CHC::makeArrayPopVerificationTarget(FunctionCall const& _arrayPop) connectBlocks( m_currentBlock, m_currentFunction->isConstructor() ? summary(*m_currentContract) : summary(*m_currentFunction), - currentPathConditions() && symbArray->length() <= 0 && m_error.currentValue() == static_cast(_arrayPop.id()) + currentPathConditions() && symbArray->length() <= 0 && m_error.currentValue() == newErrorId(_arrayPop) ); m_context.addAssertion(m_error.currentValue() == previousError); @@ -647,9 +607,10 @@ void CHC::makeArrayPopVerificationTarget(FunctionCall const& _arrayPop) void CHC::resetSourceAnalysis() { m_verificationTargets.clear(); - m_safeAssertions.clear(); + m_safeTargets.clear(); m_unsafeTargets.clear(); m_functionAssertions.clear(); + m_errorIds.clear(); m_callGraph.clear(); m_summaries.clear(); } @@ -990,13 +951,13 @@ vector CHC::initialStateVariables(ContractDefinition const& return stateVariablesAtIndex(0, _contract); } -vector CHC::stateVariablesAtIndex(int _index) +vector CHC::stateVariablesAtIndex(unsigned _index) { solAssert(m_currentContract, ""); return stateVariablesAtIndex(_index, *m_currentContract); } -vector CHC::stateVariablesAtIndex(int _index, ContractDefinition const& _contract) +vector CHC::stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract) { return applyMap( stateVariablesIncludingInheritedAndPrivate(_contract), @@ -1167,7 +1128,98 @@ void CHC::addArrayPopVerificationTarget(ASTNode const* _scope, smtutil::Expressi } } +void CHC::checkVerificationTargets() +{ + for (auto const& [scope, target]: m_verificationTargets) + { + if (target.type == VerificationTarget::Type::Assert) + checkAssertTarget(scope, target); + else + { + string satMsg; + string unknownMsg; + + if (target.type == VerificationTarget::Type::PopEmptyArray) + { + solAssert(dynamic_cast(scope), ""); + satMsg = "Empty array \"pop\" detected here."; + unknownMsg = "Empty array \"pop\" might happen here."; + } + else + solAssert(false, ""); + + auto it = m_errorIds.find(scope->id()); + solAssert(it != m_errorIds.end(), ""); + checkAndReportTarget(scope, target, it->second, satMsg, unknownMsg); + } + } +} + +void CHC::checkAssertTarget(ASTNode const* _scope, CHCVerificationTarget const& _target) +{ + solAssert(_target.type == VerificationTarget::Type::Assert, ""); + auto assertions = transactionAssertions(_scope); + for (auto const* assertion: assertions) + { + auto it = m_errorIds.find(assertion->id()); + solAssert(it != m_errorIds.end(), ""); + unsigned errorId = it->second; + + createErrorBlock(); + connectBlocks(_target.value, error(), _target.constraints && (_target.errorId == errorId)); + auto [result, model] = query(error(), assertion->location()); + // This should be fine but it's a bug in the old compiler + (void)model; + if (result == smtutil::CheckResult::UNSATISFIABLE) + m_safeTargets[assertion].insert(_target.type); + } +} + +void CHC::checkAndReportTarget( + ASTNode const* _scope, + CHCVerificationTarget const& _target, + unsigned _errorId, + string _satMsg, + string _unknownMsg +) +{ + createErrorBlock(); + connectBlocks(_target.value, error(), _target.constraints && (_target.errorId == _errorId)); + auto [result, model] = query(error(), _scope->location()); + // This should be fine but it's a bug in the old compiler + (void)model; + if (result == smtutil::CheckResult::UNSATISFIABLE) + m_safeTargets[_scope].insert(_target.type); + else if (result == smtutil::CheckResult::SATISFIABLE) + { + solAssert(!_satMsg.empty(), ""); + m_unsafeTargets[_scope].insert(_target.type); + m_outerErrorReporter.warning( + 2529_error, + _scope->location(), + _satMsg + ); + } + else if (!_unknownMsg.empty()) + m_outerErrorReporter.warning( + 1147_error, + _scope->location(), + _unknownMsg + ); +} + string CHC::uniquePrefix() { return to_string(m_blockCounter++); } + +unsigned CHC::newErrorId(frontend::Expression const& _expr) +{ + unsigned errorId = m_context.newUniqueId(); + // We need to make sure the error id is not zero, + // because error id zero actually means no error in the CHC encoding. + if (errorId == 0) + errorId = m_context.newUniqueId(); + m_errorIds.emplace(_expr.id(), errorId); + return errorId; +} diff --git a/libsolidity/formal/CHC.h b/libsolidity/formal/CHC.h index dcba90606c91..d025e31d30d3 100644 --- a/libsolidity/formal/CHC.h +++ b/libsolidity/formal/CHC.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Model checker based on Constrained Horn Clauses. @@ -36,6 +37,7 @@ #include +#include #include namespace solidity::frontend @@ -54,7 +56,8 @@ class CHC: public SMTEncoder void analyze(SourceUnit const& _sources); - std::set const& safeAssertions() const { return m_safeAssertions; } + std::map> const& safeTargets() const { return m_safeTargets; } + std::map> const& unsafeTargets() const { return m_unsafeTargets; } /// This is used if the Horn solver is not directly linked into this binary. /// @returns a list of inputs to the Horn solver that were not part of the argument to @@ -152,8 +155,8 @@ class CHC: public SMTEncoder /// of the current transaction. std::vector initialStateVariables(); std::vector initialStateVariables(ContractDefinition const& _contract); - std::vector stateVariablesAtIndex(int _index); - std::vector stateVariablesAtIndex(int _index, ContractDefinition const& _contract); + std::vector stateVariablesAtIndex(unsigned _index); + std::vector stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract); /// @returns the current symbolic values of the current state variables. std::vector currentStateVariables(); std::vector currentStateVariables(ContractDefinition const& _contract); @@ -191,6 +194,18 @@ class CHC: public SMTEncoder void addVerificationTarget(ASTNode const* _scope, VerificationTarget::Type _type, smtutil::Expression _from, smtutil::Expression _constraints, smtutil::Expression _errorId); void addAssertVerificationTarget(ASTNode const* _scope, smtutil::Expression _from, smtutil::Expression _constraints, smtutil::Expression _errorId); void addArrayPopVerificationTarget(ASTNode const* _scope, smtutil::Expression _errorId); + + void checkVerificationTargets(); + // Forward declaration. Definition is below. + struct CHCVerificationTarget; + void checkAssertTarget(ASTNode const* _scope, CHCVerificationTarget const& _target); + void checkAndReportTarget( + ASTNode const* _scope, + CHCVerificationTarget const& _target, + unsigned _errorId, + std::string _satMsg, + std::string _unknownMsg + ); //@} /// Misc. @@ -198,6 +213,10 @@ class CHC: public SMTEncoder /// Returns a prefix to be used in a new unique block name /// and increases the block counter. std::string uniquePrefix(); + + /// @returns a new unique error id associated with _expr and stores + /// it into m_errorIds. + unsigned newErrorId(Expression const& _expr); //@} /// Predicates. @@ -257,10 +276,10 @@ class CHC: public SMTEncoder std::map m_verificationTargets; - /// Assertions proven safe. - std::set m_safeAssertions; + /// Targets proven safe. + std::map> m_safeTargets; /// Targets proven unsafe. - std::set m_unsafeTargets; + std::map> m_unsafeTargets; //@} /// Control-flow. @@ -271,6 +290,11 @@ class CHC: public SMTEncoder std::map, IdCompare> m_functionAssertions; + /// Maps ASTNode ids to error ids. + /// A multimap is used instead of map anticipating the UnderOverflow + /// target which has 2 error ids. + std::multimap m_errorIds; + /// The current block. smtutil::Expression m_currentBlock = smtutil::Expression(true); diff --git a/libsolidity/formal/EncodingContext.cpp b/libsolidity/formal/EncodingContext.cpp index 57686ace460d..422eb44eeab5 100644 --- a/libsolidity/formal/EncodingContext.cpp +++ b/libsolidity/formal/EncodingContext.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -32,21 +33,21 @@ EncodingContext::EncodingContext(): void EncodingContext::reset() { resetAllVariables(); - resetSlackId(); + resetUniqueId(); m_expressions.clear(); m_globalContext.clear(); m_state.reset(); m_assertions.clear(); } -void EncodingContext::resetSlackId() +void EncodingContext::resetUniqueId() { - m_nextSlackId = 0; + m_nextUniqueId = 0; } -unsigned EncodingContext::newSlackId() +unsigned EncodingContext::newUniqueId() { - return m_nextSlackId++; + return m_nextUniqueId++; } void EncodingContext::clear() diff --git a/libsolidity/formal/EncodingContext.h b/libsolidity/formal/EncodingContext.h index fcfd5e149456..e188792d8130 100644 --- a/libsolidity/formal/EncodingContext.h +++ b/libsolidity/formal/EncodingContext.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once @@ -41,9 +42,9 @@ class EncodingContext /// To be used in the beginning of a root function visit. void reset(); /// Resets the fresh id for slack variables. - void resetSlackId(); + void resetUniqueId(); /// Returns the current fresh slack id and increments it. - unsigned newSlackId(); + unsigned newUniqueId(); /// Clears the entire context, erasing everything. /// To be used before a model checking engine starts. void clear(); @@ -173,8 +174,8 @@ class EncodingContext bool m_accumulateAssertions = true; //@} - /// Fresh ids for slack variables to be created deterministically. - unsigned m_nextSlackId = 0; + /// Central source of unique ids. + unsigned m_nextUniqueId = 0; }; } diff --git a/libsolidity/formal/ModelChecker.cpp b/libsolidity/formal/ModelChecker.cpp index f74e1327da9e..9465dd34200d 100644 --- a/libsolidity/formal/ModelChecker.cpp +++ b/libsolidity/formal/ModelChecker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -41,7 +42,12 @@ void ModelChecker::analyze(SourceUnit const& _source) return; m_chc.analyze(_source); - m_bmc.analyze(_source, m_chc.safeAssertions()); + + auto solvedTargets = m_chc.safeTargets(); + for (auto const& target: m_chc.unsafeTargets()) + solvedTargets[target.first] += target.second; + + m_bmc.analyze(_source, solvedTargets); } vector ModelChecker::unhandledQueries() diff --git a/libsolidity/formal/ModelChecker.h b/libsolidity/formal/ModelChecker.h index b4378e629073..42d116b28556 100644 --- a/libsolidity/formal/ModelChecker.h +++ b/libsolidity/formal/ModelChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Entry point to the model checking engines. * The goal of this class is to make different diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index 6faaaf600ce8..417a169211f1 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -363,8 +364,12 @@ void SMTEncoder::endVisit(Assignment const& _assignment) Token op = _assignment.assignmentOperator(); if (op != Token::Assign && !compoundOps.count(op)) { + Expression const* identifier = &_assignment.leftHandSide(); + if (auto const* indexAccess = dynamic_cast(identifier)) + identifier = leftmostBase(*indexAccess); // Give it a new index anyway to keep the SSA scheme sound. - if (auto varDecl = identifierToVariable(_assignment.leftHandSide())) + solAssert(identifier, ""); + if (auto varDecl = identifierToVariable(*identifier)) m_context.newValue(*varDecl); m_errorReporter.warning( @@ -1072,7 +1077,7 @@ void SMTEncoder::arrayPush(FunctionCall const& _funCall) m_context.addAssertion(symbArray->length() == oldLength + 1); if (arguments.empty()) - defineExpr(_funCall, element); + defineExpr(_funCall, smtutil::Expression::select(symbArray->elements(), oldLength)); arrayPushPopAssign(memberAccess->expression(), symbArray->currentValue()); } @@ -1114,6 +1119,28 @@ void SMTEncoder::arrayPushPopAssign(Expression const& _expr, smtutil::Expression } else if (auto const* indexAccess = dynamic_cast(&_expr)) arrayIndexAssignment(*indexAccess, _array); + else if (auto const* funCall = dynamic_cast(&_expr)) + { + FunctionType const& funType = dynamic_cast(*funCall->expression().annotation().type); + if (funType.kind() == FunctionType::Kind::ArrayPush) + { + auto memberAccess = dynamic_cast(&funCall->expression()); + solAssert(memberAccess, ""); + auto symbArray = dynamic_pointer_cast(m_context.expression(memberAccess->expression())); + solAssert(symbArray, ""); + + auto oldLength = symbArray->length(); + auto store = smtutil::Expression::store( + symbArray->elements(), + symbArray->length() - 1, + _array + ); + symbArray->increaseIndex(); + m_context.addAssertion(symbArray->elements() == store); + m_context.addAssertion(symbArray->length() == oldLength); + arrayPushPopAssign(memberAccess->expression(), symbArray->currentValue()); + } + } else if (dynamic_cast(&_expr)) m_errorReporter.warning( 9599_error, @@ -1253,7 +1280,7 @@ pair SMTEncoder::arithmeticOperation( // - RHS is -1 // the result is then -(type.min), which wraps back to type.min smtutil::Expression maxLeft = _left == smt::minValue(*intType); - smtutil::Expression minusOneRight = _right == -1; + smtutil::Expression minusOneRight = _right == numeric_limits::max(); smtutil::Expression wrap = smtutil::Expression::ite(maxLeft && minusOneRight, smt::minValue(*intType), valueUnbounded); return {wrap, valueUnbounded}; } @@ -1262,7 +1289,7 @@ pair SMTEncoder::arithmeticOperation( auto symbMax = smt::maxValue(*intType); smtutil::Expression intValueRange = (0 - symbMin) + symbMax + 1; - string suffix = to_string(_operation.id()) + "_" + to_string(m_context.newSlackId()); + string suffix = to_string(_operation.id()) + "_" + to_string(m_context.newUniqueId()); smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context); smt::SymbolicIntVariable m(intType, intType, "m_" + suffix, m_context); @@ -1376,9 +1403,11 @@ void SMTEncoder::bitwiseOperation(BinaryOperation const& _op) bvSize = fixedType->numBits(); isSigned = fixedType->isSigned(); } + else if (auto const* fixedBytesType = dynamic_cast(commonType)) + bvSize = fixedBytesType->numBytes() * 8; - auto bvLeft = smtutil::Expression::int2bv(expr(_op.leftExpression()), bvSize); - auto bvRight = smtutil::Expression::int2bv(expr(_op.rightExpression()), bvSize); + auto bvLeft = smtutil::Expression::int2bv(expr(_op.leftExpression(), commonType), bvSize); + auto bvRight = smtutil::Expression::int2bv(expr(_op.rightExpression(), commonType), bvSize); optional result; if (_op.getOperator() == Token::BitAnd) diff --git a/libsolidity/formal/SMTEncoder.h b/libsolidity/formal/SMTEncoder.h index 86ed21ef97d8..92ef0601afff 100644 --- a/libsolidity/formal/SMTEncoder.h +++ b/libsolidity/formal/SMTEncoder.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Encodes Solidity into SMT expressions without creating * any verification targets. diff --git a/libsolidity/formal/SSAVariable.cpp b/libsolidity/formal/SSAVariable.cpp index 5569d8f36219..bb599c35a883 100644 --- a/libsolidity/formal/SSAVariable.cpp +++ b/libsolidity/formal/SSAVariable.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/formal/SSAVariable.h b/libsolidity/formal/SSAVariable.h index bad6fa80cce6..7db69d1fdf53 100644 --- a/libsolidity/formal/SSAVariable.h +++ b/libsolidity/formal/SSAVariable.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/formal/SymbolicState.cpp b/libsolidity/formal/SymbolicState.cpp index 1ab6e18608f0..06fe1bd2aa51 100644 --- a/libsolidity/formal/SymbolicState.cpp +++ b/libsolidity/formal/SymbolicState.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/formal/SymbolicState.h b/libsolidity/formal/SymbolicState.h index 2b234466dde9..aaf6971fa975 100644 --- a/libsolidity/formal/SymbolicState.h +++ b/libsolidity/formal/SymbolicState.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index a46b88e03140..b149cb69c340 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -441,7 +442,11 @@ optional symbolicTypeConversion(TypePointer _from, TypePoin // case they'd need to be encoded as numbers. if (auto strType = dynamic_cast(_from)) if (_to->category() == frontend::Type::Category::FixedBytes) + { + if (strType->value().empty()) + return smtutil::Expression(size_t(0)); return smtutil::Expression(u256(toHex(util::asBytes(strType->value()), util::HexPrefix::Add))); + } return std::nullopt; } diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 226bd5f94697..401c9f0b6788 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 3f86b48d901c..b09938e63082 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/formal/SymbolicVariables.h b/libsolidity/formal/SymbolicVariables.h index 65dce43f02f8..bdf36afd06c4 100644 --- a/libsolidity/formal/SymbolicVariables.h +++ b/libsolidity/formal/SymbolicVariables.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/formal/VariableUsage.cpp b/libsolidity/formal/VariableUsage.cpp index 11ca44ff3be0..1634b3b58f4c 100644 --- a/libsolidity/formal/VariableUsage.cpp +++ b/libsolidity/formal/VariableUsage.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/formal/VariableUsage.h b/libsolidity/formal/VariableUsage.h index 7b55998d25d1..508efbc604a9 100644 --- a/libsolidity/formal/VariableUsage.h +++ b/libsolidity/formal/VariableUsage.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index c00c2f83cd47..512bf9b13684 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Utilities to handle the Contract ABI (https://solidity.readthedocs.io/en/develop/abi-spec.html) */ diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h index 1dd578cebf6b..76b1a4a7594f 100644 --- a/libsolidity/interface/ABI.h +++ b/libsolidity/interface/ABI.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Utilities to handle the Contract ABI (https://solidity.readthedocs.io/en/develop/abi-spec.html) */ diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 164938c60e27..27a51552e3bd 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @author Gav Wood @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -307,6 +309,11 @@ bool CompilerStack::analyze() if (source->ast && !syntaxChecker.checkSyntax(*source->ast)) noErrors = false; + DocStringTagParser DocStringTagParser(m_errorReporter); + for (Source const* source: m_sourceOrder) + if (source->ast && !DocStringTagParser.parseDocStrings(*source->ast)) + noErrors = false; + m_globalContext = make_shared(); // We need to keep the same resolver during the whole process. NameAndTypeResolver resolver(*m_globalContext, m_evmVersion, m_errorReporter); @@ -362,6 +369,7 @@ bool CompilerStack::analyze() if (!contractLevelChecker.check(*contract)) noErrors = false; + // Requires ContractLevelChecker DocStringAnalyser docStringAnalyser(m_errorReporter); for (Source const* source: m_sourceOrder) if (source->ast && !docStringAnalyser.analyseDocStrings(*source->ast)) diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 509623cc1b03..ce0f949b9ef5 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @author Gav Wood diff --git a/libsolidity/interface/DebugSettings.h b/libsolidity/interface/DebugSettings.h index 34818889c953..e0dab05bb234 100644 --- a/libsolidity/interface/DebugSettings.h +++ b/libsolidity/interface/DebugSettings.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Settings to aid debugging. */ diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 1a86f36ceef3..2b56977ff848 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/interface/GasEstimator.h b/libsolidity/interface/GasEstimator.h index 1cfcec9a7586..f814c8b8d2bf 100644 --- a/libsolidity/interface/GasEstimator.h +++ b/libsolidity/interface/GasEstimator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp index a292c7a3d05c..67ef6f17f2f9 100644 --- a/libsolidity/interface/Natspec.cpp +++ b/libsolidity/interface/Natspec.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris * @date 2014 @@ -57,28 +58,22 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef) for (auto const& it: _contractDef.interfaceFunctions()) if (it.second->hasDeclaration()) { + string value; + if (auto const* f = dynamic_cast(&it.second->declaration())) - { - string value = extractDoc(f->annotation().docTags, "notice"); - if (!value.empty()) - { - Json::Value user; - // since @notice is the only user tag if missing function should not appear - user["notice"] = Json::Value(value); - methods[it.second->externalSignature()] = user; - } - } + value = extractDoc(f->annotation().docTags, "notice"); else if (auto var = dynamic_cast(&it.second->declaration())) { solAssert(var->isStateVariable() && var->isPublic(), ""); - string value = extractDoc(var->annotation().docTags, "notice"); - if (!value.empty()) - { - Json::Value user; - // since @notice is the only user tag if missing function should not appear - user["notice"] = Json::Value(value); - methods[it.second->externalSignature()] = user; - } + value = extractDoc(var->annotation().docTags, "notice"); + } + + if (!value.empty()) + { + Json::Value user; + // since @notice is the only user tag if missing function should not appear + user["notice"] = Json::Value(value); + methods[it.second->externalSignature()] = user; } } diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h index 8d414e71a4ca..9dab62625ebd 100644 --- a/libsolidity/interface/Natspec.h +++ b/libsolidity/interface/Natspec.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris * @date 2014 diff --git a/libsolidity/interface/OptimiserSettings.h b/libsolidity/interface/OptimiserSettings.h index cd82290af073..67007fc4c54c 100644 --- a/libsolidity/interface/OptimiserSettings.h +++ b/libsolidity/interface/OptimiserSettings.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * @date 2017 diff --git a/libsolidity/interface/ReadFile.h b/libsolidity/interface/ReadFile.h index 232d39be43e6..b21e8634a157 100644 --- a/libsolidity/interface/ReadFile.h +++ b/libsolidity/interface/ReadFile.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 7293f94bc8fb..b1e355fabfbc 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * @date 2016 diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h index d1a1489c3df9..cf5be94a01e7 100644 --- a/libsolidity/interface/StandardCompiler.h +++ b/libsolidity/interface/StandardCompiler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * @date 2016 diff --git a/libsolidity/interface/StorageLayout.cpp b/libsolidity/interface/StorageLayout.cpp index 806652cfe1b8..d23344bc8add 100644 --- a/libsolidity/interface/StorageLayout.cpp +++ b/libsolidity/interface/StorageLayout.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/interface/StorageLayout.h b/libsolidity/interface/StorageLayout.h index 331a85d4644b..4cfee73a9b4c 100644 --- a/libsolidity/interface/StorageLayout.h +++ b/libsolidity/interface/StorageLayout.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Generates the storage layout of a contract. */ diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index 412750bc8b46..297333b6bf0b 100644 --- a/libsolidity/interface/Version.cpp +++ b/libsolidity/interface/Version.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/interface/Version.h b/libsolidity/interface/Version.h index f2b1ad4292aa..a5965d42edb2 100644 --- a/libsolidity/interface/Version.h +++ b/libsolidity/interface/Version.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp index 9f6f13f945d7..314f04201282 100644 --- a/libsolidity/parsing/DocStringParser.cpp +++ b/libsolidity/parsing/DocStringParser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolidity/parsing/DocStringParser.h b/libsolidity/parsing/DocStringParser.h index d5ebd2383814..4b6d6b512d3a 100644 --- a/libsolidity/parsing/DocStringParser.h +++ b/libsolidity/parsing/DocStringParser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris * @date 2014, 2015 diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 4b63cbc58073..ce08bef60208 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index f66754045585..f84cb7041788 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h index 0e8f1f85b3c7..0382aba0eb34 100644 --- a/libsolidity/parsing/Token.h +++ b/libsolidity/parsing/Token.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Solidity and Yul both share the same Token (and Scanner) API. * diff --git a/libsolutil/Algorithms.h b/libsolutil/Algorithms.h index 3897d65d2498..88e034bf4985 100644 --- a/libsolutil/Algorithms.h +++ b/libsolutil/Algorithms.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolutil/AnsiColorized.h b/libsolutil/AnsiColorized.h index 4f7ea577b098..69d10d727640 100644 --- a/libsolutil/AnsiColorized.h +++ b/libsolutil/AnsiColorized.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolutil/Assertions.h b/libsolutil/Assertions.h index 1c5a14008a93..b143e6ed7c12 100644 --- a/libsolutil/Assertions.h +++ b/libsolutil/Assertions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @file Assertions.h * @author Christian diff --git a/libsolutil/Common.h b/libsolutil/Common.h index f2d9c1d84371..aae2fa8590cd 100644 --- a/libsolutil/Common.h +++ b/libsolutil/Common.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Common.h * @author Gav Wood * @date 2014 diff --git a/libsolutil/CommonData.cpp b/libsolutil/CommonData.cpp index 2896804ca601..1dc6168369d9 100644 --- a/libsolutil/CommonData.cpp +++ b/libsolutil/CommonData.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file CommonData.cpp * @author Gav Wood * @date 2014 diff --git a/libsolutil/CommonData.h b/libsolutil/CommonData.h index a5c045646d4b..b61ba82a2c3c 100644 --- a/libsolutil/CommonData.h +++ b/libsolutil/CommonData.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file CommonData.h * @author Gav Wood * @date 2014 diff --git a/libsolutil/CommonIO.cpp b/libsolutil/CommonIO.cpp index cbe68f0d143a..43886264b2b2 100644 --- a/libsolutil/CommonIO.cpp +++ b/libsolutil/CommonIO.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file CommonIO.cpp * @author Gav Wood * @date 2014 diff --git a/libsolutil/CommonIO.h b/libsolutil/CommonIO.h index 38c8f564a43b..2a811387bdb9 100644 --- a/libsolutil/CommonIO.h +++ b/libsolutil/CommonIO.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file CommonIO.h * @author Gav Wood * @date 2014 diff --git a/libsolutil/Exceptions.cpp b/libsolutil/Exceptions.cpp index 94b40f63491c..fa4021d3be7b 100644 --- a/libsolutil/Exceptions.cpp +++ b/libsolutil/Exceptions.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolutil/Exceptions.h b/libsolutil/Exceptions.h index 971b9306f9c5..9c84c8f71e2b 100644 --- a/libsolutil/Exceptions.h +++ b/libsolutil/Exceptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolutil/FixedHash.h b/libsolutil/FixedHash.h index 7fbb8eec9757..84d6afba3a19 100644 --- a/libsolutil/FixedHash.h +++ b/libsolutil/FixedHash.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file FixedHash.h * @author Gav Wood * @date 2014 diff --git a/libsolutil/IndentedWriter.cpp b/libsolutil/IndentedWriter.cpp index 884b50e9c5cb..0e0aded3ccb2 100644 --- a/libsolutil/IndentedWriter.cpp +++ b/libsolutil/IndentedWriter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Indented text writer. diff --git a/libsolutil/IndentedWriter.h b/libsolutil/IndentedWriter.h index 29ecc4f6dd7c..47e2817fa969 100644 --- a/libsolutil/IndentedWriter.h +++ b/libsolutil/IndentedWriter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Indented text writer. diff --git a/libsolutil/InvertibleMap.h b/libsolutil/InvertibleMap.h index 4448d03d7512..3c6f3238af6d 100644 --- a/libsolutil/InvertibleMap.h +++ b/libsolutil/InvertibleMap.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolutil/IpfsHash.cpp b/libsolutil/IpfsHash.cpp index 6913d42f0808..c034ce5ba7e6 100644 --- a/libsolutil/IpfsHash.cpp +++ b/libsolutil/IpfsHash.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libsolutil/IpfsHash.h b/libsolutil/IpfsHash.h index 555b3596173e..977fb9836ba7 100644 --- a/libsolutil/IpfsHash.h +++ b/libsolutil/IpfsHash.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolutil/JSON.cpp b/libsolutil/JSON.cpp index c66aab9b2537..b3635c877991 100644 --- a/libsolutil/JSON.cpp +++ b/libsolutil/JSON.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file JSON.cpp * @author Alexander Arlt * @date 2018 @@ -32,8 +33,8 @@ using namespace std; static_assert( - (JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 2), - "Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.2." + (JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3), + "Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3." ); namespace solidity::util diff --git a/libsolutil/JSON.h b/libsolutil/JSON.h index 17633ea0775e..5328a3fafdc8 100644 --- a/libsolutil/JSON.h +++ b/libsolutil/JSON.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file JSON.h * @date 2016 * diff --git a/libsolutil/Keccak256.cpp b/libsolutil/Keccak256.cpp index 2a7a241c739f..50e849352bc4 100644 --- a/libsolutil/Keccak256.cpp +++ b/libsolutil/Keccak256.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file SHA3.cpp * @author Gav Wood * @date 2014 diff --git a/libsolutil/Keccak256.h b/libsolutil/Keccak256.h index 7135e55c0d2b..7fb7c7501a7b 100644 --- a/libsolutil/Keccak256.h +++ b/libsolutil/Keccak256.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file SHA3.h * @author Gav Wood * @date 2014 diff --git a/libsolutil/LazyInit.h b/libsolutil/LazyInit.h index fe2f6a916d22..b242484df688 100644 --- a/libsolutil/LazyInit.h +++ b/libsolutil/LazyInit.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libsolutil/Result.h b/libsolutil/Result.h index a2c471097f90..ca9563947729 100644 --- a/libsolutil/Result.h +++ b/libsolutil/Result.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libsolutil/StringUtils.cpp b/libsolutil/StringUtils.cpp index a5b0149c27da..35804c60a165 100644 --- a/libsolutil/StringUtils.cpp +++ b/libsolutil/StringUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file StringUtils.h * @author Balajiganapathi S * @date 2017 diff --git a/libsolutil/StringUtils.h b/libsolutil/StringUtils.h index caea637a2325..e7a68cedcec2 100644 --- a/libsolutil/StringUtils.h +++ b/libsolutil/StringUtils.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file StringUtils.h * @author Balajiganapathi S * @date 2017 diff --git a/libsolutil/SwarmHash.cpp b/libsolutil/SwarmHash.cpp index 4cfc0fe664bd..f35a74bd1d3f 100644 --- a/libsolutil/SwarmHash.cpp +++ b/libsolutil/SwarmHash.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file SwarmHash.cpp */ diff --git a/libsolutil/SwarmHash.h b/libsolutil/SwarmHash.h index 3905b2f5f9dc..ed7a52292d39 100644 --- a/libsolutil/SwarmHash.h +++ b/libsolutil/SwarmHash.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file SwarmHash.h */ diff --git a/libsolutil/UTF8.cpp b/libsolutil/UTF8.cpp index a7d55af6c382..4acf7a8ea9f2 100644 --- a/libsolutil/UTF8.cpp +++ b/libsolutil/UTF8.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file UTF8.cpp * @author Alex Beregszaszi * @date 2016 diff --git a/libsolutil/UTF8.h b/libsolutil/UTF8.h index cd84c3982590..59e2d41455e0 100644 --- a/libsolutil/UTF8.h +++ b/libsolutil/UTF8.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file UTF8.h * @author Alex Beregszaszi * @date 2016 diff --git a/libsolutil/Visitor.h b/libsolutil/Visitor.h index 6d771cd861df..497ed2f29253 100644 --- a/libsolutil/Visitor.h +++ b/libsolutil/Visitor.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Visitor templates. */ diff --git a/libsolutil/Whiskers.cpp b/libsolutil/Whiskers.cpp index aebe55c69c4c..3049af5c4ce6 100644 --- a/libsolutil/Whiskers.cpp +++ b/libsolutil/Whiskers.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Whiskers.cpp * @author Chris * @date 2017 diff --git a/libsolutil/Whiskers.h b/libsolutil/Whiskers.h index 5eb00dce556c..5ddb7a884016 100644 --- a/libsolutil/Whiskers.h +++ b/libsolutil/Whiskers.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file Whiskers.h * @author Chris * @date 2017 diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp index f0ac3c24255c..934cff0a446c 100644 --- a/libyul/AsmAnalysis.cpp +++ b/libyul/AsmAnalysis.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Analyzer part of inline assembly. */ @@ -71,7 +72,7 @@ AsmAnalysisInfo AsmAnalyzer::analyzeStrictAssertCorrect(Dialect const& _dialect, errors, _dialect, {}, - _object.dataNames() + _object.qualifiedDataNames() ).analyze(*_object.code); yulAssert(success && !errors.hasErrors(), "Invalid assembly/yul code."); return analysisInfo; @@ -234,7 +235,7 @@ void AsmAnalyzer::operator()(VariableDeclaration const& _varDecl) m_errorReporter.typeError( 3947_error, variable.location, - "Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "." + "Assigning value of type \"" + givenType.str() + "\" to variable of type \"" + variable.type.str() + "\"." ); } } diff --git a/libyul/AsmAnalysis.h b/libyul/AsmAnalysis.h index e0a751b1343a..552191c4d86d 100644 --- a/libyul/AsmAnalysis.h +++ b/libyul/AsmAnalysis.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Analysis part of inline assembly. */ @@ -101,7 +102,6 @@ class AsmAnalyzer /// Vists the expression and expects it to return a single boolean value. /// Reports an error otherwise. void expectBoolExpression(Expression const& _expr); - bool expectDeposit(int _deposit, int _oldHeight, langutil::SourceLocation const& _location); /// Verifies that a variable to be assigned to exists, can be assigned to /// and has the same type as the value. diff --git a/libyul/AsmAnalysisInfo.h b/libyul/AsmAnalysisInfo.h index d094ee510582..9ac179ad8508 100644 --- a/libyul/AsmAnalysisInfo.h +++ b/libyul/AsmAnalysisInfo.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Information generated during analyzer part of inline assembly. */ diff --git a/libyul/AsmData.h b/libyul/AsmData.h index f870536affab..c4040f320c7e 100644 --- a/libyul/AsmData.h +++ b/libyul/AsmData.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/libyul/AsmDataForward.h b/libyul/AsmDataForward.h index b21f46f82d5c..02216fd0140b 100644 --- a/libyul/AsmDataForward.h +++ b/libyul/AsmDataForward.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/libyul/AsmJsonConverter.cpp b/libyul/AsmJsonConverter.cpp index d2b905ecef43..58b11338d49a 100644 --- a/libyul/AsmJsonConverter.cpp +++ b/libyul/AsmJsonConverter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2019 * Converts inline assembly AST to JSON format diff --git a/libyul/AsmJsonConverter.h b/libyul/AsmJsonConverter.h index b350689fc515..3436523b7977 100644 --- a/libyul/AsmJsonConverter.h +++ b/libyul/AsmJsonConverter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2019 * @author julius diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 8dcb9a83259f..6c5d97e36d3f 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 4c1d6980f3ad..ecd62228afa5 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/libyul/AsmPrinter.cpp b/libyul/AsmPrinter.cpp index 97a7dc3ade61..c5982afc9b9d 100644 --- a/libyul/AsmPrinter.cpp +++ b/libyul/AsmPrinter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2017 diff --git a/libyul/AsmPrinter.h b/libyul/AsmPrinter.h index f7ee9ff54b86..648181cbf576 100644 --- a/libyul/AsmPrinter.h +++ b/libyul/AsmPrinter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2017 diff --git a/libyul/AsmScope.cpp b/libyul/AsmScope.cpp index 86dbce48365d..1237cba8d053 100644 --- a/libyul/AsmScope.cpp +++ b/libyul/AsmScope.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Scopes for identifiers. */ diff --git a/libyul/AsmScope.h b/libyul/AsmScope.h index 6da1ff1e059a..0857b604be07 100644 --- a/libyul/AsmScope.h +++ b/libyul/AsmScope.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Scopes for identifiers. */ diff --git a/libyul/AsmScopeFiller.cpp b/libyul/AsmScopeFiller.cpp index 90143ba4dd44..0e06954106dd 100644 --- a/libyul/AsmScopeFiller.cpp +++ b/libyul/AsmScopeFiller.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module responsible for registering identifiers inside their scopes. */ diff --git a/libyul/AsmScopeFiller.h b/libyul/AsmScopeFiller.h index f3b7a1b8f8b0..f2c35118b7db 100644 --- a/libyul/AsmScopeFiller.h +++ b/libyul/AsmScopeFiller.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module responsible for registering identifiers inside their scopes. */ diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp index 4598d6d2b90b..542de51d95b9 100644 --- a/libyul/AssemblyStack.cpp +++ b/libyul/AssemblyStack.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Full assembly stack that can support EVM-assembly and Yul as input and EVM, EVM1.5 and * Ewasm as output. @@ -137,7 +138,7 @@ bool AssemblyStack::analyzeParsed(Object& _object) m_errorReporter, languageToDialect(m_language, m_evmVersion), {}, - _object.dataNames() + _object.qualifiedDataNames() ); bool success = analyzer.analyze(*_object.code); for (auto& subNode: _object.subObjects) diff --git a/libyul/AssemblyStack.h b/libyul/AssemblyStack.h index f9d23550563e..70325208d263 100644 --- a/libyul/AssemblyStack.h +++ b/libyul/AssemblyStack.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Full assembly stack that can support EVM-assembly and Yul as input and EVM, EVM1.5 and * Ewasm as output. diff --git a/libyul/CompilabilityChecker.cpp b/libyul/CompilabilityChecker.cpp index 344266a1250c..2a99e3c7934e 100644 --- a/libyul/CompilabilityChecker.cpp +++ b/libyul/CompilabilityChecker.cpp @@ -39,7 +39,7 @@ map CompilabilityChecker::run( bool _optimizeStackAllocation ) { - if (EVMDialect const* evmDialect = dynamic_cast(&_dialect)) + if (auto const* evmDialect = dynamic_cast(&_dialect)) { NoOutputEVMDialect noOutputDialect(*evmDialect); @@ -48,8 +48,10 @@ map CompilabilityChecker::run( BuiltinContext builtinContext; builtinContext.currentObject = &_object; - for (auto name: _object.dataNames()) - builtinContext.subIDs[name] = 1; + if (!_object.name.empty()) + builtinContext.subIDs[_object.name] = 1; + for (auto const& subNode: _object.subObjects) + builtinContext.subIDs[subNode->name] = 1; NoOutputAssembly assembly; CodeTransform transform( assembly, @@ -59,14 +61,7 @@ map CompilabilityChecker::run( builtinContext, _optimizeStackAllocation ); - try - { - transform(*_object.code); - } - catch (StackTooDeepError const&) - { - yulAssert(!transform.stackErrors().empty(), "Got stack too deep exception that was not stored."); - } + transform(*_object.code); std::map functions; for (StackTooDeepError const& error: transform.stackErrors()) diff --git a/libyul/CompilabilityChecker.h b/libyul/CompilabilityChecker.h index d92f1977ecf1..1267640bf16f 100644 --- a/libyul/CompilabilityChecker.h +++ b/libyul/CompilabilityChecker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that checks whether all variables are reachable on the stack. */ diff --git a/libyul/ControlFlowSideEffects.h b/libyul/ControlFlowSideEffects.h index 5621a122b1df..5e22ad862b2b 100644 --- a/libyul/ControlFlowSideEffects.h +++ b/libyul/ControlFlowSideEffects.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libyul/Dialect.cpp b/libyul/Dialect.cpp index 407fdea2fc4f..1003c8e44a40 100644 --- a/libyul/Dialect.cpp +++ b/libyul/Dialect.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul dialect. */ diff --git a/libyul/Dialect.h b/libyul/Dialect.h index 870205833659..553f9049abdc 100644 --- a/libyul/Dialect.h +++ b/libyul/Dialect.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul dialect. */ diff --git a/libyul/Exceptions.h b/libyul/Exceptions.h index 9bb6a5d0499e..2fe155030c05 100644 --- a/libyul/Exceptions.h +++ b/libyul/Exceptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Exceptions in Yul. */ diff --git a/libyul/Object.cpp b/libyul/Object.cpp index 13ad9f8caf48..72206c4b6f6a 100644 --- a/libyul/Object.cpp +++ b/libyul/Object.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul code and data object container. */ @@ -23,9 +24,10 @@ #include #include -#include #include +#include +#include #include using namespace std; @@ -61,13 +63,54 @@ string Object::toString(Dialect const* _dialect) const return "object \"" + name.str() + "\" {\n" + indent(inner) + "\n}"; } -set Object::dataNames() const +set Object::qualifiedDataNames() const { - set names; - names.insert(name); - for (auto const& subObject: subIndexByName) - names.insert(subObject.first); - // The empty name is not valid - names.erase(YulString{}); - return names; + set qualifiedNames = name.empty() ? set{} : set{name}; + for (shared_ptr const& subObjectNode: subObjects) + { + yulAssert(qualifiedNames.count(subObjectNode->name) == 0, ""); + qualifiedNames.insert(subObjectNode->name); + if (auto const* subObject = dynamic_cast(subObjectNode.get())) + for (YulString const& subSubObj: subObject->qualifiedDataNames()) + if (subObject->name != subSubObj) + { + yulAssert(qualifiedNames.count(YulString{subObject->name.str() + "." + subSubObj.str()}) == 0, ""); + qualifiedNames.insert(YulString{subObject->name.str() + "." + subSubObj.str()}); + } + } + + yulAssert(qualifiedNames.count(YulString{}) == 0, ""); + qualifiedNames.erase(YulString{}); + return qualifiedNames; +} + +vector Object::pathToSubObject(YulString _qualifiedName) const +{ + yulAssert(_qualifiedName != name, ""); + yulAssert(subIndexByName.count(name) == 0, ""); + + if (boost::algorithm::starts_with(_qualifiedName.str(), name.str() + ".")) + _qualifiedName = YulString{_qualifiedName.str().substr(name.str().length() + 1)}; + yulAssert(!_qualifiedName.empty(), ""); + + vector subObjectPathComponents; + boost::algorithm::split(subObjectPathComponents, _qualifiedName.str(), boost::is_any_of(".")); + + vector path; + Object const* object = this; + for (string const& currentSubObjectName: subObjectPathComponents) + { + yulAssert(!currentSubObjectName.empty(), ""); + auto subIndexIt = object->subIndexByName.find(YulString{currentSubObjectName}); + yulAssert( + subIndexIt != object->subIndexByName.end(), + "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code." + ); + object = dynamic_cast(object->subObjects[subIndexIt->second].get()); + yulAssert(object, "Assembly object <" + _qualifiedName.str() + "> not found or does not contain code."); + yulAssert(object->subId != numeric_limits::max(), ""); + path.push_back({object->subId}); + } + + return path; } diff --git a/libyul/Object.h b/libyul/Object.h index 6ae79ed42cf1..deb52eb25f04 100644 --- a/libyul/Object.h +++ b/libyul/Object.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul code and data object container. */ @@ -43,6 +44,8 @@ struct ObjectNode virtual std::string toString(Dialect const* _dialect) const = 0; std::string toString() { return toString(nullptr); } + /// Name of the object. + /// Can be empty since .yul files can also just contain code, without explicitly placing it in an object. YulString name; }; @@ -67,8 +70,23 @@ struct Object: ObjectNode std::string toString(Dialect const* _dialect) const override; /// @returns the set of names of data objects accessible from within the code of - /// this object. - std::set dataNames() const; + /// this object, including the name of object itself + std::set qualifiedDataNames() const; + + /// @returns vector of subIDs if possible to reach subobject with @a _qualifiedName, throws otherwise + /// For "B.C" should return vector of two values if success (subId of B and subId of C in B). + /// In object "A" if called for "A.B" will return only one value (subId for B) + /// will return empty vector for @a _qualifiedName that equals to object name. + /// Example: + /// A1{ B2{ C3, D3 }, E2{ F3{ G4, K4, H4{ I5 } } } } + /// pathToSubObject("A1.E2.F3.H4") == {1, 0, 2} + /// pathToSubObject("E2.F3.H4") == {1, 0, 2} + /// pathToSubObject("A1.E2") == {1} + /// The path must not lead to a @a Data object (will throw in that case). + std::vector pathToSubObject(YulString _qualifiedName) const; + + /// sub id for object if it is subobject of another object, max value if it is not subobject + size_t subId = std::numeric_limits::max(); std::shared_ptr code; std::vector> subObjects; diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 7e50fa88e6c6..f1d38ad730be 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Parser for Yul code and data object container. */ diff --git a/libyul/ObjectParser.h b/libyul/ObjectParser.h index 1bd9d956fd3f..6c6f527cd159 100644 --- a/libyul/ObjectParser.h +++ b/libyul/ObjectParser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Parser for Yul code and data object container. */ diff --git a/libyul/SideEffects.h b/libyul/SideEffects.h index 2a0232973545..e9c12d9c8720 100644 --- a/libyul/SideEffects.h +++ b/libyul/SideEffects.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libyul/Utilities.cpp b/libyul/Utilities.cpp index 59e0adce3afd..af72888fa42d 100644 --- a/libyul/Utilities.cpp +++ b/libyul/Utilities.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Some useful snippets for the optimiser. */ diff --git a/libyul/Utilities.h b/libyul/Utilities.h index 8b4547be3e31..53913e6fd477 100644 --- a/libyul/Utilities.h +++ b/libyul/Utilities.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Small useful snippets for the optimiser. */ diff --git a/libyul/YulString.h b/libyul/YulString.h index 0abe1f38ddf5..6985794ecbab 100644 --- a/libyul/YulString.h +++ b/libyul/YulString.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * String abstraction that avoids copies. */ diff --git a/libyul/backends/evm/AbstractAssembly.h b/libyul/backends/evm/AbstractAssembly.h index 42622272cd87..a8327c346e10 100644 --- a/libyul/backends/evm/AbstractAssembly.h +++ b/libyul/backends/evm/AbstractAssembly.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Abstract assembly interface, subclasses of which are to be used with the generic @@ -101,9 +102,9 @@ class AbstractAssembly /// Creates a new sub-assembly, which can be referenced using dataSize and dataOffset. virtual std::pair, SubID> createSubAssembly() = 0; /// Appends the offset of the given sub-assembly or data. - virtual void appendDataOffset(SubID _sub) = 0; + virtual void appendDataOffset(std::vector const& _subPath) = 0; /// Appends the size of the given sub-assembly or data. - virtual void appendDataSize(SubID _sub) = 0; + virtual void appendDataSize(std::vector const& _subPath) = 0; /// Appends the given data to the assembly and returns its ID. virtual SubID appendData(bytes const& _data) = 0; @@ -111,6 +112,9 @@ class AbstractAssembly virtual void appendImmutable(std::string const& _identifier) = 0; /// Appends an assignment to an immutable variable. virtual void appendImmutableAssignment(std::string const& _identifier) = 0; + + /// Mark this assembly as invalid. Any attempt to request bytecode from it should throw. + virtual void markAsInvalid() = 0; }; enum class IdentifierContext { LValue, RValue, VariableDeclaration }; diff --git a/libyul/backends/evm/AsmCodeGen.cpp b/libyul/backends/evm/AsmCodeGen.cpp index 327ce8895518..15d646755306 100644 --- a/libyul/backends/evm/AsmCodeGen.cpp +++ b/libyul/backends/evm/AsmCodeGen.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Adaptor between the abstract assembly and eth assembly. */ @@ -146,22 +147,28 @@ pair, AbstractAssembly::SubID> EthAssemblyAdapter:: return {make_shared(*assembly), static_cast(sub.data())}; } -void EthAssemblyAdapter::appendDataOffset(AbstractAssembly::SubID _sub) +void EthAssemblyAdapter::appendDataOffset(vector const& _subPath) { - auto it = m_dataHashBySubId.find(_sub); - if (it == m_dataHashBySubId.end()) - m_assembly.pushSubroutineOffset(_sub); - else + if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end()) + { + yulAssert(_subPath.size() == 1, ""); m_assembly << evmasm::AssemblyItem(evmasm::PushData, it->second); + return; + } + + m_assembly.pushSubroutineOffset(m_assembly.encodeSubPath(_subPath)); } -void EthAssemblyAdapter::appendDataSize(AbstractAssembly::SubID _sub) +void EthAssemblyAdapter::appendDataSize(vector const& _subPath) { - auto it = m_dataHashBySubId.find(_sub); - if (it == m_dataHashBySubId.end()) - m_assembly.pushSubroutineSize(static_cast(_sub)); - else + if (auto it = m_dataHashBySubId.find(_subPath[0]); it != m_dataHashBySubId.end()) + { + yulAssert(_subPath.size() == 1, ""); m_assembly << u256(m_assembly.data(h256(it->second)).size()); + return; + } + + m_assembly.pushSubroutineSize(m_assembly.encodeSubPath(_subPath)); } AbstractAssembly::SubID EthAssemblyAdapter::appendData(bytes const& _data) @@ -182,6 +189,11 @@ void EthAssemblyAdapter::appendImmutableAssignment(std::string const& _identifie m_assembly.appendImmutableAssignment(_identifier); } +void EthAssemblyAdapter::markAsInvalid() +{ + m_assembly.markAsInvalid(); +} + EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag) { u256 id = _tag.data(); @@ -231,18 +243,12 @@ void CodeGenerator::assemble( _identifierAccess, _useNamedLabelsForFunctions ); - try - { - transform(_parsedData); - } - catch (StackTooDeepError const& _e) - { + transform(_parsedData); + if (!transform.stackErrors().empty()) assertThrow( false, langutil::StackTooDeepError, "Stack too deep when compiling inline assembly" + - (_e.comment() ? ": " + *_e.comment() : ".") + (transform.stackErrors().front().comment() ? ": " + *transform.stackErrors().front().comment() : ".") ); - } - yulAssert(transform.stackErrors().empty(), "Stack errors present but not thrown."); } diff --git a/libyul/backends/evm/AsmCodeGen.h b/libyul/backends/evm/AsmCodeGen.h index 6ff02009c6b9..ee56f7fcb972 100644 --- a/libyul/backends/evm/AsmCodeGen.h +++ b/libyul/backends/evm/AsmCodeGen.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Adaptor between the abstract assembly and eth assembly. */ @@ -57,13 +58,15 @@ class EthAssemblyAdapter: public AbstractAssembly void appendReturnsub(int, int) override; void appendAssemblySize() override; std::pair, SubID> createSubAssembly() override; - void appendDataOffset(SubID _sub) override; - void appendDataSize(SubID _sub) override; + void appendDataOffset(std::vector const& _subPath) override; + void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void markAsInvalid() override; + private: static LabelID assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag); void appendJumpInstruction(evmasm::Instruction _instruction, JumpType _jumpType); diff --git a/libyul/backends/evm/ConstantOptimiser.cpp b/libyul/backends/evm/ConstantOptimiser.cpp index d8399d095f4c..9148b0793677 100644 --- a/libyul/backends/evm/ConstantOptimiser.cpp +++ b/libyul/backends/evm/ConstantOptimiser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that replaces constants by expressions that compute them. */ diff --git a/libyul/backends/evm/ConstantOptimiser.h b/libyul/backends/evm/ConstantOptimiser.h index 7423b5270046..d6844bbe6dcb 100644 --- a/libyul/backends/evm/ConstantOptimiser.h +++ b/libyul/backends/evm/ConstantOptimiser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that replaces constants by expressions that compute them. */ diff --git a/libyul/backends/evm/EVMAssembly.cpp b/libyul/backends/evm/EVMAssembly.cpp index 73194ef8ad9d..99945383e528 100644 --- a/libyul/backends/evm/EVMAssembly.cpp +++ b/libyul/backends/evm/EVMAssembly.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Assembly interface for EVM and EVM1.5. */ @@ -102,7 +103,7 @@ void EVMAssembly::appendJumpTo(LabelID _labelId, int _stackDiffAfter, JumpType _ { if (m_evm15) { - m_bytecode.push_back(uint8_t(evmasm::Instruction::JUMPTO)); + m_bytecode.push_back(uint8_t(evmasm::Instruction::EIP615_JUMPTO)); appendLabelReferenceInternal(_labelId); m_stackHeight += _stackDiffAfter; } @@ -117,7 +118,7 @@ void EVMAssembly::appendJumpToIf(LabelID _labelId, JumpType) { if (m_evm15) { - m_bytecode.push_back(uint8_t(evmasm::Instruction::JUMPIF)); + m_bytecode.push_back(uint8_t(evmasm::Instruction::EIP615_JUMPIF)); appendLabelReferenceInternal(_labelId); m_stackHeight--; } @@ -133,7 +134,7 @@ void EVMAssembly::appendBeginsub(LabelID _labelId, int _arguments) yulAssert(m_evm15, "BEGINSUB used for EVM 1.0"); yulAssert(_arguments >= 0, ""); setLabelToCurrentPosition(_labelId); - m_bytecode.push_back(uint8_t(evmasm::Instruction::BEGINSUB)); + m_bytecode.push_back(uint8_t(evmasm::Instruction::EIP615_BEGINSUB)); m_stackHeight += _arguments; } @@ -141,7 +142,7 @@ void EVMAssembly::appendJumpsub(LabelID _labelId, int _arguments, int _returns) { yulAssert(m_evm15, "JUMPSUB used for EVM 1.0"); yulAssert(_arguments >= 0 && _returns >= 0, ""); - m_bytecode.push_back(uint8_t(evmasm::Instruction::JUMPSUB)); + m_bytecode.push_back(uint8_t(evmasm::Instruction::EIP615_JUMPSUB)); appendLabelReferenceInternal(_labelId); m_stackHeight += _returns - _arguments; } @@ -150,12 +151,13 @@ void EVMAssembly::appendReturnsub(int _returns, int _stackDiffAfter) { yulAssert(m_evm15, "RETURNSUB used for EVM 1.0"); yulAssert(_returns >= 0, ""); - m_bytecode.push_back(uint8_t(evmasm::Instruction::RETURNSUB)); + m_bytecode.push_back(uint8_t(evmasm::Instruction::EIP615_RETURNSUB)); m_stackHeight += _stackDiffAfter - _returns; } evmasm::LinkerObject EVMAssembly::finalize() { + yulAssert(!m_invalid, "Attempted to finalize invalid assembly object."); size_t bytecodeSize = m_bytecode.size(); for (auto const& ref: m_assemblySizePositions) updateReference(ref, assemblySizeReferenceSize, u256(bytecodeSize)); @@ -200,12 +202,12 @@ pair, AbstractAssembly::SubID> EVMAssembly::createS return {}; } -void EVMAssembly::appendDataOffset(AbstractAssembly::SubID) +void EVMAssembly::appendDataOffset(vector const&) { yulAssert(false, "Data not implemented."); } -void EVMAssembly::appendDataSize(AbstractAssembly::SubID) +void EVMAssembly::appendDataSize(vector const&) { yulAssert(false, "Data not implemented."); } diff --git a/libyul/backends/evm/EVMAssembly.h b/libyul/backends/evm/EVMAssembly.h index 9ee974bbb890..6e6878476db7 100644 --- a/libyul/backends/evm/EVMAssembly.h +++ b/libyul/backends/evm/EVMAssembly.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Assembly interface for EVM and EVM1.5. */ @@ -79,13 +80,15 @@ class EVMAssembly: public AbstractAssembly /// Append the assembled size as a constant. void appendAssemblySize() override; std::pair, SubID> createSubAssembly() override; - void appendDataOffset(SubID _sub) override; - void appendDataSize(SubID _sub) override; + void appendDataOffset(std::vector const& _subPath) override; + void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void markAsInvalid() override { m_invalid = true; } + /// Resolves references inside the bytecode and returns the linker object. evmasm::LinkerObject finalize(); @@ -102,6 +105,7 @@ class EVMAssembly: public AbstractAssembly std::map m_labelPositions; std::map m_labelReferences; std::vector m_assemblySizePositions; + bool m_invalid = false; }; } diff --git a/libyul/backends/evm/EVMCodeTransform.cpp b/libyul/backends/evm/EVMCodeTransform.cpp index 9182bb393450..95f787400f65 100644 --- a/libyul/backends/evm/EVMCodeTransform.cpp +++ b/libyul/backends/evm/EVMCodeTransform.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Common code generator for translating Yul / inline assembly to EVM and EVM1.5. */ @@ -141,7 +142,7 @@ bool CodeTransform::unreferenced(Scope::Variable const& _var) const return !m_context->variableReferences.count(&_var) || m_context->variableReferences[&_var] == 0; } -void CodeTransform::freeUnusedVariables() +void CodeTransform::freeUnusedVariables(bool _popUnusedSlotsAtStackTop) { if (!m_allowStackOpt) return; @@ -154,18 +155,19 @@ void CodeTransform::freeUnusedVariables() deleteVariable(var); } - while (m_unusedStackSlots.count(m_assembly.stackHeight() - 1)) - { - yulAssert(m_unusedStackSlots.erase(m_assembly.stackHeight() - 1), ""); - m_assembly.appendInstruction(evmasm::Instruction::POP); - } + if (_popUnusedSlotsAtStackTop) + while (m_unusedStackSlots.count(m_assembly.stackHeight() - 1)) + { + yulAssert(m_unusedStackSlots.erase(m_assembly.stackHeight() - 1), ""); + m_assembly.appendInstruction(evmasm::Instruction::POP); + } } void CodeTransform::deleteVariable(Scope::Variable const& _var) { yulAssert(m_allowStackOpt, ""); yulAssert(m_context->variableStackHeights.count(&_var) > 0, ""); - m_unusedStackSlots.insert(m_context->variableStackHeights[&_var]); + m_unusedStackSlots.insert(static_cast(m_context->variableStackHeights[&_var])); m_context->variableStackHeights.erase(&_var); m_context->variableReferences.erase(&_var); m_variablesScheduledForDeletion.erase(&_var); @@ -181,6 +183,7 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl) { std::visit(*this, *_varDecl.value); expectDeposit(static_cast(numVariables), static_cast(heightAtStart)); + freeUnusedVariables(false); } else { @@ -235,6 +238,7 @@ void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight) m_assembly.appendConstant(u256(0)); // Store error. m_stackErrors.emplace_back(std::move(_error)); + m_assembly.markAsInvalid(); } void CodeTransform::operator()(Assignment const& _assignment) @@ -402,7 +406,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) yulAssert(m_scope->identifiers.count(_function.name), ""); Scope::Function& function = std::get(m_scope->identifiers.at(_function.name)); - int height = m_evm15 ? 0 : 1; + size_t height = m_evm15 ? 0 : 1; yulAssert(m_info.scopes.at(&_function.body), ""); Scope* varScope = m_info.scopes.at(m_info.virtualBlocks.at(&_function).get()).get(); yulAssert(varScope, ""); @@ -420,7 +424,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) else m_assembly.appendLabel(functionEntryID(_function.name, function)); - m_assembly.setStackHeight(height); + m_assembly.setStackHeight(static_cast(height)); for (auto const& v: _function.returnVariables) { @@ -433,31 +437,28 @@ void CodeTransform::operator()(FunctionDefinition const& _function) m_context->functionExitPoints.push( CodeTransformContext::JumpInfo{m_assembly.newLabelId(), m_assembly.stackHeight()} ); - try - { - CodeTransform( - m_assembly, - m_info, - _function.body, - m_allowStackOpt, - m_dialect, - m_builtinContext, - m_evm15, - m_identifierAccess, - m_useNamedLabelsForFunctions, - m_context - )(_function.body); - } - catch (StackTooDeepError const& _error) + CodeTransform subTransform( + m_assembly, + m_info, + _function.body, + m_allowStackOpt, + m_dialect, + m_builtinContext, + m_evm15, + m_identifierAccess, + m_useNamedLabelsForFunctions, + m_context + ); + subTransform(_function.body); + if (!subTransform.m_stackErrors.empty()) { - // This exception will be re-thrown after the end of the surrounding block. - // It enables us to see which functions compiled successfully and which did not. - // Even if we emit actual code, add an illegal instruction to make sure that tests - // will catch it. - StackTooDeepError error(_error); - if (error.functionName.empty()) - error.functionName = _function.name; - stackError(std::move(error), height); + m_assembly.markAsInvalid(); + for (StackTooDeepError& stackError: subTransform.m_stackErrors) + { + if (stackError.functionName.empty()) + stackError.functionName = _function.name; + m_stackErrors.emplace_back(std::move(stackError)); + } } m_assembly.appendLabel(m_context->functionExitPoints.top().label); @@ -502,7 +503,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function) } else { - m_assembly.appendInstruction(evmasm::swapInstruction(stackLayout.size() - static_cast(stackLayout.back()) - 1)); + m_assembly.appendInstruction(evmasm::swapInstruction(static_cast(stackLayout.size()) - static_cast(stackLayout.back()) - 1u)); swap(stackLayout[static_cast(stackLayout.back())], stackLayout.back()); } for (size_t i = 0; i < stackLayout.size(); ++i) @@ -603,9 +604,6 @@ void CodeTransform::operator()(Block const& _block) finalizeBlock(_block, blockStartStackHeight); m_scope = originalScope; - - if (!m_stackErrors.empty()) - BOOST_THROW_EXCEPTION(m_stackErrors.front()); } AbstractAssembly::LabelID CodeTransform::functionEntryID(YulString _name, Scope::Function const& _function) @@ -726,7 +724,8 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString to_string(heightDiff - limit) + " slot(s) too deep inside the stack." ); - BOOST_THROW_EXCEPTION(m_stackErrors.back()); + m_assembly.markAsInvalid(); + return _forSwap ? 2 : 1; } return heightDiff; } diff --git a/libyul/backends/evm/EVMCodeTransform.h b/libyul/backends/evm/EVMCodeTransform.h index 3c9506b4797f..40cfe375f6c1 100644 --- a/libyul/backends/evm/EVMCodeTransform.h +++ b/libyul/backends/evm/EVMCodeTransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Common code generator for translating Yul / inline assembly to EVM and EVM1.5. */ @@ -161,8 +162,9 @@ class CodeTransform bool unreferenced(Scope::Variable const& _var) const; /// Marks slots of variables that are not used anymore /// and were defined in the current scope for reuse. - /// Also POPs unused topmost stack slots. - void freeUnusedVariables(); + /// Also POPs unused topmost stack slots, + /// unless @a _popUnusedSlotsAtStackTop is set to false. + void freeUnusedVariables(bool _popUnusedSlotsAtStackTop = true); /// Marks the stack slot of @a _var to be reused. void deleteVariable(Scope::Variable const& _var); @@ -200,6 +202,8 @@ class CodeTransform /// 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. + /// @param _forSwap if true, produces stack error if the difference is invalid for a swap + /// opcode, otherwise checks for validity for a dup opcode. size_t variableHeightDiff(Scope::Variable const& _var, YulString _name, bool _forSwap); void expectDeposit(int _deposit, int _oldHeight) const; diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index bf0c63bfa50c..c552b6e220d9 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul dialects for EVM. */ @@ -143,7 +144,7 @@ map createBuiltins(langutil::EVMVersion _evmVe FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context, - std::function + std::function const& ) { yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); @@ -153,18 +154,19 @@ map createBuiltins(langutil::EVMVersion _evmVe _assembly.appendAssemblySize(); else { - yulAssert( - _context.subIDs.count(dataName) != 0, - "Could not find assembly object <" + dataName.str() + ">." - ); - _assembly.appendDataSize(_context.subIDs.at(dataName)); + vector subIdPath = + _context.subIDs.count(dataName) == 0 ? + _context.currentObject->pathToSubObject(dataName) : + vector{_context.subIDs.at(dataName)}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataSize(subIdPath); } })); builtins.emplace(createFunction("dataoffset", 1, 1, SideEffects{}, {true}, []( FunctionCall const& _call, AbstractAssembly& _assembly, BuiltinContext& _context, - std::function + std::function const& ) { yulAssert(_context.currentObject, "No object available."); yulAssert(_call.arguments.size() == 1, ""); @@ -174,11 +176,12 @@ map createBuiltins(langutil::EVMVersion _evmVe _assembly.appendConstant(0); else { - yulAssert( - _context.subIDs.count(dataName) != 0, - "Could not find assembly object <" + dataName.str() + ">." - ); - _assembly.appendDataOffset(_context.subIDs.at(dataName)); + vector subIdPath = + _context.subIDs.count(dataName) == 0 ? + _context.currentObject->pathToSubObject(dataName) : + vector{_context.subIDs.at(dataName)}; + yulAssert(!subIdPath.empty(), "Could not find assembly object <" + dataName.str() + ">."); + _assembly.appendDataOffset(subIdPath); } })); builtins.emplace(createFunction( diff --git a/libyul/backends/evm/EVMDialect.h b/libyul/backends/evm/EVMDialect.h index 68f0b7046fd7..fe1c67a4a5a2 100644 --- a/libyul/backends/evm/EVMDialect.h +++ b/libyul/backends/evm/EVMDialect.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul dialects for EVM. */ diff --git a/libyul/backends/evm/EVMMetrics.cpp b/libyul/backends/evm/EVMMetrics.cpp index f3508afb34d9..5fb6d863a0fb 100644 --- a/libyul/backends/evm/EVMMetrics.cpp +++ b/libyul/backends/evm/EVMMetrics.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module providing metrics for the EVM optimizer. */ diff --git a/libyul/backends/evm/EVMMetrics.h b/libyul/backends/evm/EVMMetrics.h index b6a23e3c877c..63e0d3c8fc49 100644 --- a/libyul/backends/evm/EVMMetrics.h +++ b/libyul/backends/evm/EVMMetrics.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module providing metrics for the optimizer. */ diff --git a/libyul/backends/evm/EVMObjectCompiler.cpp b/libyul/backends/evm/EVMObjectCompiler.cpp index 6463b4a46ca6..5eb83a6a8f9d 100644 --- a/libyul/backends/evm/EVMObjectCompiler.cpp +++ b/libyul/backends/evm/EVMObjectCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Compiler that transforms Yul Objects to EVM bytecode objects. */ @@ -25,6 +26,7 @@ #include #include +#include using namespace solidity::yul; using namespace std; @@ -40,11 +42,12 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) BuiltinContext context; context.currentObject = &_object; - for (auto& subNode: _object.subObjects) - if (Object* subObject = dynamic_cast(subNode.get())) + for (auto const& subNode: _object.subObjects) + if (auto* subObject = dynamic_cast(subNode.get())) { auto subAssemblyAndID = m_assembly.createSubAssembly(); context.subIDs[subObject->name] = subAssemblyAndID.second; + subObject->subId = subAssemblyAndID.second; compile(*subObject, *subAssemblyAndID.first, m_dialect, m_evm15, _optimize); } else @@ -59,5 +62,6 @@ void EVMObjectCompiler::run(Object& _object, bool _optimize) // which should be native to this part of the code. CodeTransform transform{m_assembly, *_object.analysisInfo, *_object.code, m_dialect, context, _optimize, m_evm15}; transform(*_object.code); - yulAssert(transform.stackErrors().empty(), "Stack errors present but not thrown."); + if (!transform.stackErrors().empty()) + BOOST_THROW_EXCEPTION(transform.stackErrors().front()); } diff --git a/libyul/backends/evm/EVMObjectCompiler.h b/libyul/backends/evm/EVMObjectCompiler.h index fb40ac7395e4..74ea71ac6ced 100644 --- a/libyul/backends/evm/EVMObjectCompiler.h +++ b/libyul/backends/evm/EVMObjectCompiler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Compiler that transforms Yul Objects to EVM bytecode objects. */ diff --git a/libyul/backends/evm/NoOutputAssembly.cpp b/libyul/backends/evm/NoOutputAssembly.cpp index ee280338d8b3..733795523202 100644 --- a/libyul/backends/evm/NoOutputAssembly.cpp +++ b/libyul/backends/evm/NoOutputAssembly.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Assembly interface that ignores everything. Can be used as a backend for a compilation dry-run. */ @@ -131,12 +132,12 @@ pair, AbstractAssembly::SubID> NoOutputAssembly::cr return {}; } -void NoOutputAssembly::appendDataOffset(AbstractAssembly::SubID) +void NoOutputAssembly::appendDataOffset(std::vector const&) { appendInstruction(evmasm::Instruction::PUSH1); } -void NoOutputAssembly::appendDataSize(AbstractAssembly::SubID) +void NoOutputAssembly::appendDataSize(std::vector const&) { appendInstruction(evmasm::Instruction::PUSH1); } diff --git a/libyul/backends/evm/NoOutputAssembly.h b/libyul/backends/evm/NoOutputAssembly.h index ec7e5f2ecead..b2153e42a7a3 100644 --- a/libyul/backends/evm/NoOutputAssembly.h +++ b/libyul/backends/evm/NoOutputAssembly.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Assembly interface that ignores everything. Can be used as a backend for a compilation dry-run. */ @@ -67,13 +68,15 @@ class NoOutputAssembly: public AbstractAssembly void appendAssemblySize() override; std::pair, SubID> createSubAssembly() override; - void appendDataOffset(SubID _sub) override; - void appendDataSize(SubID _sub) override; + void appendDataOffset(std::vector const& _subPath) override; + void appendDataSize(std::vector const& _subPath) override; SubID appendData(bytes const& _data) override; void appendImmutable(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override; + void markAsInvalid() override {} + private: bool m_evm15 = false; ///< if true, switch to evm1.5 mode int m_stackHeight = 0; diff --git a/libyul/backends/wasm/BinaryTransform.cpp b/libyul/backends/wasm/BinaryTransform.cpp index 38438e12eb73..5746dfaafe86 100644 --- a/libyul/backends/wasm/BinaryTransform.cpp +++ b/libyul/backends/wasm/BinaryTransform.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that transforms internal Wasm representation to binary. */ diff --git a/libyul/backends/wasm/BinaryTransform.h b/libyul/backends/wasm/BinaryTransform.h index c505fe2dc1b5..348250546785 100644 --- a/libyul/backends/wasm/BinaryTransform.h +++ b/libyul/backends/wasm/BinaryTransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that transforms internal Wasm representation to binary. */ diff --git a/libyul/backends/wasm/EVMToEwasmTranslator.cpp b/libyul/backends/wasm/EVMToEwasmTranslator.cpp index ebcdd961b98c..dc180b24094c 100644 --- a/libyul/backends/wasm/EVMToEwasmTranslator.cpp +++ b/libyul/backends/wasm/EVMToEwasmTranslator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Translates Yul code from EVM dialect to Ewasm dialect. */ @@ -1248,7 +1249,7 @@ Object EVMToEwasmTranslator::run(Object const& _object) ErrorList errors; ErrorReporter errorReporter(errors); - AsmAnalyzer analyzer(*ret.analysisInfo, errorReporter, WasmDialect::instance(), {}, _object.dataNames()); + AsmAnalyzer analyzer(*ret.analysisInfo, errorReporter, WasmDialect::instance(), {}, _object.qualifiedDataNames()); if (!analyzer.analyze(*ret.code)) { string message = "Invalid code generated after EVM to wasm translation.\n"; diff --git a/libyul/backends/wasm/EVMToEwasmTranslator.h b/libyul/backends/wasm/EVMToEwasmTranslator.h index 0bd86a317e73..ecb34ec1120b 100644 --- a/libyul/backends/wasm/EVMToEwasmTranslator.h +++ b/libyul/backends/wasm/EVMToEwasmTranslator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Translates Yul code from EVM dialect to Ewasm dialect. */ diff --git a/libyul/backends/wasm/TextTransform.cpp b/libyul/backends/wasm/TextTransform.cpp index ee2aa86e471d..059f8960021a 100644 --- a/libyul/backends/wasm/TextTransform.cpp +++ b/libyul/backends/wasm/TextTransform.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that transforms internal Wasm representation to text. */ diff --git a/libyul/backends/wasm/TextTransform.h b/libyul/backends/wasm/TextTransform.h index b8b21f7f2e6d..eb14da65d971 100644 --- a/libyul/backends/wasm/TextTransform.h +++ b/libyul/backends/wasm/TextTransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that transforms internal Wasm representation to text. */ diff --git a/libyul/backends/wasm/WasmAST.h b/libyul/backends/wasm/WasmAST.h index b22b0db84430..ced3b7bc6492 100644 --- a/libyul/backends/wasm/WasmAST.h +++ b/libyul/backends/wasm/WasmAST.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Simplified in-memory representation of a Wasm AST. */ diff --git a/libyul/backends/wasm/WasmCodeTransform.cpp b/libyul/backends/wasm/WasmCodeTransform.cpp index 5171db1b1331..de87028a9864 100644 --- a/libyul/backends/wasm/WasmCodeTransform.cpp +++ b/libyul/backends/wasm/WasmCodeTransform.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Common code generator for translating Yul / inline assembly to Wasm. */ diff --git a/libyul/backends/wasm/WasmCodeTransform.h b/libyul/backends/wasm/WasmCodeTransform.h index 326778b3de8d..79d3552c6474 100644 --- a/libyul/backends/wasm/WasmCodeTransform.h +++ b/libyul/backends/wasm/WasmCodeTransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Common code generator for translating Yul / inline assembly to Wasm. */ diff --git a/libyul/backends/wasm/WasmDialect.cpp b/libyul/backends/wasm/WasmDialect.cpp index 39138dfb2861..edf113a13a5b 100644 --- a/libyul/backends/wasm/WasmDialect.cpp +++ b/libyul/backends/wasm/WasmDialect.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Dialects for Wasm. */ @@ -38,13 +39,18 @@ WasmDialect::WasmDialect() "add", "sub", "mul", + // TODO: div_s "div_u", + // TODO: rem_s "rem_u", "and", "or", "xor", "shl", + // TODO: shr_s "shr_u", + // TODO: rotl + // TODO: rotr }) addFunction(t.str() + "." + name, {t, t}, {t}); @@ -52,9 +58,13 @@ WasmDialect::WasmDialect() for (auto const& name: { "eq", "ne", + // TODO: lt_s "lt_u", + // TODO: gt_s "gt_u", + // TODO: le_s "le_u", + // TODO: ge_s "ge_u" }) addFunction(t.str() + "." + name, {t, t}, {i32}); @@ -62,8 +72,13 @@ WasmDialect::WasmDialect() addFunction("i32.eqz", {i32}, {i32}); addFunction("i64.eqz", {i64}, {i32}); - addFunction("i32.clz", {i32}, {i32}); - addFunction("i64.clz", {i64}, {i64}); + for (auto t: types) + for (auto const& name: { + "clz", + "ctz", + "popcnt", + }) + addFunction(t.str() + "." + name, {t}, {t}); addFunction("i32.wrap_i64", {i64}, {i32}); @@ -73,6 +88,7 @@ WasmDialect::WasmDialect() m_functions["i32.store"_yulstring].sideEffects.invalidatesStorage = false; addFunction("i64.store", {i32, i64}, {}, false); m_functions["i64.store"_yulstring].sideEffects.invalidatesStorage = false; + // TODO: add i32.store16, i64.store8, i64.store16, i64.store32 addFunction("i32.store8", {i32, i32}, {}, false); m_functions["i32.store8"_yulstring].sideEffects.invalidatesStorage = false; @@ -89,6 +105,7 @@ WasmDialect::WasmDialect() m_functions["i64.load"_yulstring].sideEffects.invalidatesMemory = false; m_functions["i64.load"_yulstring].sideEffects.sideEffectFree = true; m_functions["i64.load"_yulstring].sideEffects.sideEffectFreeIfNoMSize = true; + // TODO: add i32.load8, i32.load16, i64.load8, i64.load16, i64.load32 // Drop is actually overloaded for all types, but Yul does not support that. // Because of that, we introduce "i32.drop" and "i64.drop". diff --git a/libyul/backends/wasm/WasmDialect.h b/libyul/backends/wasm/WasmDialect.h index e5f3c9fc4315..a718f0b743af 100644 --- a/libyul/backends/wasm/WasmDialect.h +++ b/libyul/backends/wasm/WasmDialect.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Dialects for Wasm. */ diff --git a/libyul/backends/wasm/WasmObjectCompiler.cpp b/libyul/backends/wasm/WasmObjectCompiler.cpp index 52d485a7fc77..2b4f0c3558e4 100644 --- a/libyul/backends/wasm/WasmObjectCompiler.cpp +++ b/libyul/backends/wasm/WasmObjectCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Compiler that transforms Yul Objects to Wasm text and binary representation (Ewasm flavoured). */ diff --git a/libyul/backends/wasm/WasmObjectCompiler.h b/libyul/backends/wasm/WasmObjectCompiler.h index c5932a976b4b..52e48a9d5ecf 100644 --- a/libyul/backends/wasm/WasmObjectCompiler.h +++ b/libyul/backends/wasm/WasmObjectCompiler.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Compiler that transforms Yul Objects to Wasm text and binary representation (Ewasm flavoured). */ diff --git a/libyul/backends/wasm/WordSizeTransform.cpp b/libyul/backends/wasm/WordSizeTransform.cpp index 473f7324f3d6..73dda9d0c663 100644 --- a/libyul/backends/wasm/WordSizeTransform.cpp +++ b/libyul/backends/wasm/WordSizeTransform.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libyul/backends/wasm/WordSizeTransform.h b/libyul/backends/wasm/WordSizeTransform.h index 5771afea82ef..1bf7dcacaf0f 100644 --- a/libyul/backends/wasm/WordSizeTransform.h +++ b/libyul/backends/wasm/WordSizeTransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Replace every u256 variable with four u64 variables. */ diff --git a/libyul/optimiser/ASTCopier.cpp b/libyul/optimiser/ASTCopier.cpp index 16f257818d0e..8dc08f6fa1d6 100644 --- a/libyul/optimiser/ASTCopier.cpp +++ b/libyul/optimiser/ASTCopier.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Creates an independent copy of an AST, renaming identifiers to be unique. */ diff --git a/libyul/optimiser/ASTCopier.h b/libyul/optimiser/ASTCopier.h index 3a05d2ca3b8a..8afb50d97152 100644 --- a/libyul/optimiser/ASTCopier.h +++ b/libyul/optimiser/ASTCopier.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Creates an independent copy of an AST, renaming identifiers to be unique. */ diff --git a/libyul/optimiser/ASTWalker.cpp b/libyul/optimiser/ASTWalker.cpp index 728949a4e695..057f94b88782 100644 --- a/libyul/optimiser/ASTWalker.cpp +++ b/libyul/optimiser/ASTWalker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Generic AST walker. */ diff --git a/libyul/optimiser/ASTWalker.h b/libyul/optimiser/ASTWalker.h index 20f7fb9b4cc7..c62be4844ba5 100644 --- a/libyul/optimiser/ASTWalker.h +++ b/libyul/optimiser/ASTWalker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Generic AST walker. */ diff --git a/libyul/optimiser/BlockFlattener.cpp b/libyul/optimiser/BlockFlattener.cpp index 02e4c42f55c9..24f57594c5d2 100644 --- a/libyul/optimiser/BlockFlattener.cpp +++ b/libyul/optimiser/BlockFlattener.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/BlockFlattener.h b/libyul/optimiser/BlockFlattener.h index 31d3307d15cd..87a1af7cf1a3 100644 --- a/libyul/optimiser/BlockFlattener.h +++ b/libyul/optimiser/BlockFlattener.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/BlockHasher.cpp b/libyul/optimiser/BlockHasher.cpp index 53d263f944ab..4fb199982e9b 100644 --- a/libyul/optimiser/BlockHasher.cpp +++ b/libyul/optimiser/BlockHasher.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that calculates hash values for block prefixes. */ diff --git a/libyul/optimiser/BlockHasher.h b/libyul/optimiser/BlockHasher.h index 3b90f0c4de7a..36826e1583be 100644 --- a/libyul/optimiser/BlockHasher.h +++ b/libyul/optimiser/BlockHasher.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that calculates hash values for blocks. */ diff --git a/libyul/optimiser/CallGraphGenerator.cpp b/libyul/optimiser/CallGraphGenerator.cpp index d3805e7f72d0..85fb1c66c9c9 100644 --- a/libyul/optimiser/CallGraphGenerator.cpp +++ b/libyul/optimiser/CallGraphGenerator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST walker that generates the call graph. */ @@ -30,6 +31,47 @@ using namespace solidity; using namespace solidity::yul; using namespace solidity::util; +namespace +{ +// TODO: This algorithm is non-optimal. +struct CallGraphCycleFinder +{ + CallGraph const& callGraph; + set containedInCycle{}; + set visited{}; + vector currentPath{}; + + void visit(YulString _function) + { + if (visited.count(_function)) + return; + if ( + auto it = find(currentPath.begin(), currentPath.end(), _function); + it != currentPath.end() + ) + containedInCycle.insert(it, currentPath.end()); + else + { + currentPath.emplace_back(_function); + if (callGraph.functionCalls.count(_function)) + for (auto const& child: callGraph.functionCalls.at(_function)) + visit(child); + currentPath.pop_back(); + visited.insert(_function); + } + } +}; +} + +set CallGraph::recursiveFunctions() const +{ + CallGraphCycleFinder cycleFinder{*this}; + // Visiting the root only is not enough, since there may be disconnected recursive functions. + for (auto const& call: functionCalls) + cycleFinder.visit(call.first); + return cycleFinder.containedInCycle; +} + CallGraph CallGraphGenerator::callGraph(Block const& _ast) { CallGraphGenerator gen; diff --git a/libyul/optimiser/CallGraphGenerator.h b/libyul/optimiser/CallGraphGenerator.h index 2a05c7564930..11224eeaaebb 100644 --- a/libyul/optimiser/CallGraphGenerator.h +++ b/libyul/optimiser/CallGraphGenerator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST walker that generates the call graph. */ @@ -35,6 +36,10 @@ struct CallGraph { std::map> functionCalls; std::set functionsWithLoops; + /// @returns the set of functions contained in cycles in the call graph, i.e. + /// functions that are part of a (mutual) recursion. + /// Note that this does not include functions that merely call recursive functions. + std::set recursiveFunctions() const; }; /** diff --git a/libyul/optimiser/CircularReferencesPruner.cpp b/libyul/optimiser/CircularReferencesPruner.cpp index f9c849568b3b..2fe6a1d80734 100644 --- a/libyul/optimiser/CircularReferencesPruner.cpp +++ b/libyul/optimiser/CircularReferencesPruner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libyul/optimiser/CircularReferencesPruner.h b/libyul/optimiser/CircularReferencesPruner.h index 2a51045d12e7..0602445af4ab 100644 --- a/libyul/optimiser/CircularReferencesPruner.h +++ b/libyul/optimiser/CircularReferencesPruner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimization stage that removes functions that call each other but are * otherwise unreferenced. diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index 04fc36a8ca71..f11de51a4281 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that replaces expressions known to be the current value of a variable * in scope by a reference to that variable. diff --git a/libyul/optimiser/ConditionalSimplifier.cpp b/libyul/optimiser/ConditionalSimplifier.cpp index 453d2d9ce6ef..f95ef830a726 100644 --- a/libyul/optimiser/ConditionalSimplifier.cpp +++ b/libyul/optimiser/ConditionalSimplifier.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/ConditionalSimplifier.h b/libyul/optimiser/ConditionalSimplifier.h index 18f8a74b200c..9a48b813f90f 100644 --- a/libyul/optimiser/ConditionalSimplifier.h +++ b/libyul/optimiser/ConditionalSimplifier.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/ConditionalUnsimplifier.cpp b/libyul/optimiser/ConditionalUnsimplifier.cpp index f11079032123..28bc11a0c0e2 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.cpp +++ b/libyul/optimiser/ConditionalUnsimplifier.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/ConditionalUnsimplifier.h b/libyul/optimiser/ConditionalUnsimplifier.h index 116ab2536406..975011b957a7 100644 --- a/libyul/optimiser/ConditionalUnsimplifier.h +++ b/libyul/optimiser/ConditionalUnsimplifier.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/ControlFlowSimplifier.cpp b/libyul/optimiser/ControlFlowSimplifier.cpp index 1d6b096155fb..044061d9d077 100644 --- a/libyul/optimiser/ControlFlowSimplifier.cpp +++ b/libyul/optimiser/ControlFlowSimplifier.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/ControlFlowSimplifier.h b/libyul/optimiser/ControlFlowSimplifier.h index f8ea1af1ec24..3ebbe7c9aeee 100644 --- a/libyul/optimiser/ControlFlowSimplifier.h +++ b/libyul/optimiser/ControlFlowSimplifier.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index d3cb8d28048f..237b4859701d 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Base class to perform data flow analysis during AST walks. * Tracks assignments and is used as base class for both Rematerialiser and diff --git a/libyul/optimiser/DeadCodeEliminator.cpp b/libyul/optimiser/DeadCodeEliminator.cpp index 2416af514f58..1bb4f460d278 100644 --- a/libyul/optimiser/DeadCodeEliminator.cpp +++ b/libyul/optimiser/DeadCodeEliminator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that removes unreachable code. */ diff --git a/libyul/optimiser/DeadCodeEliminator.h b/libyul/optimiser/DeadCodeEliminator.h index d1607b49e671..d47bf86ea8f8 100644 --- a/libyul/optimiser/DeadCodeEliminator.h +++ b/libyul/optimiser/DeadCodeEliminator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that removes unused variables and functions. */ diff --git a/libyul/optimiser/Disambiguator.cpp b/libyul/optimiser/Disambiguator.cpp index 50aa93599aef..2e20d4be29ad 100644 --- a/libyul/optimiser/Disambiguator.cpp +++ b/libyul/optimiser/Disambiguator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that makes all identifiers unique. */ diff --git a/libyul/optimiser/Disambiguator.h b/libyul/optimiser/Disambiguator.h index 997a9cf2006e..6d8a3775cff4 100644 --- a/libyul/optimiser/Disambiguator.h +++ b/libyul/optimiser/Disambiguator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that makes all identifiers unique. */ diff --git a/libyul/optimiser/EquivalentFunctionCombiner.cpp b/libyul/optimiser/EquivalentFunctionCombiner.cpp index d62768a25bee..8cea5d63edda 100644 --- a/libyul/optimiser/EquivalentFunctionCombiner.cpp +++ b/libyul/optimiser/EquivalentFunctionCombiner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that combines syntactically equivalent functions. */ diff --git a/libyul/optimiser/EquivalentFunctionCombiner.h b/libyul/optimiser/EquivalentFunctionCombiner.h index 19ddbd71ff96..d43fa3986ed3 100644 --- a/libyul/optimiser/EquivalentFunctionCombiner.h +++ b/libyul/optimiser/EquivalentFunctionCombiner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that combines syntactically equivalent functions. */ diff --git a/libyul/optimiser/EquivalentFunctionDetector.cpp b/libyul/optimiser/EquivalentFunctionDetector.cpp index 6c617a4e4387..5c49ddb89fdf 100644 --- a/libyul/optimiser/EquivalentFunctionDetector.cpp +++ b/libyul/optimiser/EquivalentFunctionDetector.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that combines syntactically equivalent functions. */ diff --git a/libyul/optimiser/EquivalentFunctionDetector.h b/libyul/optimiser/EquivalentFunctionDetector.h index 62825bcfa4b3..107b355e6048 100644 --- a/libyul/optimiser/EquivalentFunctionDetector.h +++ b/libyul/optimiser/EquivalentFunctionDetector.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that combines syntactically equivalent functions. */ diff --git a/libyul/optimiser/ExpressionInliner.cpp b/libyul/optimiser/ExpressionInliner.cpp index f17b594f3d9f..ca29a58290e4 100644 --- a/libyul/optimiser/ExpressionInliner.cpp +++ b/libyul/optimiser/ExpressionInliner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that performs function inlining inside expressions. */ diff --git a/libyul/optimiser/ExpressionInliner.h b/libyul/optimiser/ExpressionInliner.h index 92bdebffc14c..f3a8833dfc34 100644 --- a/libyul/optimiser/ExpressionInliner.h +++ b/libyul/optimiser/ExpressionInliner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that performs function inlining. */ diff --git a/libyul/optimiser/ExpressionJoiner.cpp b/libyul/optimiser/ExpressionJoiner.cpp index 45c23dcc3022..fa9aac9ceb50 100644 --- a/libyul/optimiser/ExpressionJoiner.cpp +++ b/libyul/optimiser/ExpressionJoiner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that undoes what the ExpressionSplitter did, i.e. * it more or less inlines variable declarations. diff --git a/libyul/optimiser/ExpressionJoiner.h b/libyul/optimiser/ExpressionJoiner.h index 709a822e7dcf..db3217de0aee 100644 --- a/libyul/optimiser/ExpressionJoiner.h +++ b/libyul/optimiser/ExpressionJoiner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that undoes what the ExpressionSplitter did, i.e. * it more or less inlines variable declarations. diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index da30560575fe..ec3a6eb78ce1 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that uses the simplification rules to simplify expressions. */ diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index ce83b4e1eb39..b8703e2a27f3 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that uses the simplification rules to simplify expressions. */ diff --git a/libyul/optimiser/ExpressionSplitter.cpp b/libyul/optimiser/ExpressionSplitter.cpp index 30a5fd5e9e82..2c15b6eb528b 100644 --- a/libyul/optimiser/ExpressionSplitter.cpp +++ b/libyul/optimiser/ExpressionSplitter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that turns complex expressions into multiple variable * declarations. diff --git a/libyul/optimiser/ExpressionSplitter.h b/libyul/optimiser/ExpressionSplitter.h index 107be25905d4..ebcdd7f6d394 100644 --- a/libyul/optimiser/ExpressionSplitter.h +++ b/libyul/optimiser/ExpressionSplitter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that turns complex expressions into multiple variable * declarations. diff --git a/libyul/optimiser/ForLoopConditionIntoBody.cpp b/libyul/optimiser/ForLoopConditionIntoBody.cpp index 22c3e76dce08..a5b907ce71b8 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.cpp +++ b/libyul/optimiser/ForLoopConditionIntoBody.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libyul/optimiser/ForLoopConditionIntoBody.h b/libyul/optimiser/ForLoopConditionIntoBody.h index 633403c967a9..2a9c92c23783 100644 --- a/libyul/optimiser/ForLoopConditionIntoBody.h +++ b/libyul/optimiser/ForLoopConditionIntoBody.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.cpp b/libyul/optimiser/ForLoopConditionOutOfBody.cpp index fc7d48d6255d..f13b417e8b84 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.cpp +++ b/libyul/optimiser/ForLoopConditionOutOfBody.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libyul/optimiser/ForLoopConditionOutOfBody.h b/libyul/optimiser/ForLoopConditionOutOfBody.h index b5f8c8d023c6..ba3b7eb18309 100644 --- a/libyul/optimiser/ForLoopConditionOutOfBody.h +++ b/libyul/optimiser/ForLoopConditionOutOfBody.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/ForLoopInitRewriter.cpp b/libyul/optimiser/ForLoopInitRewriter.cpp index 163a999cd6ba..62d5201998de 100644 --- a/libyul/optimiser/ForLoopInitRewriter.cpp +++ b/libyul/optimiser/ForLoopInitRewriter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/ForLoopInitRewriter.h b/libyul/optimiser/ForLoopInitRewriter.h index e2143ca618c3..96ae0cca7e98 100644 --- a/libyul/optimiser/ForLoopInitRewriter.h +++ b/libyul/optimiser/ForLoopInitRewriter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/FullInliner.cpp b/libyul/optimiser/FullInliner.cpp index a0c80533d139..2e9dd1e05044 100644 --- a/libyul/optimiser/FullInliner.cpp +++ b/libyul/optimiser/FullInliner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that performs function inlining for arbitrary functions. */ diff --git a/libyul/optimiser/FullInliner.h b/libyul/optimiser/FullInliner.h index 1c1ad0d95355..8092e478e57b 100644 --- a/libyul/optimiser/FullInliner.h +++ b/libyul/optimiser/FullInliner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that performs function inlining for arbitrary functions. */ diff --git a/libyul/optimiser/FunctionGrouper.cpp b/libyul/optimiser/FunctionGrouper.cpp index 60a1fa0130a8..86d59dd53455 100644 --- a/libyul/optimiser/FunctionGrouper.cpp +++ b/libyul/optimiser/FunctionGrouper.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that changes the code of a block so that all non-function definition * statements are moved to a block of their own followed by all function definitions. diff --git a/libyul/optimiser/FunctionGrouper.h b/libyul/optimiser/FunctionGrouper.h index ef36198936e7..0bfbb2f069f5 100644 --- a/libyul/optimiser/FunctionGrouper.h +++ b/libyul/optimiser/FunctionGrouper.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that changes the code of a black so that all non-function definition * instructions are moved to a block of their own followed by all function definitions. diff --git a/libyul/optimiser/FunctionHoister.cpp b/libyul/optimiser/FunctionHoister.cpp index 303cf1fb38a8..a02feeda8e4b 100644 --- a/libyul/optimiser/FunctionHoister.cpp +++ b/libyul/optimiser/FunctionHoister.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that changes the code so that it consists of a block starting with * a single block followed only by function definitions and with no functions defined diff --git a/libyul/optimiser/FunctionHoister.h b/libyul/optimiser/FunctionHoister.h index 7106c03a423e..39e692c8a516 100644 --- a/libyul/optimiser/FunctionHoister.h +++ b/libyul/optimiser/FunctionHoister.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that changes the code so that all function definitions are at the top * level block. diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp index c9a1f084b605..c7830d48098f 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.cpp +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that identifies functions to be inlined. */ diff --git a/libyul/optimiser/InlinableExpressionFunctionFinder.h b/libyul/optimiser/InlinableExpressionFunctionFinder.h index 0583107d1b30..3c0b768e67cf 100644 --- a/libyul/optimiser/InlinableExpressionFunctionFinder.h +++ b/libyul/optimiser/InlinableExpressionFunctionFinder.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that identifies functions to be inlined. */ diff --git a/libyul/optimiser/KnowledgeBase.cpp b/libyul/optimiser/KnowledgeBase.cpp index c68085420b4e..0692d0c0665a 100644 --- a/libyul/optimiser/KnowledgeBase.cpp +++ b/libyul/optimiser/KnowledgeBase.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Class that can answer questions about values of variables and their relations. */ diff --git a/libyul/optimiser/KnowledgeBase.h b/libyul/optimiser/KnowledgeBase.h index 8d7bcdd904ce..7d4cdfb6b860 100644 --- a/libyul/optimiser/KnowledgeBase.h +++ b/libyul/optimiser/KnowledgeBase.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Class that can answer questions about values of variables and their relations. */ diff --git a/libyul/optimiser/LoadResolver.cpp b/libyul/optimiser/LoadResolver.cpp index 4d40281ecebf..7635f9d61a11 100644 --- a/libyul/optimiser/LoadResolver.cpp +++ b/libyul/optimiser/LoadResolver.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that replaces expressions of type ``sload(x)`` by the value * currently stored in storage, if known. diff --git a/libyul/optimiser/LoadResolver.h b/libyul/optimiser/LoadResolver.h index f2d11ed2a0f3..00579e95fb88 100644 --- a/libyul/optimiser/LoadResolver.h +++ b/libyul/optimiser/LoadResolver.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that replaces expressions of type ``sload(x)`` by the value * currently stored in storage, if known. diff --git a/libyul/optimiser/LoopInvariantCodeMotion.cpp b/libyul/optimiser/LoopInvariantCodeMotion.cpp index b7d7874c28f4..9a81e5fc8d5e 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.cpp +++ b/libyul/optimiser/LoopInvariantCodeMotion.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/libyul/optimiser/LoopInvariantCodeMotion.h b/libyul/optimiser/LoopInvariantCodeMotion.h index 7b7bd6c88b7f..a3bf1784f822 100644 --- a/libyul/optimiser/LoopInvariantCodeMotion.h +++ b/libyul/optimiser/LoopInvariantCodeMotion.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/MainFunction.cpp b/libyul/optimiser/MainFunction.cpp index e91cadb4d036..83968651d174 100644 --- a/libyul/optimiser/MainFunction.cpp +++ b/libyul/optimiser/MainFunction.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Changes the topmost block to be a function with a specific name ("main") which has no * inputs nor outputs. diff --git a/libyul/optimiser/MainFunction.h b/libyul/optimiser/MainFunction.h index 771624bef85f..92781f81ccd7 100644 --- a/libyul/optimiser/MainFunction.h +++ b/libyul/optimiser/MainFunction.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Changes the topmost block to be a function with a specific name ("main") which has no * inputs nor outputs. diff --git a/libyul/optimiser/Metrics.h b/libyul/optimiser/Metrics.h index 19ca5616f0fb..5aa8dbe4b921 100644 --- a/libyul/optimiser/Metrics.h +++ b/libyul/optimiser/Metrics.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module providing metrics for the optimizer. */ diff --git a/libyul/optimiser/NameCollector.cpp b/libyul/optimiser/NameCollector.cpp index f9bb40bf491e..5c6f2ab79fc6 100644 --- a/libyul/optimiser/NameCollector.cpp +++ b/libyul/optimiser/NameCollector.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST walker that collects all defined names. */ diff --git a/libyul/optimiser/NameCollector.h b/libyul/optimiser/NameCollector.h index a48aa1a3bdda..0bedab3f8ad4 100644 --- a/libyul/optimiser/NameCollector.h +++ b/libyul/optimiser/NameCollector.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST walkers that collect facts about identifiers and definitions. */ diff --git a/libyul/optimiser/NameDispenser.cpp b/libyul/optimiser/NameDispenser.cpp index fb1c1dd1c997..cfc7fdcb961d 100644 --- a/libyul/optimiser/NameDispenser.cpp +++ b/libyul/optimiser/NameDispenser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that can create new unique names. */ diff --git a/libyul/optimiser/NameDispenser.h b/libyul/optimiser/NameDispenser.h index 372e4bd2c273..1ef8c92e7014 100644 --- a/libyul/optimiser/NameDispenser.h +++ b/libyul/optimiser/NameDispenser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that can create new unique names. */ diff --git a/libyul/optimiser/NameDisplacer.cpp b/libyul/optimiser/NameDisplacer.cpp index 052b011ef814..81248819cd3a 100644 --- a/libyul/optimiser/NameDisplacer.cpp +++ b/libyul/optimiser/NameDisplacer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that renames identifiers to free up certain names. */ diff --git a/libyul/optimiser/NameDisplacer.h b/libyul/optimiser/NameDisplacer.h index ba61cbf9d96d..d1b3e4363b07 100644 --- a/libyul/optimiser/NameDisplacer.h +++ b/libyul/optimiser/NameDisplacer.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that renames identifiers to free up certain names. */ diff --git a/libyul/optimiser/OptimiserStep.h b/libyul/optimiser/OptimiserStep.h index ebad295515b4..3da161957d5d 100644 --- a/libyul/optimiser/OptimiserStep.h +++ b/libyul/optimiser/OptimiserStep.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libyul/optimiser/OptimizerUtilities.cpp b/libyul/optimiser/OptimizerUtilities.cpp index 132301696b98..3cb66d68930e 100644 --- a/libyul/optimiser/OptimizerUtilities.cpp +++ b/libyul/optimiser/OptimizerUtilities.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Some useful snippets for the optimiser. */ diff --git a/libyul/optimiser/OptimizerUtilities.h b/libyul/optimiser/OptimizerUtilities.h index 01bb7dae6d31..61d970877e72 100644 --- a/libyul/optimiser/OptimizerUtilities.h +++ b/libyul/optimiser/OptimizerUtilities.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Small useful snippets for the optimiser. */ diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/RedundantAssignEliminator.cpp index 5d1d0557b82b..170cf1d79772 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/RedundantAssignEliminator.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that removes assignments to variables that are not used * until they go out of scope or are re-assigned. diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/RedundantAssignEliminator.h index 3d61e84fb254..81e977e8d2e5 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/RedundantAssignEliminator.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that removes assignments to variables that are not used * until they go out of scope or are re-assigned. diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index 1316f0373bbc..b7e98a6b83d4 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that replaces variables by their most recently assigned expressions. */ diff --git a/libyul/optimiser/SSAReverser.cpp b/libyul/optimiser/SSAReverser.cpp index a4373fb667ab..decdc4ea4489 100644 --- a/libyul/optimiser/SSAReverser.cpp +++ b/libyul/optimiser/SSAReverser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/SSAReverser.h b/libyul/optimiser/SSAReverser.h index 0a6e0e1b01d0..bb6e98bc8ded 100644 --- a/libyul/optimiser/SSAReverser.h +++ b/libyul/optimiser/SSAReverser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/SSATransform.cpp b/libyul/optimiser/SSATransform.cpp index 21165cd47315..332b7af1dc87 100644 --- a/libyul/optimiser/SSATransform.cpp +++ b/libyul/optimiser/SSATransform.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that turns subsequent assignments to variable declarations * and assignments. diff --git a/libyul/optimiser/SSATransform.h b/libyul/optimiser/SSATransform.h index 201b1981a335..74e52b62ac92 100644 --- a/libyul/optimiser/SSATransform.h +++ b/libyul/optimiser/SSATransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser component that turns subsequent assignments to variable declarations * and assignments. diff --git a/libyul/optimiser/SSAValueTracker.cpp b/libyul/optimiser/SSAValueTracker.cpp index ec898ad3ce6f..452123447953 100644 --- a/libyul/optimiser/SSAValueTracker.cpp +++ b/libyul/optimiser/SSAValueTracker.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that collects variables that are never assigned to and their * initial values. diff --git a/libyul/optimiser/SSAValueTracker.h b/libyul/optimiser/SSAValueTracker.h index 24f4809478d5..f206cab5e89f 100644 --- a/libyul/optimiser/SSAValueTracker.h +++ b/libyul/optimiser/SSAValueTracker.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that collects variables that are never assigned to and their * initial values. diff --git a/libyul/optimiser/Semantics.cpp b/libyul/optimiser/Semantics.cpp index f9d831b7abef..4a7b8db12875 100644 --- a/libyul/optimiser/Semantics.cpp +++ b/libyul/optimiser/Semantics.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST walkers that collect semantical facts. */ @@ -102,33 +103,13 @@ map SideEffectsPropagator::sideEffects( // is actually a bit different from "not movable". map ret; - for (auto const& function: _directCallGraph.functionsWithLoops) + for (auto const& function: _directCallGraph.functionsWithLoops + _directCallGraph.recursiveFunctions()) { ret[function].movable = false; ret[function].sideEffectFree = false; ret[function].sideEffectFreeIfNoMSize = false; } - // Detect recursive functions. - for (auto const& call: _directCallGraph.functionCalls) - { - // TODO we could shortcut the search as soon as we find a - // function that has as bad side-effects as we can - // ever achieve via recursion. - auto search = [&](YulString const& _functionName, util::CycleDetector& _cycleDetector, size_t) { - for (auto const& callee: _directCallGraph.functionCalls.at(_functionName)) - if (!_dialect.builtin(callee)) - if (_cycleDetector.run(callee)) - return; - }; - if (util::CycleDetector(search).run(call.first)) - { - ret[call.first].movable = false; - ret[call.first].sideEffectFree = false; - ret[call.first].sideEffectFreeIfNoMSize = false; - } - } - for (auto const& call: _directCallGraph.functionCalls) { YulString funName = call.first; diff --git a/libyul/optimiser/Semantics.h b/libyul/optimiser/Semantics.h index 46d2984cab25..a4f7b810230a 100644 --- a/libyul/optimiser/Semantics.h +++ b/libyul/optimiser/Semantics.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST walkers that collect semantical facts. */ diff --git a/libyul/optimiser/SimplificationRules.cpp b/libyul/optimiser/SimplificationRules.cpp index 7a9b6576a633..2fe5de3e546c 100644 --- a/libyul/optimiser/SimplificationRules.cpp +++ b/libyul/optimiser/SimplificationRules.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module for applying replacement rules against Expressions. */ diff --git a/libyul/optimiser/SimplificationRules.h b/libyul/optimiser/SimplificationRules.h index b897ed492b95..05e4e0d590bd 100644 --- a/libyul/optimiser/SimplificationRules.h +++ b/libyul/optimiser/SimplificationRules.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Module for applying replacement rules against Expressions. */ diff --git a/libyul/optimiser/StackCompressor.h b/libyul/optimiser/StackCompressor.h index 6c9f1ff9a148..f10a6ba1767b 100644 --- a/libyul/optimiser/StackCompressor.h +++ b/libyul/optimiser/StackCompressor.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that aggressively rematerializes certain variables ina a function to free * space on the stack until it is compilable. diff --git a/libyul/optimiser/StructuralSimplifier.cpp b/libyul/optimiser/StructuralSimplifier.cpp index 0d5da95c1c59..09fe9ca1fa16 100644 --- a/libyul/optimiser/StructuralSimplifier.cpp +++ b/libyul/optimiser/StructuralSimplifier.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include #include diff --git a/libyul/optimiser/StructuralSimplifier.h b/libyul/optimiser/StructuralSimplifier.h index 8b9df5beb17e..3fd59efde42c 100644 --- a/libyul/optimiser/StructuralSimplifier.h +++ b/libyul/optimiser/StructuralSimplifier.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/libyul/optimiser/Substitution.cpp b/libyul/optimiser/Substitution.cpp index 6a0dc4800f41..ee2323577954 100644 --- a/libyul/optimiser/Substitution.cpp +++ b/libyul/optimiser/Substitution.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST copier that replaces certain identifiers with expressions. */ diff --git a/libyul/optimiser/Substitution.h b/libyul/optimiser/Substitution.h index 369754fea2ee..f76dcc72ea47 100644 --- a/libyul/optimiser/Substitution.h +++ b/libyul/optimiser/Substitution.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Specific AST copier that replaces certain identifiers with expressions. */ diff --git a/libyul/optimiser/Suite.cpp b/libyul/optimiser/Suite.cpp index 9f2511e7232c..a12ecd194d96 100644 --- a/libyul/optimiser/Suite.cpp +++ b/libyul/optimiser/Suite.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser suite that combines all steps and also provides the settings for the heuristics. */ diff --git a/libyul/optimiser/Suite.h b/libyul/optimiser/Suite.h index 790b2f9ad037..affbd37c0fd8 100644 --- a/libyul/optimiser/Suite.h +++ b/libyul/optimiser/Suite.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimiser suite that combines all steps and also provides the settings for the heuristics. */ diff --git a/libyul/optimiser/SyntacticalEquality.h b/libyul/optimiser/SyntacticalEquality.h index 7cf5dc24a37d..774a223cc3d3 100644 --- a/libyul/optimiser/SyntacticalEquality.h +++ b/libyul/optimiser/SyntacticalEquality.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Component that can compare ASTs for equality on a syntactic basis. */ diff --git a/libyul/optimiser/TypeInfo.cpp b/libyul/optimiser/TypeInfo.cpp index adb6e1ccef41..740856c72815 100644 --- a/libyul/optimiser/TypeInfo.cpp +++ b/libyul/optimiser/TypeInfo.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Helper class that keeps track of the types while performing optimizations. */ diff --git a/libyul/optimiser/TypeInfo.h b/libyul/optimiser/TypeInfo.h index 48c6c1fba820..f458cbe443e0 100644 --- a/libyul/optimiser/TypeInfo.h +++ b/libyul/optimiser/TypeInfo.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Helper class that keeps track of the types while performing optimizations. */ diff --git a/libyul/optimiser/UnusedPruner.h b/libyul/optimiser/UnusedPruner.h index 837088059db5..af77d911af85 100644 --- a/libyul/optimiser/UnusedPruner.h +++ b/libyul/optimiser/UnusedPruner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Optimisation stage that removes unused variables and functions. */ diff --git a/libyul/optimiser/VarDeclInitializer.cpp b/libyul/optimiser/VarDeclInitializer.cpp index 66c5b45056be..ca6c89feb7da 100644 --- a/libyul/optimiser/VarDeclInitializer.cpp +++ b/libyul/optimiser/VarDeclInitializer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libyul/optimiser/VarDeclInitializer.h b/libyul/optimiser/VarDeclInitializer.h index 75bb1493c8ee..3d2d51c34df6 100644 --- a/libyul/optimiser/VarDeclInitializer.h +++ b/libyul/optimiser/VarDeclInitializer.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/libyul/optimiser/VarNameCleaner.cpp b/libyul/optimiser/VarNameCleaner.cpp index f9b9e7899048..15d215f2cf23 100644 --- a/libyul/optimiser/VarNameCleaner.cpp +++ b/libyul/optimiser/VarNameCleaner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/libyul/optimiser/VarNameCleaner.h b/libyul/optimiser/VarNameCleaner.h index 911f67ca66e4..2c26cc7a67bf 100644 --- a/libyul/optimiser/VarNameCleaner.h +++ b/libyul/optimiser/VarNameCleaner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/scripts/build_emscripten.sh b/scripts/build_emscripten.sh index 7a052aa77eb6..f4b0fe647a7c 100755 --- a/scripts/build_emscripten.sh +++ b/scripts/build_emscripten.sh @@ -34,5 +34,6 @@ else BUILD_DIR="$1" fi -docker run -v $(pwd):/root/project -w /root/project ethereum/solidity-buildpack-deps:emsdk-1.39.15-2 \ +docker run -v $(pwd):/root/project -w /root/project \ + solbuildpackpusher/solidity-buildpack-deps@sha256:d557d015918c3cf68b0d22839bab41013f0757b651a7fef21595f89721dbebcc \ ./scripts/travis-emscripten/build_emscripten.sh $BUILD_DIR diff --git a/scripts/ci/build.sh b/scripts/ci/build.sh new file mode 100755 index 000000000000..a939412f6dc5 --- /dev/null +++ b/scripts/ci/build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -ex + +ROOTDIR="$(dirname "$0")/../.." +cd "${ROOTDIR}" + +# shellcheck disable=SC2166 +if [ "$CIRCLE_BRANCH" = release -o -n "$CIRCLE_TAG" -o -n "$FORCE_RELEASE" ]; then echo -n >prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" >prerelease.txt; fi +if [ -n "$CIRCLE_SHA1" ] +then + echo -n "$CIRCLE_SHA1" >commit_hash.txt +fi + +mkdir -p build +cd build + +# shellcheck disable=SC2166 +[ -n "$COVERAGE" -a "$CIRCLE_BRANCH" != release -a -z "$CIRCLE_TAG" ] && CMAKE_OPTIONS="$CMAKE_OPTIONS -DCOVERAGE=ON" + +# shellcheck disable=SC2086 +cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" $CMAKE_OPTIONS -G "Unix Makefiles" + +make diff --git a/scripts/ci/build_ossfuzz.sh b/scripts/ci/build_ossfuzz.sh new file mode 100755 index 000000000000..42f7b3a3959c --- /dev/null +++ b/scripts/ci/build_ossfuzz.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e + +ROOTDIR="$(dirname "$0")/../.." +BUILDDIR="${ROOTDIR}/build" + +mkdir -p "${BUILDDIR}" +cd "${BUILDDIR}" + +protoc --proto_path=../test/tools/ossfuzz yulProto.proto --cpp_out=../test/tools/ossfuzz +protoc --proto_path=../test/tools/ossfuzz abiV2Proto.proto --cpp_out=../test/tools/ossfuzz +protoc --proto_path=../test/tools/ossfuzz solProto.proto --cpp_out=../test/tools/ossfuzz +cmake .. -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:-Release}" -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/libfuzzer.cmake + +make ossfuzz ossfuzz_proto ossfuzz_abiv2 -j 4 diff --git a/scripts/ci/buildpack-deps_test_emscripten.sh b/scripts/ci/buildpack-deps_test_emscripten.sh new file mode 120000 index 000000000000..6e838fba7fb3 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_emscripten.sh @@ -0,0 +1 @@ +../../scripts/travis-emscripten/build_emscripten.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu1604.clang.ossfuzz.sh b/scripts/ci/buildpack-deps_test_ubuntu1604.clang.ossfuzz.sh new file mode 120000 index 000000000000..86beda7dd2c3 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu1604.clang.ossfuzz.sh @@ -0,0 +1 @@ +build_ossfuzz.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu1804.sh b/scripts/ci/buildpack-deps_test_ubuntu1804.sh new file mode 120000 index 000000000000..c07a74de4fb4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu1804.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu2004.clang.sh b/scripts/ci/buildpack-deps_test_ubuntu2004.clang.sh new file mode 120000 index 000000000000..c07a74de4fb4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2004.clang.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/ci/buildpack-deps_test_ubuntu2004.sh b/scripts/ci/buildpack-deps_test_ubuntu2004.sh new file mode 120000 index 000000000000..c07a74de4fb4 --- /dev/null +++ b/scripts/ci/buildpack-deps_test_ubuntu2004.sh @@ -0,0 +1 @@ +build.sh \ No newline at end of file diff --git a/scripts/ci/docker_upgrade.sh b/scripts/ci/docker_upgrade.sh new file mode 100755 index 000000000000..16d6222305bf --- /dev/null +++ b/scripts/ci/docker_upgrade.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -e + +function error() { + echo >&2 "ERROR: ${1} Aborting." && false +} + +function warning() { + echo >&2 "WARNING: ${1}" +} + +[[ $# == 3 ]] || error "Expected exactly 3 parameters: '${0} '." + +IMAGE_NAME="${1}" +IMAGE_VARIANT="${2}" +DOCKER_REPOSITORY="${3}" +DOCKERFILE="scripts/docker/${IMAGE_NAME}/Dockerfile.${IMAGE_VARIANT}" + +echo "-- check_dockerfile_was_changed" + +# exit, if the dockerfile was not changed. +if git diff --quiet origin/develop HEAD -- "${DOCKERFILE}"; then + echo "${DOCKERFILE} was not changed. Nothing to do." + exit 0 +fi + +echo "-- check_version" + +PREV_VERSION=$(git diff origin/develop HEAD -- "${DOCKERFILE}" | grep -e '^\s*-LABEL\s\+version=".*"\s*$' | awk -F'"' '{ print $2 }') +NEXT_VERSION=$(git diff origin/develop HEAD -- "${DOCKERFILE}" | grep -e '^\s*+LABEL\s\+version=".*"\s*$' | awk -F'"' '{ print $2 }') + +[[ $NEXT_VERSION != "" ]] || error "No version label defined in Dockerfile. You may need to add 'LABEL version' in '${DOCKERFILE}'." + +[[ $PREV_VERSION != "" ]] || { + warning "no previous version found. Will set \$PREV_VERSION = 0." + PREV_VERSION=0 +} + +if [[ $((PREV_VERSION + 1)) != $((NEXT_VERSION)) ]]; then + error "Version label in Dockerfile was not incremented. You may need to change 'LABEL version' in '${DOCKERFILE}'." +fi + +echo "-- build_docker" + +# This is a workaround: we run `docker build` twice to prevent the `layer does not exist` problem. +# See https://github.com/moby/moby/issues/37965. +docker build "scripts/docker/${IMAGE_NAME}" --file "scripts/docker/${IMAGE_NAME}/Dockerfile.${IMAGE_VARIANT}" --tag "${IMAGE_NAME}" || + docker build "scripts/docker/${IMAGE_NAME}" --file "scripts/docker/${IMAGE_NAME}/Dockerfile.${IMAGE_VARIANT}" --tag "${IMAGE_NAME}" + +echo "-- test_docker @ '${PWD}'" + +docker run --rm --volume "${PWD}:/root/project" "${IMAGE_NAME}" "/root/project/scripts/ci/${IMAGE_NAME}_test_${IMAGE_VARIANT}.sh" + +echo "-- push_docker" + +VERSION=$(docker inspect --format='{{.Config.Labels.version}}' "${IMAGE_NAME}") +DOCKER_IMAGE_ID="${DOCKER_REPOSITORY}:${IMAGE_VARIANT}" + +docker tag "${IMAGE_NAME}" "${DOCKER_IMAGE_ID}-${VERSION}" +docker push "${DOCKER_IMAGE_ID}-${VERSION}" + +REPO_DIGEST=$(docker inspect --format='{{.RepoDigests}}' "${DOCKER_IMAGE_ID}-${VERSION}") + +echo "::set-env name=DOCKER_IMAGE::${DOCKER_IMAGE_ID}-${VERSION}" +echo "::set-env name=DOCKER_REPO_DIGEST::${REPO_DIGEST}" diff --git a/scripts/create_source_tarball.sh b/scripts/create_source_tarball.sh index a4b4fbec13a3..d75650a53e0d 100755 --- a/scripts/create_source_tarball.sh +++ b/scripts/create_source_tarball.sh @@ -31,7 +31,7 @@ REPO_ROOT="$(dirname "$0")"/.. fi # Add dependencies mkdir -p "$SOLDIR/deps/downloads/" 2>/dev/null || true - wget -O "$SOLDIR/deps/downloads/jsoncpp-1.9.2.tar.gz" https://github.com/open-source-parsers/jsoncpp/archive/1.9.2.tar.gz + wget -O "$SOLDIR/deps/downloads/jsoncpp-1.9.3.tar.gz" https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz mkdir -p "$REPO_ROOT/upload" tar --owner 0 --group 0 -czf "$REPO_ROOT/upload/solidity_$versionstring.tar.gz" -C "$TEMPDIR" "solidity_$versionstring" rm -r "$TEMPDIR" diff --git a/.circleci/docker/Dockerfile.emscripten b/scripts/docker/buildpack-deps/Dockerfile.emscripten similarity index 99% rename from .circleci/docker/Dockerfile.emscripten rename to scripts/docker/buildpack-deps/Dockerfile.emscripten index d2456bb2ae0b..2d9ce401ddc1 100644 --- a/.circleci/docker/Dockerfile.emscripten +++ b/scripts/docker/buildpack-deps/Dockerfile.emscripten @@ -29,6 +29,7 @@ # make version=1.39.15 build # FROM emscripten/emsdk:1.39.15 AS base +LABEL version="1" ADD emscripten.jam /usr/src RUN set -ex; \ @@ -63,3 +64,4 @@ RUN set -ex; \ cxxflags="-s DISABLE_EXCEPTION_CATCHING=0 -Wno-unused-local-typedef -Wno-variadic-macros -Wno-c99-extensions -Wno-all" \ --prefix=/emsdk/emscripten/sdk/system install; \ rm -r /usr/src/boost_1_73_0 + diff --git a/.circleci/docker/Dockerfile.ubuntu1604.clang.ossfuzz b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz similarity index 99% rename from .circleci/docker/Dockerfile.ubuntu1604.clang.ossfuzz rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz index f7dfc7001bdf..ceea17d8180c 100644 --- a/.circleci/docker/Dockerfile.ubuntu1604.clang.ossfuzz +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1604.clang.ossfuzz @@ -22,6 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM gcr.io/oss-fuzz-base/base-clang as base +LABEL version="1" ARG DEBIAN_FRONTEND=noninteractive @@ -99,3 +100,4 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include + diff --git a/.circleci/docker/Dockerfile.ubuntu1804 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1804 similarity index 99% rename from .circleci/docker/Dockerfile.ubuntu1804 rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu1804 index fa651900b873..51eed0a9e4ed 100644 --- a/.circleci/docker/Dockerfile.ubuntu1804 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu1804 @@ -22,6 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:bionic AS base +LABEL version="1" ARG DEBIAN_FRONTEND=noninteractive @@ -91,3 +92,4 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include + diff --git a/.circleci/docker/Dockerfile.ubuntu2004 b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 similarity index 99% rename from .circleci/docker/Dockerfile.ubuntu2004 rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 index a021b6533486..591e430af77a 100644 --- a/.circleci/docker/Dockerfile.ubuntu2004 +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004 @@ -22,6 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base +LABEL version="1" ARG DEBIAN_FRONTEND=noninteractive @@ -60,3 +61,4 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include + diff --git a/.circleci/docker/Dockerfile.ubuntu2004.clang b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang similarity index 99% rename from .circleci/docker/Dockerfile.ubuntu2004.clang rename to scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang index c8d057eb11a0..c1663fdba7a9 100644 --- a/.circleci/docker/Dockerfile.ubuntu2004.clang +++ b/scripts/docker/buildpack-deps/Dockerfile.ubuntu2004.clang @@ -22,6 +22,7 @@ # (c) 2016-2019 solidity contributors. #------------------------------------------------------------------------------ FROM buildpack-deps:focal AS base +LABEL version="1" ARG DEBIAN_FRONTEND=noninteractive @@ -62,3 +63,4 @@ FROM base COPY --from=libraries /usr/lib /usr/lib COPY --from=libraries /usr/bin /usr/bin COPY --from=libraries /usr/include /usr/include + diff --git a/scripts/docker/buildpack-deps/README.md b/scripts/docker/buildpack-deps/README.md new file mode 100644 index 000000000000..004a89e91f78 --- /dev/null +++ b/scripts/docker/buildpack-deps/README.md @@ -0,0 +1,35 @@ +# buildpack-deps docker images + +The `buildpack-deps` docker images are used to compile and test solidity within our CI. + +## GitHub Workflow + +The creation of the images are triggered by a single workflow, defined in `.github/workflows/buildpack-deps.yml`. +For each resulting `buildpack-deps` docker image a strategy is defined in the workflow file - the image variant. +The workflow gets triggered, if any Dockerfile defined in `scripts/docker/buildpack-deps/Dockerfile.*` were changed +within the PR. + +### Versioning + +The version of the docker images can be defined within the Dockerfile with `LABEL version`. A new docker image +will only be created and pushed, if the new version is incremented by `1` compared with the version of the Dockerfile +located in `develop`. + +### Build, Test & Push + +Note that the whole workflow - including all defined strategies (image variants) - will be triggered, +even if only a single Dockerfile was change. The full workflow will only gets executed, if the corresponding +Dockerfile was changed. The execution of workflows of unchanged Dockerfiles will not continue and just return success. +See `scripts/ci/docker_upgrade.sh`. + +If the version check was successful, the docker image will be built using the Dockerfile located in +`scripts/docker/buildpack-deps/Dockerfile.*`. + +The resulting docker image will be tested by executing +the corresponding `scripts/ci/buildpack-deps_test_*` scripts. These scripts are normally symlinked to `scripts/ci/build.sh`, +except for the `buildpack-deps-ubuntu1604.clang.ossfuzz` docker image, that is symlinked to `scripts/ci/build_ossfuzz.sh`. +These scripts `scripts/ci/build.sh` and `scripts/ci/build_ossfuzz.sh` are also used by CircleCI, see `.circleci/config.yml`. + +If the tests passed successfully, the docker image will get tagged by the version defined within the corresponding `Dockerfile`. +Finally, a comment will be added to the PR that contains the full repository, version and repository digest +of the freshly created docker image. \ No newline at end of file diff --git a/.circleci/docker/emscripten.jam b/scripts/docker/buildpack-deps/emscripten.jam similarity index 100% rename from .circleci/docker/emscripten.jam rename to scripts/docker/buildpack-deps/emscripten.jam diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 7ab136e84c84..8ab9b04dc679 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -36,24 +36,26 @@ def in_comment(source, pos): return slash_star_pos > star_slash_pos -def find_ids_in_source_file(file_name, ids): +def find_ids_in_source_file(file_name, id_to_file_names): source = read_file(file_name) for m in re.finditer(SOURCE_FILE_PATTERN, source): if in_comment(source, m.start()): continue underscore_pos = m.group(0).index("_") id = m.group(0)[0:underscore_pos] - if id in ids: - ids[id] += 1 + if id in id_to_file_names: + id_to_file_names[id].append(file_name) else: - ids[id] = 1 + id_to_file_names[id] = [file_name] -def get_used_ids(file_names): - used_ids = {} +def find_ids_in_source_files(file_names): + """Returns a dictionary with list of source files for every appearance of every id""" + + id_to_file_names = {} for file_name in file_names: - find_ids_in_source_file(file_name, used_ids) - return used_ids + find_ids_in_source_file(file_name, id_to_file_names) + return id_to_file_names def get_next_id(available_ids): @@ -63,7 +65,7 @@ def get_next_id(available_ids): return next_id -def fix_ids_in_file(file_name, available_ids, used_ids): +def fix_ids_in_source_file(file_name, id_to_count, available_ids): source = read_file(file_name) k = 0 @@ -75,11 +77,11 @@ def fix_ids_in_file(file_name, available_ids, used_ids): id = m.group(0)[0:underscore_pos] # incorrect id or id has a duplicate somewhere - if not in_comment(source, m.start()) and (len(id) != 4 or id[0] == "0" or used_ids[id] > 1): - assert id in used_ids + if not in_comment(source, m.start()) and (len(id) != 4 or id[0] == "0" or id_to_count[id] > 1): + assert id in id_to_count new_id = get_next_id(available_ids) - assert new_id not in used_ids - used_ids[id] -= 1 + assert new_id not in id_to_count + id_to_count[id] -= 1 else: new_id = id @@ -94,10 +96,15 @@ def fix_ids_in_file(file_name, available_ids, used_ids): print(f"Fixed file: {file_name}") -def fix_ids(used_ids, file_names): - available_ids = {str(id) for id in range(1000, 10000)} - used_ids.keys() +def fix_ids_in_source_files(file_names, id_to_count): + """ + Fixes ids in given source files; + id_to_count contains number of appearances of every id in sources + """ + + available_ids = {str(id) for id in range(1000, 10000)} - id_to_count.keys() for file_name in file_names: - fix_ids_in_file(file_name, available_ids, used_ids) + fix_ids_in_source_file(file_name, id_to_count, available_ids) def find_files(top_dir, sub_dirs, extensions): @@ -121,10 +128,18 @@ def find_ids_in_test_file(file_name): def find_ids_in_test_files(file_names): - used_ids = set() + """Returns a set containing all ids in tests""" + + ids = set() for file_name in file_names: - used_ids |= find_ids_in_test_file(file_name) - return used_ids + ids |= find_ids_in_test_file(file_name) + return ids + + +def find_ids_in_cmdline_test_err(file_name): + source = read_file(file_name) + pattern = r' \(\d\d\d\d\):' + return {m.group(0)[-6:-2] for m in re.finditer(pattern, source, flags=re.MULTILINE)} def print_ids(ids): @@ -136,7 +151,23 @@ def print_ids(ids): print(id, end="") -def examine_id_coverage(top_dir, used_ids): +def print_ids_per_file(ids, id_to_file_names, top_dir): + file_name_to_ids = {} + for id in ids: + for file_name in id_to_file_names[id]: + relpath = path.relpath(file_name, top_dir) + if relpath not in file_name_to_ids: + file_name_to_ids[relpath] = [] + file_name_to_ids[relpath].append(id) + + for file_name in sorted(file_name_to_ids): + print(file_name) + for id in sorted(file_name_to_ids[file_name]): + print(f" {id}", end="") + print() + + +def examine_id_coverage(top_dir, source_id_to_file_names): test_sub_dirs = [ path.join("test", "libsolidity", "errorRecoveryTests"), path.join("test", "libsolidity", "smtCheckerTests"), @@ -147,22 +178,28 @@ def examine_id_coverage(top_dir, used_ids): test_sub_dirs, [".sol"] ) - covered_ids = find_ids_in_test_files(test_file_names) + source_ids = source_id_to_file_names.keys() + test_ids = find_ids_in_test_files(test_file_names) + + # special case, we are interested in warnings which are ignored by regular tests: + # Warning (1878): SPDX license identifier not provided in source file. .... + # Warning (3420): Source file does not specify required compiler version! + test_ids |= find_ids_in_cmdline_test_err(path.join(top_dir, "test", "cmdlineTests", "error_codes", "err")) - print(f"IDs in source files: {len(used_ids)}") - print(f"IDs in test files : {len(covered_ids)} ({len(covered_ids) - len(used_ids)})") + print(f"IDs in source files: {len(source_ids)}") + print(f"IDs in test files : {len(test_ids)} ({len(test_ids) - len(source_ids)})") print() - unused_covered_ids = covered_ids - used_ids - if len(unused_covered_ids) != 0: + test_only_ids = test_ids - source_ids + if len(test_only_ids) != 0: print("Error. The following error codes found in tests, but not in sources:") - print_ids(unused_covered_ids) + print_ids(test_only_ids) return 1 - used_uncovered_ids = used_ids - covered_ids - if len(used_uncovered_ids) != 0: + source_only_ids = source_ids - test_ids + if len(source_only_ids) != 0: print("The following error codes found in sources, but not in tests:") - print_ids(used_uncovered_ids) + print_ids_per_file(source_only_ids, source_id_to_file_names, top_dir) print("\n\nPlease make sure to add appropriate tests.") return 1 @@ -176,22 +213,22 @@ def main(argv): fix = False no_confirm = False examine_coverage = False - next = False + next_id = False opts, args = getopt.getopt(argv, "", ["check", "fix", "no-confirm", "examine-coverage", "next"]) for opt, arg in opts: - if opt == '--check': + if opt == "--check": check = True elif opt == "--fix": fix = True - elif opt == '--no-confirm': + elif opt == "--no-confirm": no_confirm = True - elif opt == '--examine-coverage': + elif opt == "--examine-coverage": examine_coverage = True - elif opt == '--next': - next = True + elif opt == "--next": + next_id = True - if [check, fix, examine_coverage, next].count(True) != 1: + if [check, fix, examine_coverage, next_id].count(True) != 1: print("usage: python error_codes.py --check | --fix [--no-confirm] | --examine-coverage | --next") exit(1) @@ -202,32 +239,34 @@ def main(argv): ["libevmasm", "liblangutil", "libsolc", "libsolidity", "libsolutil", "libyul", "solc"], [".h", ".cpp"] ) - used_ids = get_used_ids(source_file_names) + source_id_to_file_names = find_ids_in_source_files(source_file_names) ok = True - for id in sorted(used_ids): + for id in sorted(source_id_to_file_names): if len(id) != 4: print(f"ID {id} length != 4") ok = False if id[0] == "0": print(f"ID {id} starts with zero") ok = False - if used_ids[id] > 1: - print(f"ID {id} appears {used_ids[id]} times") + if len(source_id_to_file_names[id]) > 1: + print(f"ID {id} appears {len(source_id_to_file_names[id])} times") ok = False if examine_coverage: if not ok: print("Incorrect IDs have to be fixed before applying --examine-coverage") - res = examine_id_coverage(cwd, used_ids.keys()) + exit(1) + res = examine_id_coverage(cwd, source_id_to_file_names) exit(res) random.seed() - if next: + if next_id: if not ok: print("Incorrect IDs have to be fixed before applying --next") - available_ids = {str(id) for id in range(1000, 10000)} - used_ids.keys() + exit(1) + available_ids = {str(id) for id in range(1000, 10000)} - source_id_to_file_names.keys() next_id = get_next_id(available_ids) print(f"Next ID: {next_id}") exit(0) @@ -252,7 +291,10 @@ def main(argv): if answer not in "yY": exit(1) - fix_ids(used_ids, source_file_names) + # number of appearances for every id + source_id_to_count = { id: len(file_names) for id, file_names in source_id_to_file_names.items() } + + fix_ids_in_source_files(source_file_names, source_id_to_count) print("Fixing completed") exit(2) diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index 267346e417cb..d15f8d221bb4 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -107,7 +107,7 @@ mv solidity solc # Fetch jsoncpp dependency mkdir -p ./solc/deps/downloads/ 2>/dev/null || true -wget -O ./solc/deps/downloads/jsoncpp-1.9.2.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/1.9.2.tar.gz +wget -O ./solc/deps/downloads/jsoncpp-1.9.3.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/1.9.3.tar.gz # Determine version cd solc diff --git a/scripts/run_proofs.sh b/scripts/run_proofs.sh index bc6cd8e8ac4a..db6b0e02b289 100755 --- a/scripts/run_proofs.sh +++ b/scripts/run_proofs.sh @@ -10,16 +10,18 @@ git fetch origin error=0 for new_proof in $(git diff origin/develop --name-only test/formal/) do - set +e - echo "Proving $new_proof..." - output=$(python3 "$new_proof") - result=$? - set -e + if [ -e "$new_proof" ]; then + set +e + echo "Proving $new_proof..." + output=$(python3 "$new_proof") + result=$? + set -e - if [[ "$result" != 0 ]] - then - echo "Proof $(basename "$new_proof" ".py") failed: $output." - error=1 + if [[ "$result" != 0 ]] + then + echo "Proof $(basename "$new_proof" ".py") failed: $output." + error=1 + fi fi done diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh index 5c7e3f052a95..3162e13b661a 100755 --- a/scripts/travis-emscripten/build_emscripten.sh +++ b/scripts/travis-emscripten/build_emscripten.sh @@ -53,7 +53,7 @@ cmake \ -DBoost_USE_STATIC_RUNTIME=1 \ -DTESTS=0 \ .. -make -j 4 soljson +make soljson # Patch soljson.js for backwards compatibility. # TODO: remove this with 0.7. # "viiiii" encodes the signature of the callback function. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 3bd374676e52..412d7f094e14 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris * @author Gav Wood diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 1aed728216f9..e79d8140688f 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris * @date 2014 diff --git a/solc/main.cpp b/solc/main.cpp index 5307e40ad0e0..ae56066edf92 100644 --- a/solc/main.cpp +++ b/solc/main.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/test/Common.cpp b/test/Common.cpp index 69bfd21ee447..b56cb3257734 100644 --- a/test/Common.cpp +++ b/test/Common.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/Common.h b/test/Common.h index 119050f393b6..eaad7f0bac64 100644 --- a/test/Common.h +++ b/test/Common.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/CommonSyntaxTest.cpp b/test/CommonSyntaxTest.cpp index ff99d6e24a62..34ddf719e403 100644 --- a/test/CommonSyntaxTest.cpp +++ b/test/CommonSyntaxTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/CommonSyntaxTest.h b/test/CommonSyntaxTest.h index df165ea1a3fc..db3a6e50c57e 100644 --- a/test/CommonSyntaxTest.h +++ b/test/CommonSyntaxTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 108dae4f1e43..51dc833521c9 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * EVM execution host, i.e. component that implements a simulated Ethereum blockchain * for testing purposes. diff --git a/test/EVMHost.h b/test/EVMHost.h index 1e3540012834..af38426be19b 100644 --- a/test/EVMHost.h +++ b/test/EVMHost.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * EVM execution host, i.e. component that implements a simulated Ethereum blockchain * for testing purposes. diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index ebe63b2657c7..b3841f6b4d20 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 6fea5310a7b8..56321a1190e3 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/test/InteractiveTests.h b/test/InteractiveTests.h index 409d8607daf4..46d8a2973a79 100644 --- a/test/InteractiveTests.h +++ b/test/InteractiveTests.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once @@ -46,6 +47,7 @@ struct Testsuite bool smt; bool needsVM; TestCase::TestCaseCreator testCaseCreator; + std::vector labels{}; }; @@ -64,8 +66,8 @@ Testsuite const g_interactiveTestsuites[] = { {"Semantic", "libsolidity", "semanticTests", false, true, &SemanticTest::create}, {"JSON AST", "libsolidity", "ASTJSON", false, false, &ASTJSONTest::create}, {"JSON ABI", "libsolidity", "ABIJson", false, false, &ABIJsonTest::create}, - {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SMTCheckerTest::create}, - {"SMT Checker JSON", "libsolidity", "smtCheckerTestsJSON", true, false, &SMTCheckerJSONTest::create}, + {"SMT Checker", "libsolidity", "smtCheckerTests", true, false, &SMTCheckerTest::create, {"nooptions"}}, + {"SMT Checker JSON", "libsolidity", "smtCheckerTestsJSON", true, false, &SMTCheckerJSONTest::create, {"nooptions"}}, {"Gas Estimates", "libsolidity", "gasTests", false, false, &GasTest::create} }; diff --git a/test/Metadata.cpp b/test/Metadata.cpp index cb5892b8af03..f70b8ea5f2dc 100644 --- a/test/Metadata.cpp +++ b/test/Metadata.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Metadata processing helpers. diff --git a/test/Metadata.h b/test/Metadata.h index f032f1d1f7cf..c91ceb559fa2 100644 --- a/test/Metadata.h +++ b/test/Metadata.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Metadata processing helpers. diff --git a/test/TestCase.cpp b/test/TestCase.cpp index e6f4b212aab5..7cf5c790eb09 100644 --- a/test/TestCase.cpp +++ b/test/TestCase.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/TestCase.h b/test/TestCase.h index f846b7f87f46..1815409fe018 100644 --- a/test/TestCase.h +++ b/test/TestCase.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/TestCaseReader.cpp b/test/TestCaseReader.cpp index 2f90678ed56e..d38e883ea567 100644 --- a/test/TestCaseReader.cpp +++ b/test/TestCaseReader.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -37,6 +38,13 @@ TestCaseReader::TestCaseReader(string const& _filename): m_unreadSettings = m_settings; } +TestCaseReader::TestCaseReader(istringstream const& _str) +{ + tie(m_sources, m_lineNumber) = parseSourcesAndSettingsWithLineNumber( + static_cast(const_cast(_str)) + ); +} + string const& TestCaseReader::source() const { if (m_sources.sources.size() != 1) diff --git a/test/TestCaseReader.h b/test/TestCaseReader.h index 9f94f898d642..620565aee3e6 100644 --- a/test/TestCaseReader.h +++ b/test/TestCaseReader.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include @@ -41,6 +42,7 @@ class TestCaseReader public: TestCaseReader() = default; explicit TestCaseReader(std::string const& _filename); + explicit TestCaseReader(std::istringstream const& _testCode); SourceMap const& sources() const { return m_sources; } std::string const& source() const; diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 5b45cc758214..8f065a7bb5dd 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file boostTest.cpp * @author Marko Simovic * @date 2014 @@ -65,6 +66,7 @@ int registerTests( boost::filesystem::path const& _basepath, boost::filesystem::path const& _path, bool _enforceViaYul, + vector const& _labels, TestCase::TestCaseCreator _testCaseCreator ) { @@ -83,6 +85,7 @@ int registerTests( *sub_suite, _basepath, _path / entry.path().filename(), _enforceViaYul, + _labels, _testCaseCreator ); _suite.add(sub_suite); @@ -95,7 +98,7 @@ int registerTests( static vector> filenames; filenames.emplace_back(make_unique(_path.string())); - _suite.add(make_test_case( + auto test_case = make_test_case( [config, _testCaseCreator] { BOOST_REQUIRE_NO_THROW({ @@ -125,7 +128,10 @@ int registerTests( _path.stem().string(), *filenames.back(), 0 - )); + ); + for (auto const& _label: _labels) + test_case->add_label(_label); + _suite.add(test_case); numTestsAdded = 1; } return numTestsAdded; @@ -174,6 +180,7 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) options.testPath / ts.path, ts.subpath, options.enforceViaYul, + ts.labels, ts.testCaseCreator ) > 0, std::string("no ") + ts.title + " tests found"); } diff --git a/test/cmdlineTests/dup_opt_peephole/args b/test/cmdlineTests/dup_opt_peephole/args new file mode 100644 index 000000000000..d3047670e161 --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/args @@ -0,0 +1 @@ +--asm \ No newline at end of file diff --git a/test/cmdlineTests/dup_opt_peephole/err b/test/cmdlineTests/dup_opt_peephole/err new file mode 100644 index 000000000000..cfaa88dcfeba --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/err @@ -0,0 +1,5 @@ +Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. +--> dup_opt_peephole/input.sol + +Warning: Source file does not specify required compiler version! +--> dup_opt_peephole/input.sol diff --git a/test/cmdlineTests/dup_opt_peephole/input.sol b/test/cmdlineTests/dup_opt_peephole/input.sol new file mode 100644 index 000000000000..1474a8f44668 --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/input.sol @@ -0,0 +1,9 @@ +contract C { + fallback() external { + assembly { + let x := calldataload(0) + x := x + sstore(0, x) + } + } +} diff --git a/test/cmdlineTests/dup_opt_peephole/output b/test/cmdlineTests/dup_opt_peephole/output new file mode 100644 index 000000000000..020260c2b39e --- /dev/null +++ b/test/cmdlineTests/dup_opt_peephole/output @@ -0,0 +1,54 @@ + +======= dup_opt_peephole/input.sol:C ======= +EVM assembly: + /* "dup_opt_peephole/input.sol":0:111 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_1 + jumpi + 0x00 + dup1 + revert +tag_1: + pop + dataSize(sub_0) + dup1 + dataOffset(sub_0) + 0x00 + codecopy + 0x00 + return +stop + +sub_0: assembly { + /* "dup_opt_peephole/input.sol":0:111 contract C {... */ + mstore(0x40, 0x80) + callvalue + dup1 + iszero + tag_3 + jumpi + 0x00 + dup1 + revert + tag_3: + pop + /* "dup_opt_peephole/input.sol":74:75 0 */ + 0x00 + /* "dup_opt_peephole/input.sol":61:76 calldataload(0) */ + calldataload + /* "dup_opt_peephole/input.sol":100:101 x */ + dup1 + /* "dup_opt_peephole/input.sol":97:98 0 */ + 0x00 + /* "dup_opt_peephole/input.sol":90:102 sstore(0, x) */ + sstore + /* "dup_opt_peephole/input.sol":47:106 {... */ + pop + /* "dup_opt_peephole/input.sol":0:111 contract C {... */ + stop + + auxdata: AUXDATA REMOVED +} diff --git a/test/cmdlineTests/error_codes/err b/test/cmdlineTests/error_codes/err index 1d983a7fd19e..a10362a863a8 100644 --- a/test/cmdlineTests/error_codes/err +++ b/test/cmdlineTests/error_codes/err @@ -1,26 +1,29 @@ +Warning (1878): SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. +--> error_codes/input.sol + Error (4937): No visibility specified. Did you intend to add "public"? - --> error_codes/input.sol:4:5: + --> error_codes/input.sol:2:5: | -4 | function f() { +2 | function f() { | ^ (Relevant source part starts here and spans across multiple lines). Warning (3420): Source file does not specify required compiler version! --> error_codes/input.sol Error (4247): Expression has to be an lvalue. - --> error_codes/input.sol:5:9: + --> error_codes/input.sol:3:9: | -5 | 2=0; +3 | 2=0; | ^ Error (7407): Type int_const 0 is not implicitly convertible to expected type int_const 2. - --> error_codes/input.sol:5:11: + --> error_codes/input.sol:3:11: | -5 | 2=0; +3 | 2=0; | ^ Error (2614): Indexed expression has to be a type, mapping or array (is literal_string "") - --> error_codes/input.sol:6:9: + --> error_codes/input.sol:4:9: | -6 | ""[2]; +4 | ""[2]; | ^^ diff --git a/test/cmdlineTests/error_codes/input.sol b/test/cmdlineTests/error_codes/input.sol index 78aceb41f1e3..5ea2800c567c 100644 --- a/test/cmdlineTests/error_codes/input.sol +++ b/test/cmdlineTests/error_codes/input.sol @@ -1,5 +1,3 @@ -// SPDX-License-Identifier: GPL-3.0 - contract C { function f() { 2=0; diff --git a/test/cmdlineTests/standard_yul_object_invalid_sub/input.json b/test/cmdlineTests/standard_yul_object_invalid_sub/input.json new file mode 100644 index 000000000000..ccc142d254c1 --- /dev/null +++ b/test/cmdlineTests/standard_yul_object_invalid_sub/input.json @@ -0,0 +1,17 @@ +{ + "language": "Yul", + "sources": + { + "A": + { + "content": "object \"NamedObject\" { code { let x := dataoffset(\"NamedObject.\") sstore(add(x, 0), 0) } object \"OtherObject\" { code { revert(0, 0) } } }" + } + }, + "settings": + { + "outputSelection": + { + "*": { "*": ["*"], "": [ "*" ] } + } + } +} \ No newline at end of file diff --git a/test/cmdlineTests/standard_yul_object_invalid_sub/output.json b/test/cmdlineTests/standard_yul_object_invalid_sub/output.json new file mode 100644 index 000000000000..5008d4916c23 --- /dev/null +++ b/test/cmdlineTests/standard_yul_object_invalid_sub/output.json @@ -0,0 +1,4 @@ +{"errors":[{"component":"general","formattedMessage":"A:1:40: TypeError: Unknown data object \"NamedObject.\". +object \"NamedObject\" { code { let x := dataoffset(\"NamedObject.\") sstore(add(x, 0), 0) } object \"OtherObject\" { code { revert(0, 0) } } } + ^--------^ +","message":"Unknown data object \"NamedObject.\".","severity":"error","sourceLocation":{"end":49,"file":"A","start":39},"type":"TypeError"}]} diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 71e47aa0cd68..b3621238b63d 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/test/contracts/ContractInterface.h b/test/contracts/ContractInterface.h index 4d063947e99f..1bc1d9e39a74 100644 --- a/test/contracts/ContractInterface.h +++ b/test/contracts/ContractInterface.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index a2998379fb96..f953cda9a538 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 46800fa78522..503282094eef 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/test/formal/combine_byte_shl.py b/test/formal/combine_byte_shl.py new file mode 100644 index 000000000000..e2a6034ffd33 --- /dev/null +++ b/test/formal/combine_byte_shl.py @@ -0,0 +1,29 @@ +from rule import Rule +from opcodes import * + +""" +byte(A, shl(B, X)) +given B % 8 == 0 && A <= 32 && B <= 256 +-> +byte(A + B / 8, X) +""" + +rule = Rule() + +n_bits = 256 + +# Input vars +X = BitVec('X', n_bits) +A = BitVec('A', n_bits) +B = BitVec('B', n_bits) + +# Non optimized result +nonopt = BYTE(A, SHL(B, X)) +# Optimized result +opt = BYTE(A + B / 8, X) + +rule.require(B % 8 == 0) +rule.require(ULE(A, 32)) +rule.require(ULE(B, 256)) + +rule.check(nonopt, opt) diff --git a/test/formal/combine_byte_shr_1.py b/test/formal/combine_byte_shr_1.py new file mode 100644 index 000000000000..4938e73f75c0 --- /dev/null +++ b/test/formal/combine_byte_shr_1.py @@ -0,0 +1,30 @@ +from rule import Rule +from opcodes import * + +""" +byte(A, shr(B, X)) +given B % 8 == 0 && A < n_bits/8 && B <= n_bits && A >= B / 8 +-> +byte(A - B / 8, X) +""" + +rule = Rule() + +n_bits = 256 + +# Input vars +X = BitVec('X', n_bits) +A = BitVec('A', n_bits) +B = BitVec('B', n_bits) + +# Non optimized result +nonopt = BYTE(A, SHR(B, X)) +# Optimized result +opt = BYTE(A - B / 8, X) + +rule.require(B % 8 == 0) +rule.require(ULT(A, n_bits/8)) +rule.require(ULE(B, n_bits)) +rule.require(UGE(A, DIV(B,8))) + +rule.check(nonopt, opt) diff --git a/test/formal/combine_byte_shr_2.py b/test/formal/combine_byte_shr_2.py new file mode 100644 index 000000000000..d74114e855ab --- /dev/null +++ b/test/formal/combine_byte_shr_2.py @@ -0,0 +1,30 @@ +from rule import Rule +from opcodes import * + +""" +byte(A, shr(B, X)) +given B % 8 == 0 && A < n_bits/8 && B <= n_bits && A < B / 8 +-> +0 +""" + +rule = Rule() + +n_bits = 256 + +# Input vars +X = BitVec('X', n_bits) +A = BitVec('A', n_bits) +B = BitVec('B', n_bits) + +# Non optimized result +nonopt = BYTE(A, SHR(B, X)) +# Optimized result +opt = 0 + +rule.require(B % 8 == 0) +rule.require(ULT(A, n_bits/8)) +rule.require(ULE(B, n_bits)) +rule.require(ULT(A, DIV(B,8))) + +rule.check(nonopt, opt) diff --git a/test/formal/opcodes.py b/test/formal/opcodes.py index 589bd9520bb5..24d53484bdac 100644 --- a/test/formal/opcodes.py +++ b/test/formal/opcodes.py @@ -56,3 +56,7 @@ def SHR(x, y): def SAR(x, y): return y >> x + +def BYTE(i, x): + bit = (i + 1) * 8 + return If(UGT(bit, x.size()), BitVecVal(0, x.size()), (LShR(x, (x.size() - bit))) & 0xff) diff --git a/test/libevmasm/Assembler.cpp b/test/libevmasm/Assembler.cpp index cdb7046bef05..c93d7b58d35a 100644 --- a/test/libevmasm/Assembler.cpp +++ b/test/libevmasm/Assembler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * @date 2018 @@ -28,6 +29,7 @@ #include #include #include +#include using namespace std; using namespace solidity::langutil; @@ -253,6 +255,24 @@ BOOST_AUTO_TEST_CASE(immutable) ); } +BOOST_AUTO_TEST_CASE(subobject_encode_decode) +{ + Assembly assembly; + + shared_ptr subAsmPtr = make_shared(); + shared_ptr subSubAsmPtr = make_shared(); + + assembly.appendSubroutine(subAsmPtr); + subAsmPtr->appendSubroutine(subSubAsmPtr); + + BOOST_CHECK(assembly.encodeSubPath({0}) == 0); + BOOST_REQUIRE_THROW(assembly.encodeSubPath({1}), solidity::evmasm::AssemblyException); + BOOST_REQUIRE_THROW(assembly.decodeSubPath(1), solidity::evmasm::AssemblyException); + + vector subPath{0, 0}; + BOOST_CHECK(assembly.decodeSubPath(assembly.encodeSubPath(subPath)) == subPath); +} + BOOST_AUTO_TEST_SUITE_END() } // end namespaces diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 4690ceddc0a3..741dc7523ff1 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/test/liblangutil/CharStream.cpp b/test/liblangutil/CharStream.cpp index 3b9d980c1fc8..d1189c3e99c7 100644 --- a/test/liblangutil/CharStream.cpp +++ b/test/liblangutil/CharStream.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Rocky Bernstein * @date 2019 diff --git a/test/liblangutil/SourceLocation.cpp b/test/liblangutil/SourceLocation.cpp index c5b47d0f682a..ff1664dfebe7 100644 --- a/test/liblangutil/SourceLocation.cpp +++ b/test/liblangutil/SourceLocation.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Yoichi Hirai * @date 2016 diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index 39bf7602c6ca..2c3711ea3b2d 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for Solidity's ABI decoder. */ diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 777f991a340c..b804a458df8b 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for Solidity's ABI encoder. */ diff --git a/test/libsolidity/ABIJsonTest.h b/test/libsolidity/ABIJsonTest.h index 702d36dbfe98..0cc7e674e796 100644 --- a/test/libsolidity/ABIJsonTest.h +++ b/test/libsolidity/ABIJsonTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the solidity compiler ABI JSON Interface output. */ diff --git a/test/libsolidity/ABITestsCommon.h b/test/libsolidity/ABITestsCommon.h index b2afcf125ce2..c5eea01ca4ea 100644 --- a/test/libsolidity/ABITestsCommon.h +++ b/test/libsolidity/ABITestsCommon.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp index 974e0f4863c9..979c79aa5c60 100644 --- a/test/libsolidity/ASTJSONTest.cpp +++ b/test/libsolidity/ASTJSONTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h index 45d7a08b9c0b..4e74d79f376f 100644 --- a/test/libsolidity/ASTJSONTest.h +++ b/test/libsolidity/ASTJSONTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 80c20c760733..bd28de2401cd 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Framework for testing features from the analysis phase of compiler. */ diff --git a/test/libsolidity/AnalysisFramework.h b/test/libsolidity/AnalysisFramework.h index db75ad3017a1..293e0e17c562 100644 --- a/test/libsolidity/AnalysisFramework.h +++ b/test/libsolidity/AnalysisFramework.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Framework for testing features from the analysis phase of compiler. */ diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 23bf1a2f829a..12e088fac1d5 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Lefteris Karapetsas * @date 2015 diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp index 1f51006ed74e..42b527e5bf82 100644 --- a/test/libsolidity/ErrorCheck.cpp +++ b/test/libsolidity/ErrorCheck.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file ErrorCheck.cpp * @author Yoichi Hirai * @date 2016 diff --git a/test/libsolidity/ErrorCheck.h b/test/libsolidity/ErrorCheck.h index 5deae56dc901..e01c2ca52484 100644 --- a/test/libsolidity/ErrorCheck.h +++ b/test/libsolidity/ErrorCheck.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file ErrorCheck.h * @author Yoichi Hirai * @date 2016 diff --git a/test/libsolidity/GasCosts.cpp b/test/libsolidity/GasCosts.cpp index 252b7759be17..2ad1368a6911 100644 --- a/test/libsolidity/GasCosts.cpp +++ b/test/libsolidity/GasCosts.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Tests that check that the cost of certain operations stay within range. */ diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index 09e257664546..c8296beb14ee 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/test/libsolidity/GasTest.cpp b/test/libsolidity/GasTest.cpp index d76979c9c7b6..f996f7352283 100644 --- a/test/libsolidity/GasTest.cpp +++ b/test/libsolidity/GasTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libsolidity/GasTest.h b/test/libsolidity/GasTest.h index d8bd0acadda0..da14e529286f 100644 --- a/test/libsolidity/GasTest.h +++ b/test/libsolidity/GasTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index aa4cab9b8332..bbbefb33e9db 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp index 9802e37c23d1..3375f8f92d7c 100644 --- a/test/libsolidity/LibSolc.cpp +++ b/test/libsolidity/LibSolc.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Unit tests for libsolc/libsolc.cpp. diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 66398381ef7f..a7347a21a628 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -55,7 +55,7 @@ class SMTCheckerFramework: public AnalysisFramework BOOST_FIXTURE_TEST_SUITE(SMTChecker, SMTCheckerFramework) -BOOST_AUTO_TEST_CASE(import_base) +BOOST_AUTO_TEST_CASE(import_base, *boost::unit_test::label("no_options")) { CompilerStack c; c.setSources({ @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(import_base) BOOST_CHECK_EQUAL(asserts, 1); } -BOOST_AUTO_TEST_CASE(import_library) +BOOST_AUTO_TEST_CASE(import_library, *boost::unit_test::label("no_options")) { CompilerStack c; c.setSources({ diff --git a/test/libsolidity/SMTCheckerJSONTest.cpp b/test/libsolidity/SMTCheckerJSONTest.cpp index e1b977cf5ecc..ca6608905d12 100644 --- a/test/libsolidity/SMTCheckerJSONTest.cpp +++ b/test/libsolidity/SMTCheckerJSONTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libsolidity/SMTCheckerJSONTest.h b/test/libsolidity/SMTCheckerJSONTest.h index b5d199e7ddbd..6de7f36c9573 100644 --- a/test/libsolidity/SMTCheckerJSONTest.h +++ b/test/libsolidity/SMTCheckerJSONTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libsolidity/SMTCheckerTest.cpp b/test/libsolidity/SMTCheckerTest.cpp index 7daa6f182298..51d1e7b364a4 100644 --- a/test/libsolidity/SMTCheckerTest.cpp +++ b/test/libsolidity/SMTCheckerTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include @@ -26,7 +27,7 @@ using namespace solidity::langutil; using namespace solidity::frontend; using namespace solidity::frontend::test; -SMTCheckerTest::SMTCheckerTest(string const& _filename, langutil::EVMVersion _evmVersion): SyntaxTest(_filename, _evmVersion) +SMTCheckerTest::SMTCheckerTest(string const& _filename): SyntaxTest(_filename, EVMVersion{}) { auto const& choice = m_reader.stringSetting("SMTSolvers", "any"); if (choice == "any") diff --git a/test/libsolidity/SMTCheckerTest.h b/test/libsolidity/SMTCheckerTest.h index 34f526cd9b83..522abb677106 100644 --- a/test/libsolidity/SMTCheckerTest.h +++ b/test/libsolidity/SMTCheckerTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once @@ -31,9 +32,9 @@ class SMTCheckerTest: public SyntaxTest public: static std::unique_ptr create(Config const& _config) { - return std::make_unique(_config.filename, _config.evmVersion); + return std::make_unique(_config.filename); } - SMTCheckerTest(std::string const& _filename, langutil::EVMVersion _evmVersion); + SMTCheckerTest(std::string const& _filename); TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override; diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 36b9c82147a3..a3e1661ef8df 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index e3b40f1e4695..180e49bd7ceb 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -46,7 +46,7 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer m_lineOffset(m_reader.lineNumber()), m_enforceViaYul(enforceViaYul) { - string choice = m_reader.stringSetting("compileViaYul", "false"); + string choice = m_reader.stringSetting("compileViaYul", "default"); if (choice == "also") { m_runWithYul = true; @@ -64,6 +64,11 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer // Do not try to run via yul if explicitly denied. m_enforceViaYul = false; } + else if (choice == "default") + { + m_runWithYul = false; + m_runWithoutYul = true; + } else BOOST_THROW_EXCEPTION(runtime_error("Invalid compileViaYul value: " + choice + ".")); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index d449cd27e321..59f01096d4e6 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @author Gav Wood diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 29b3b8b4390d..d0f4227cc1e7 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2016 @@ -61,18 +62,40 @@ bytes SolidityExecutionFramework::multiSourceCompileContract( evmasm::LinkerObject obj; if (m_compileViaYul) { - yul::AssemblyStack asmStack( - m_evmVersion, - yul::AssemblyStack::Language::StrictAssembly, - // Ignore optimiser settings here because we need Yul optimisation to - // get code that does not exhaust the stack. - OptimiserSettings::full() - ); - bool analysisSuccessful = asmStack.parseAndAnalyze("", m_compiler.yulIROptimized(contractName)); - solAssert(analysisSuccessful, "Code that passed analysis in CompilerStack can't have errors"); + // Try compiling twice: If the first run fails due to stack errors, forcefully enable + // the optimizer. + for (bool forceEnableOptimizer: {false, true}) + { + OptimiserSettings optimiserSettings = m_optimiserSettings; + if (!forceEnableOptimizer && !optimiserSettings.runYulOptimiser) + { + // Enable some optimizations on the first run + optimiserSettings.runYulOptimiser = true; + optimiserSettings.yulOptimiserSteps = "uljmul jmul"; + } + else if (forceEnableOptimizer) + optimiserSettings = OptimiserSettings::full(); - asmStack.optimize(); - obj = std::move(*asmStack.assemble(yul::AssemblyStack::Machine::EVM).bytecode); + yul::AssemblyStack asmStack( + m_evmVersion, + yul::AssemblyStack::Language::StrictAssembly, + optimiserSettings + ); + bool analysisSuccessful = asmStack.parseAndAnalyze("", m_compiler.yulIROptimized(contractName)); + solAssert(analysisSuccessful, "Code that passed analysis in CompilerStack can't have errors"); + + try + { + asmStack.optimize(); + obj = std::move(*asmStack.assemble(yul::AssemblyStack::Machine::EVM).bytecode); + break; + } + catch (...) + { + if (forceEnableOptimizer || optimiserSettings == OptimiserSettings::full()) + throw; + } + } } else obj = m_compiler.object(contractName); diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 5be310c87760..9efe22b2096e 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 10083b8274ae..a1db40747783 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 8edf470f406c..26e293b68b7b 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -77,7 +77,7 @@ class DocumentationChecker BOOST_REQUIRE(Error::containsErrorOfType(m_compilerStack.errors(), Error::Type::DocstringParsingError)); } -private: +protected: CompilerStack m_compilerStack; }; @@ -1277,13 +1277,7 @@ BOOST_AUTO_TEST_CASE(dev_default_inherit_variable) )"; char const *natspec = R"ABCDEF({ - "methods": - { - "x()": - { - "details": "test" - } - } + "methods": { "x()": { "details": "test" } } })ABCDEF"; char const *natspec1 = R"ABCDEF({ @@ -1318,15 +1312,82 @@ BOOST_AUTO_TEST_CASE(user_default_inherit_variable) )"; char const *natspec = R"ABCDEF({ - "methods": + "methods": { "x()": { "notice": "Hello world" } } + })ABCDEF"; + + checkNatspec(sourceCode, "C", natspec, true); + checkNatspec(sourceCode, "D", natspec, true); +} + +BOOST_AUTO_TEST_CASE(dev_explicit_inherit_variable) +{ + char const *sourceCode = R"( + contract B { + function x() virtual external returns (uint) { + return 1; + } + } + + contract C { + /// @notice Hello world + /// @dev test + function x() virtual external returns (uint) { + return 1; + } + } + + contract D is C, B { + /// @inheritdoc C + uint public override(C, B) x; + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": { "x()": { "details": "test" } } + })ABCDEF"; + + char const *natspec1 = R"ABCDEF({ + "methods" : {}, + "stateVariables" : { - "x()": + "x" : { - "notice": "Hello world" + "details" : "test" } } })ABCDEF"; + checkNatspec(sourceCode, "C", natspec, false); + checkNatspec(sourceCode, "D", natspec1, false); +} + +BOOST_AUTO_TEST_CASE(user_explicit_inherit_variable) +{ + char const *sourceCode = R"( + contract B { + function x() virtual external returns (uint) { + return 1; + } + } + + contract C { + /// @notice Hello world + /// @dev test + function x() virtual external returns (uint) { + return 1; + } + } + + contract D is C, B { + /// @inheritdoc C + uint public override(C, B) x; + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": { "x()": { "notice": "Hello world" } } + })ABCDEF"; + checkNatspec(sourceCode, "C", natspec, true); checkNatspec(sourceCode, "D", natspec, true); } @@ -1423,6 +1484,411 @@ BOOST_AUTO_TEST_CASE(user_default_inherit) checkNatspec(sourceCode, "Token", natspec, true); } +BOOST_AUTO_TEST_CASE(dev_explicit_inherit) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 { + function transfer(address to, uint amount) virtual external returns (bool) { + return false; + } + } + + contract Token is ERC21, ERC20 { + /// @inheritdoc ERC20 + function transfer(address to, uint amount) override(ERC21, ERC20) external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "test", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, false); + checkNatspec(sourceCode, "Token", natspec, false); +} + +BOOST_AUTO_TEST_CASE(user_explicit_inherit) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 { + function transfer(address to, uint amount) virtual external returns (bool) { + return false; + } + } + + contract Token is ERC21, ERC20 { + /// @inheritdoc ERC20 + function transfer(address to, uint amount) override(ERC21, ERC20) external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "notice": "Transfer ``amount`` from ``msg.sender`` to ``to``." + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, true); + checkNatspec(sourceCode, "Token", natspec, true); +} + +BOOST_AUTO_TEST_CASE(dev_explicit_inherit2) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 is ERC20 { + function transfer(address to, uint amount) virtual override external returns (bool) { + return false; + } + } + + contract Token is ERC20 { + /// @inheritdoc ERC20 + function transfer(address to, uint amount) override external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "test", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, false); + checkNatspec(sourceCode, "ERC21", natspec, false); + checkNatspec(sourceCode, "Token", natspec, false); +} + +BOOST_AUTO_TEST_CASE(user_explicit_inherit2) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 is ERC20 { + function transfer(address to, uint amount) virtual override external returns (bool) { + return false; + } + } + + contract Token is ERC20 { + /// @inheritdoc ERC20 + function transfer(address to, uint amount) override external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "notice": "Transfer ``amount`` from ``msg.sender`` to ``to``." + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, true); + checkNatspec(sourceCode, "ERC21", natspec, true); + checkNatspec(sourceCode, "Token", natspec, true); +} + +BOOST_AUTO_TEST_CASE(dev_explicit_inherit_partial2) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 is ERC20 { + /// @inheritdoc ERC20 + /// @dev override dev comment + /// @notice override notice + function transfer(address to, uint amount) virtual override external returns (bool) { + return false; + } + } + + contract Token is ERC21 { + function transfer(address to, uint amount) override external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "test", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + char const *natspec2 = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "override dev comment", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, false); + checkNatspec(sourceCode, "Token", natspec2, false); +} + +BOOST_AUTO_TEST_CASE(user_explicit_inherit_partial2) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 is ERC20 { + /// @inheritdoc ERC20 + /// @dev override dev comment + /// @notice override notice + function transfer(address to, uint amount) virtual override external returns (bool) { + return false; + } + } + + contract Token is ERC21 { + function transfer(address to, uint amount) override external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "notice": "Transfer ``amount`` from ``msg.sender`` to ``to``." + } + } + })ABCDEF"; + + char const *natspec2 = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "notice": "override notice" + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, true); + checkNatspec(sourceCode, "Token", natspec2, true); +} +BOOST_AUTO_TEST_CASE(dev_explicit_inherit_partial) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 { + function transfer(address to, uint amount) virtual external returns (bool) { + return false; + } + } + + contract Token is ERC21, ERC20 { + /// @inheritdoc ERC20 + /// @dev override dev comment + /// @notice override notice + function transfer(address to, uint amount) override(ERC21, ERC20) external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "test", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + char const *natspec2 = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "override dev comment", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, false); + checkNatspec(sourceCode, "Token", natspec2, false); +} + +BOOST_AUTO_TEST_CASE(user_explicit_inherit_partial) +{ + char const *sourceCode = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + contract ERC21 { + function transfer(address to, uint amount) virtual external returns (bool) { + return false; + } + } + + contract Token is ERC21, ERC20 { + /// @inheritdoc ERC20 + /// @dev override dev comment + /// @notice override notice + function transfer(address to, uint amount) override(ERC21, ERC20) external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "notice": "Transfer ``amount`` from ``msg.sender`` to ``to``." + } + } + })ABCDEF"; + + char const *natspec2 = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "notice": "override notice" + } + } + })ABCDEF"; + + checkNatspec(sourceCode, "ERC20", natspec, true); + checkNatspec(sourceCode, "Token", natspec2, true); +} + BOOST_AUTO_TEST_CASE(dev_inherit_parameter_mismatch) { char const *sourceCode = R"( @@ -1517,6 +1983,80 @@ BOOST_AUTO_TEST_CASE(user_inherit_parameter_mismatch) checkNatspec(sourceCode, "Token", natspec2, true); } +BOOST_AUTO_TEST_CASE(dev_explicit_inehrit_complex) +{ + char const *sourceCode1 = R"( + interface ERC20 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer + /// @dev test + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + + interface ERC21 { + /// Transfer ``amount`` from ``msg.sender`` to ``to``. + /// @author Programmer2 + /// @dev test2 + /// @param to address to transfer to + /// @param amount amount to transfer + function transfer(address to, uint amount) external returns (bool); + } + )"; + + char const *sourceCode2 = R"( + import "Interfaces.sol" as myInterfaces; + + contract Token is myInterfaces.ERC20, myInterfaces.ERC21 { + /// @inheritdoc myInterfaces.ERC20 + function transfer(address too, uint amount) + override(myInterfaces.ERC20, myInterfaces.ERC21) external returns (bool) { + return false; + } + } + )"; + + char const *natspec = R"ABCDEF({ + "methods": + { + "transfer(address,uint256)": + { + "author": "Programmer", + "details": "test", + "params": + { + "amount": "amount to transfer", + "to": "address to transfer to" + } + } + } + })ABCDEF"; + + m_compilerStack.reset(); + m_compilerStack.setSources({ + {"Interfaces.sol", "pragma solidity >=0.0;\n" + std::string(sourceCode1)}, + {"Testfile.sol", "pragma solidity >=0.0;\n" + std::string(sourceCode2)} + }); + + m_compilerStack.setEVMVersion(solidity::test::CommonOptions::get().evmVersion()); + + BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); + + Json::Value generatedDocumentation = m_compilerStack.natspecDev("Token"); + Json::Value expectedDocumentation; + util::jsonParseStrict(natspec, expectedDocumentation); + + expectedDocumentation["version"] = Json::Value(Natspec::c_natspecVersion); + expectedDocumentation["kind"] = Json::Value("dev"); + + BOOST_CHECK_MESSAGE( + expectedDocumentation == generatedDocumentation, + "Expected:\n" << expectedDocumentation.toStyledString() << + "\n but got:\n" << generatedDocumentation.toStyledString() + ); +} + } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 4062b1928b2b..952eac9402bc 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2014 @@ -708,6 +709,19 @@ BOOST_AUTO_TEST_CASE(shift_optimizer_bug) compareVersions("g(uint256)", u256(-1)); } +BOOST_AUTO_TEST_CASE(avoid_double_cleanup) +{ + char const* sourceCode = R"( + contract C { + receive() external payable { + abi.encodePacked(uint200(0)); + } + } + )"; + compileBothVersions(sourceCode, 0, "C", 50); + // Check that there is no double AND instruction in the resulting code + BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::AND), 1); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index bc9f169046ac..b837b3878af8 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @author Christian * @date 2015 diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 0b2098097616..570350466356 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Unit tests for interface/StandardCompiler.h. diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 48a293b65446..c554366e955a 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libsolidity/SyntaxTest.h b/test/libsolidity/SyntaxTest.h index dbc5d68b3440..b71691bea121 100644 --- a/test/libsolidity/SyntaxTest.h +++ b/test/libsolidity/SyntaxTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2.sol index 1dbf320bd534..6d7b27f58efb 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2.sol @@ -18,5 +18,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb diff --git a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_calldata.sol b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_calldata.sol index a5e7a9af8913..9ed9ada784e9 100644 --- a/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_calldata.sol +++ b/test/libsolidity/semanticTests/abiEncoderV1/abi_decode_v2_calldata.sol @@ -12,5 +12,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f(bytes): 0x20, 0xe0, 0x20, 0x21, 0x40, 0x3, 0xa, 0xb, 0xc -> 0x20, 0x21, 0x40, 0x3, 0xa, 0xb, 0xc diff --git a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol index f6510b53da59..bfa7507120d1 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/abi_encode_v2.sol @@ -45,6 +45,8 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f0() -> 0x20, 0x0 // f1() -> 0x20, 0x40, 0x1, 0x2 diff --git a/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_member_offset.sol b/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_member_offset.sol index fb8e6c3c5d43..196967a441aa 100644 --- a/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_member_offset.sol +++ b/test/libsolidity/semanticTests/abiEncoderV2/calldata_struct_member_offset.sol @@ -19,5 +19,7 @@ contract C { return (b.b, this.g(b)); } } +// ==== +// compileViaYul: also // ---- // f() -> 11, 11 diff --git a/test/libsolidity/semanticTests/array/calldata_array_of_struct.sol b/test/libsolidity/semanticTests/array/calldata_array_of_struct.sol index 33311226500a..170dee6ee556 100644 --- a/test/libsolidity/semanticTests/array/calldata_array_of_struct.sol +++ b/test/libsolidity/semanticTests/array/calldata_array_of_struct.sol @@ -20,5 +20,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f((uint256,uint256)[]): 0x20, 0x2, 0x1, 0x2, 0x3, 0x4 -> 2, 1, 2, 3, 4 diff --git a/test/libsolidity/semanticTests/array/create_memory_array.sol b/test/libsolidity/semanticTests/array/create_memory_array.sol index fd4fe943cb65..cf00ccaa6142 100644 --- a/test/libsolidity/semanticTests/array/create_memory_array.sol +++ b/test/libsolidity/semanticTests/array/create_memory_array.sol @@ -16,6 +16,7 @@ contract C { return (x[199], y[203][1], z[170].a[1], z[170].b[99]); } } - +// ==== +// compileViaYul: also // ---- // f() -> "A", 8, 4, "B" diff --git a/test/libsolidity/semanticTests/array/delete_memory_array.sol b/test/libsolidity/semanticTests/array/delete_memory_array.sol new file mode 100644 index 000000000000..64fc9a9724ec --- /dev/null +++ b/test/libsolidity/semanticTests/array/delete_memory_array.sol @@ -0,0 +1,17 @@ +contract C { + + function len() public returns (uint ret) { + uint[] memory data = new uint[](2); + data[0] = 234; + data[1] = 123; + delete data; + assembly { + ret := mload(data) + } + } +} + +// ==== +// compileViaYul: also +// ---- +// len() -> 0 diff --git a/test/libsolidity/semanticTests/array/delete_storage_array.sol b/test/libsolidity/semanticTests/array/delete_storage_array.sol new file mode 100644 index 000000000000..f0bb769788bc --- /dev/null +++ b/test/libsolidity/semanticTests/array/delete_storage_array.sol @@ -0,0 +1,40 @@ +contract C { + uint[] data; + + function len() public returns (uint ret) { + data.push(234); + data.push(123); + delete data; + assembly { + ret := sload(data_slot) + } + } + + function val() public returns (uint ret) { + assembly { + sstore(0, 2) + mstore(0, 0) + sstore(keccak256(0, 32), 234) + sstore(add(keccak256(0, 32), 1), 123) + } + + assert(data[0] == 234); + assert(data[1] == 123); + + delete data; + + uint size = 999; + + assembly { + size := sload(0) + mstore(0, 0) + ret := sload(keccak256(0, 32)) + } + } +} + +// ==== +// compileViaYul: also +// ---- +// len() -> 0 +// val() -> 0 diff --git a/test/libsolidity/semanticTests/array/fixed_arrays_in_storage.sol b/test/libsolidity/semanticTests/array/fixed_arrays_in_storage.sol index b65a3d254d54..3f5c0d5dd8dc 100644 --- a/test/libsolidity/semanticTests/array/fixed_arrays_in_storage.sol +++ b/test/libsolidity/semanticTests/array/fixed_arrays_in_storage.sol @@ -33,6 +33,8 @@ contract c { l2 = ids.length; } } +// ==== +// compileViaYul: also // ---- // setIDStatic(uint256): 0xb -> // getID(uint256): 0x2 -> 0xb diff --git a/test/libsolidity/semanticTests/array/inline_array_index_access_ints.sol b/test/libsolidity/semanticTests/array/inline_array_index_access_ints.sol index 8dc5a7451b9f..fc7c85438609 100644 --- a/test/libsolidity/semanticTests/array/inline_array_index_access_ints.sol +++ b/test/libsolidity/semanticTests/array/inline_array_index_access_ints.sol @@ -4,5 +4,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> 3 diff --git a/test/libsolidity/semanticTests/array/inline_array_singleton.sol b/test/libsolidity/semanticTests/array/inline_array_singleton.sol index 5925aba0f28e..e8373854de7f 100644 --- a/test/libsolidity/semanticTests/array/inline_array_singleton.sol +++ b/test/libsolidity/semanticTests/array/inline_array_singleton.sol @@ -4,6 +4,7 @@ contract C { return [4][0]; } } - +// ==== +// compileViaYul: also // ---- // f() -> 4 diff --git a/test/libsolidity/semanticTests/array/inline_array_storage_to_memory_conversion_ints.sol b/test/libsolidity/semanticTests/array/inline_array_storage_to_memory_conversion_ints.sol index f3f37ea20edb..960b7fdb5d34 100644 --- a/test/libsolidity/semanticTests/array/inline_array_storage_to_memory_conversion_ints.sol +++ b/test/libsolidity/semanticTests/array/inline_array_storage_to_memory_conversion_ints.sol @@ -7,5 +7,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> 3, 6 diff --git a/test/libsolidity/semanticTests/calldata/calldata_array_dynamic_bytes.sol b/test/libsolidity/semanticTests/calldata/calldata_array_dynamic_bytes.sol index c2c2fa70a678..b59885de88b7 100644 --- a/test/libsolidity/semanticTests/calldata/calldata_array_dynamic_bytes.sol +++ b/test/libsolidity/semanticTests/calldata/calldata_array_dynamic_bytes.sol @@ -66,6 +66,8 @@ contract C { // found expectation comments: // same offset for both arrays @ ABI_CHECK( +// ==== +// compileViaYul: false // ---- // f1(bytes[1]): 0x20, 0x20, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3 // f2(bytes[1],bytes[1]): 0x40, 0xa0, 0x20, 0x3, hex"0102030000000000000000000000000000000000000000000000000000000000", 0x20, 0x2, hex"0102000000000000000000000000000000000000000000000000000000000000" -> 0x3, 0x1, 0x2, 0x3, 0x2, 0x1, 0x2 diff --git a/test/libsolidity/semanticTests/calldata/calldata_bytes_external.sol b/test/libsolidity/semanticTests/calldata/calldata_bytes_external.sol index 9917e736a945..9be9e8eab650 100644 --- a/test/libsolidity/semanticTests/calldata/calldata_bytes_external.sol +++ b/test/libsolidity/semanticTests/calldata/calldata_bytes_external.sol @@ -7,6 +7,7 @@ contract CalldataTest { } } // ==== +// compileViaYul: also // EVMVersion: >=byzantium // ---- // tester(bytes): 0x20, 0x08, "abcdefgh" -> "c" diff --git a/test/libsolidity/semanticTests/calldata/calldata_struct_cleaning.sol b/test/libsolidity/semanticTests/calldata/calldata_struct_cleaning.sol index dbf6e44405e2..6b4eb2f07ff1 100644 --- a/test/libsolidity/semanticTests/calldata/calldata_struct_cleaning.sol +++ b/test/libsolidity/semanticTests/calldata/calldata_struct_cleaning.sol @@ -16,6 +16,8 @@ contract C { } } } +// ==== +// compileViaYul: also // ---- // f((uint8,bytes1)): 0x12, hex"3400000000000000000000000000000000000000000000000000000000000000" -> 0x12, hex"3400000000000000000000000000000000000000000000000000000000000000" # double check that the valid case goes through # // f((uint8,bytes1)): 0x1234, hex"5678000000000000000000000000000000000000000000000000000000000000" -> FAILURE diff --git a/test/libsolidity/semanticTests/calldata/calldata_struct_internal.sol b/test/libsolidity/semanticTests/calldata/calldata_struct_internal.sol index a463b5d33960..810900dd67ff 100644 --- a/test/libsolidity/semanticTests/calldata/calldata_struct_internal.sol +++ b/test/libsolidity/semanticTests/calldata/calldata_struct_internal.sol @@ -13,5 +13,7 @@ contract C { return f(s); } } +// ==== +// compileViaYul: also // ---- // f(uint256,(uint256,uint256),uint256): 7, 1, 2, 4 -> 1, 2 diff --git a/test/libsolidity/semanticTests/dirty_calldata_bytes.sol b/test/libsolidity/semanticTests/dirty_calldata_bytes.sol index 05a3793f60b7..f3cd7b912466 100644 --- a/test/libsolidity/semanticTests/dirty_calldata_bytes.sol +++ b/test/libsolidity/semanticTests/dirty_calldata_bytes.sol @@ -8,5 +8,7 @@ contract C { correct = r == (0x64 << 248); } } +// ==== +// compileViaYul: also // ---- -// f(bytes): 0x20, 0x04, "dead" -> true \ No newline at end of file +// f(bytes): 0x20, 0x04, "dead" -> true diff --git a/test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol b/test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol index 1c9d7db3022b..df5c672d1040 100644 --- a/test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol +++ b/test/libsolidity/semanticTests/dirty_calldata_dynamic_array.sol @@ -8,5 +8,7 @@ contract C { correct = r == 0x7fff; } } +// ==== +// compileViaYul: also // ---- -// f(int16[]): 0x20, 0x02, 0x7fff, 0x7fff -> true \ No newline at end of file +// f(int16[]): 0x20, 0x02, 0x7fff, 0x7fff -> true diff --git a/test/libsolidity/semanticTests/functionCall/call_options_overload.sol b/test/libsolidity/semanticTests/functionCall/call_options_overload.sol new file mode 100644 index 000000000000..8938d8f0c318 --- /dev/null +++ b/test/libsolidity/semanticTests/functionCall/call_options_overload.sol @@ -0,0 +1,16 @@ +contract C { + function f(uint x) external payable returns (uint) { return 1; } + function f(uint x, uint y) external payable returns (uint) { return 2; } + function call() public payable returns (uint v, uint x, uint y, uint z) { + v = this.f{value: 10}(2); + x = this.f{gas: 1000}(2, 3); + y = this.f{gas: 1000, value: 10}(2, 3); + z = this.f{gas: 1000}{value: 10}(2, 3); + } + receive() external payable {} +} +// ==== +// compileViaYul: also +// ---- +// (), 1 ether +// call() -> 1, 2, 2, 2 diff --git a/test/libsolidity/semanticTests/isoltestFormatting.sol b/test/libsolidity/semanticTests/isoltestFormatting.sol index 9380dc01588e..a6e25172e9d1 100644 --- a/test/libsolidity/semanticTests/isoltestFormatting.sol +++ b/test/libsolidity/semanticTests/isoltestFormatting.sol @@ -8,6 +8,8 @@ contract C { return a; } } +// ==== +// compileViaYul: also // ---- // f() -> 4, 11, 0x0111, 0x333333, 2222222222222222222 // g() -> 0x10, 0x0100, 0x0101, 0x333333, 2222222222222222222 diff --git a/test/libsolidity/semanticTests/libraries/internal_library_function_bound.sol b/test/libsolidity/semanticTests/libraries/internal_library_function_bound.sol index f59ec9440dff..a6ea94fedbf6 100644 --- a/test/libsolidity/semanticTests/libraries/internal_library_function_bound.sol +++ b/test/libsolidity/semanticTests/libraries/internal_library_function_bound.sol @@ -22,5 +22,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> 2 diff --git a/test/libsolidity/semanticTests/libraries/internal_library_function_return_var_size.sol b/test/libsolidity/semanticTests/libraries/internal_library_function_return_var_size.sol index 21417b599b43..1406e0117473 100644 --- a/test/libsolidity/semanticTests/libraries/internal_library_function_return_var_size.sol +++ b/test/libsolidity/semanticTests/libraries/internal_library_function_return_var_size.sol @@ -22,5 +22,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> 2 diff --git a/test/libsolidity/semanticTests/multiSource/import.sol b/test/libsolidity/semanticTests/multiSource/import.sol index 2a0f43d53978..d3f5ed301997 100644 --- a/test/libsolidity/semanticTests/multiSource/import.sol +++ b/test/libsolidity/semanticTests/multiSource/import.sol @@ -7,6 +7,8 @@ import "A"; contract B is A { function f(uint256 x) public view returns(uint256) { return x; } } +// ==== +// compileViaYul: also // ---- // f(uint256): 1337 -> 1337 // g(uint256): 1337 -> 1338 diff --git a/test/libsolidity/semanticTests/optimizer/shift_bytes.sol b/test/libsolidity/semanticTests/optimizer/shift_bytes.sol new file mode 100644 index 000000000000..5a85160f96be --- /dev/null +++ b/test/libsolidity/semanticTests/optimizer/shift_bytes.sol @@ -0,0 +1,44 @@ +// This tests the optimizer rule +// byte(A, shl(B, X)) +// -> +// byte(A + B / 8, X) +// given A <= 32 && B % 8 == 0 && B <= 256 +// +// and the respective rule about shr +contract C { + function f(uint a) public returns (uint, uint, uint) { + uint x = a << (256 - 8); + assembly { + x := byte(0, x) + } + uint y = a << 8; + assembly { + y := byte(30, y) + } + uint z = a << 16; + assembly { + z := byte(1, z) + } + return (x, y, z); + } + function g(uint a) public returns (uint, uint, uint) { + uint x = a >> (256 - 16); + assembly { + x := byte(31, x) + } + uint y = a >> 8; + assembly { + y := byte(4, y) + } + uint z = a >> 16; + assembly { + z := byte(7, z) + } + return (x, y, z); + } +} +// ==== +// compileViaYul: also +// ---- +// f(uint256): 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -> 0x1f, 0x1f, 3 +// g(uint256): 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -> 1, 3, 5 diff --git a/test/libsolidity/semanticTests/smoke/structs.sol b/test/libsolidity/semanticTests/smoke/structs.sol index 979dbdcc003d..6a7286e57459 100644 --- a/test/libsolidity/semanticTests/smoke/structs.sol +++ b/test/libsolidity/semanticTests/smoke/structs.sol @@ -17,6 +17,8 @@ contract C { return T(23, 42, "any"); } } +// ==== +// compileViaYul: also // ---- // s() -> 23, 42 // t() -> 0x20, 23, 42, 0x60, 3, "any" diff --git a/test/libsolidity/semanticTests/snark.sol b/test/libsolidity/semanticTests/snark.sol index 83f16f091cff..4ab6a61fc605 100644 --- a/test/libsolidity/semanticTests/snark.sol +++ b/test/libsolidity/semanticTests/snark.sol @@ -288,6 +288,7 @@ contract Test { /// testMul() -> true // // ==== +// compileViaYul: also // EVMVersion: >=constantinople // ---- // library: Pairing diff --git a/test/libsolidity/semanticTests/specialFunctions/keccak256_optimized.sol b/test/libsolidity/semanticTests/specialFunctions/keccak256_optimized.sol new file mode 100644 index 000000000000..cb3c8d608764 --- /dev/null +++ b/test/libsolidity/semanticTests/specialFunctions/keccak256_optimized.sol @@ -0,0 +1,19 @@ +// tests compile-time evaluation of keccak256 on literal strings +contract C { + function short() public pure returns (bool) { + bytes32 a = keccak256("abcdefghijklmn"); + bytes memory s = "abcdefghijklmn"; + return a == keccak256(s); + } + bytes32 constant sc = keccak256("abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn"); + function long() public pure returns (bool, bool) { + bytes32 a = keccak256("abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn"); + bytes memory s = "abcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn"; + return (a == keccak256(s), sc == keccak256(s)); + } +} +// ==== +// compileViaYul: also +// ---- +// short() -> true +// long() -> true, true diff --git a/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol b/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol index daeee6ba6f4d..50a0d68f7725 100644 --- a/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol +++ b/test/libsolidity/semanticTests/storage/packed_storage_structs_bytes.sol @@ -41,5 +41,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // test() -> true diff --git a/test/libsolidity/semanticTests/storage/packed_storage_structs_enum.sol b/test/libsolidity/semanticTests/storage/packed_storage_structs_enum.sol index 9c9f778f0f85..3f2983f46236 100644 --- a/test/libsolidity/semanticTests/storage/packed_storage_structs_enum.sol +++ b/test/libsolidity/semanticTests/storage/packed_storage_structs_enum.sol @@ -29,5 +29,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // test() -> 1 diff --git a/test/libsolidity/semanticTests/storage/packed_storage_structs_uint.sol b/test/libsolidity/semanticTests/storage/packed_storage_structs_uint.sol index 8c91576f5003..611fda3ccf57 100644 --- a/test/libsolidity/semanticTests/storage/packed_storage_structs_uint.sol +++ b/test/libsolidity/semanticTests/storage/packed_storage_structs_uint.sol @@ -26,5 +26,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // test() -> 1 diff --git a/test/libsolidity/semanticTests/strings/unicode_escapes.sol b/test/libsolidity/semanticTests/strings/unicode_escapes.sol new file mode 100644 index 000000000000..fc57aa48ed74 --- /dev/null +++ b/test/libsolidity/semanticTests/strings/unicode_escapes.sol @@ -0,0 +1,24 @@ +contract C { + function oneByteUTF8() public pure returns (string memory) { + return "aaa\u0024aaa"; // usdollar + } + + function twoBytesUTF8() public pure returns (string memory) { + return "aaa\u00A2aaa"; // cent + } + + function threeBytesUTF8() public pure returns (string memory) { + return "aaa\u20ACaaa"; // euro + } + + function combined() public pure returns (string memory) { + return "\u0024\u00A2\u20AC"; + } +} +// ==== +// compileViaYul: also +// ---- +// oneByteUTF8() -> 0x20, 7, "aaa$aaa" +// twoBytesUTF8() -> 0x20, 8, "aaa\xc2\xa2aaa" +// threeBytesUTF8() -> 0x20, 9, "aaa\xe2\x82\xacaaa" +// combined() -> 0x20, 6, "$\xc2\xa2\xe2\x82\xac" diff --git a/test/libsolidity/semanticTests/strings/unicode_string.sol b/test/libsolidity/semanticTests/strings/unicode_string.sol new file mode 100644 index 000000000000..73616e479434 --- /dev/null +++ b/test/libsolidity/semanticTests/strings/unicode_string.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure returns (string memory) { + return "😃, 😭, and 😈"; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 0x20, 0x14, "\xf0\x9f\x98\x83, \xf0\x9f\x98\xad, and \xf0\x9f\x98\x88" diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct.sol index a7ecf2bd02d6..d3a79a181e23 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct.sol @@ -13,5 +13,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f((uint256,uint256)): 42, 23 -> 42, 23 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_and_ints.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_and_ints.sol index c3b8249e8f61..21fada9c232c 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_struct_and_ints.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_struct_and_ints.sol @@ -16,5 +16,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f(uint256,(uint256,uint256),uint256): 1, 2, 3, 4 -> 1, 2, 3, 4 diff --git a/test/libsolidity/semanticTests/structs/calldata/calldata_structs.sol b/test/libsolidity/semanticTests/structs/calldata/calldata_structs.sol index 4139c1073b65..0e62ee4ef319 100644 --- a/test/libsolidity/semanticTests/structs/calldata/calldata_structs.sol +++ b/test/libsolidity/semanticTests/structs/calldata/calldata_structs.sol @@ -23,5 +23,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f((uint256,uint256),(uint256),(uint256,uint256)): 1, 2, 3, 4, 5 -> 1, 2, 3, 4, 5 diff --git a/test/libsolidity/semanticTests/structs/calldata/dynamic_nested.sol b/test/libsolidity/semanticTests/structs/calldata/dynamic_nested.sol index 59cde317189a..8d6b7310300b 100644 --- a/test/libsolidity/semanticTests/structs/calldata/dynamic_nested.sol +++ b/test/libsolidity/semanticTests/structs/calldata/dynamic_nested.sol @@ -7,5 +7,7 @@ contract C { return (s.children.length, s.a, s.children[0].b, s.children[1].b); } } +// ==== +// compileViaYul: also // ---- // f((uint256,(uint256)[])): 32, 17, 64, 2, 23, 42 -> 2, 17, 23, 42 diff --git a/test/libsolidity/semanticTests/structs/calldata/dynamically_encoded.sol b/test/libsolidity/semanticTests/structs/calldata/dynamically_encoded.sol index 3acea52e7fa5..815de9a28574 100644 --- a/test/libsolidity/semanticTests/structs/calldata/dynamically_encoded.sol +++ b/test/libsolidity/semanticTests/structs/calldata/dynamically_encoded.sol @@ -6,5 +6,7 @@ contract C { return (s.a.length, s.a[0], s.a[1]); } } +// ==== +// compileViaYul: also // ---- // f((uint256[])): 32, 32, 2, 42, 23 -> 2, 42, 23 diff --git a/test/libsolidity/semanticTests/various/code_access_content.sol b/test/libsolidity/semanticTests/various/code_access_content.sol index 2c115d6c8dae..c0a74fe1a354 100644 --- a/test/libsolidity/semanticTests/various/code_access_content.sol +++ b/test/libsolidity/semanticTests/various/code_access_content.sol @@ -36,7 +36,8 @@ contract C { return true; } } - +// ==== +// compileViaYul: also // ---- // testRuntime() -> true // testCreation() -> true diff --git a/test/libsolidity/semanticTests/various/code_access_runtime.sol b/test/libsolidity/semanticTests/various/code_access_runtime.sol index cc1401c6f1bc..36264f84dd81 100644 --- a/test/libsolidity/semanticTests/various/code_access_runtime.sol +++ b/test/libsolidity/semanticTests/various/code_access_runtime.sol @@ -10,18 +10,18 @@ contract D { } } - contract C { function test() public returns (uint256) { - D d = new D(); - bytes32 hash; - assembly { hash := extcodehash(d) } - assert(hash == keccak256(type(D).runtimeCode)); - return 42; + D d = new D(); + bytes32 hash; + assembly { hash := extcodehash(d) } + assert(hash == keccak256(type(D).runtimeCode)); + return 42; } } // ==== // EVMVersion: >=constantinople +// compileViaYul: also // ---- // test() -> 42 diff --git a/test/libsolidity/semanticTests/various/cross_contract_types.sol b/test/libsolidity/semanticTests/various/cross_contract_types.sol index 47842cc030bb..88528ce07633 100644 --- a/test/libsolidity/semanticTests/various/cross_contract_types.sol +++ b/test/libsolidity/semanticTests/various/cross_contract_types.sol @@ -13,5 +13,7 @@ contract Test { } } +// ==== +// compileViaYul: also // ---- // f() -> 3 diff --git a/test/libsolidity/semanticTests/various/inline_tuple_with_rational_numbers.sol b/test/libsolidity/semanticTests/various/inline_tuple_with_rational_numbers.sol index e350a11d3f51..477d14740c30 100644 --- a/test/libsolidity/semanticTests/various/inline_tuple_with_rational_numbers.sol +++ b/test/libsolidity/semanticTests/various/inline_tuple_with_rational_numbers.sol @@ -5,5 +5,7 @@ contract c { } } +// ==== +// compileViaYul: also // ---- // f() -> 1 diff --git a/test/libsolidity/semanticTests/various/memory_overwrite.sol b/test/libsolidity/semanticTests/various/memory_overwrite.sol index 7312509e2ff0..3ab0a2aa2e63 100644 --- a/test/libsolidity/semanticTests/various/memory_overwrite.sol +++ b/test/libsolidity/semanticTests/various/memory_overwrite.sol @@ -6,5 +6,7 @@ contract C { } } +// ==== +// compileViaYul: also // ---- // f() -> 0x20, 5, "b23a5" diff --git a/test/libsolidity/semanticTests/various/negative_stack_height.sol b/test/libsolidity/semanticTests/various/negative_stack_height.sol index d5074dc911fc..8f36538e47e9 100644 --- a/test/libsolidity/semanticTests/various/negative_stack_height.sol +++ b/test/libsolidity/semanticTests/various/negative_stack_height.sol @@ -58,6 +58,7 @@ contract C { ) {} } - +// ==== +// compileViaYul: false // ---- // constructor() -> diff --git a/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_1.sol b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_1.sol new file mode 100644 index 000000000000..8acd7998a2c1 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_1.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +contract C { + int[][] array2d; + function l() public { + array2d.push().push(); + assert(array2d.length > 0); + assert(array2d[array2d.length - 1].length > 0); + } +} diff --git a/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_1_fail.sol b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_1_fail.sol new file mode 100644 index 000000000000..a85638189d8c --- /dev/null +++ b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_1_fail.sol @@ -0,0 +1,12 @@ +pragma experimental SMTChecker; +contract C { + int[][] array2d; + function l() public { + array2d.push().push(); + assert(array2d.length > 2); + assert(array2d[array2d.length - 1].length > 3); + } +} +// ---- +// Warning 4661: (113-139): Assertion violation happens here +// Warning 4661: (143-189): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2.sol b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2.sol new file mode 100644 index 000000000000..b6fd8e8c9b57 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2.sol @@ -0,0 +1,11 @@ +pragma experimental SMTChecker; +contract C { + int[][][] array2d; + function l() public { + array2d.push().push().push(); + assert(array2d.length > 0); + uint last = array2d[array2d.length - 1].length; + assert(last > 0); + assert(array2d[array2d.length - 1][last - 1].length > 0); + } +} diff --git a/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol new file mode 100644 index 000000000000..3d22b862a543 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/array_members/push_push_no_args_2_fail.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; +contract C { + int[][][] array2d; + function l() public { + array2d.push().push().push(); + assert(array2d.length > 2); + uint last = array2d[array2d.length - 1].length; + assert(last > 3); + assert(array2d[array2d.length - 1][last - 1].length > 4); + } +} +// ---- +// Warning 4661: (122-148): Assertion violation happens here +// Warning 4661: (202-218): Assertion violation happens here +// Warning 4661: (222-278): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1.sol b/test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1.sol new file mode 100644 index 000000000000..527d06534bdd --- /dev/null +++ b/test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1.sol @@ -0,0 +1,18 @@ +pragma experimental SMTChecker; +contract C { + int[][] array2d; + function l() public { + s().push(); + // False positive. + // Knowledge is erased because `s()` is a storage pointer. + assert(array2d[2].length > 0); + } + function s() internal returns (int[] storage) { + array2d.push(); + array2d.push(); + array2d.push(); + return array2d[2]; + } +} +// ---- +// Warning 4661: (184-213): Assertion violation happens here diff --git a/test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1_safe.sol b/test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1_safe.sol new file mode 100644 index 000000000000..843b46b16a64 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1_safe.sol @@ -0,0 +1,15 @@ +pragma experimental SMTChecker; +contract C { + int[][] array2d; + function l() public { + s(); + array2d[2].push(); + assert(array2d[2].length > 0); + } + function s() internal returns (int[] storage) { + array2d.push(); + array2d.push(); + array2d.push(); + return array2d[2]; + } +} diff --git a/test/libsolidity/smtCheckerTests/operators/bitwise_and_fixed_bytes.sol b/test/libsolidity/smtCheckerTests/operators/bitwise_and_fixed_bytes.sol new file mode 100644 index 000000000000..c3212bb23c69 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/bitwise_and_fixed_bytes.sol @@ -0,0 +1,8 @@ +pragma experimental SMTChecker; +contract C { + function f() public pure returns (byte) { + return (byte("") & ("")); + } +} +// ---- +// Warning 5084: (101-109): Type conversion is not yet fully supported and might yield false positives. diff --git a/test/libsolidity/smtCheckerTests/operators/bitwise_xor_fixed_bytes.sol b/test/libsolidity/smtCheckerTests/operators/bitwise_xor_fixed_bytes.sol new file mode 100644 index 000000000000..3852563be270 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/bitwise_xor_fixed_bytes.sol @@ -0,0 +1,9 @@ +pragma experimental SMTChecker; +contract Simp { + function f3() public pure returns (byte) { + bytes memory y = "def"; + return y[0] ^ "e"; + } +} +// ---- +// Warning 1093: (142-152): Assertion checker does not yet implement this bitwise operator. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_1.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_1.sol index a17f2f466efc..24e61cf58315 100644 --- a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_1.sol +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_1.sol @@ -1,13 +1,10 @@ pragma experimental SMTChecker; - contract C { - function f(bool b) public pure { - uint v = 0; + int[1] c; + function f(bool b) public { if (b) - v |= 1; - assert(v == 1); + c[0] |= 1; } } // ---- -// Warning 9149: (106-112): Assertion checker does not yet implement this assignment operator. -// Warning 4661: (116-130): Assertion violation happens here +// Warning 9149: (97-106): Assertion checker does not yet implement this assignment operator. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_2.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_2.sol new file mode 100644 index 000000000000..4569afa88325 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_2.sol @@ -0,0 +1,10 @@ +pragma experimental SMTChecker; +contract C { + int[1][20] c; + function f(bool b) public { + if (b) + c[10][0] |= 1; + } +} +// ---- +// Warning 9149: (101-114): Assertion checker does not yet implement this assignment operator. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_3.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_3.sol new file mode 100644 index 000000000000..617ae7af3b9a --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_3.sol @@ -0,0 +1,16 @@ +pragma experimental SMTChecker; +contract C { + struct S { + uint x; + } + S s; + function f(bool b) public { + if (b) + s.x |= 1; + } +} +// ---- +// Warning 8115: (71-74): Assertion checker does not yet support the type of this variable. +// Warning 7650: (117-120): Assertion checker does not yet support this expression. +// Warning 8364: (117-118): Assertion checker does not yet implement type struct C.S storage ref +// Warning 9149: (117-125): Assertion checker does not yet implement this assignment operator. diff --git a/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_4.sol b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_4.sol new file mode 100644 index 000000000000..091f0ca0d8e9 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/operators/compound_bitwise_or_4.sol @@ -0,0 +1,17 @@ +pragma experimental SMTChecker; +contract C { + struct S { + uint[] x; + } + S s; + function f(bool b) public { + if (b) + s.x[2] |= 1; + } +} +// ---- +// Warning 8115: (73-76): Assertion checker does not yet support the type of this variable. +// Warning 7650: (119-122): Assertion checker does not yet support this expression. +// Warning 8364: (119-120): Assertion checker does not yet implement type struct C.S storage ref +// Warning 9118: (119-125): Assertion checker does not yet implement this expression. +// Warning 9149: (119-130): Assertion checker does not yet implement this assignment operator. diff --git a/test/libsolidity/smtCheckerTests/types/event_with_rational_size_array.sol b/test/libsolidity/smtCheckerTests/types/event_with_rational_size_array.sol new file mode 100644 index 000000000000..98dfcec33112 --- /dev/null +++ b/test/libsolidity/smtCheckerTests/types/event_with_rational_size_array.sol @@ -0,0 +1,2 @@ +pragma experimental SMTChecker; +contract a { event b(uint[(1 / 1)]); } diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/078_fallback_function_twice.sol b/test/libsolidity/syntaxTests/duplicateFunctions/fallback_function_twice.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/078_fallback_function_twice.sol rename to test/libsolidity/syntaxTests/duplicateFunctions/fallback_function_twice.sol diff --git a/test/libsolidity/syntaxTests/duplicateFunctions/receive_function_thrice.sol b/test/libsolidity/syntaxTests/duplicateFunctions/receive_function_thrice.sol new file mode 100644 index 000000000000..2160dc05518d --- /dev/null +++ b/test/libsolidity/syntaxTests/duplicateFunctions/receive_function_thrice.sol @@ -0,0 +1,8 @@ +contract C { + receive() external payable { } + receive() external payable { } + receive() external payable { } +} +// ---- +// DeclarationError 4046: (52-82): Only one receive function is allowed. +// DeclarationError 4046: (87-117): Only one receive function is allowed. diff --git a/test/libsolidity/syntaxTests/functionCalls/call_options_overload.sol b/test/libsolidity/syntaxTests/functionCalls/call_options_overload.sol deleted file mode 100644 index 11021f7d7f44..000000000000 --- a/test/libsolidity/syntaxTests/functionCalls/call_options_overload.sol +++ /dev/null @@ -1,9 +0,0 @@ -contract C { - function f(uint x) external payable { } - function f(uint x, uint y) external payable { } - function call() internal { - this.f{value: 10}(2); - } -} -// ---- -// TypeError 6675: (148-154): Member "f" not unique after argument-dependent lookup in contract C. diff --git a/test/libsolidity/syntaxTests/iceRegressionTests/oversized_var.sol b/test/libsolidity/syntaxTests/iceRegressionTests/oversized_var.sol new file mode 100644 index 000000000000..45e2779c5e0b --- /dev/null +++ b/test/libsolidity/syntaxTests/iceRegressionTests/oversized_var.sol @@ -0,0 +1,15 @@ +contract b { + struct c { + uint [2 ** 253] a; + } + + c d; + function e() public { + var d = d; + } +} +// ---- +// Warning 2519: (105-110): This declaration shadows an existing declaration. +// Warning 3408: (66-69): Variable "d" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 2332: (105-110): Type "b.c" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// SyntaxError 1719: (105-114): Use of the "var" keyword is disallowed. Use explicit declaration `struct b.c storage pointer d = ...` instead. diff --git a/test/libsolidity/syntaxTests/imports/declaration_not_found.sol b/test/libsolidity/syntaxTests/imports/declaration_not_found.sol new file mode 100644 index 000000000000..b02868e542e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/imports/declaration_not_found.sol @@ -0,0 +1,7 @@ +==== Source: a ==== +contract A { } +==== Source: b ==== +import {C} from "a"; +contract B { } +// ---- +// DeclarationError 2904: (b:0-20): Declaration "C" not found in "a" (referenced as "a"). diff --git a/test/libsolidity/syntaxTests/largeTypes/large_storage_array_mapping.sol b/test/libsolidity/syntaxTests/largeTypes/large_storage_array_mapping.sol index 01a68bcda6a1..2dfc50a415f2 100644 --- a/test/libsolidity/syntaxTests/largeTypes/large_storage_array_mapping.sol +++ b/test/libsolidity/syntaxTests/largeTypes/large_storage_array_mapping.sol @@ -2,4 +2,4 @@ contract C { mapping(uint => uint[2**100]) x; } // ---- -// Warning 7325: (17-48): Type "uint256[1267650600228229401496703205376]" has large size and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (17-46): Type "uint256[1267650600228229401496703205376]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/largeTypes/large_storage_structs.sol b/test/libsolidity/syntaxTests/largeTypes/large_storage_structs.sol index 2956a65494b1..a29401d948ef 100644 --- a/test/libsolidity/syntaxTests/largeTypes/large_storage_structs.sol +++ b/test/libsolidity/syntaxTests/largeTypes/large_storage_structs.sol @@ -23,9 +23,9 @@ contract C { struct Q0 { - uint[1][][10**20 + 4] x; - uint[10**20 + 4][][1] y; - uint[][10**20 + 4] z; + uint[1][][10**20 + 1] x; + uint[10**20 + 2][][1] y; + uint[][10**20 + 3] z; uint[10**20 + 4][] t; } Q0 q0; @@ -57,11 +57,12 @@ contract C { // ---- // Warning 3408: (106-111): Variable "s0" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. // Warning 3408: (171-176): Variable "s1" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. -// Warning 7325: (341-346): Type "C.P[103]" has large size and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. -// Warning 7325: (341-346): Type "C.P[104]" has large size and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (341-343): Type "C.P[103]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (341-343): Type "C.P[104]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. // Warning 3408: (505-510): Variable "q0" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. -// Warning 7325: (505-510): Type "uint256[100000000000000000004]" has large size and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (505-507): Type "uint256[100000000000000000002]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (505-507): Type "uint256[100000000000000000004]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. // Warning 3408: (576-581): Variable "q1" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. -// Warning 7325: (647-652): Type "uint256[100000000000000000006]" has large size and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (647-649): Type "uint256[100000000000000000006]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. // Warning 3408: (715-720): Variable "q3" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. -// Warning 7325: (783-788): Type "uint256[100000000000000000008]" has large size and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 7325: (783-785): Type "uint256[100000000000000000008]" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_array.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_array.sol new file mode 100644 index 000000000000..123773403a2c --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/oversized_array.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >= 0.0; +contract C { + uint[2**255][2] a; +} +// ---- +// TypeError 7676: (60-97): Contract too large for storage. +// TypeError 1534: (77-94): Type too large for storage. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_contract.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_contract.sol new file mode 100644 index 000000000000..44c7274e6468 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/oversized_contract.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >= 0.0; +contract C { + uint[2**255] a; + uint[2**255] b; +} +// ---- +// TypeError 7676: (60-114): Contract too large for storage. +// Warning 3408: (77-91): Variable "a" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 3408: (97-111): Variable "b" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_contract_inheritance.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_contract_inheritance.sol new file mode 100644 index 000000000000..24073d4c0316 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/oversized_contract_inheritance.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >= 0.0; +contract C { + uint[2**255] a; +} +contract D is C { + uint[2**255] b; +} +// ---- +// TypeError 7676: (95-134): Contract too large for storage. +// Warning 3408: (77-91): Variable "a" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. +// Warning 3408: (117-131): Variable "b" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/largeTypes/oversized_struct.sol b/test/libsolidity/syntaxTests/largeTypes/oversized_struct.sol new file mode 100644 index 000000000000..757ec9e4afc8 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/oversized_struct.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >= 0.0; +contract C { + struct S { + uint[2**255] a; + uint[2**255] b; + } + S s; +} +// ---- +// TypeError 7676: (60-152): Contract too large for storage. +// TypeError 1534: (146-149): Type too large for storage. diff --git a/test/libsolidity/syntaxTests/largeTypes/storage_parameter.sol b/test/libsolidity/syntaxTests/largeTypes/storage_parameter.sol new file mode 100644 index 000000000000..b32815028923 --- /dev/null +++ b/test/libsolidity/syntaxTests/largeTypes/storage_parameter.sol @@ -0,0 +1,6 @@ +contract C { + struct S { uint256[2**255] x; } + function f(S storage) internal {} +} +// ---- +// Warning 2332: (64-65): Type "C.S" covers a large part of storage and thus makes collisions likely. Either use mappings or dynamic arrays and allow their size to be increased only in small quantities per transaction. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol index 2bf491b5d8df..a21a18d9c2bf 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/356_payable_internal.sol @@ -2,4 +2,4 @@ contract test { function f() payable internal {} } // ---- -// TypeError 5587: (20-52): Internal functions cannot be payable. +// TypeError 5587: (20-52): "internal" and "private" functions cannot be payable. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol index fcc0dba35402..3436ce76fda4 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/357_payable_private.sol @@ -2,4 +2,4 @@ contract test { function f() payable private {} } // ---- -// TypeError 5587: (20-51): Internal functions cannot be payable. +// TypeError 5587: (20-51): "internal" and "private" functions cannot be payable. diff --git a/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc.sol b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc.sol new file mode 100644 index 000000000000..678872d7a00f --- /dev/null +++ b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc.sol @@ -0,0 +1,7 @@ +contract C { + /// @inheritdoc X + function f() internal { + } +} +// ---- +// DocstringParsingError 9397: (17-34): Documentation tag @inheritdoc references inexistent contract "X". diff --git a/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc2.sol b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc2.sol new file mode 100644 index 000000000000..4d97ff93d43c --- /dev/null +++ b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc2.sol @@ -0,0 +1,10 @@ +contract D { +} + +contract C is D { + /// @inheritdoc D + function f() internal { + } +} +// ---- +// DocstringParsingError 4682: (38-55): Documentation tag @inheritdoc references contract "D", but the contract does not contain a function that is overridden by this function. diff --git a/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc3.sol b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc3.sol new file mode 100644 index 000000000000..d00e1e7ea1ac --- /dev/null +++ b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc3.sol @@ -0,0 +1,11 @@ +contract D { + struct S { uint a; } +} + +contract C is D { + /// @inheritdoc D.S + function f() internal { + } +} +// ---- +// DocstringParsingError 1430: (63-82): Documentation tag @inheritdoc reference "D.S" is not a contract. diff --git a/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc_wrong_type.sol b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc_wrong_type.sol new file mode 100644 index 000000000000..510f6622fdca --- /dev/null +++ b/test/libsolidity/syntaxTests/natspec/invalid/docstring_inheritdoc_wrong_type.sol @@ -0,0 +1,8 @@ +contract C { + struct S { uint a; } + /// @inheritdoc S + function f() internal { + } +} +// ---- +// DocstringParsingError 1430: (42-59): Documentation tag @inheritdoc reference "S" is not a contract. diff --git a/test/libsolidity/syntaxTests/natspec/invalid/inherit_doc_events.sol b/test/libsolidity/syntaxTests/natspec/invalid/inherit_doc_events.sol new file mode 100644 index 000000000000..e7fb1a822fc9 --- /dev/null +++ b/test/libsolidity/syntaxTests/natspec/invalid/inherit_doc_events.sol @@ -0,0 +1,17 @@ +contract ERC20 { + /// @notice This event is emitted when a transfer occurs. + /// @param from The source account. + /// @param to The destination account. + /// @param amount The amount. + /// @dev A test case! + event Transfer(address indexed from, address indexed to, uint amount); +} + +contract A is ERC20 { + /// @inheritdoc ERC20 + event Transfer(); +} + + +// ---- +// DocstringParsingError 6546: (305-326): Documentation tag @inheritdoc not valid for events. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol b/test/libsolidity/syntaxTests/string/invalid_utf8_explicit_string.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/186_invalid_utf8_explicit.sol rename to test/libsolidity/syntaxTests/string/invalid_utf8_explicit_string.sol diff --git a/test/libsolidity/syntaxTests/string/invalid_utf8_hex_string.sol b/test/libsolidity/syntaxTests/string/invalid_utf8_hex_string.sol new file mode 100644 index 000000000000..d72ee5af0dda --- /dev/null +++ b/test/libsolidity/syntaxTests/string/invalid_utf8_hex_string.sol @@ -0,0 +1,5 @@ +contract C { + string s = hex"a000"; +} +// ---- +// TypeError 7407: (28-37): Type literal_string (contains invalid UTF-8 sequence at position 0) is not implicitly convertible to expected type string storage ref. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/185_invalid_utf8_implicit.sol b/test/libsolidity/syntaxTests/string/invalid_utf8_implicit_string.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/185_invalid_utf8_implicit.sol rename to test/libsolidity/syntaxTests/string/invalid_utf8_implicit_string.sol diff --git a/test/libsolidity/syntaxTests/string/invalid_utf8_in_bytes.sol b/test/libsolidity/syntaxTests/string/invalid_utf8_in_bytes.sol new file mode 100644 index 000000000000..c5af0d094f10 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/invalid_utf8_in_bytes.sol @@ -0,0 +1,6 @@ +contract C { + bytes b1 = "\xa0\x00"; + bytes32 b2 = "\xa0\x00"; + bytes b3 = hex"a000"; +} +// ---- diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/187_large_utf8_codepoint.sol b/test/libsolidity/syntaxTests/string/large_utf8_codepoint.sol similarity index 100% rename from test/libsolidity/syntaxTests/nameAndTypeResolution/187_large_utf8_codepoint.sol rename to test/libsolidity/syntaxTests/string/large_utf8_codepoint.sol diff --git a/test/libsolidity/syntaxTests/string/string_unicode.sol b/test/libsolidity/syntaxTests/string/string_unicode.sol new file mode 100644 index 000000000000..380ad9e39d60 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/string_unicode.sol @@ -0,0 +1,6 @@ +contract test { + function f() public pure returns (string memory) { + return "😃, 😭, and 😈"; + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/unicode_escape_literals.sol b/test/libsolidity/syntaxTests/string/unicode_escape_literals.sol similarity index 60% rename from test/libsolidity/syntaxTests/unicode_escape_literals.sol rename to test/libsolidity/syntaxTests/string/unicode_escape_literals.sol index d78e6aa09750..011f58b409f6 100644 --- a/test/libsolidity/syntaxTests/unicode_escape_literals.sol +++ b/test/libsolidity/syntaxTests/string/unicode_escape_literals.sol @@ -1,5 +1,4 @@ contract test { - function oneByteUTF8() public pure returns (bytes32) { bytes32 usdollar = "aaa\u0024aaa"; return usdollar; @@ -15,17 +14,8 @@ contract test { return eur; } - function together() public pure returns (bytes32) { + function combined() public pure returns (bytes32) { bytes32 res = "\u0024\u00A2\u20AC"; return res; } - - // this function returns an invalid unicode character - function invalidLiteral() public pure returns(bytes32) { - bytes32 invalid = "\u00xx"; - return invalid; - } - } -// ---- -// ParserError 8936: (678-681): Invalid escape sequence. diff --git a/test/libsolidity/syntaxTests/string/unicode_escape_literals_invalid_codepoint.sol b/test/libsolidity/syntaxTests/string/unicode_escape_literals_invalid_codepoint.sol new file mode 100644 index 000000000000..46a0de5f4fe5 --- /dev/null +++ b/test/libsolidity/syntaxTests/string/unicode_escape_literals_invalid_codepoint.sol @@ -0,0 +1,7 @@ +contract test { + function f() public pure returns (string memory) { + return "\xc1"; + } +} +// ---- +// TypeError 6359: (86-92): Return argument type literal_string (contains invalid UTF-8 sequence at position 0) is not implicitly convertible to expected type (type of first return variable) string memory. diff --git a/test/libsolidity/syntaxTests/string/unicode_escape_literals_invalid_format.sol b/test/libsolidity/syntaxTests/string/unicode_escape_literals_invalid_format.sol new file mode 100644 index 000000000000..6afcd94afcff --- /dev/null +++ b/test/libsolidity/syntaxTests/string/unicode_escape_literals_invalid_format.sol @@ -0,0 +1,10 @@ +contract test { + // this function returns an invalid unicode character + function invalidLiteral() public pure returns (bytes32) { + bytes32 invalid = "\u00xx"; + return invalid; + } + +} +// ---- +// ParserError 8936: (162-165): Invalid escape sequence. diff --git a/test/libsolidity/syntaxTests/types/event_with_rational_size_array.sol b/test/libsolidity/syntaxTests/types/event_with_rational_size_array.sol new file mode 100644 index 000000000000..d0846345a445 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/event_with_rational_size_array.sol @@ -0,0 +1 @@ +contract a { event b(uint[(1 / 1)]); } diff --git a/test/libsolidity/syntaxTests/types/var_type_suggest.sol b/test/libsolidity/syntaxTests/types/var_type_suggest.sol index 65d91cd1e159..61ee7d317cb4 100644 --- a/test/libsolidity/syntaxTests/types/var_type_suggest.sol +++ b/test/libsolidity/syntaxTests/types/var_type_suggest.sol @@ -20,11 +20,11 @@ contract C { } } // ---- -// SyntaxError 1719: (224-238): Use of the "var" keyword is disallowed. Use explicit declaration `int16 s = ...´ instead. -// SyntaxError 1719: (248-261): Use of the "var" keyword is disallowed. Use explicit declaration `uint16 i = ...´ instead. -// SyntaxError 1719: (271-287): Use of the "var" keyword is disallowed. Use explicit declaration `string memory t = ...´ instead. -// SyntaxError 1719: (297-307): Use of the "var" keyword is disallowed. Use explicit declaration `function (uint256) pure returns (uint256) g2 = ...´ instead. +// SyntaxError 1719: (224-238): Use of the "var" keyword is disallowed. Use explicit declaration `int16 s = ...` instead. +// SyntaxError 1719: (248-261): Use of the "var" keyword is disallowed. Use explicit declaration `uint16 i = ...` instead. +// SyntaxError 1719: (271-287): Use of the "var" keyword is disallowed. Use explicit declaration `string memory t = ...` instead. +// SyntaxError 1719: (297-307): Use of the "var" keyword is disallowed. Use explicit declaration `function (uint256) pure returns (uint256) g2 = ...` instead. // SyntaxError 3478: (317-350): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. -// SyntaxError 1719: (360-384): Use of the "var" keyword is disallowed. Use explicit declaration `(uint8 a, string memory b) = ...´ instead. -// SyntaxError 1719: (394-411): Use of the "var" keyword is disallowed. Use explicit declaration `(uint256 x, , uint256 z) = ...´ instead. +// SyntaxError 1719: (360-384): Use of the "var" keyword is disallowed. Use explicit declaration `(uint8 a, string memory b) = ...` instead. +// SyntaxError 1719: (394-411): Use of the "var" keyword is disallowed. Use explicit declaration `(uint256 x, , uint256 z) = ...` instead. // TypeError 7364: (421-438): Different number of components on the left hand side (2) than on the right hand side (1). diff --git a/test/libsolidity/syntaxTests/unexpected.sol b/test/libsolidity/syntaxTests/unexpected.sol new file mode 100644 index 000000000000..79ee1b6cbecb --- /dev/null +++ b/test/libsolidity/syntaxTests/unexpected.sol @@ -0,0 +1,3 @@ +unexpected +// ---- +// ParserError 7858: (0-10): Expected pragma, import directive or contract/interface/library/struct/enum definition. diff --git a/test/libsolidity/util/BytesUtils.cpp b/test/libsolidity/util/BytesUtils.cpp index fd2cd2fcf730..d095a0a7647c 100644 --- a/test/libsolidity/util/BytesUtils.cpp +++ b/test/libsolidity/util/BytesUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -22,6 +23,7 @@ #include +#include #include #include @@ -198,8 +200,7 @@ string BytesUtils::formatString(bytes const& _bytes, size_t _cutOff) if (isprint(v)) os << v; else - os << "\\x" << setw(2) << setfill('0') << hex << v; - + os << "\\x" << toHex(v); } } os << "\""; diff --git a/test/libsolidity/util/ContractABIUtils.cpp b/test/libsolidity/util/ContractABIUtils.cpp index 2e600e4c181d..a3a19e6e5129 100644 --- a/test/libsolidity/util/ContractABIUtils.cpp +++ b/test/libsolidity/util/ContractABIUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/libsolidity/util/TestFileParser.cpp b/test/libsolidity/util/TestFileParser.cpp index 52e4156aabfe..046193d39112 100644 --- a/test/libsolidity/util/TestFileParser.cpp +++ b/test/libsolidity/util/TestFileParser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/libsolidity/util/TestFileParserTests.cpp b/test/libsolidity/util/TestFileParserTests.cpp index 4fb44d7cdd07..6b3ba2d7a67f 100644 --- a/test/libsolidity/util/TestFileParserTests.cpp +++ b/test/libsolidity/util/TestFileParserTests.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for Solidity's test expectation parser. */ diff --git a/test/libsolidity/util/TestFunctionCallTests.cpp b/test/libsolidity/util/TestFunctionCallTests.cpp index 7b34cbe8ecd5..dc3030384f54 100644 --- a/test/libsolidity/util/TestFunctionCallTests.cpp +++ b/test/libsolidity/util/TestFunctionCallTests.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libsolutil/Checksum.cpp b/test/libsolutil/Checksum.cpp index 159c55efc858..ab7ccf631a01 100644 --- a/test/libsolutil/Checksum.cpp +++ b/test/libsolutil/Checksum.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the address checksum. */ diff --git a/test/libsolutil/CommonData.cpp b/test/libsolutil/CommonData.cpp index d8434c79d16c..670a71d14c71 100644 --- a/test/libsolutil/CommonData.cpp +++ b/test/libsolutil/CommonData.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the StringUtils routines. */ diff --git a/test/libsolutil/IndentedWriter.cpp b/test/libsolutil/IndentedWriter.cpp index 3d0963e9ff23..0938f9617592 100644 --- a/test/libsolutil/IndentedWriter.cpp +++ b/test/libsolutil/IndentedWriter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for IndentedWriter. */ diff --git a/test/libsolutil/IpfsHash.cpp b/test/libsolutil/IpfsHash.cpp index 9d6f0f8fc2cb..c99650a4b06d 100644 --- a/test/libsolutil/IpfsHash.cpp +++ b/test/libsolutil/IpfsHash.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the ipfs hash computation routine. */ @@ -29,7 +30,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(IpfsHash) +BOOST_AUTO_TEST_SUITE(IpfsHash, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(test_small) { diff --git a/test/libsolutil/IterateReplacing.cpp b/test/libsolutil/IterateReplacing.cpp index d1598dbc3981..a54841560960 100644 --- a/test/libsolutil/IterateReplacing.cpp +++ b/test/libsolutil/IterateReplacing.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the iterateReplacing function */ @@ -29,7 +30,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(IterateReplacing) +BOOST_AUTO_TEST_SUITE(IterateReplacing, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(no_replacement) { diff --git a/test/libsolutil/JSON.cpp b/test/libsolutil/JSON.cpp index e45c6fdec35d..6663978774f1 100644 --- a/test/libsolutil/JSON.cpp +++ b/test/libsolutil/JSON.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2018 * Unit tests for JSON.h. @@ -30,7 +31,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(JsonTest) +BOOST_AUTO_TEST_SUITE(JsonTest, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(json_pretty_print) { diff --git a/test/libsolutil/Keccak256.cpp b/test/libsolutil/Keccak256.cpp index 4bb3bddd6a50..17de6c885273 100644 --- a/test/libsolutil/Keccak256.cpp +++ b/test/libsolutil/Keccak256.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for keccak256. */ @@ -26,7 +27,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(Keccak256) +BOOST_AUTO_TEST_SUITE(Keccak256, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(empty) { diff --git a/test/libsolutil/LazyInit.cpp b/test/libsolutil/LazyInit.cpp index 346805c82093..51ee3ee1e720 100644 --- a/test/libsolutil/LazyInit.cpp +++ b/test/libsolutil/LazyInit.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -59,7 +60,7 @@ T valueOf(LazyInit _lazyInit) } -BOOST_AUTO_TEST_SUITE(LazyInitTests) +BOOST_AUTO_TEST_SUITE(LazyInitTests, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(default_constructed_is_empty) { diff --git a/test/libsolutil/StringUtils.cpp b/test/libsolutil/StringUtils.cpp index e50260e88b4f..f678c0da7716 100644 --- a/test/libsolutil/StringUtils.cpp +++ b/test/libsolutil/StringUtils.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the StringUtils routines. */ @@ -33,7 +34,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(StringUtils) +BOOST_AUTO_TEST_SUITE(StringUtils, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(test_similarity) { diff --git a/test/libsolutil/SwarmHash.cpp b/test/libsolutil/SwarmHash.cpp index a976bfccf0d2..3b13cd38213b 100644 --- a/test/libsolutil/SwarmHash.cpp +++ b/test/libsolutil/SwarmHash.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the swarm hash computation routine. */ @@ -31,7 +32,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(SwarmHash) +BOOST_AUTO_TEST_SUITE(SwarmHash, *boost::unit_test::label("nooptions")) string bzzr0HashHex(string const& _input) { diff --git a/test/libsolutil/UTF8.cpp b/test/libsolutil/UTF8.cpp index b3e969b9b5e0..d6a14bcff804 100644 --- a/test/libsolutil/UTF8.cpp +++ b/test/libsolutil/UTF8.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for UTF-8 validation. */ @@ -30,7 +31,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(UTF8) +BOOST_AUTO_TEST_SUITE(UTF8, *boost::unit_test::label("nooptions")) namespace { diff --git a/test/libsolutil/Whiskers.cpp b/test/libsolutil/Whiskers.cpp index 093b0acb69fd..1cc889127797 100644 --- a/test/libsolutil/Whiskers.cpp +++ b/test/libsolutil/Whiskers.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Unit tests for the mini moustache class. */ @@ -29,7 +30,7 @@ using namespace std; namespace solidity::util::test { -BOOST_AUTO_TEST_SUITE(WhiskersTest) +BOOST_AUTO_TEST_SUITE(WhiskersTest, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(no_templates) { diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp index 57ee7ffa619b..b0b07a8fb8ef 100644 --- a/test/libyul/Common.cpp +++ b/test/libyul/Common.cpp @@ -90,7 +90,7 @@ pair, shared_ptr> yul::test::parse( if (!parserResult->code || errorReporter.hasErrors()) return {}; shared_ptr analysisInfo = make_shared(); - AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->dataNames()); + AsmAnalyzer analyzer(*analysisInfo, errorReporter, _dialect, {}, parserResult->qualifiedDataNames()); // TODO this should be done recursively. if (!analyzer.analyze(*parserResult->code) || errorReporter.hasErrors()) return {}; diff --git a/test/libyul/CompilabilityChecker.cpp b/test/libyul/CompilabilityChecker.cpp index 51aefc6107f5..ad1a6fd5eade 100644 --- a/test/libyul/CompilabilityChecker.cpp +++ b/test/libyul/CompilabilityChecker.cpp @@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE(nested) x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1) } })"); - BOOST_CHECK_EQUAL(out, "h: 9 "); + BOOST_CHECK_EQUAL(out, "h: 9 g: 5 f: 5 "); } BOOST_AUTO_TEST_CASE(also_in_outer_block) @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(also_in_outer_block) function g(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19) -> w, v { } })"); - BOOST_CHECK_EQUAL(out, ": 9 "); + BOOST_CHECK_EQUAL(out, "g: 5 : 9 "); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libyul/EwasmTranslationTest.cpp b/test/libyul/EwasmTranslationTest.cpp index 8ef5ba0a01a6..be9ed77d957b 100644 --- a/test/libyul/EwasmTranslationTest.cpp +++ b/test/libyul/EwasmTranslationTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -98,12 +99,10 @@ string EwasmTranslationTest::interpret() { InterpreterState state; state.maxTraceSize = 10000; - state.maxSteps = 100000; - WasmDialect dialect; - Interpreter interpreter(state, dialect); + state.maxSteps = 1000000; try { - interpreter(*m_object->code); + Interpreter::run(state, WasmDialect{}, *m_object->code); } catch (InterpreterTerminatedGeneric const&) { diff --git a/test/libyul/EwasmTranslationTest.h b/test/libyul/EwasmTranslationTest.h index e0a90482bc46..f6307bdbc5c4 100644 --- a/test/libyul/EwasmTranslationTest.h +++ b/test/libyul/EwasmTranslationTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libyul/FunctionSideEffects.cpp b/test/libyul/FunctionSideEffects.cpp index aa7d1e503927..56051ffddc66 100644 --- a/test/libyul/FunctionSideEffects.cpp +++ b/test/libyul/FunctionSideEffects.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libyul/FunctionSideEffects.h b/test/libyul/FunctionSideEffects.h index 23bebebcc846..ac0653733f03 100644 --- a/test/libyul/FunctionSideEffects.h +++ b/test/libyul/FunctionSideEffects.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libyul/Inliner.cpp b/test/libyul/Inliner.cpp index de47f48854db..f44d86618f82 100644 --- a/test/libyul/Inliner.cpp +++ b/test/libyul/Inliner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * @date 2017 * Unit tests for the Yul function inliner. diff --git a/test/libyul/ObjectCompilerTest.cpp b/test/libyul/ObjectCompilerTest.cpp index 4b34da7b11bd..950c0210f04e 100644 --- a/test/libyul/ObjectCompilerTest.cpp +++ b/test/libyul/ObjectCompilerTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/libyul/ObjectCompilerTest.h b/test/libyul/ObjectCompilerTest.h index 4a1c75486b1e..85a46a1cf3df 100644 --- a/test/libyul/ObjectCompilerTest.h +++ b/test/libyul/ObjectCompilerTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libyul/StackReuseCodegen.cpp b/test/libyul/StackReuseCodegen.cpp index 5103befb03cd..1b6b91657944 100644 --- a/test/libyul/StackReuseCodegen.cpp +++ b/test/libyul/StackReuseCodegen.cpp @@ -43,7 +43,7 @@ string assemble(string const& _input) } } -BOOST_AUTO_TEST_SUITE(StackReuseCodegen) +BOOST_AUTO_TEST_SUITE(StackReuseCodegen, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_CASE(smoke_test) { @@ -345,6 +345,69 @@ BOOST_AUTO_TEST_CASE(reuse_slots_function_with_gaps) ); } +BOOST_AUTO_TEST_CASE(reuse_on_decl_assign_to_last_used) +{ + string in = R"({ + let x := 5 + let y := x // y should reuse the stack slot of x + sstore(y, y) + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x5 " + "DUP1 SWAP1 POP " + "DUP1 DUP2 SSTORE " + "POP " + ); +} + +BOOST_AUTO_TEST_CASE(reuse_on_decl_assign_to_last_used_expr) +{ + string in = R"({ + let x := 5 + let y := add(x, 2) // y should reuse the stack slot of x + sstore(y, y) + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x5 " + "PUSH1 0x2 DUP2 ADD " + "SWAP1 POP " + "DUP1 DUP2 SSTORE " + "POP " + ); +} + +BOOST_AUTO_TEST_CASE(reuse_on_decl_assign_to_not_last_used) +{ + string in = R"({ + let x := 5 + let y := x // y should not reuse the stack slot of x, since x is still used below + sstore(y, x) + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x5 " + "DUP1 " + "DUP2 DUP2 SSTORE " + "POP POP " + ); +} + +BOOST_AUTO_TEST_CASE(reuse_on_decl_assign_not_same_scope) +{ + string in = R"({ + let x := 5 + { + let y := x // y should not reuse the stack slot of x, since x is not in the same scope + sstore(y, y) + } + })"; + BOOST_CHECK_EQUAL(assemble(in), + "PUSH1 0x5 " + "DUP1 " + "DUP1 DUP2 SSTORE " + "POP POP " + ); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libyul/SyntaxTest.cpp b/test/libyul/SyntaxTest.cpp index 944ceaf33bb7..bb0751b828df 100644 --- a/test/libyul/SyntaxTest.cpp +++ b/test/libyul/SyntaxTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/libyul/SyntaxTest.h b/test/libyul/SyntaxTest.h index 342aa28458c0..7234e1f2c6bf 100644 --- a/test/libyul/SyntaxTest.h +++ b/test/libyul/SyntaxTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libyul/YulInterpreterTest.cpp b/test/libyul/YulInterpreterTest.cpp index 9925b95463f5..78e81578569b 100644 --- a/test/libyul/YulInterpreterTest.cpp +++ b/test/libyul/YulInterpreterTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -88,10 +89,9 @@ string YulInterpreterTest::interpret() InterpreterState state; state.maxTraceSize = 10000; state.maxSteps = 10000; - Interpreter interpreter(state, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); try { - interpreter(*m_ast); + Interpreter::run(state, EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{}), *m_ast); } catch (InterpreterTerminatedGeneric const&) { diff --git a/test/libyul/YulInterpreterTest.h b/test/libyul/YulInterpreterTest.h index ee60abe17671..88e535fb0138 100644 --- a/test/libyul/YulInterpreterTest.h +++ b/test/libyul/YulInterpreterTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index 95d7bee64c0c..436c46a656ac 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/libyul/YulOptimizerTest.h b/test/libyul/YulOptimizerTest.h index 3d351c3a2c06..5bba65682cef 100644 --- a/test/libyul/YulOptimizerTest.h +++ b/test/libyul/YulOptimizerTest.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/test/libyul/objectCompiler/subObjectAccess.yul b/test/libyul/objectCompiler/subObjectAccess.yul new file mode 100644 index 000000000000..4fddc2483f07 --- /dev/null +++ b/test/libyul/objectCompiler/subObjectAccess.yul @@ -0,0 +1,104 @@ +object "A" { + code { + pop(dataoffset("A")) + pop(datasize("A")) + pop(dataoffset("B")) + pop(datasize("B")) + pop(dataoffset("B.C")) + pop(datasize("B.C")) + pop(dataoffset("B.E")) + pop(datasize("B.E")) + pop(dataoffset("B.C.D")) + pop(datasize("B.C.D")) + } + + data "data1" "Hello, World!" + + object "B" { + code { + pop(dataoffset("C")) + pop(datasize("C")) + pop(dataoffset("E")) + pop(datasize("E")) + pop(dataoffset("C.D")) + pop(datasize("C.D")) + } + object "C" { + code { + pop(dataoffset("D")) + pop(datasize("D")) + } + object "D" { + code { + invalid() + } + } + } + object "E" { + code { + invalid() + } + } + } +} +// ---- +// Assembly: +// /* "source":26:46 */ +// pop(0x00) +// /* "source":51:69 */ +// pop(bytecodeSize) +// /* "source":74:94 */ +// pop(dataOffset(sub_0)) +// /* "source":99:117 */ +// pop(dataSize(sub_0)) +// /* "source":122:144 */ +// pop(dataOffset(sub_0.sub_0)) +// /* "source":149:169 */ +// pop(dataSize(sub_0.sub_0)) +// /* "source":174:196 */ +// pop(dataOffset(sub_0.sub_1)) +// /* "source":201:221 */ +// pop(dataSize(sub_0.sub_1)) +// /* "source":226:250 */ +// pop(dataOffset(sub_0.sub_0.sub_0)) +// /* "source":255:277 */ +// pop(dataSize(sub_0.sub_0.sub_0)) +// stop +// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421 +// +// sub_0: assembly { +// /* "source":347:367 */ +// pop(dataOffset(sub_0)) +// /* "source":374:392 */ +// pop(dataSize(sub_0)) +// /* "source":399:419 */ +// pop(dataOffset(sub_1)) +// /* "source":426:444 */ +// pop(dataSize(sub_1)) +// /* "source":451:473 */ +// pop(dataOffset(sub_0.sub_0)) +// /* "source":480:500 */ +// pop(dataSize(sub_0.sub_0)) +// stop +// +// sub_0: assembly { +// /* "source":545:565 */ +// pop(dataOffset(sub_0)) +// /* "source":574:592 */ +// pop(dataSize(sub_0)) +// stop +// +// sub_0: assembly { +// /* "source":645:654 */ +// invalid +// } +// } +// +// sub_1: assembly { +// /* "source":717:726 */ +// invalid +// } +// } +// Bytecode: 600050604650601f50601d50603e50600850603d50600150603c50600150fe601350600850601b50600150601c50600150fe600750600150fefefefefefe600750600150fefe +// Opcodes: PUSH1 0x0 POP PUSH1 0x46 POP PUSH1 0x1F POP PUSH1 0x1D POP PUSH1 0x3E POP PUSH1 0x8 POP PUSH1 0x3D POP PUSH1 0x1 POP PUSH1 0x3C POP PUSH1 0x1 POP INVALID PUSH1 0x13 POP PUSH1 0x8 POP PUSH1 0x1B POP PUSH1 0x1 POP PUSH1 0x1C POP PUSH1 0x1 POP INVALID PUSH1 0x7 POP PUSH1 0x1 POP INVALID INVALID INVALID INVALID INVALID INVALID PUSH1 0x7 POP PUSH1 0x1 POP INVALID INVALID +// SourceMappings: 26:20:0:-:0;;51:18;;74:20;;99:18;;122:22;;149:20;;174:22;;201:20;;226:24;;255:22; diff --git a/test/libyul/yulInterpreterTests/and_create.yul b/test/libyul/yulInterpreterTests/and_create.yul new file mode 100644 index 000000000000..8907081506bf --- /dev/null +++ b/test/libyul/yulInterpreterTests/and_create.yul @@ -0,0 +1,13 @@ +{ + let u160max := 0xffffffffffffffffffffffffffffffffffffffff + let a := create(0, u160max, 0) + let b := and(u160max, create(0, u160max, 0)) + mstore(0, eq(a, b)) +} +// ---- +// Trace: +// CREATE(0, 0xffffffffffffffffffffffffffffffffffffffff, 0) +// CREATE(0, 0xffffffffffffffffffffffffffffffffffffffff, 0) +// Memory dump: +// 0: 0000000000000000000000000000000000000000000000000000000000000001 +// Storage dump: diff --git a/test/libyul/yulInterpreterTests/and_create2.yul b/test/libyul/yulInterpreterTests/and_create2.yul new file mode 100644 index 000000000000..46df2a9caece --- /dev/null +++ b/test/libyul/yulInterpreterTests/and_create2.yul @@ -0,0 +1,15 @@ +{ + let u160max := 0xffffffffffffffffffffffffffffffffffffffff + let a := create2(0, u160max, 0, 0) + let b := and(u160max, create2(0, u160max, 0, 0)) + mstore(0, eq(a, b)) +} +// ==== +// EVMVersion: >=constantinople +// ---- +// Trace: +// CREATE2(0, 0xffffffffffffffffffffffffffffffffffffffff, 0, 0) +// CREATE2(0, 0xffffffffffffffffffffffffffffffffffffffff, 0, 0) +// Memory dump: +// 0: 0000000000000000000000000000000000000000000000000000000000000001 +// Storage dump: diff --git a/test/libyul/yulSyntaxTests/invalid_type2.yul b/test/libyul/yulSyntaxTests/invalid_type2.yul index 25320b055142..2ad035dcfc74 100644 --- a/test/libyul/yulSyntaxTests/invalid_type2.yul +++ b/test/libyul/yulSyntaxTests/invalid_type2.yul @@ -5,4 +5,4 @@ // dialect: evmTyped // ---- // TypeError 5473: (15-28): "invalidType" is not a valid type (user defined types are not yet supported). -// TypeError 3947: (10-11): Assigning value of type "invalidType" to variable of type "u256. +// TypeError 3947: (10-11): Assigning value of type "invalidType" to variable of type "u256". diff --git a/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul b/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul index e81474613dd4..7b8d012bb597 100644 --- a/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul +++ b/test/libyul/yulSyntaxTests/user_defined_functions_fail.yul @@ -8,5 +8,5 @@ // ==== // dialect: evmTyped // ---- -// TypeError 3947: (126-127): Assigning value of type "bool" to variable of type "u256. -// TypeError 3947: (129-136): Assigning value of type "u256" to variable of type "bool. +// TypeError 3947: (126-127): Assigning value of type "bool" to variable of type "u256". +// TypeError 3947: (129-136): Assigning value of type "u256" to variable of type "bool". diff --git a/test/tools/IsolTestOptions.cpp b/test/tools/IsolTestOptions.cpp index 28552a86ad45..84e2babe921e 100644 --- a/test/tools/IsolTestOptions.cpp +++ b/test/tools/IsolTestOptions.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file IsolTestOptions.cpp * @date 2019 */ diff --git a/test/tools/IsolTestOptions.h b/test/tools/IsolTestOptions.h index 93d365191500..118ac95d3ec2 100644 --- a/test/tools/IsolTestOptions.h +++ b/test/tools/IsolTestOptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** @file IsolTestOptions.h */ diff --git a/test/tools/afl_fuzzer.cpp b/test/tools/afl_fuzzer.cpp index 81c3a2bfca1a..ea4a5a8283b1 100644 --- a/test/tools/afl_fuzzer.cpp +++ b/test/tools/afl_fuzzer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Executable for use with AFL . */ diff --git a/test/tools/fuzzer_common.cpp b/test/tools/fuzzer_common.cpp index ac2e13775f34..cb153e0e8b2a 100644 --- a/test/tools/fuzzer_common.cpp +++ b/test/tools/fuzzer_common.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -71,16 +72,16 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize, runCompiler(jsonCompactPrint(config), _quiet); } -void FuzzerUtil::testCompiler(string const& _input, bool _optimize) +void FuzzerUtil::testCompiler(StringMap const& _input, bool _optimize, unsigned _rand) { frontend::CompilerStack compiler; - EVMVersion evmVersion = s_evmVersions[_input.size() % s_evmVersions.size()]; + EVMVersion evmVersion = s_evmVersions[_rand % s_evmVersions.size()]; frontend::OptimiserSettings optimiserSettings; if (_optimize) optimiserSettings = frontend::OptimiserSettings::standard(); else optimiserSettings = frontend::OptimiserSettings::minimal(); - compiler.setSources({{"", _input}}); + compiler.setSources(_input); compiler.setEVMVersion(evmVersion); compiler.setOptimiserSettings(optimiserSettings); try diff --git a/test/tools/fuzzer_common.h b/test/tools/fuzzer_common.h index 801c8c1c18bd..cd30adc970dc 100644 --- a/test/tools/fuzzer_common.h +++ b/test/tools/fuzzer_common.h @@ -14,7 +14,11 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 +#include + +#include #include /** @@ -27,5 +31,9 @@ struct FuzzerUtil static void testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet); static void testConstantOptimizer(std::string const& _input, bool _quiet); static void testStandardCompiler(std::string const& _input, bool _quiet); - static void testCompiler(std::string const& _input, bool _optimize); + /// Compiles @param _input which is a map of input file name to source code + /// string with optimisation turned on if @param _optimize is true + /// (off otherwise) and a pseudo-random @param _rand that selects the EVM + /// version to be compiled for. + static void testCompiler(solidity::StringMap const& _input, bool _optimize, unsigned _rand); }; diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 07802edf12f9..3bdb16b0f4e9 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt index ccd71a983c82..a799bd736e03 100644 --- a/test/tools/ossfuzz/CMakeLists.txt +++ b/test/tools/ossfuzz/CMakeLists.txt @@ -8,20 +8,26 @@ add_dependencies(ossfuzz strictasm_assembly_ossfuzz ) + if (OSSFUZZ) add_custom_target(ossfuzz_proto) - add_dependencies(ossfuzz_proto yul_proto_ossfuzz yul_proto_diff_ossfuzz sol_proto_ossfuzz) + add_dependencies(ossfuzz_proto + sol_proto_ossfuzz + yul_proto_ossfuzz + yul_proto_diff_ossfuzz + yul_proto_diff_custom_mutate_ossfuzz + ) add_custom_target(ossfuzz_abiv2) add_dependencies(ossfuzz_abiv2 abiv2_proto_ossfuzz) endif() if (OSSFUZZ) - add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp) + add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp ../../TestCaseReader.cpp) target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm) set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) - add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp) + add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp ../../TestCaseReader.cpp) target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm) set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) @@ -49,6 +55,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) + target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) add_executable(yul_proto_diff_ossfuzz yulProto_diff_ossfuzz.cpp yulFuzzerCommon.cpp protoToYul.cpp yulProto.pb.cc) target_include_directories(yul_proto_diff_ossfuzz PRIVATE /usr/include/libprotobuf-mutator) @@ -59,6 +66,24 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) + target_compile_options(yul_proto_diff_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) + + add_executable(yul_proto_diff_custom_mutate_ossfuzz + yulProto_diff_ossfuzz.cpp + yulFuzzerCommon.cpp + protoToYul.cpp + yulProto.pb.cc + protomutators/YulProtoMutator.cpp +) + target_include_directories(yul_proto_diff_custom_mutate_ossfuzz PRIVATE /usr/include/libprotobuf-mutator) + target_link_libraries(yul_proto_diff_custom_mutate_ossfuzz PRIVATE yul + yulInterpreter + protobuf-mutator-libfuzzer.a + protobuf-mutator.a + protobuf.a +) + set_target_properties(yul_proto_diff_custom_mutate_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) + target_compile_options(yul_proto_diff_custom_mutate_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) add_executable(abiv2_proto_ossfuzz ../../EVMHost.cpp @@ -78,6 +103,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(abiv2_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) + target_compile_options(abiv2_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) add_executable(sol_proto_ossfuzz solProtoFuzzer.cpp @@ -97,6 +123,7 @@ if (OSSFUZZ) protobuf.a ) set_target_properties(sol_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE}) + target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion) else() add_library(solc_opt_ossfuzz solc_opt_ossfuzz.cpp diff --git a/test/tools/ossfuzz/abiV2Proto.proto b/test/tools/ossfuzz/abiV2Proto.proto index b581c9904bd3..b6640bbe977c 100644 --- a/test/tools/ossfuzz/abiV2Proto.proto +++ b/test/tools/ossfuzz/abiV2Proto.proto @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 syntax = "proto2"; diff --git a/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp b/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp index 89d5a35660b9..8c529630f8c4 100644 --- a/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp +++ b/test/tools/ossfuzz/abiV2ProtoFuzzer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/tools/ossfuzz/const_opt_ossfuzz.cpp b/test/tools/ossfuzz/const_opt_ossfuzz.cpp index 13ceb840851b..60b1febbc52c 100644 --- a/test/tools/ossfuzz/const_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/const_opt_ossfuzz.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/tools/ossfuzz/protoToSol.cpp b/test/tools/ossfuzz/protoToSol.cpp index aefbb41b9b5a..73ed34b0d352 100644 --- a/test/tools/ossfuzz/protoToSol.cpp +++ b/test/tools/ossfuzz/protoToSol.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/tools/ossfuzz/protoToSol.h b/test/tools/ossfuzz/protoToSol.h index de2220752210..39f830528c8e 100644 --- a/test/tools/ossfuzz/protoToSol.h +++ b/test/tools/ossfuzz/protoToSol.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/test/tools/ossfuzz/protoToYul.cpp b/test/tools/ossfuzz/protoToYul.cpp index 8d5ced0a85f2..1d78dc8020a7 100644 --- a/test/tools/ossfuzz/protoToYul.cpp +++ b/test/tools/ossfuzz/protoToYul.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include @@ -178,19 +179,27 @@ bool ProtoConverter::functionCallNotPossible(FunctionCall_Returns _type) (_type == FunctionCall::MULTIASSIGN && !varDeclAvailable()); } +unsigned ProtoConverter::numVarsInScope() +{ + if (m_inFunctionDef) + return m_currentFuncVars.size(); + else + return m_currentGlobalVars.size(); +} + void ProtoConverter::visit(VarRef const& _x) { if (m_inFunctionDef) { // Ensure that there is at least one variable declaration to reference in function scope. yulAssert(m_currentFuncVars.size() > 0, "Proto fuzzer: No variables to reference."); - m_output << *m_currentFuncVars[_x.varnum() % m_currentFuncVars.size()]; + m_output << *m_currentFuncVars[static_cast(_x.varnum()) % m_currentFuncVars.size()]; } else { // Ensure that there is at least one variable declaration to reference in nested scopes. yulAssert(m_currentGlobalVars.size() > 0, "Proto fuzzer: No global variables to reference."); - m_output << *m_currentGlobalVars[_x.varnum() % m_currentGlobalVars.size()]; + m_output << *m_currentGlobalVars[static_cast(_x.varnum()) % m_currentGlobalVars.size()]; } } @@ -830,18 +839,18 @@ void ProtoConverter::visitFunctionInputParams(FunctionCall const& _x, unsigned _ case 4: visit(_x.in_param4()); m_output << ", "; - BOOST_FALLTHROUGH; + [[fallthrough]]; case 3: visit(_x.in_param3()); m_output << ", "; - BOOST_FALLTHROUGH; + [[fallthrough]]; case 2: visit(_x.in_param2()); m_output << ", "; - BOOST_FALLTHROUGH; + [[fallthrough]]; case 1: visit(_x.in_param1()); - BOOST_FALLTHROUGH; + [[fallthrough]]; case 0: break; default: @@ -966,23 +975,43 @@ void ProtoConverter::visit(FunctionCall const& _x) "Proto fuzzer: Function call with too many output params encountered." ); + // Return early if numOutParams > number of available variables + if (numOutParams > numVarsInScope()) + return; + + // Copy variables in scope in order to prevent repeated references + vector variables; + if (m_inFunctionDef) + for (auto var: m_currentFuncVars) + variables.push_back(*var); + else + for (auto var: m_currentGlobalVars) + variables.push_back(*var); + + auto refVar = [](vector& _var, unsigned _rand, bool _comma = true) -> string + { + auto index = _rand % _var.size(); + string ref = _var[index]; + _var.erase(_var.begin() + index); + if (_comma) + ref += ", "; + return ref; + }; + // Convert LHS of multi assignment // We reverse the order of out param visits since the order does not matter. // This helps reduce the size of this switch statement. switch (numOutParams) { case 4: - visit(_x.out_param4()); - m_output << ", "; - BOOST_FALLTHROUGH; + m_output << refVar(variables, _x.out_param4().varnum()); + [[fallthrough]]; case 3: - visit(_x.out_param3()); - m_output << ", "; - BOOST_FALLTHROUGH; + m_output << refVar(variables, _x.out_param3().varnum()); + [[fallthrough]]; case 2: - visit(_x.out_param2()); - m_output << ", "; - visit(_x.out_param1()); + m_output << refVar(variables, _x.out_param2().varnum()); + m_output << refVar(variables, _x.out_param1().varnum(), false); break; default: yulAssert(false, "Proto fuzzer: Function call with too many or too few input parameters."); diff --git a/test/tools/ossfuzz/protoToYul.h b/test/tools/ossfuzz/protoToYul.h index 9f7240f5eeb0..9b8de148057d 100644 --- a/test/tools/ossfuzz/protoToYul.h +++ b/test/tools/ossfuzz/protoToYul.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include @@ -120,6 +121,8 @@ class ProtoConverter void closeFunctionScope(); /// Adds @a _vars to current scope void addVarsToScope(std::vector const& _vars); + /// @returns number of variables that are in scope + unsigned numVarsInScope(); std::string createHex(std::string const& _hexBytes); diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp new file mode 100644 index 000000000000..32fda663d56b --- /dev/null +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp @@ -0,0 +1,147 @@ +#include + +#include + +#include + +using namespace solidity::yul::test::yul_fuzzer; +using namespace protobuf_mutator; +using namespace std; + +using YPM = YulProtoMutator; + +MutationInfo::MutationInfo(ProtobufMessage const* _message, string const& _info): + ScopeGuard([&]{ exitInfo(); }), + m_protobufMsg(_message) +{ + writeLine("----------------------------------"); + writeLine("YULMUTATOR: " + _info); + writeLine("Before"); + writeLine(SaveMessageAsText(*m_protobufMsg)); +} + +void MutationInfo::exitInfo() +{ + writeLine("After"); + writeLine(SaveMessageAsText(*m_protobufMsg)); +} + +/// Initialize deterministic PRNG. +static YulRandomNumGenerator s_rand(1337); + +/// Add m/sstore(0, variable) +static LPMPostProcessor addStoreToZero( + [](Block* _message, unsigned _seed) + { + if (_seed % YPM::s_highIP == 0) + { + MutationInfo m{_message, "Added store to zero"}; + auto storeStmt = new StoreFunc(); + storeStmt->set_st(YPM::EnumTypeConverter{}.enumFromSeed(s_rand())); + storeStmt->set_allocated_loc(YPM::litExpression(0)); + storeStmt->set_allocated_val(YPM::refExpression(s_rand)); + auto stmt = _message->add_statements(); + stmt->set_allocated_storage_func(storeStmt); + } + } +); + +Literal* YPM::intLiteral(unsigned _value) +{ + auto lit = new Literal(); + lit->set_intval(_value); + return lit; +} + +VarRef* YPM::varRef(unsigned _seed) +{ + auto varref = new VarRef(); + varref->set_varnum(_seed); + return varref; +} + +Expression* YPM::refExpression(YulRandomNumGenerator& _rand) +{ + auto refExpr = new Expression(); + refExpr->set_allocated_varref(varRef(_rand())); + return refExpr; +} + +Expression* YPM::litExpression(unsigned _value) +{ + auto lit = intLiteral(_value); + auto expr = new Expression(); + expr->set_allocated_cons(lit); + return expr; +} + +template +T YPM::EnumTypeConverter::validEnum(unsigned _seed) +{ + auto ret = static_cast(_seed % (enumMax() - enumMin() + 1) + enumMin()); + if constexpr (std::is_same_v, FunctionCall_Returns>) + yulAssert(FunctionCall_Returns_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, StoreFunc_Storage>) + yulAssert(StoreFunc_Storage_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, NullaryOp_NOp>) + yulAssert(NullaryOp_NOp_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, BinaryOp_BOp>) + yulAssert(BinaryOp_BOp_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, UnaryOp_UOp>) + yulAssert(UnaryOp_UOp_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, LowLevelCall_Type>) + yulAssert(LowLevelCall_Type_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, Create_Type>) + yulAssert(Create_Type_IsValid(ret), "Yul proto mutator: Invalid enum"); + else if constexpr (std::is_same_v, UnaryOpData_UOpData>) + yulAssert(UnaryOpData_UOpData_IsValid(ret), "Yul proto mutator: Invalid enum"); + else + static_assert(AlwaysFalse::value, "Yul proto mutator: non-exhaustive visitor."); + return ret; +} + +template +unsigned YPM::EnumTypeConverter::enumMax() +{ + if constexpr (std::is_same_v, FunctionCall_Returns>) + return FunctionCall_Returns_Returns_MAX; + else if constexpr (std::is_same_v, StoreFunc_Storage>) + return StoreFunc_Storage_Storage_MAX; + else if constexpr (std::is_same_v, NullaryOp_NOp>) + return NullaryOp_NOp_NOp_MAX; + else if constexpr (std::is_same_v, BinaryOp_BOp>) + return BinaryOp_BOp_BOp_MAX; + else if constexpr (std::is_same_v, UnaryOp_UOp>) + return UnaryOp_UOp_UOp_MAX; + else if constexpr (std::is_same_v, LowLevelCall_Type>) + return LowLevelCall_Type_Type_MAX; + else if constexpr (std::is_same_v, Create_Type>) + return Create_Type_Type_MAX; + else if constexpr (std::is_same_v, UnaryOpData_UOpData>) + return UnaryOpData_UOpData_UOpData_MAX; + else + static_assert(AlwaysFalse::value, "Yul proto mutator: non-exhaustive visitor."); +} + +template +unsigned YPM::EnumTypeConverter::enumMin() +{ + if constexpr (std::is_same_v, FunctionCall_Returns>) + return FunctionCall_Returns_Returns_MIN; + else if constexpr (std::is_same_v, StoreFunc_Storage>) + return StoreFunc_Storage_Storage_MIN; + else if constexpr (std::is_same_v, NullaryOp_NOp>) + return NullaryOp_NOp_NOp_MIN; + else if constexpr (std::is_same_v, BinaryOp_BOp>) + return BinaryOp_BOp_BOp_MIN; + else if constexpr (std::is_same_v, UnaryOp_UOp>) + return UnaryOp_UOp_UOp_MIN; + else if constexpr (std::is_same_v, LowLevelCall_Type>) + return LowLevelCall_Type_Type_MIN; + else if constexpr (std::is_same_v, Create_Type>) + return Create_Type_Type_MIN; + else if constexpr (std::is_same_v, UnaryOpData_UOpData>) + return UnaryOpData_UOpData_UOpData_MIN; + else + static_assert(AlwaysFalse::value, "Yul proto mutator: non-exhaustive visitor."); +} diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.h b/test/tools/ossfuzz/protomutators/YulProtoMutator.h new file mode 100644 index 000000000000..0627a34687fd --- /dev/null +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.h @@ -0,0 +1,98 @@ +#pragma once + +#include + +#include + +#include + +#include + +namespace solidity::yul::test::yul_fuzzer +{ + +using ProtobufMessage = google::protobuf::Message; + +template +using LPMPostProcessor = protobuf_mutator::libfuzzer::PostProcessorRegistration; + +class MutationInfo: public ScopeGuard +{ +public: + MutationInfo(ProtobufMessage const* _message, std::string const& _info); + + static void writeLine(std::string const& _str) + { + std::cout << _str << std::endl; + } + void exitInfo(); + + ProtobufMessage const* m_protobufMsg; +}; + +struct YulRandomNumGenerator +{ + using RandomEngine = std::minstd_rand; + + explicit YulRandomNumGenerator(unsigned _seed): m_random(RandomEngine(_seed)) {} + + unsigned operator()() + { + return m_random(); + } + + RandomEngine m_random; +}; + +struct YulProtoMutator +{ + /// @param _value: Value of the integer literal + /// @returns an integer literal protobuf message initialized with + /// the given value. + static Literal* intLiteral(unsigned _value); + + /// @param _seed: Pseudo-random unsigned integer used as index + /// of variable to be referenced + /// @returns a variable reference protobuf message. + static VarRef* varRef(unsigned _seed); + + /// @param _value: value of literal expression + /// @returns an expression protobuf message + static Expression* litExpression(unsigned _value); + + /// @param _rand: Pseudo-random number generator + /// of variable to be referenced + /// @returns a variable reference protobuf message + static Expression* refExpression(YulRandomNumGenerator& _rand); + + /// Helper type for type matching visitor. + template struct AlwaysFalse: std::false_type {}; + + /// Template struct for obtaining a valid enum value of + /// template type from a pseudo-random unsigned integer. + /// @param _seed: Pseudo-random integer + /// @returns Valid enum of enum type T + template + struct EnumTypeConverter + { + T enumFromSeed(unsigned _seed) + { + return validEnum(_seed); + } + + /// @returns a valid enum of type T from _seed + T validEnum(unsigned _seed); + /// @returns maximum enum value for enum of type T + static unsigned enumMax(); + /// @returns minimum enum value for enum of type T + static unsigned enumMin(); + }; + + /// Modulo for mutations that should occur rarely + static constexpr unsigned s_lowIP = 31; + /// Modulo for mutations that should occur not too often + static constexpr unsigned s_mediumIP = 29; + /// Modulo for mutations that should occur often + static constexpr unsigned s_highIP = 23; +}; +} diff --git a/test/tools/ossfuzz/solProto.proto b/test/tools/ossfuzz/solProto.proto index 86e938c7c806..59d989cf903b 100644 --- a/test/tools/ossfuzz/solProto.proto +++ b/test/tools/ossfuzz/solProto.proto @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 syntax = "proto2"; diff --git a/test/tools/ossfuzz/solProtoFuzzer.cpp b/test/tools/ossfuzz/solProtoFuzzer.cpp index 80facb3e132f..e9e77dcc4fe0 100644 --- a/test/tools/ossfuzz/solProtoFuzzer.cpp +++ b/test/tools/ossfuzz/solProtoFuzzer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include @@ -202,7 +203,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input ofstream of(dump_path); - of.write(sol_source.data(), sol_source.size()); + of.write(sol_source.data(), static_cast(sol_source.size())); } if (char const* dump_path = getenv("SOL_DEBUG_FILE")) diff --git a/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp b/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp index efed3769f58e..8d615c0bde4d 100644 --- a/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_noopt_ossfuzz.cpp @@ -14,9 +14,15 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include +#include + +#include + +using namespace solidity::frontend::test; using namespace std; extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) @@ -24,7 +30,17 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) if (_size <= 600) { string input(reinterpret_cast(_data), _size); - FuzzerUtil::testCompiler(input, /*optimize=*/false); + map sourceCode; + try + { + TestCaseReader t = TestCaseReader(std::istringstream(input)); + sourceCode = t.sources().sources; + } + catch (runtime_error const&) + { + return 0; + } + FuzzerUtil::testCompiler(sourceCode, /*optimize=*/false, /*_rand=*/_size); } return 0; } diff --git a/test/tools/ossfuzz/solc_opt_ossfuzz.cpp b/test/tools/ossfuzz/solc_opt_ossfuzz.cpp index fc431ffe56d0..0d9c7f44e754 100644 --- a/test/tools/ossfuzz/solc_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/solc_opt_ossfuzz.cpp @@ -14,17 +14,33 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include +#include + +#include + +using namespace solidity::frontend::test; using namespace std; extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size) { if (_size <= 600) { - string input(reinterpret_cast(_data), _size); - FuzzerUtil::testCompiler(input, /*optimize=*/true); + string input(reinterpret_cast(_data), _size); + map sourceCode; + try + { + TestCaseReader t = TestCaseReader(std::istringstream(input)); + sourceCode = t.sources().sources; + } + catch (runtime_error const&) + { + return 0; + } + FuzzerUtil::testCompiler(sourceCode, /*optimize=*/true, /*rand=*/_size); } return 0; } diff --git a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp index b9373a3010b7..458bde745996 100644 --- a/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_assembly_ossfuzz.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp index b4211dfc9f92..bd6d249b3523 100644 --- a/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_diff_ossfuzz.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp index a8378f72e995..646e6ea6a5a2 100644 --- a/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp +++ b/test/tools/ossfuzz/strictasm_opt_ossfuzz.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/tools/ossfuzz/yulFuzzerCommon.cpp b/test/tools/ossfuzz/yulFuzzerCommon.cpp index 214caf3f8f53..86cea8327f97 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.cpp +++ b/test/tools/ossfuzz/yulFuzzerCommon.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include using namespace std; @@ -44,12 +45,11 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret( 0xc7, 0x60, 0x5f, 0x7c, 0xcd, 0xfb, 0x92, 0xcd, 0x8e, 0xf3, 0x9b, 0xe4, 0x4f, 0x6c, 0x14, 0xde }; - Interpreter interpreter(state, _dialect); TerminationReason reason = TerminationReason::None; try { - interpreter(*_ast); + Interpreter::run(state, _dialect, *_ast); } catch (StepLimitReached const&) { diff --git a/test/tools/ossfuzz/yulFuzzerCommon.h b/test/tools/ossfuzz/yulFuzzerCommon.h index 08e17e3817af..cc20d6163ab6 100644 --- a/test/tools/ossfuzz/yulFuzzerCommon.h +++ b/test/tools/ossfuzz/yulFuzzerCommon.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/test/tools/ossfuzz/yulProto.proto b/test/tools/ossfuzz/yulProto.proto index 3180b421a0ce..d87d067f2677 100644 --- a/test/tools/ossfuzz/yulProto.proto +++ b/test/tools/ossfuzz/yulProto.proto @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 syntax = "proto2"; diff --git a/test/tools/ossfuzz/yulProtoFuzzer.cpp b/test/tools/ossfuzz/yulProtoFuzzer.cpp index b78f6fc5c8bf..1095994bf13a 100644 --- a/test/tools/ossfuzz/yulProtoFuzzer.cpp +++ b/test/tools/ossfuzz/yulProtoFuzzer.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -43,7 +44,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input ofstream of(dump_path); - of.write(yul_source.data(), yul_source.size()); + of.write(yul_source.data(), static_cast(yul_source.size())); } if (yul_source.size() > 1200) diff --git a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp index fd0f2e0a52c4..c95b4db7ff0f 100644 --- a/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp +++ b/test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -64,7 +65,7 @@ DEFINE_PROTO_FUZZER(Program const& _input) // With libFuzzer binary run this to generate a YUL source file x.yul: // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input ofstream of(dump_path); - of.write(yul_source.data(), yul_source.size()); + of.write(yul_source.data(), static_cast(yul_source.size())); } YulStringRepository::reset(); @@ -96,15 +97,17 @@ DEFINE_PROTO_FUZZER(Program const& _input) EVMDialect::strictAssemblyForEVMObjects(version) ); - if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached) + if ( + termReason == yulFuzzerUtil::TerminationReason::StepLimitReached || + termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached + ) return; stack.optimize(); - termReason = yulFuzzerUtil::interpret( + yulFuzzerUtil::interpret( os2, stack.parserResult()->code, - EVMDialect::strictAssemblyForEVMObjects(version), - (yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 4) + EVMDialect::strictAssemblyForEVMObjects(version) ); bool isTraceEq = (os1.str() == os2.str()); diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp index c17fa33e86b5..e5acf394849d 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter module that evaluates EVM instructions. */ @@ -303,11 +304,11 @@ u256 EVMInstructionInterpreter::eval( case Instruction::CREATE: accessMemory(arg[1], arg[2]); logTrace(_instruction, arg); - return 0xcccccc + arg[1]; + return u160(0xcccccc + arg[1]); case Instruction::CREATE2: accessMemory(arg[2], arg[3]); logTrace(_instruction, arg); - return 0xdddddd + arg[1]; + return u160(0xdddddd + arg[1]); case Instruction::CALL: case Instruction::CALLCODE: // TODO assign returndata @@ -409,17 +410,17 @@ u256 EVMInstructionInterpreter::eval( case Instruction::SWAP14: case Instruction::SWAP15: case Instruction::SWAP16: - // --------------- EVM 2.0 --------------- - case Instruction::JUMPTO: - case Instruction::JUMPIF: - case Instruction::JUMPV: - case Instruction::JUMPSUB: - case Instruction::JUMPSUBV: - case Instruction::BEGINSUB: - case Instruction::BEGINDATA: - case Instruction::RETURNSUB: - case Instruction::PUTLOCAL: - case Instruction::GETLOCAL: + // --------------- EIP-615 --------------- + case Instruction::EIP615_JUMPTO: + case Instruction::EIP615_JUMPIF: + case Instruction::EIP615_JUMPV: + case Instruction::EIP615_JUMPSUB: + case Instruction::EIP615_JUMPSUBV: + case Instruction::EIP615_BEGINSUB: + case Instruction::EIP615_BEGINDATA: + case Instruction::EIP615_RETURNSUB: + case Instruction::EIP615_PUTLOCAL: + case Instruction::EIP615_GETLOCAL: { yulAssert(false, ""); return 0; diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.h b/test/tools/yulInterpreter/EVMInstructionInterpreter.h index 02104178b5d7..05d27df9616e 100644 --- a/test/tools/yulInterpreter/EVMInstructionInterpreter.h +++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter module that evaluates EVM instructions. */ diff --git a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp index b09fb5a87381..61c7b4817c04 100644 --- a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp +++ b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter module that evaluates Ewasm builtins. */ @@ -51,8 +52,9 @@ void copyZeroExtended( _target[_targetOffset + i] = _sourceOffset + i < _source.size() ? _source[_sourceOffset + i] : 0; } -/// Count leading zeros for uint64 -uint64_t clz(uint64_t _v) +/// Count leading zeros for uint64. Following WebAssembly rules, it returns 64 for @a _v being zero. +/// NOTE: the clz builtin of the compiler may or may not do this +uint64_t clz64(uint64_t _v) { if (_v == 0) return 64; @@ -66,6 +68,50 @@ uint64_t clz(uint64_t _v) return r; } +/// Count trailing zeros for uint32. Following WebAssembly rules, it returns 32 for @a _v being zero. +/// NOTE: the ctz builtin of the compiler may or may not do this +uint32_t ctz32(uint32_t _v) +{ + if (_v == 0) + return 32; + + uint32_t r = 0; + while (!(_v & 1)) + { + r++; + _v >>= 1; + } + return r; +} + +/// Count trailing zeros for uint64. Following WebAssembly rules, it returns 64 for @a _v being zero. +/// NOTE: the ctz builtin of the compiler may or may not do this +uint64_t ctz64(uint64_t _v) +{ + if (_v == 0) + return 64; + + uint64_t r = 0; + while (!(_v & 1)) + { + r++; + _v >>= 1; + } + return r; +} + +/// Count number of bits set for uint64 +uint64_t popcnt(uint64_t _v) +{ + uint64_t r = 0; + while (_v) + { + r += (_v & 1); + _v >>= 1; + } + return r; +} + } using u512 = boost::multiprecision::number>; @@ -76,11 +122,12 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector const& _a for (u256 const& a: _arguments) arg.emplace_back(uint64_t(a & uint64_t(-1))); - if (_fun == "datasize"_yulstring) + string fun = _fun.str(); + if (fun == "datasize") return u256(keccak256(h256(_arguments.at(0)))) & 0xfff; - else if (_fun == "dataoffset"_yulstring) + else if (fun == "dataoffset") return u256(keccak256(h256(_arguments.at(0) + 2))) & 0xfff; - else if (_fun == "datacopy"_yulstring) + else if (fun == "datacopy") { // This is identical to codecopy. if (accessMemory(_arguments.at(0), _arguments.at(2))) @@ -93,49 +140,57 @@ u256 EwasmBuiltinInterpreter::evalBuiltin(YulString _fun, vector const& _a ); return 0; } - else if (_fun == "i32.drop"_yulstring || _fun == "i64.drop"_yulstring || _fun == "nop"_yulstring) + else if (fun == "i32.drop" || fun == "i64.drop" || fun == "nop") return {}; - else if (_fun == "i32.wrap_i64"_yulstring) + else if (fun == "i32.wrap_i64") return arg.at(0) & uint32_t(-1); - else if (_fun == "i64.extend_i32_u"_yulstring) + else if (fun == "i64.extend_i32_u") // Return the same as above because everything is u256 anyway. return arg.at(0) & uint32_t(-1); - else if (_fun == "unreachable"_yulstring) + else if (fun == "unreachable") { logTrace(evmasm::Instruction::INVALID, {}); throw ExplicitlyTerminated(); } - else if (_fun == "i64.store"_yulstring) + else if (fun == "i64.store") { accessMemory(arg[0], 8); writeMemoryWord(arg[0], arg[1]); return 0; } - else if (_fun == "i64.store8"_yulstring || _fun == "i32.store8"_yulstring) + else if (fun == "i64.store8" || fun == "i32.store8") { accessMemory(arg[0], 1); writeMemoryByte(arg[0], static_cast(arg[1] & 0xff)); return 0; } - else if (_fun == "i64.load"_yulstring) + else if (fun == "i64.load") { accessMemory(arg[0], 8); return readMemoryWord(arg[0]); } - else if (_fun == "i32.store"_yulstring) + else if (fun == "i32.store") { accessMemory(arg[0], 4); writeMemoryHalfWord(arg[0], arg[1]); return 0; } - else if (_fun == "i32.load"_yulstring) + else if (fun == "i32.load") { accessMemory(arg[0], 4); return readMemoryHalfWord(arg[0]); } - - - string prefix = _fun.str(); + else if (_fun == "i32.clz"_yulstring) + // NOTE: the clz implementation assumes 64-bit inputs, hence the adjustment + return clz64(arg[0] & uint32_t(-1)) - 32; + else if (_fun == "i64.clz"_yulstring) + return clz64(arg[0]); + else if (_fun == "i32.ctz"_yulstring) + return ctz32(uint32_t(arg[0] & uint32_t(-1))); + else if (_fun == "i64.ctz"_yulstring) + return ctz64(arg[0]); + + string prefix = fun; string suffix; auto dot = prefix.find("."); if (dot != string::npos) @@ -202,8 +257,8 @@ u256 EwasmBuiltinInterpreter::evalWasmBuiltin(string const& _fun, vector c return arg[0] != arg[1] ? 1 : 0; else if (_fun == "eqz") return arg[0] == 0 ? 1 : 0; - else if (_fun == "clz") - return clz(arg[0]); + else if (_fun == "popcnt") + return popcnt(arg[0]); else if (_fun == "lt_u") return arg[0] < arg[1] ? 1 : 0; else if (_fun == "gt_u") diff --git a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.h b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.h index 62b6bc0245ab..78cf9216e0e7 100644 --- a/test/tools/yulInterpreter/EwasmBuiltinInterpreter.h +++ b/test/tools/yulInterpreter/EwasmBuiltinInterpreter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter module that evaluates Ewasm builtins. */ diff --git a/test/tools/yulInterpreter/Interpreter.cpp b/test/tools/yulInterpreter/Interpreter.cpp index 5f0861d143dd..a8496793fff1 100644 --- a/test/tools/yulInterpreter/Interpreter.cpp +++ b/test/tools/yulInterpreter/Interpreter.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter. */ @@ -64,6 +65,12 @@ void InterpreterState::dumpTraceAndState(ostream& _out) const _out << " " << slot.first.hex() << ": " << slot.second.hex() << endl; } +void Interpreter::run(InterpreterState& _state, Dialect const& _dialect, Block const& _ast) +{ + Scope scope; + Interpreter{_state, _dialect, scope}(_ast); +} + void Interpreter::operator()(ExpressionStatement const& _expressionStatement) { evaluateMulti(_expressionStatement.expression); @@ -94,8 +101,7 @@ void Interpreter::operator()(VariableDeclaration const& _declaration) YulString varName = _declaration.variables.at(i).name; solAssert(!m_variables.count(varName), ""); m_variables[varName] = values.at(i); - solAssert(!m_scopes.back().count(varName), ""); - m_scopes.back().emplace(varName, nullptr); + m_scope->names.emplace(varName, nullptr); } } @@ -128,8 +134,8 @@ void Interpreter::operator()(ForLoop const& _forLoop) { solAssert(_forLoop.condition, ""); - openScope(); - ScopeGuard g([this]{ closeScope(); }); + enterScope(_forLoop.pre); + ScopeGuard g([this]{ leaveScope(); }); for (auto const& statement: _forLoop.pre.statements) { @@ -139,6 +145,11 @@ void Interpreter::operator()(ForLoop const& _forLoop) } while (evaluate(*_forLoop.condition) != 0) { + // Increment step for each loop iteration for loops with + // an empty body and post blocks to prevent a deadlock. + if (_forLoop.body.statements.size() == 0 && _forLoop.post.statements.size() == 0) + incrementStep(); + m_state.controlFlowState = ControlFlowState::Default; (*this)(_forLoop.body); if (m_state.controlFlowState == ControlFlowState::Break || m_state.controlFlowState == ControlFlowState::Leave) @@ -170,52 +181,68 @@ void Interpreter::operator()(Leave const&) void Interpreter::operator()(Block const& _block) { - m_state.numSteps++; - if (m_state.maxSteps > 0 && m_state.numSteps >= m_state.maxSteps) - { - m_state.trace.emplace_back("Interpreter execution step limit reached."); - throw StepLimitReached(); - } - openScope(); + enterScope(_block); // Register functions. for (auto const& statement: _block.statements) if (holds_alternative(statement)) { FunctionDefinition const& funDef = std::get(statement); - solAssert(!m_scopes.back().count(funDef.name), ""); - m_scopes.back().emplace(funDef.name, &funDef); + m_scope->names.emplace(funDef.name, &funDef); } for (auto const& statement: _block.statements) { + incrementStep(); visit(statement); if (m_state.controlFlowState != ControlFlowState::Default) break; } - closeScope(); + leaveScope(); } u256 Interpreter::evaluate(Expression const& _expression) { - ExpressionEvaluator ev(m_state, m_dialect, m_variables, m_scopes); + ExpressionEvaluator ev(m_state, m_dialect, *m_scope, m_variables); ev.visit(_expression); return ev.value(); } vector Interpreter::evaluateMulti(Expression const& _expression) { - ExpressionEvaluator ev(m_state, m_dialect, m_variables, m_scopes); + ExpressionEvaluator ev(m_state, m_dialect, *m_scope, m_variables); ev.visit(_expression); return ev.values(); } -void Interpreter::closeScope() +void Interpreter::enterScope(Block const& _block) +{ + if (!m_scope->subScopes.count(&_block)) + m_scope->subScopes[&_block] = make_unique(Scope{ + {}, + {}, + m_scope + }); + m_scope = m_scope->subScopes[&_block].get(); +} + +void Interpreter::leaveScope() { - for (auto const& [var, funDeclaration]: m_scopes.back()) + for (auto const& [var, funDeclaration]: m_scope->names) if (!funDeclaration) - solAssert(m_variables.erase(var) == 1, ""); - m_scopes.pop_back(); + m_variables.erase(var); + m_scope = m_scope->parent; + yulAssert(m_scope, ""); +} + +void Interpreter::incrementStep() +{ + m_state.numSteps++; + if (m_state.maxSteps > 0 && m_state.numSteps >= m_state.maxSteps) + { + m_state.trace.emplace_back("Interpreter execution step limit reached."); + throw StepLimitReached(); + } } void ExpressionEvaluator::operator()(Literal const& _literal) @@ -253,10 +280,15 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) return; } - auto [functionScopes, fun] = findFunctionAndScope(_funCall.functionName.name); + Scope* scope = &m_scope; + for (; scope; scope = scope->parent) + if (scope->names.count(_funCall.functionName.name)) + break; + yulAssert(scope, ""); - solAssert(fun, "Function not found."); - solAssert(m_values.size() == fun->parameters.size(), ""); + FunctionDefinition const* fun = scope->names.at(_funCall.functionName.name); + yulAssert(fun, "Function not found."); + yulAssert(m_values.size() == fun->parameters.size(), ""); map variables; for (size_t i = 0; i < fun->parameters.size(); ++i) variables[fun->parameters.at(i).name] = m_values.at(i); @@ -264,7 +296,7 @@ void ExpressionEvaluator::operator()(FunctionCall const& _funCall) variables[fun->returnVariables.at(i).name] = 0; m_state.controlFlowState = ControlFlowState::Default; - Interpreter interpreter(m_state, m_dialect, variables, functionScopes); + Interpreter interpreter(m_state, m_dialect, *scope, std::move(variables)); interpreter(fun->body); m_state.controlFlowState = ControlFlowState::Default; @@ -297,27 +329,3 @@ void ExpressionEvaluator::evaluateArgs(vector const& _expr) m_values = std::move(values); std::reverse(m_values.begin(), m_values.end()); } - -pair< - vector>, - FunctionDefinition const* -> ExpressionEvaluator::findFunctionAndScope(YulString _functionName) const -{ - FunctionDefinition const* fun = nullptr; - std::vector> newScopes; - for (auto const& scope: m_scopes) - { - // Copy over all functions. - newScopes.emplace_back(); - for (auto const& [name, funDef]: scope) - if (funDef) - newScopes.back().emplace(name, funDef); - // Stop at the called function. - if (scope.count(_functionName)) - { - fun = scope.at(_functionName); - break; - } - } - return {move(newScopes), fun}; -} diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h index f50cbe6c4a8a..00e02f6e222f 100644 --- a/test/tools/yulInterpreter/Interpreter.h +++ b/test/tools/yulInterpreter/Interpreter.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter. */ @@ -96,23 +97,37 @@ struct InterpreterState void dumpTraceAndState(std::ostream& _out) const; }; +/** + * Scope structure built and maintained during execution. + */ +struct Scope +{ + /// Used for variables and functions. Value is nullptr for variables. + std::map names; + std::map> subScopes; + Scope* parent = nullptr; +}; + /** * Yul interpreter. */ class Interpreter: public ASTWalker { public: + static void run(InterpreterState& _state, Dialect const& _dialect, Block const& _ast); + Interpreter( InterpreterState& _state, Dialect const& _dialect, - std::map _variables = {}, - std::vector> _scopes = {} + Scope& _scope, + std::map _variables = {} ): m_dialect(_dialect), m_state(_state), m_variables(std::move(_variables)), - m_scopes(std::move(_scopes)) - {} + m_scope(&_scope) + { + } void operator()(ExpressionStatement const& _statement) override; void operator()(Assignment const& _assignment) override; @@ -136,18 +151,18 @@ class Interpreter: public ASTWalker /// Evaluates the expression and returns its value. std::vector evaluateMulti(Expression const& _expression); - void openScope() { m_scopes.emplace_back(); } - /// Unregisters variables and functions. - void closeScope(); + void enterScope(Block const& _block); + void leaveScope(); + + /// Increment interpreter step count, throwing exception if step limit + /// is reached. + void incrementStep(); Dialect const& m_dialect; InterpreterState& m_state; /// Values of variables. std::map m_variables; - /// Scopes of variables and functions. Used for lookup, clearing at end of blocks - /// and passing over the visible functions across function calls. - /// The pointer is nullptr if and only if the key is a variable. - std::vector> m_scopes; + Scope* m_scope; }; /** @@ -159,13 +174,13 @@ class ExpressionEvaluator: public ASTWalker ExpressionEvaluator( InterpreterState& _state, Dialect const& _dialect, - std::map const& _variables, - std::vector> const& _scopes + Scope& _scope, + std::map const& _variables ): m_state(_state), m_dialect(_dialect), m_variables(_variables), - m_scopes(_scopes) + m_scope(_scope) {} void operator()(Literal const&) override; @@ -184,19 +199,11 @@ class ExpressionEvaluator: public ASTWalker /// stores it in m_value. void evaluateArgs(std::vector const& _expr); - /// Finds the function called @a _functionName in the current scope stack and returns - /// the function's scope stack (with variables removed) and definition. - std::pair< - std::vector>, - FunctionDefinition const* - > findFunctionAndScope(YulString _functionName) const; - InterpreterState& m_state; Dialect const& m_dialect; /// Values of variables. std::map const& m_variables; - /// Stack of scopes in the current context. - std::vector> const& m_scopes; + Scope& m_scope; /// Current value of the expression std::vector m_values; }; diff --git a/test/tools/yulopti.cpp b/test/tools/yulopti.cpp index 9f5d560852e5..e4605d10f896 100644 --- a/test/tools/yulopti.cpp +++ b/test/tools/yulopti.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Interactive yul optimizer */ diff --git a/test/tools/yulrun.cpp b/test/tools/yulrun.cpp index 1e82fba7fc4c..e682e98bac85 100644 --- a/test/tools/yulrun.cpp +++ b/test/tools/yulrun.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Yul interpreter. */ @@ -88,11 +89,10 @@ void interpret(string const& _source) InterpreterState state; state.maxTraceSize = 10000; - Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); - Interpreter interpreter(state, dialect); try { - interpreter(*ast); + Dialect const& dialect(EVMDialect::strictAssemblyForEVMObjects(langutil::EVMVersion{})); + Interpreter::run(state, dialect, *ast); } catch (InterpreterTerminatedGeneric const&) { diff --git a/test/yulPhaser/AlgorithmRunner.cpp b/test/yulPhaser/AlgorithmRunner.cpp index 042cd4c2bf39..cb8f7633ed0b 100644 --- a/test/yulPhaser/AlgorithmRunner.cpp +++ b/test/yulPhaser/AlgorithmRunner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -121,7 +122,7 @@ class AlgorithmRunnerAutosaveFixture: public AlgorithmRunnerFixture RandomisingAlgorithm m_algorithm; }; -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(AlgorithmRunnerTest) BOOST_FIXTURE_TEST_CASE(run_should_call_runNextRound_once_per_round, AlgorithmRunnerFixture) diff --git a/test/yulPhaser/Chromosome.cpp b/test/yulPhaser/Chromosome.cpp index 442f7967f612..ecf754e8e7d4 100644 --- a/test/yulPhaser/Chromosome.cpp +++ b/test/yulPhaser/Chromosome.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -46,7 +47,7 @@ using namespace solidity::util; namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(ChromosomeTest) BOOST_AUTO_TEST_CASE(constructor_should_convert_from_string_to_optimisation_steps) diff --git a/test/yulPhaser/Common.cpp b/test/yulPhaser/Common.cpp index 39e6dd7843fe..417b9ce3c2be 100644 --- a/test/yulPhaser/Common.cpp +++ b/test/yulPhaser/Common.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -66,7 +67,7 @@ map const StringToTestEnumMap = invertMap(TestEnumToStringMap) } -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(CommonTest) BOOST_FIXTURE_TEST_CASE(readLinesFromFile_should_return_all_lines_from_a_text_file_as_strings_without_newlines, ReadLinesFromFileFixture) diff --git a/test/yulPhaser/FitnessMetrics.cpp b/test/yulPhaser/FitnessMetrics.cpp index e668b54e9d17..7c1ae2d96b33 100644 --- a/test/yulPhaser/FitnessMetrics.cpp +++ b/test/yulPhaser/FitnessMetrics.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -95,7 +96,7 @@ class FitnessMetricCombinationFixture: public ProgramBasedMetricFixture }; }; -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(FitnessMetricsTest) BOOST_AUTO_TEST_SUITE(ProgramBasedMetricTest) diff --git a/test/yulPhaser/GeneticAlgorithms.cpp b/test/yulPhaser/GeneticAlgorithms.cpp index d7ef8db57c94..cfac86db04f7 100644 --- a/test/yulPhaser/GeneticAlgorithms.cpp +++ b/test/yulPhaser/GeneticAlgorithms.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -56,7 +57,7 @@ class ClassicGeneticAlgorithmFixture: public GeneticAlgorithmFixture }; }; -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(GeneticAlgorithmsTest) BOOST_AUTO_TEST_SUITE(RandomAlgorithmTest) @@ -212,7 +213,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_generate_individuals_in_the_crossove BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(ClassicGeneticAlgorithmTest) -BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_individuals_with_probability_proportional_to_fitness, ClassicGeneticAlgorithmFixture) +// FIXME: This test runs *very* slowly (tens of seconds). Investigate, fix and re-enable. +BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_individuals_with_probability_proportional_to_fitness, ClassicGeneticAlgorithmFixture, *boost::unit_test::disabled()) { constexpr double relativeTolerance = 0.1; constexpr size_t populationSize = 1000; @@ -253,7 +255,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_individuals_with_probability_ BOOST_TEST(abs(meanSquaredError(newFitness, expectedValue) - variance) < variance * relativeTolerance); } -BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_only_individuals_existing_in_the_original_population, ClassicGeneticAlgorithmFixture) +// FIXME: This test runs *very* slowly (tens of seconds). Investigate, fix and re-enable. +BOOST_FIXTURE_TEST_CASE(runNextRound_should_select_only_individuals_existing_in_the_original_population, ClassicGeneticAlgorithmFixture, *boost::unit_test::disabled()) { constexpr size_t populationSize = 1000; auto population = Population::makeRandom(m_fitnessMetric, populationSize, 1, 10); @@ -297,7 +300,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_crossover, ClassicGeneticAlgorith BOOST_TEST(totalCrossed >= 2); } -BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_mutation, ClassicGeneticAlgorithmFixture) +// FIXME: This test runs *very* slowly (tens of seconds). Investigate, fix and re-enable. +BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_mutation, ClassicGeneticAlgorithmFixture, *boost::unit_test::disabled()) { m_options.mutationChance = 0.6; ClassicGeneticAlgorithm algorithm(m_options); @@ -326,7 +330,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_mutation, ClassicGeneticAlgorithm BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } -BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_deletion, ClassicGeneticAlgorithmFixture) +// FIXME: This test runs *very* slowly (tens of seconds). Investigate, fix and re-enable. +BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_deletion, ClassicGeneticAlgorithmFixture, *boost::unit_test::disabled()) { m_options.deletionChance = 0.6; ClassicGeneticAlgorithm algorithm(m_options); @@ -355,7 +360,8 @@ BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_deletion, ClassicGeneticAlgorithm BOOST_TEST(abs(meanSquaredError(bernoulliTrials, expectedValue) - variance) < variance * relativeTolerance); } -BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_addition, ClassicGeneticAlgorithmFixture) +// FIXME: This test runs *very* slowly (tens of seconds). Investigate, fix and re-enable. +BOOST_FIXTURE_TEST_CASE(runNextRound_should_do_addition, ClassicGeneticAlgorithmFixture, *boost::unit_test::disabled()) { m_options.additionChance = 0.6; ClassicGeneticAlgorithm algorithm(m_options); diff --git a/test/yulPhaser/Mutations.cpp b/test/yulPhaser/Mutations.cpp index b20cb8e4cb7a..dfdd600a3f3c 100644 --- a/test/yulPhaser/Mutations.cpp +++ b/test/yulPhaser/Mutations.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -33,7 +34,7 @@ using namespace solidity::util; namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(MutationsTest) BOOST_AUTO_TEST_SUITE(GeneRandomisationTest) @@ -179,8 +180,8 @@ BOOST_AUTO_TEST_CASE(alternativeMutations_should_choose_between_mutations_with_g for (size_t i = 0; i < 10; ++i) { Chromosome mutatedChromosome = mutation(chromosome); - cCount += (mutatedChromosome == Chromosome("c") ? 1 : 0); - fCount += (mutatedChromosome == Chromosome("f") ? 1 : 0); + cCount += (mutatedChromosome == Chromosome("c") ? 1u : 0u); + fCount += (mutatedChromosome == Chromosome("f") ? 1u : 0u); } // This particular seed results in 7 "c"s out of 10 which looks plausible given the 80% chance. diff --git a/test/yulPhaser/PairSelections.cpp b/test/yulPhaser/PairSelections.cpp index 62a4dd4bcfaf..f3d13a5b3b27 100644 --- a/test/yulPhaser/PairSelections.cpp +++ b/test/yulPhaser/PairSelections.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -31,7 +32,7 @@ using namespace std; namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(PairSelectionsTest) BOOST_AUTO_TEST_SUITE(RandomPairSelectionTest) diff --git a/test/yulPhaser/Phaser.cpp b/test/yulPhaser/Phaser.cpp index 5cef037786a8..673c43824a75 100644 --- a/test/yulPhaser/Phaser.cpp +++ b/test/yulPhaser/Phaser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -103,7 +104,7 @@ class PoulationFactoryFixture }; }; -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(PhaserTest) BOOST_AUTO_TEST_SUITE(GeneticAlgorithmFactoryTest) diff --git a/test/yulPhaser/Population.cpp b/test/yulPhaser/Population.cpp index 5fd8c2073cf1..955ccc49bd65 100644 --- a/test/yulPhaser/Population.cpp +++ b/test/yulPhaser/Population.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -59,7 +60,7 @@ class PopulationFixture shared_ptr m_fitnessMetric = make_shared(); }; -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(PopulationTest) BOOST_AUTO_TEST_CASE(isFitter_should_use_fitness_as_the_main_criterion) diff --git a/test/yulPhaser/Program.cpp b/test/yulPhaser/Program.cpp index 0a7520dd7b7c..b7dd1f8edce9 100644 --- a/test/yulPhaser/Program.cpp +++ b/test/yulPhaser/Program.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -57,7 +58,7 @@ namespace namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(ProgramTest) BOOST_AUTO_TEST_CASE(copy_constructor_should_make_deep_copy_of_ast) diff --git a/test/yulPhaser/ProgramCache.cpp b/test/yulPhaser/ProgramCache.cpp index 3b652e3fbffa..7fb74fca9ef6 100644 --- a/test/yulPhaser/ProgramCache.cpp +++ b/test/yulPhaser/ProgramCache.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include @@ -70,7 +71,7 @@ class ProgramCacheFixture ProgramCache m_programCache{m_program}; }; -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(ProgramCacheTest) BOOST_AUTO_TEST_CASE(CacheStats_operator_plus_should_add_stats_together) diff --git a/test/yulPhaser/Selections.cpp b/test/yulPhaser/Selections.cpp index d25766ae6284..e5ef00327c82 100644 --- a/test/yulPhaser/Selections.cpp +++ b/test/yulPhaser/Selections.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -34,7 +35,7 @@ using namespace solidity::util; namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(SelectionsTest) BOOST_AUTO_TEST_SUITE(RangeSelectionTest) diff --git a/test/yulPhaser/SimulationRNG.cpp b/test/yulPhaser/SimulationRNG.cpp index 0cdacc428d63..36a04612e310 100644 --- a/test/yulPhaser/SimulationRNG.cpp +++ b/test/yulPhaser/SimulationRNG.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -28,7 +29,7 @@ using namespace std; namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(RandomTest) BOOST_AUTO_TEST_CASE(bernoulliTrial_should_produce_samples_with_right_expected_value_and_variance) diff --git a/test/yulPhaser/TestHelpers.cpp b/test/yulPhaser/TestHelpers.cpp index 2f4b40b02bbe..348973a48a24 100644 --- a/test/yulPhaser/TestHelpers.cpp +++ b/test/yulPhaser/TestHelpers.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/test/yulPhaser/TestHelpers.h b/test/yulPhaser/TestHelpers.h index 514d2eda76bd..732e4ec7a71d 100644 --- a/test/yulPhaser/TestHelpers.h +++ b/test/yulPhaser/TestHelpers.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Miscellaneous utilities for use in yul-phaser's test cases. * diff --git a/test/yulPhaser/TestHelpersTest.cpp b/test/yulPhaser/TestHelpersTest.cpp index 7fc4ef0afa90..b90d65f5e75c 100644 --- a/test/yulPhaser/TestHelpersTest.cpp +++ b/test/yulPhaser/TestHelpersTest.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include @@ -34,7 +35,7 @@ namespace fs = boost::filesystem; namespace solidity::phaser::test { -BOOST_AUTO_TEST_SUITE(Phaser) +BOOST_AUTO_TEST_SUITE(Phaser, *boost::unit_test::label("nooptions")) BOOST_AUTO_TEST_SUITE(TestHelpersTest) BOOST_AUTO_TEST_CASE(ChromosomeLengthMetric_evaluate_should_return_chromosome_length) diff --git a/tools/solidityUpgrade/SourceTransform.h b/tools/solidityUpgrade/SourceTransform.h index a33a1d97ed15..57181198390d 100644 --- a/tools/solidityUpgrade/SourceTransform.h +++ b/tools/solidityUpgrade/SourceTransform.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/solidityUpgrade/SourceUpgrade.cpp b/tools/solidityUpgrade/SourceUpgrade.cpp index 7005fd336155..5379f4b705a0 100644 --- a/tools/solidityUpgrade/SourceUpgrade.cpp +++ b/tools/solidityUpgrade/SourceUpgrade.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/tools/solidityUpgrade/SourceUpgrade.h b/tools/solidityUpgrade/SourceUpgrade.h index 9ace60e575af..e5ad378b3326 100644 --- a/tools/solidityUpgrade/SourceUpgrade.h +++ b/tools/solidityUpgrade/SourceUpgrade.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/tools/solidityUpgrade/Upgrade050.cpp b/tools/solidityUpgrade/Upgrade050.cpp index 18a495080819..8e1a2f0273ff 100644 --- a/tools/solidityUpgrade/Upgrade050.cpp +++ b/tools/solidityUpgrade/Upgrade050.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/tools/solidityUpgrade/Upgrade050.h b/tools/solidityUpgrade/Upgrade050.h index 58670e7b2096..a678b04e5a6e 100644 --- a/tools/solidityUpgrade/Upgrade050.h +++ b/tools/solidityUpgrade/Upgrade050.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/tools/solidityUpgrade/Upgrade060.cpp b/tools/solidityUpgrade/Upgrade060.cpp index 30214ddfccfd..58aa94d15fbd 100644 --- a/tools/solidityUpgrade/Upgrade060.cpp +++ b/tools/solidityUpgrade/Upgrade060.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/tools/solidityUpgrade/Upgrade060.h b/tools/solidityUpgrade/Upgrade060.h index e2386d104b66..9a8880b9628c 100644 --- a/tools/solidityUpgrade/Upgrade060.h +++ b/tools/solidityUpgrade/Upgrade060.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/tools/solidityUpgrade/UpgradeChange.cpp b/tools/solidityUpgrade/UpgradeChange.cpp index a897a4e130dc..a4036f77535e 100644 --- a/tools/solidityUpgrade/UpgradeChange.cpp +++ b/tools/solidityUpgrade/UpgradeChange.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/tools/solidityUpgrade/UpgradeSuite.h b/tools/solidityUpgrade/UpgradeSuite.h index b9b094e70e43..33aeb40ebab9 100644 --- a/tools/solidityUpgrade/UpgradeSuite.h +++ b/tools/solidityUpgrade/UpgradeSuite.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once #include diff --git a/tools/solidityUpgrade/main.cpp b/tools/solidityUpgrade/main.cpp index 0f2b7a473500..d13639b9af85 100644 --- a/tools/solidityUpgrade/main.cpp +++ b/tools/solidityUpgrade/main.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/tools/yulPhaser/AlgorithmRunner.cpp b/tools/yulPhaser/AlgorithmRunner.cpp index 402735e0d2c3..d5ad75575c54 100644 --- a/tools/yulPhaser/AlgorithmRunner.cpp +++ b/tools/yulPhaser/AlgorithmRunner.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/AlgorithmRunner.h b/tools/yulPhaser/AlgorithmRunner.h index 4326ce227b5e..71f71bb3d1b7 100644 --- a/tools/yulPhaser/AlgorithmRunner.h +++ b/tools/yulPhaser/AlgorithmRunner.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Contains the implementation of a class that manages the execution of a genetic algorithm. */ diff --git a/tools/yulPhaser/Chromosome.cpp b/tools/yulPhaser/Chromosome.cpp index 832c2cf804b8..453c62d39a30 100644 --- a/tools/yulPhaser/Chromosome.cpp +++ b/tools/yulPhaser/Chromosome.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Chromosome.h b/tools/yulPhaser/Chromosome.h index 7d8f1b912dfa..95f3ae58e656 100644 --- a/tools/yulPhaser/Chromosome.h +++ b/tools/yulPhaser/Chromosome.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/yulPhaser/Common.cpp b/tools/yulPhaser/Common.cpp index aa7ba85b5c26..a23210172d49 100644 --- a/tools/yulPhaser/Common.cpp +++ b/tools/yulPhaser/Common.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Common.h b/tools/yulPhaser/Common.h index c37afa2fbd22..b2164cc9ee3d 100644 --- a/tools/yulPhaser/Common.h +++ b/tools/yulPhaser/Common.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Miscellaneous utilities for use in yul-phaser. */ diff --git a/tools/yulPhaser/Exceptions.h b/tools/yulPhaser/Exceptions.h index 6807d7180c1c..e4aa19b52736 100644 --- a/tools/yulPhaser/Exceptions.h +++ b/tools/yulPhaser/Exceptions.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/yulPhaser/FitnessMetrics.cpp b/tools/yulPhaser/FitnessMetrics.cpp index 134c13dfcef7..66c79fda2223 100644 --- a/tools/yulPhaser/FitnessMetrics.cpp +++ b/tools/yulPhaser/FitnessMetrics.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/FitnessMetrics.h b/tools/yulPhaser/FitnessMetrics.h index 50f4c896feb8..f881df7a583a 100644 --- a/tools/yulPhaser/FitnessMetrics.h +++ b/tools/yulPhaser/FitnessMetrics.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Contains an abstract base class representing a fitness metric and its concrete implementations. */ diff --git a/tools/yulPhaser/GeneticAlgorithms.cpp b/tools/yulPhaser/GeneticAlgorithms.cpp index 4a90503aa1fd..907703738ad2 100644 --- a/tools/yulPhaser/GeneticAlgorithms.cpp +++ b/tools/yulPhaser/GeneticAlgorithms.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include diff --git a/tools/yulPhaser/GeneticAlgorithms.h b/tools/yulPhaser/GeneticAlgorithms.h index f6c809a8b6de..58dc83b95deb 100644 --- a/tools/yulPhaser/GeneticAlgorithms.h +++ b/tools/yulPhaser/GeneticAlgorithms.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Contains an abstract base class representing a genetic algorithm and its concrete implementations. */ diff --git a/tools/yulPhaser/Mutations.cpp b/tools/yulPhaser/Mutations.cpp index f2876e395ab9..f9d51744eac4 100644 --- a/tools/yulPhaser/Mutations.cpp +++ b/tools/yulPhaser/Mutations.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Mutations.h b/tools/yulPhaser/Mutations.h index 04e7050afda5..abdc4b10c753 100644 --- a/tools/yulPhaser/Mutations.h +++ b/tools/yulPhaser/Mutations.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Mutation and crossover operators for use in genetic algorithms. */ diff --git a/tools/yulPhaser/PairSelections.cpp b/tools/yulPhaser/PairSelections.cpp index 8934c3e1789c..cce99cef5c6d 100644 --- a/tools/yulPhaser/PairSelections.cpp +++ b/tools/yulPhaser/PairSelections.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/PairSelections.h b/tools/yulPhaser/PairSelections.h index a80fff8972be..2a4144bcb71a 100644 --- a/tools/yulPhaser/PairSelections.h +++ b/tools/yulPhaser/PairSelections.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Contains an abstract base class representing a selection of pairs of elements from a collection * and its concrete implementations. diff --git a/tools/yulPhaser/Phaser.cpp b/tools/yulPhaser/Phaser.cpp index 731560fe6162..589ff93a80f4 100644 --- a/tools/yulPhaser/Phaser.cpp +++ b/tools/yulPhaser/Phaser.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Phaser.h b/tools/yulPhaser/Phaser.h index 8ba5fc938367..20a47a3a56a5 100644 --- a/tools/yulPhaser/Phaser.h +++ b/tools/yulPhaser/Phaser.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Contains the main class that controls yul-phaser based on command-line parameters and * associated factories for building instances of phaser's components. diff --git a/tools/yulPhaser/Population.cpp b/tools/yulPhaser/Population.cpp index 1b846122e34f..c4b50636991a 100644 --- a/tools/yulPhaser/Population.cpp +++ b/tools/yulPhaser/Population.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Population.h b/tools/yulPhaser/Population.h index c405f702ce9a..b8cde75cc377 100644 --- a/tools/yulPhaser/Population.h +++ b/tools/yulPhaser/Population.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/yulPhaser/Program.cpp b/tools/yulPhaser/Program.cpp index 2fd29f51a516..a1d79f75aa87 100644 --- a/tools/yulPhaser/Program.cpp +++ b/tools/yulPhaser/Program.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Program.h b/tools/yulPhaser/Program.h index b96843ee4c27..12026805b217 100644 --- a/tools/yulPhaser/Program.h +++ b/tools/yulPhaser/Program.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/yulPhaser/ProgramCache.cpp b/tools/yulPhaser/ProgramCache.cpp index b174ad07f397..351532aa74fa 100644 --- a/tools/yulPhaser/ProgramCache.cpp +++ b/tools/yulPhaser/ProgramCache.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/ProgramCache.h b/tools/yulPhaser/ProgramCache.h index 25c796a3d241..d0e51a37ef4f 100644 --- a/tools/yulPhaser/ProgramCache.h +++ b/tools/yulPhaser/ProgramCache.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/yulPhaser/Selections.cpp b/tools/yulPhaser/Selections.cpp index 920a7d7f1af2..e34c80eaf2a8 100644 --- a/tools/yulPhaser/Selections.cpp +++ b/tools/yulPhaser/Selections.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/Selections.h b/tools/yulPhaser/Selections.h index a0ed2657f0c1..a643b9a220de 100644 --- a/tools/yulPhaser/Selections.h +++ b/tools/yulPhaser/Selections.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 /** * Contains an abstract base class representing a selection of elements from a collection * and its concrete implementations. diff --git a/tools/yulPhaser/SimulationRNG.cpp b/tools/yulPhaser/SimulationRNG.cpp index 26f438909718..7a73f81ad962 100644 --- a/tools/yulPhaser/SimulationRNG.cpp +++ b/tools/yulPhaser/SimulationRNG.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include diff --git a/tools/yulPhaser/SimulationRNG.h b/tools/yulPhaser/SimulationRNG.h index d16189f9ebca..7e5cc14422f4 100644 --- a/tools/yulPhaser/SimulationRNG.h +++ b/tools/yulPhaser/SimulationRNG.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #pragma once diff --git a/tools/yulPhaser/main.cpp b/tools/yulPhaser/main.cpp index d0c00fcdace1..1ec936dd4397 100644 --- a/tools/yulPhaser/main.cpp +++ b/tools/yulPhaser/main.cpp @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ +// SPDX-License-Identifier: GPL-3.0 #include #include