diff options
206 files changed, 6530 insertions, 1728 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index a2e34b37..e3596d2b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -200,7 +200,7 @@ jobs: command: build/test/soltest -t 'syntaxTest*' -- --no-ipc --testpath test - run: name: Coverage of type checker - command: codecov --flags type_checker --gcov-root build + command: codecov --flags syntax --gcov-root build - run: *run_tests - run: name: Coverage of all diff --git a/.editorconfig b/.editorconfig index 86a837c1..7b8a7be9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,7 @@ trim_trailing_whitespace = true [*.{cpp,h}] indent_style = tab +indent_size = 4 [*.{py,rst,sh,yml}] indent_style = space diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..196cbb32 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug Report +about: Bug reports about the Solidity Compiler. +--- + +## Prerequisites + +- First, many thanks for taking part in the community. We really appreciate that. +- We realize there is a lot of data requested here. We ask only that you do your best to provide as much information as possible so we can better help you. +- Support questions are better asked in one of the following locations: + - [Solidity chat](https://gitter.im/ethereum/solidity) + - [Stack Overflow](https://ethereum.stackexchange.com/) +- Ensure the issue isn't already reported. +- The issue should be reproducible with the latest solidity version , however, this isn't a hard requirement and being reproducible with an older version is sufficient. + +*Delete the above section and the instructions in the sections below before submitting* + +## Description + +Please shortly describe the bug you have found, and what you expect instead. + +## Environment + +- Compiler version: +- Framework/IDE (e.g. Truffle or Remix): +- EVM execution environment / backend / blockchain client: +- Operating system: + +## Steps to Reproduce + +Please provide a *minimal* source code example to trigger the bug you have found. +Please also mention any command line flags that are necessary for triggering the bug. +Provide as much information as necessary to reproduce the bug. + +``` +// Some *minimal* Solidity source code to reproduce the bug. +// ... +``` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..6b98fb99 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,37 @@ +--- +name: Feature Request +about: Solidity language or infrastructure feature requests. +--- + +## Prerequisites + +- First, many thanks for taking part in the community. We really appreciate that. +- We realize there is a lot of data requested here. We ask only that you do your best to provide as much information as possible so we can better help you. +- Support questions are better asked in one of the following locations: + - [Solidity chat](https://gitter.im/ethereum/solidity) + - [Stack Overflow](https://ethereum.stackexchange.com/) +- Ensure the issue isn't already reported (check `feature` and `language design` labels). + +*Delete the above section and the instructions in the sections below before submitting* + +## Abstract + +Please describe by example what problem you see in the current Solidity language +and reason about it. + +## Motivation + +In this section you describe how you propose to address the problem you described earlier, +including by giving one or more exemplary source code snippets for demonstration. + +## Specification + +The technical specification should describe the syntax and semantics of any new feature. The +specification should be detailed enough to allow any developer to implement the functionality. + +## Backwards Compatibility + +All language changes that introduce backwards incompatibilities must include a section describing +these incompatibilities and their severity. + +Please describe how you propose to deal with these incompatibilities. diff --git a/.github/ISSUE_TEMPLATE/general.md b/.github/ISSUE_TEMPLATE/general.md new file mode 100644 index 00000000..2d277865 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/general.md @@ -0,0 +1,19 @@ +--- +name: General Feedback +about: Any general feedback (neither feature request nor bug reports) +--- + +## Prerequisites + +- First, many thanks for taking part in the community. We really appreciate that. +- Read the [contributing guidelines](http://solidity.readthedocs.io/en/latest/contributing.html). +- Support questions are better asked in one of the following locations: + - [Solidity chat](https://gitter.im/ethereum/solidity) + - [Stack Overflow](https://ethereum.stackexchange.com/) +- Ensure the issue isn't already reported. + +*Delete the above section and the instructions in the sections below before submitting* + +## Description + +Please describe the purpose of your ticket. diff --git a/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 43f82f50..6f544bc1 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,9 +6,10 @@ Please also note that this project is released with a [Contributor Code of Condu ### Checklist - [ ] Code compiles correctly -- [ ] All tests passing -- [ ] Created tests which fail without the change (if possible) -- [ ] Extended the README / documentation, if necessary +- [ ] All tests are passing +- [ ] New tests have been created which fail without the change (if possible) +- [ ] README / documentation was extended, if necessary +- [ ] Changelog entry (if change is visible to the user) - [ ] Used meaningful commit messages ### Description diff --git a/Changelog.md b/Changelog.md index c21f0ae9..539d8c61 100644 --- a/Changelog.md +++ b/Changelog.md @@ -17,6 +17,7 @@ Breaking Changes: * Commandline interface: Remove obsolete ``--formal`` option. * Commandline interface: Rename the ``--julia`` option to ``--yul``. * Commandline interface: Require ``-`` if standard input is used as source. + * Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error. * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. * General: Disallow declaring empty structs. * General: Disallow raw ``callcode`` (was already deprecated in 0.4.12). It is still possible to use it via inline assembly. @@ -32,6 +33,8 @@ Breaking Changes: * General: Remove assembly instruction aliases ``sha3`` and ``suicide`` * General: C99-style scoping rules are enforced now. This was already the case in the experimental 0.5.0 mode. * General: Disallow combining hex numbers with unit denominations (e.g. ``0x1e wei``). This was already the case in the experimental 0.5.0 mode. + * JSON AST: Remove ``constant`` and ``payable`` fields (the information is encoded in the ``stateMutability`` field). + * Interface: Remove "clone contract" feature. The ``--clone-bin`` and ``--combined-json clone-bin`` commandline options are not available anymore. * Name Resolver: Do not exclude public state variables when looking for conflicting declarations. * Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence. * Parser: Disallow trailing dots that are not followed by a number. @@ -53,7 +56,8 @@ Breaking Changes: * Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode. * Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode. * Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract. - * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. + * Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore. + * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. * References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Named return values in function types are an error. @@ -65,6 +69,7 @@ Language Features: * General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions. * General: Support ``pop()`` for storage arrays. * General: Scoping rules now follow the C99-style. + * General: Allow ``enum``s in interfaces. Compiler Features: * C API (``libsolc``): Export the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods. @@ -75,10 +80,18 @@ Compiler Features: Bugfixes: * Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum. * Code Generator: Fix allocation of byte arrays (zeroed out too much memory). + * Code Generator: Properly handle negative number literals in ABIEncoderV2. + * Commandline Interface: Correctly handle paths with backslashes on windows. * Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions. + * References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own. * References Resolver: Enforce ``storage`` as data location for mappings. + * References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``. * References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter. + * Type Checker: Disallow assignments to mappings within tuple assignments as well. + * Type Checker: Allow assignments to local variables of mapping types. * Type Checker: Consider fixed size arrays when checking for recursive structs. + * Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined. + * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. * Type System: Allow arbitrary exponents for literals with a mantissa of zero. ### 0.4.24 (2018-05-16) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index ee8cb1b3..b0786ce2 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -36,13 +36,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA add_compile_options(-Wextra) add_compile_options(-Werror) - # Disable warnings about unknown pragmas (which is enabled by -Wall). I assume we have external - # dependencies (probably Boost) which have some of these. Whatever the case, we shouldn't be - # disabling these globally. Instead, we should pragma around just the problem #includes. - # - # TODO - Track down what breaks if we do NOT do this. - add_compile_options(-Wno-unknown-pragmas) - # Configuration-specific compiler settings. set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") @@ -73,13 +66,13 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA # TODO - Is this even necessary? Why? # See http://stackoverflow.com/questions/19774778/when-is-it-necessary-to-use-use-the-flag-stdlib-libstdc. add_compile_options(-stdlib=libstdc++) - + # Tell Boost that we're using Clang's libc++. Not sure exactly why we need to do. add_definitions(-DBOOST_ASIO_HAS_CLANG_LIBCXX) - + # Use fancy colors in the compiler diagnostics add_compile_options(-fcolor-diagnostics) - + # See "How to silence unused command line argument error with clang without disabling it?" # When using -Werror with clang, it transforms "warning: argument unused during compilation" messages # into errors, which makes sense. @@ -146,9 +139,6 @@ endif () if (SANITIZE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=${SANITIZE}") - if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/sanitizer-blacklist.txt") - endif() endif() # Code coverage support. diff --git a/cmake/EthOptions.cmake b/cmake/EthOptions.cmake index b4efd6c9..a79e5135 100644 --- a/cmake/EthOptions.cmake +++ b/cmake/EthOptions.cmake @@ -2,7 +2,7 @@ macro(configure_project) set(NAME ${PROJECT_NAME}) # features - eth_default_option(PROFILING OFF) + eth_default_option(COVERAGE OFF) # components eth_default_option(TESTS ON) @@ -27,7 +27,7 @@ macro(print_config NAME) message("-- CMAKE_BUILD_TYPE Build type ${CMAKE_BUILD_TYPE}") message("-- TARGET_PLATFORM Target platform ${CMAKE_SYSTEM_NAME}") message("--------------------------------------------------------------- features") - message("-- PROFILING Profiling support ${PROFILING}") + message("-- COVERAGE Coverage support ${COVERAGE}") message("------------------------------------------------------------- components") if (SUPPORT_TESTS) message("-- TESTS Build tests ${TESTS}") diff --git a/cmake/EthPolicy.cmake b/cmake/EthPolicy.cmake index 31b09f15..4e29898c 100644 --- a/cmake/EthPolicy.cmake +++ b/cmake/EthPolicy.cmake @@ -4,32 +4,16 @@ macro (eth_policy) # link_directories() treats paths relative to the source dir. cmake_policy(SET CMP0015 NEW) - # let cmake autolink dependencies on windows - cmake_policy(SET CMP0020 NEW) + # Avoid warnings in CMake 3.0.2: + cmake_policy(SET CMP0042 NEW) + cmake_policy(SET CMP0043 NEW) - # CMake 2.8.12 and lower allowed the use of targets and files with double - # colons in target_link_libraries, - cmake_policy(SET CMP0028 OLD) + # allow VERSION argument in project() + cmake_policy(SET CMP0048 NEW) - if (${CMAKE_VERSION} VERSION_GREATER 3.0) - - # fix MACOSX_RPATH - cmake_policy(SET CMP0042 OLD) - - # ignore COMPILE_DEFINITIONS_<Config> properties - cmake_policy(SET CMP0043 OLD) - - # allow VERSION argument in project() - cmake_policy(SET CMP0048 NEW) - - endif() - - if (${CMAKE_VERSION} VERSION_GREATER 3.1) - + if (POLICY CMP0054) # do not interpret if() arguments as variables! cmake_policy(SET CMP0054 NEW) - endif() - endmacro() diff --git a/cmake/jsoncpp.cmake b/cmake/jsoncpp.cmake index e886c609..ea3218ef 100644 --- a/cmake/jsoncpp.cmake +++ b/cmake/jsoncpp.cmake @@ -10,8 +10,16 @@ set(prefix "${CMAKE_BINARY_DIR}/deps") set(JSONCPP_LIBRARY "${prefix}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}jsoncpp${CMAKE_STATIC_LIBRARY_SUFFIX}") set(JSONCPP_INCLUDE_DIR "${prefix}/include") -if(NOT MSVC) - set(JSONCPP_EXTRA_FLAGS "-std=c++11") +# TODO: Investigate why this breaks some emscripten builds and +# check whether this can be removed after updating the emscripten +# versions used in the CI runs. +if(EMSCRIPTEN) + # Do not include all flags in CMAKE_CXX_FLAGS for emscripten, + # but only use -std=c++11. Using all flags causes build failures + # at the moment. + set(JSONCPP_CXX_FLAGS -std=c++11) +else() + set(JSONCPP_CXX_FLAGS ${CMAKE_CXX_FLAGS}) endif() set(byproducts "") @@ -34,7 +42,7 @@ ExternalProject_Add(jsoncpp-project -DCMAKE_POSITION_INDEPENDENT_CODE=${BUILD_SHARED_LIBS} -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_PKGCONFIG_SUPPORT=OFF - -DCMAKE_CXX_FLAGS=${JSONCPP_EXTRA_FLAGS} + -DCMAKE_CXX_FLAGS=${JSONCPP_CXX_FLAGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${byproducts} ) diff --git a/cmake/templates/license.h.in b/cmake/templates/license.h.in index 84524a52..4f22d8f4 100644 --- a/cmake/templates/license.h.in +++ b/cmake/templates/license.h.in @@ -66,6 +66,37 @@ jsoncpp: Public Domain "license" you can re-license your copy using whatever license you like. +scanner/token: + The libsolidity/parsing/{scanner,token}.{h,cpp} files are dervied from + code originating from the V8 project licensed under the following terms: + + Copyright 2006-2012, the V8 project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + All other code is licensed under GPL version 3: )"}; diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..f20980ef --- /dev/null +++ b/codecov.yml @@ -0,0 +1,18 @@ +codecov: + branch: develop +coverage: + range: 70...100 + status: + project: + default: + target: auto + paths: "!test/" + syntax: + target: auto + paths: "libsolidity/analysis" + flags: syntax + tests: + target: auto + paths: "test/" +comment: + layout: "reach, diff, flags" diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 82c9f67a..ec84d123 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -391,7 +391,7 @@ In effect, a log entry using this ABI is described as: - ``topics[n]``: ``EVENT_INDEXED_ARGS[n - 1]`` (``EVENT_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that are indexed); - ``data``: ``abi_serialise(EVENT_NON_INDEXED_ARGS)`` (``EVENT_NON_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that are not indexed, ``abi_serialise`` is the ABI serialisation function used for returning a series of typed values from a function, as described above). -For all fixed-length Solidity types, the ``EVENT_INDEXED_ARGS`` array contains the 32-byte encoded value directly. However, for *types of dynamic length*, which include ``string``, ``bytes``, and arrays, ``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of the encoded value, rather than the encoded value directly. This allows applications to efficiently query for values of dynamic-length types (by setting the hash of the encoded value as the topic), but leaves applications unable to decode indexed values they have not queried for. For dynamic-length types, application developers face a trade-off between fast search for predetermined values (if the argument is indexed) and legibility of arbitrary values (which requires that the arguments not be indexed). Developers may overcome this tradeoff and achieve both efficient search and arbitrary legibility by defining events with two arguments — one indexed, one not — intended to hold the same value. +For all fixed-length Solidity types, the ``EVENT_INDEXED_ARGS`` array contains the 32-byte encoded value directly. However, for *types of dynamic length*, which include ``string``, ``bytes``, and arrays, ``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of the packed encoded value (see :ref:`abi_packed_mode`), rather than the encoded value directly. This allows applications to efficiently query for values of dynamic-length types (by setting the hash of the encoded value as the topic), but leaves applications unable to decode indexed values they have not queried for. For dynamic-length types, application developers face a trade-off between fast search for predetermined values (if the argument is indexed) and legibility of arbitrary values (which requires that the arguments not be indexed). Developers may overcome this tradeoff and achieve both efficient search and arbitrary legibility by defining events with two arguments — one indexed, one not — intended to hold the same value. .. _abi_json: diff --git a/docs/assembly.rst b/docs/assembly.rst index ec6ac876..91ba076a 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -21,10 +21,9 @@ often hard to address the correct stack slot and provide arguments to opcodes at point on the stack. Solidity's inline assembly tries to facilitate that and other issues arising when writing manual assembly by the following features: -* functional-style opcodes: ``mul(1, add(2, 3))`` instead of ``push1 3 push1 2 add push1 1 mul`` +* functional-style opcodes: ``mul(1, add(2, 3))`` * assembly-local variables: ``let x := add(2, 3) let y := mload(0x40) x := add(x, y)`` * access to external variables: ``function f(uint x) public { assembly { x := sub(x, 1) } }`` -* labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))`` * loops: ``for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }`` * if statements: ``if slt(x, 0) { x := sub(0, x) }`` * switch statements: ``switch x case 0 { y := mul(x, 2) } default { y := 0 }`` @@ -134,7 +133,6 @@ usual ``//`` and ``/* */`` comments. Inline assembly is marked by ``assembly { . these curly braces, the following can be used (see the later sections for more details) - literals, i.e. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters) - - opcodes (in "instruction style"), e.g. ``mload sload dup1 sstore``, for a list see below - opcodes in functional style, e.g. ``add(1, mlod(0))`` - labels, e.g. ``name:`` - variable declarations, e.g. ``let x := 7``, ``let x := add(y, 3)`` or ``let x`` (initial value of empty (0) is assigned) @@ -416,57 +414,8 @@ changes during the call, and thus references to local variables will be wrong. Labels ------ -.. note:: - Labels are deprecated. Please use functions, loops, if or switch statements instead. - -Another problem in EVM assembly is that ``jump`` and ``jumpi`` use absolute addresses -which can change easily. Solidity inline assembly provides labels to make the use of -jumps easier. Note that labels are a low-level feature and it is possible to write -efficient assembly without labels, just using assembly functions, loops, if and switch instructions -(see below). The following code computes an element in the Fibonacci series. - -.. code:: - - { - let n := calldataload(4) - let a := 1 - let b := a - loop: - jumpi(loopend, eq(n, 0)) - a add swap1 - n := sub(n, 1) - jump(loop) - loopend: - mstore(0, a) - return(0, 0x20) - } - -Please note that automatically accessing stack variables can only work if the -assembler knows the current stack height. This fails to work if the jump source -and target have different stack heights. It is still fine to use such jumps, but -you should just not access any stack variables (even assembly variables) in that case. - -Furthermore, the stack height analyser goes through the code opcode by opcode -(and not according to control flow), so in the following case, the assembler -will have a wrong impression about the stack height at label ``two``: - -.. code:: - - { - let x := 8 - jump(two) - one: - // Here the stack height is 2 (because we pushed x and 7), - // but the assembler thinks it is 1 because it reads - // from top to bottom. - // Accessing the stack variable x here will lead to errors. - x := 9 - jump(three) - two: - 7 // push something onto the stack - jump(one) - three: - } +Support for labels has been removed in version 0.5.0 of Solidity. +Please use functions, loops, if or switch statements instead. Declaring Assembly-Local Variables ---------------------------------- @@ -660,12 +609,21 @@ first. Solidity manages memory in a very simple way: There is a "free memory pointer" at position ``0x40`` in memory. If you want to allocate memory, just use the memory -from that point on and update the pointer accordingly. +starting from where this pointer points at and update it accordingly. +There is no built-in mechanism to release or free allocated memory. +Here is an assembly snippet that can be used for allocating memory:: + + function allocate(length) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, length)) + } The first 64 bytes of memory can be used as "scratch space" for short-term allocation. The 32 bytes after the free memory pointer (i.e. starting at ``0x60``) is meant to be zero permanently and is used as the initial value for empty dynamic memory arrays. +This means that the allocatable memory starts at ``0x80``, which is the initial value +of the free memory pointer. Elements in memory arrays in Solidity always occupy multiples of 32 bytes (yes, this is even true for ``byte[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory @@ -749,7 +707,7 @@ We consider the runtime bytecode of the following Solidity program:: The following assembly will be generated:: { - mstore(0x40, 0x60) // store the "free memory pointer" + mstore(0x40, 0x80) // store the "free memory pointer" // function dispatcher switch div(calldataload(0), exp(2, 226)) case 0xb3de648b { diff --git a/docs/contracts.rst b/docs/contracts.rst index 2149167b..561d2f97 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1158,7 +1158,6 @@ Interfaces are similar to abstract contracts, but they cannot have any functions - Cannot define constructor. - Cannot define variables. - Cannot define structs. -- Cannot define enums. Some of these restrictions might be lifted in the future. diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index c2df0d3a..786c3341 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -9,22 +9,12 @@ This list was originally compiled by `fivedogit <mailto:fivedogit@gmail.com>`_. Basic Questions *************** -Is it possible to do something on a specific block number? (e.g. publish a contract or execute a transaction) -============================================================================================================= - -Transactions are not guaranteed to happen on the next block or any future -specific block, since it is up to the miners to include transactions and not up -to the submitter of the transaction. This applies to function calls/transactions and contract -creation transactions. - -If you want to schedule future calls of your contract, you can use the -`alarm clock <http://www.ethereum-alarm-clock.com/>`_. - What is the transaction "payload"? ================================== This is just the bytecode "data" sent along with the request. + Create a contract that can be killed and return funds ===================================================== @@ -167,11 +157,6 @@ arguments for you. See `ping.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_ping.sol>`_ and `pong.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_pong.sol>`_. -Is unused gas automatically refunded? -===================================== - -Yes and it is immediate, i.e. done as part of the transaction. - When returning a value of say ``uint`` type, is it possible to return an ``undefined`` or "null"-like value? ============================================================================================================ @@ -229,76 +214,6 @@ No, a function call from one contract to another does not create its own transac you have to look in the overall transaction. This is also the reason why several block explorer do not show Ether sent between contracts correctly. -What is the ``memory`` keyword? What does it do? -================================================ - -The Ethereum Virtual Machine has three areas where it can store items. - -The first is "storage", where all the contract state variables reside. -Every contract has its own storage and it is persistent between function calls -and quite expensive to use. - -The second is "memory", this is used to hold temporary values. It -is erased between (external) function calls and is cheaper to use. - -The third one is the stack, which is used to hold small local variables. -It is almost free to use, but can only hold a limited amount of values. - -For almost all types, you cannot specify where they should be stored, because -they are copied every time they are used. - -The types where the so-called storage location is important are structs -and arrays. If you e.g. pass such variables in function calls, their -data is not copied if it can stay in memory or stay in storage. -This means that you can modify their content in the called function -and these modifications will still be visible in the caller. - -There are defaults for the storage location depending on which type -of variable it concerns: - -* state variables are always in storage -* function arguments are in memory by default -* local variables of mapping type reference storage by default -* local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack - -For local variables of struct or array type the storage location has to be stated explicitly. - -Example:: - - pragma solidity ^0.4.0; - - contract C { - uint[] data1; - uint[] data2; - - function appendOne() public { - append(data1); - } - - function appendTwo() public { - append(data2); - } - - function append(uint[] storage d) internal { - d.push(1); - } - } - -The function ``append`` can work both on ``data1`` and ``data2`` and its modifications will be -stored permanently. If you remove the ``storage`` keyword, the default -is to use ``memory`` for function arguments. This has the effect that -at the point where ``append(data1)`` or ``append(data2)`` is called, an -independent copy of the state variable is created in memory and -``append`` operates on this copy (which does not support ``.push`` - but that -is another issue). The modifications to this independent copy do not -carry back to ``data1`` or ``data2``. - -.. warning:: - Prior to version 0.5.0, a common mistake was to declare a local variable and assume that it will - be created in memory, although it will be created in storage. Using such a variable without initializing - could lead to unexpected behavior. Starting from 0.5.0, however, the storage location for local variables - has to be specified explicitly and local storage variables have to be initialized, which should prevent - these kinds of mistakes. ****************** Advanced Questions diff --git a/docs/index.rst b/docs/index.rst index 75af4827..af27d534 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -125,6 +125,9 @@ Solidity Tools * `evmdis <https://github.com/Arachnid/evmdis>`_ EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. +* `ABI to solidity interface converter <https://gist.github.com/chriseth/8f533d133fa0c15b0d6eaf3ec502c82b>`_ + A script for generating contract interfaces from the ABI of a smart contract. + .. note:: Information like variable names, comments, and source code formatting is lost in the compilation process and it is not possible to completely recover the original source code. Decompiling smart contracts to view the original source code might not be possible, or the end result that useful. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index e1b61d8b..f5769363 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -260,6 +260,10 @@ blocks that are added on top, the less likely it is. So it might be that your tr are reverted and even removed from the blockchain, but the longer you wait, the less likely it will be. +.. note:: + Transactions are not guaranteed to happen on the next block or any future specific block, since it is up to the miners to include transactions and not the submitter of the transaction. This applies to function calls and contract creation transactions alike. + + If you want to schedule future calls of your contract, you can use the `alarm clock <http://www.ethereum-alarm-clock.com/>`_ service. .. _the-ethereum-virtual-machine: @@ -352,19 +356,21 @@ If the gas is used up at any point (i.e. it is negative), an out-of-gas exception is triggered, which reverts all modifications made to the state in the current call frame. +Any unused gas is refunded at the end of the transaction. + .. index:: ! storage, ! memory, ! stack Storage, Memory and the Stack ============================= -Each account has a persistent memory area which is called **storage**. +The Ethereum Virtual Machine has three areas where it can store data. + +Each account has a data area called **storage**, which is persistent between function calls. Storage is a key-value store that maps 256-bit words to 256-bit words. -It is not possible to enumerate storage from within a contract -and it is comparatively costly to read and even more so, to modify -storage. A contract can neither read nor write to any storage apart -from its own. +It is not possible to enumerate storage from within a contract and it is comparatively costly to read, and even more to modify storage. +A contract can neither read nor write to any storage apart from its own. -The second memory area is called **memory**, of which a contract obtains +The second data area is called **memory**, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when @@ -373,7 +379,7 @@ within a word). At the time of expansion, the cost in gas must be paid. Memory i costly the larger it grows (it scales quadratically). The EVM is not a register machine but a stack machine, so all -computations are performed on an area called the **stack**. It has a maximum size of +computations are performed on an data area called the **stack**. It has a maximum size of 1024 elements and contains words of 256 bits. Access to the stack is limited to the top end in the following way: It is possible to copy one of @@ -412,7 +418,7 @@ a top-level message call which in turn can create further message calls. A contract can decide how much of its remaining **gas** should be sent with the inner message call and how much it wants to retain. If an out-of-gas exception happens in the inner call (or any -other exception), this will be signalled by an error value put onto the stack. +other exception), this will be signaled by an error value put onto the stack. In this case, only the gas sent together with the call is used up. In Solidity, the calling contract causes a manual exception by default in such situations, so that exceptions "bubble up" the call stack. @@ -470,21 +476,17 @@ these **create calls** and normal message calls is that the payload data is executed and the result stored as code and the caller / creator receives the address of the new contract on the stack. -.. index:: selfdestruct +.. index:: selfdestruct, self-destruct, deactivate -Self-destruct -============= +Deactivate and Self-destruct +============================ -The only possibility that code is removed from the blockchain is -when a contract at that address performs the ``selfdestruct`` operation. -The remaining Ether stored at that address is sent to a designated -target and then the storage and code is removed from the state. +The only way to remove code from the blockchain is when a contract at that address performs the ``selfdestruct`` operation. The remaining Ether stored at that address is sent to a designated target and then the storage and code is removed from the state. Removing the contract in theory sounds like a good idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost. -.. warning:: Even if a contract's code does not contain a call to ``selfdestruct``, - it can still perform that operation using ``delegatecall`` or ``callcode``. +.. note:: + Even if a contract's code does not contain a call to ``selfdestruct``, it can still perform that operation using ``delegatecall`` or ``callcode``. -.. note:: The pruning of old contracts may or may not be implemented by Ethereum - clients. Additionally, archive nodes could choose to keep the contract storage - and code indefinitely. +If you want to deactivate your contracts, you should instead **disable** them by changing some internal state which causes all functions to revert. This makes it impossible to use the contract, as it returns Ether immediately. -.. note:: Currently **external accounts** cannot be removed from the state. +.. warning:: + Even if a contract is removed by "selfdestruct", it is still part of the history of the blockchain and probably retained by most Ethereum nodes. So using "selfdestruct" is not the same as deleting data from a hard disk. diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 19e3aae5..53e126b4 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -229,7 +229,7 @@ Import statements should always be placed at the top of the file. Yes:: - import "owned"; + import "./Owned.sol"; contract A { @@ -237,7 +237,7 @@ Yes:: } - contract B is owned { + contract B is Owned { ... } @@ -248,10 +248,10 @@ No:: } - import "owned"; + import "./Owned.sol"; - contract B is owned { + contract B is Owned { ... } @@ -867,7 +867,65 @@ indistinguishable from the numerals one and zero. Contract and Library Names ========================== -Contracts and libraries should be named using the CapWords style. Examples: ``SimpleToken``, ``SmartBank``, ``CertificateHashRepository``, ``Player``. +* Contracts and libraries should be named using the CapWords style. Examples: ``SimpleToken``, ``SmartBank``, ``CertificateHashRepository``, ``Player``, ``Congress``, ``Owned``. +* Contract and library names should also match their filenames. +* If a contract file includes multiple contracts and/or libraries, then the filename should match the *core contract*. This is not recommended however if it can be avoided. + +As shown in the example below, if the contract name is `Congress` and the library name is `Owned`, then their associated filenames should be `Congress.sol` and `Owned.sol`. + +Yes:: + + // Owned.sol + contract Owned { + address public owner; + + constructor() public { + owner = msg.sender; + } + + modifier onlyOwner { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) public onlyOwner { + owner = newOwner; + } + } + + // Congress.sol + import "./Owned.sol"; + + contract Congress is Owned, TokenRecipient { + ... + } + +No:: + + // owned.sol + contract owned { + address public owner; + + constructor() public { + owner = msg.sender; + } + + modifier onlyOwner { + require(msg.sender == owner); + _; + } + + function transferOwnership(address newOwner) public onlyOwner { + owner = newOwner; + } + } + + // Congress.sol + import "./owned.sol"; + + contract Congress is owned, tokenRecipient { + ... + } Struct Names diff --git a/docs/types.rst b/docs/types.rst index 566c4c19..fbc83972 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -104,6 +104,14 @@ Operators: * ``<=``, ``<``, ``==``, ``!=``, ``>=`` and ``>`` +.. warning:: + If you convert a type that uses a larger byte size to an ``address``, for example ``bytes32``, then the ``address`` is truncated. + To reduce conversion ambiguity version 0.4.24 and higher of the compiler force you make the truncation explicit in the conversion. + Take for example the address ``0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC``. + + You can use ``address(uint160(bytes20(b)))``, which results in ``0x111122223333444455556666777788889999aAaa``, + or you can use ``address(uint160(uint256(b)))``, which results in ``0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc``. + .. note:: Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. diff --git a/docs/yul.rst b/docs/yul.rst index 87ec0c03..87fd95eb 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -108,7 +108,7 @@ Grammar:: 'break' | 'continue' FunctionCall = Identifier '(' ( Expression ( ',' Expression )* )? ')' - Identifier = [a-zA-Z_$] [a-zA-Z_0-9]* + Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]* IdentifierList = Identifier ( ',' Identifier)* TypeName = Identifier | BuiltinTypeName BuiltinTypeName = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' ) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 2543855d..0363d9a2 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -40,7 +40,6 @@ #include <libdevcore/vector_ref.h> #if defined(__GNUC__) -#pragma warning(push) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif // defined(__GNUC__) @@ -57,7 +56,6 @@ #include <boost/multiprecision/cpp_int.hpp> #if defined(__GNUC__) -#pragma warning(pop) #pragma GCC diagnostic pop #endif // defined(__GNUC__) diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index 0063a8d4..9693d02a 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -187,3 +187,23 @@ boost::filesystem::path dev::weaklyCanonicalFilesystemPath(boost::filesystem::pa return head / tail; } } + +string dev::absolutePath(string const& _path, string const& _reference) +{ + boost::filesystem::path p(_path); + // Anything that does not start with `.` is an absolute path. + if (p.begin() == p.end() || (*p.begin() != "." && *p.begin() != "..")) + return _path; + boost::filesystem::path result(_reference); + result.remove_filename(); + for (boost::filesystem::path::iterator it = p.begin(); it != p.end(); ++it) + if (*it == "..") + result = result.parent_path(); + else if (*it != ".") + result /= *it; + return result.generic_string(); +} + +string dev::sanitizePath(string const& _path) { + return boost::filesystem::path(_path).generic_string(); +} diff --git a/libdevcore/CommonIO.h b/libdevcore/CommonIO.h index 9ba68e74..928b6d15 100644 --- a/libdevcore/CommonIO.h +++ b/libdevcore/CommonIO.h @@ -62,4 +62,10 @@ std::string toString(_T const& _t) /// Should be replaced by the boost implementation as soon as support for boost<1.60 can be dropped. boost::filesystem::path weaklyCanonicalFilesystemPath(boost::filesystem::path const &_path); +/// @returns the absolute path corresponding to @a _path relative to @a _reference. +std::string absolutePath(std::string const& _path, std::string const& _reference); + +/// Helper function to return path converted strings. +std::string sanitizePath(std::string const& _path); + } diff --git a/libdevcore/StringUtils.cpp b/libdevcore/StringUtils.cpp index 2ff86bd5..01bdc675 100644 --- a/libdevcore/StringUtils.cpp +++ b/libdevcore/StringUtils.cpp @@ -85,17 +85,11 @@ size_t dev::stringDistance(string const& _str1, string const& _str2) string dev::quotedAlternativesList(vector<string> const& suggestions) { - if (suggestions.empty()) - return ""; - if (suggestions.size() == 1) - return "\"" + suggestions.front() + "\""; + vector<string> quotedSuggestions; - string choices = "\"" + suggestions.front() + "\""; - for (size_t i = 1; i + 1 < suggestions.size(); ++i) - choices += ", \"" + suggestions[i] + "\""; + for (auto& suggestion: suggestions) + quotedSuggestions.push_back("\"" + suggestion + "\""); - choices += " or \"" + suggestions.back() + "\""; - - return choices; + return joinHumanReadable(quotedSuggestions, ", ", " or "); } diff --git a/libdevcore/StringUtils.h b/libdevcore/StringUtils.h index acd93e32..4fb5a748 100644 --- a/libdevcore/StringUtils.h +++ b/libdevcore/StringUtils.h @@ -36,4 +36,43 @@ size_t stringDistance(std::string const& _str1, std::string const& _str2); // Return a string having elements of suggestions as quoted, alternative suggestions. e.g. "a", "b" or "c" std::string quotedAlternativesList(std::vector<std::string> const& suggestions); +/// Joins collection of strings into one string with separators between, last separator can be different. +/// @param _list collection of strings to join +/// @param _separator defaults to ", " +/// @param _lastSeparator (optional) will be used to separate last two strings instead of _separator +/// @example join(vector<string>{"a", "b", "c"}, "; ", " or ") == "a; b or c" +template<class T> +std::string joinHumanReadable +( + T const& _list, + std::string const& _separator = ", ", + std::string const& _lastSeparator = "" +) +{ + auto it = begin(_list); + auto itEnd = end(_list); + + std::string result; + + // append first string + if (it != itEnd) + { + result += *it; + ++it; + } + + for (;it != itEnd; ++it) + { + if ((next(it) == itEnd) && !_lastSeparator.empty()) + result += _lastSeparator; // last iteration + else + result += _separator; + + // append string + result += *it; + } + + return result; +} + } diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index f9bbad2c..37c5fdd4 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -21,6 +21,7 @@ #include "./Instruction.h" +#include <algorithm> #include <functional> #include <libdevcore/Common.h> #include <libdevcore/CommonIO.h> @@ -325,13 +326,20 @@ void dev::solidity::eachInstruction( size_t additional = 0; if (isValidInstruction(instr)) additional = instructionInfo(instr).additional; + u256 data; - for (size_t i = 0; i < additional; ++i) + + // fill the data with the additional data bytes from the instruction stream + while (additional > 0 && next(it) < _mem.end()) { data <<= 8; - if (++it < _mem.end()) - data |= *it; + data |= *++it; + --additional; } + + // pad the remaining number of additional octets with zeros + data <<= 8 * additional; + _onInstruction(instr, data); } } diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index 8568b163..cd50550e 100644 --- a/libevmasm/KnownState.h +++ b/libevmasm/KnownState.h @@ -29,12 +29,18 @@ #include <tuple> #include <memory> #include <ostream> -#pragma warning(push) -#pragma GCC diagnostic push + +#if defined(__clang__) +#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wredeclared-class-member" +#endif // defined(__clang__) + #include <boost/bimap.hpp> -#pragma warning(pop) -#pragma GCC diagnostic pop + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif // defined(__clang__) + #include <libdevcore/CommonIO.h> #include <libdevcore/Exceptions.h> #include <libevmasm/ExpressionClasses.h> diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index 7a2bc484..0573856b 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -46,7 +46,7 @@ template <class S> S modWorkaround(S const& _a, S const& _b) /// @returns a list of simplification rules given certain match placeholders. /// A, B and C should represent constants, X and Y arbitrary expressions. -/// The simplifications should neven change the order of evaluation of +/// The simplifications should never change the order of evaluation of /// arbitrary operations. template <class Pattern> std::vector<SimplificationRule<Pattern>> simplificationRuleList( diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 3e82889a..0aef05a9 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -22,12 +22,18 @@ #include "CodeFragment.h" #include <boost/algorithm/string.hpp> -#pragma warning(push) + +#if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" +#endif // defined(__GNUC__) + #include <boost/spirit/include/support_utree.hpp> -#pragma warning(pop) + +#if defined(__GNUC__) #pragma GCC diagnostic pop +#endif // defined(__GNUC__) + #include <libdevcore/CommonIO.h> #include <libevmasm/Instruction.h> #include "CompilerState.h" diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index 6edf7986..483d08c8 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -144,12 +144,12 @@ void ControlFlowAnalyzer::checkUnassignedStorageReturnValues( ssl.append("Problematic end of function:", _function.location()); } - m_errorReporter.warning( + m_errorReporter.typeError( returnVal->location(), - "This variable is of storage pointer type and might be returned without assignment. " - "This can cause storage corruption. Assign the variable (potentially from itself) " - "to remove this warning.", - ssl + ssl, + "This variable is of storage pointer type and might be returned without assignment and " + "could be used uninitialized. Assign the variable (potentially from itself) " + "to fix this error." ); } } diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 823378c7..c5c429ce 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -231,7 +231,7 @@ vector<Declaration const*> NameAndTypeResolver::cleanedDeclarations( shared_ptr<FunctionType const> newFunctionType { d->functionType(false) }; if (!newFunctionType) newFunctionType = d->functionType(true); - return newFunctionType && functionType->hasEqualArgumentTypes(*newFunctionType); + return newFunctionType && functionType->hasEqualParameterTypes(*newFunctionType); } )) uniqueFunctions.push_back(declaration); @@ -295,10 +295,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res { setScope(contract); if (!resolveNamesAndTypes(*node, false)) - { success = false; - break; - } } if (!success) diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index a9a998b0..501521f5 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -47,7 +47,6 @@ bool ReferencesResolver::visit(Block const& _block) { if (!m_resolveInsideCode) return false; - m_experimental050Mode = _block.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); m_resolver.setScope(&_block); return true; } @@ -64,7 +63,6 @@ bool ReferencesResolver::visit(ForStatement const& _for) { if (!m_resolveInsideCode) return false; - m_experimental050Mode = _for.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); m_resolver.setScope(&_for); return true; } @@ -258,6 +256,11 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) string("_slot").size() : string("_offset").size() )); + if (realName.empty()) + { + declarationError(_identifier.location, "In variable names _slot and _offset can only be used as a suffix."); + return size_t(-1); + } declarations = m_resolver.nameFromCurrentScope(realName); } if (declarations.size() != 1) @@ -277,7 +280,7 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) // Will be re-generated later with correct information // We use the latest EVM version because we will re-run it anyway. assembly::AsmAnalysisInfo analysisInfo; - boost::optional<Error::Type> errorTypeForLoose = m_experimental050Mode ? Error::Type::SyntaxError : Error::Type::Warning; + boost::optional<Error::Type> errorTypeForLoose = Error::Type::SyntaxError; assembly::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), errorTypeForLoose, assembly::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations()); return false; } @@ -294,134 +297,138 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) if (_variable.annotation().type) return; + if (!_variable.typeName()) + { + // This can still happen in very unusual cases where a developer uses constructs, such as + // `var a;`, however, such code will have generated errors already. + // However, we cannot blindingly solAssert() for that here, as the TypeChecker (which is + // invoking ReferencesResolver) is generating it, so the error is most likely(!) generated + // after this step. + return; + } + TypePointer type; - if (_variable.typeName()) + type = _variable.typeName()->annotation().type; + using Location = VariableDeclaration::Location; + Location varLoc = _variable.referenceLocation(); + DataLocation typeLoc = DataLocation::Memory; + // References are forced to calldata for external function parameters (not return) + // and memory for parameters (also return) of publicly visible functions. + // They default to memory for function parameters and storage for local variables. + // As an exception, "storage" is allowed for library functions. + if (auto ref = dynamic_cast<ReferenceType const*>(type.get())) { - type = _variable.typeName()->annotation().type; - using Location = VariableDeclaration::Location; - Location varLoc = _variable.referenceLocation(); - DataLocation typeLoc = DataLocation::Memory; - // References are forced to calldata for external function parameters (not return) - // and memory for parameters (also return) of publicly visible functions. - // They default to memory for function parameters and storage for local variables. - // As an exception, "storage" is allowed for library functions. - if (auto ref = dynamic_cast<ReferenceType const*>(type.get())) + bool isPointer = true; + if (_variable.isExternalCallableParameter()) { - bool isPointer = true; - if (_variable.isExternalCallableParameter()) + auto const& contract = dynamic_cast<ContractDefinition const&>( + *dynamic_cast<Declaration const&>(*_variable.scope()).scope() + ); + if (contract.isLibrary()) { - auto const& contract = dynamic_cast<ContractDefinition const&>( - *dynamic_cast<Declaration const&>(*_variable.scope()).scope() - ); - if (contract.isLibrary()) - { - if (varLoc == Location::Memory) - fatalTypeError(_variable.location(), - "Location has to be calldata or storage for external " - "library functions (remove the \"memory\" keyword)." - ); - } - else - { - // force location of external function parameters (not return) to calldata - if (varLoc != Location::CallData && varLoc != Location::Default) - fatalTypeError(_variable.location(), - "Location has to be calldata for external functions " - "(remove the \"memory\" or \"storage\" keyword)." - ); - } - if (varLoc == Location::Default) - typeLoc = DataLocation::CallData; - else - typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; + if (varLoc == Location::Memory) + fatalTypeError(_variable.location(), + "Location has to be calldata or storage for external " + "library functions (remove the \"memory\" keyword)." + ); } - else if (_variable.isCallableParameter() && dynamic_cast<Declaration const&>(*_variable.scope()).isPublic()) + else { - auto const& contract = dynamic_cast<ContractDefinition const&>( - *dynamic_cast<Declaration const&>(*_variable.scope()).scope() + // force location of external function parameters (not return) to calldata + if (varLoc != Location::CallData && varLoc != Location::Default) + fatalTypeError(_variable.location(), + "Location has to be calldata for external functions " + "(remove the \"memory\" or \"storage\" keyword)." + ); + } + if (varLoc == Location::Default) + typeLoc = DataLocation::CallData; + else + typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; + } + else if (_variable.isCallableParameter() && dynamic_cast<Declaration const&>(*_variable.scope()).isPublic()) + { + auto const& contract = dynamic_cast<ContractDefinition const&>( + *dynamic_cast<Declaration const&>(*_variable.scope()).scope() + ); + // force locations of public or external function (return) parameters to memory + if (varLoc != Location::Memory && varLoc != Location::Default && !contract.isLibrary()) + fatalTypeError(_variable.location(), + "Location has to be memory for publicly visible functions " + "(remove the \"storage\" or \"calldata\" keyword)." ); - // force locations of public or external function (return) parameters to memory - if (varLoc != Location::Memory && varLoc != Location::Default && !contract.isLibrary()) + if (varLoc == Location::Default || !contract.isLibrary()) + typeLoc = DataLocation::Memory; + else + { + if (varLoc == Location::CallData) fatalTypeError(_variable.location(), - "Location has to be memory for publicly visible functions " - "(remove the \"storage\" or \"calldata\" keyword)." + "Location cannot be calldata for non-external functions " + "(remove the \"calldata\" keyword)." ); - if (varLoc == Location::Default || !contract.isLibrary()) + typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; + } + } + else + { + if (_variable.isConstant()) + { + if (varLoc != Location::Default && varLoc != Location::Memory) + fatalTypeError( + _variable.location(), + "Data location has to be \"memory\" (or unspecified) for constants." + ); + typeLoc = DataLocation::Memory; + } + else if (varLoc == Location::Default) + { + if (_variable.isCallableParameter()) typeLoc = DataLocation::Memory; else { - if (varLoc == Location::CallData) - fatalTypeError(_variable.location(), - "Location cannot be calldata for non-external functions " - "(remove the \"calldata\" keyword)." + typeLoc = DataLocation::Storage; + if (_variable.isLocalVariable()) + typeError( + _variable.location(), + "Data location must be specified as either \"memory\" or \"storage\"." ); - typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage; } } else { - if (_variable.isConstant()) + switch (varLoc) { - if (varLoc != Location::Default && varLoc != Location::Memory) - fatalTypeError( - _variable.location(), - "Data location has to be \"memory\" (or unspecified) for constants." - ); + case Location::Memory: typeLoc = DataLocation::Memory; + break; + case Location::Storage: + typeLoc = DataLocation::Storage; + break; + case Location::CallData: + fatalTypeError(_variable.location(), + "Variable cannot be declared as \"calldata\" (remove the \"calldata\" keyword)." + ); + break; + default: + solAssert(false, "Unknown data location"); } - else if (varLoc == Location::Default) - { - if (_variable.isCallableParameter()) - typeLoc = DataLocation::Memory; - else - { - typeLoc = DataLocation::Storage; - if (_variable.isLocalVariable()) - typeError( - _variable.location(), - "Data location must be specified as either \"memory\" or \"storage\"." - ); - } - } - else - { - switch (varLoc) - { - case Location::Memory: - typeLoc = DataLocation::Memory; - break; - case Location::Storage: - typeLoc = DataLocation::Storage; - break; - case Location::CallData: - fatalTypeError(_variable.location(), - "Variable cannot be declared as \"calldata\" (remove the \"calldata\" keyword)." - ); - break; - default: - solAssert(false, "Unknown data location"); - } - } - isPointer = !_variable.isStateVariable(); } - type = ref->copyForLocation(typeLoc, isPointer); + isPointer = !_variable.isStateVariable(); } - else if (dynamic_cast<MappingType const*>(type.get())) - { - if (_variable.isLocalVariable() && varLoc != Location::Storage) - typeError( - _variable.location(), - "Data location for mappings must be specified as \"storage\"." - ); - } - else if (varLoc != Location::Default && !ref) - typeError(_variable.location(), "Data location can only be given for array or struct types."); - - _variable.annotation().type = type; + type = ref->copyForLocation(typeLoc, isPointer); } - else if (!_variable.canHaveAutoType()) - typeError(_variable.location(), "Explicit type needed."); - // otherwise we have a "var"-declaration whose type is resolved by the first assignment + else if (dynamic_cast<MappingType const*>(type.get())) + { + if (_variable.isLocalVariable() && varLoc != Location::Storage) + typeError( + _variable.location(), + "Data location for mappings must be specified as \"storage\"." + ); + } + else if (varLoc != Location::Default && !ref) + typeError(_variable.location(), "Data location can only be given for array or struct types."); + + _variable.annotation().type = type; } void ReferencesResolver::typeError(SourceLocation const& _location, string const& _description) diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 4e8f54b5..24ec4643 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -94,7 +94,6 @@ private: std::vector<ParameterList const*> m_returnParameters; bool const m_resolveInsideCode; bool m_errorOccurred = false; - bool m_experimental050Mode = false; }; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8f504ffe..bd3187ae 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -214,7 +214,7 @@ void TypeChecker::findDuplicateDefinitions(map<string, vector<T>> const& _defini SecondarySourceLocation ssl; for (size_t j = i + 1; j < overloads.size(); ++j) - if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j]))) + if (FunctionType(*overloads[i]).hasEqualParameterTypes(FunctionType(*overloads[j]))) { ssl.append("Other declaration is here:", overloads[j]->location()); reported.insert(j); @@ -252,7 +252,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont FunctionTypePointer funType = make_shared<FunctionType>(*function); auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) { - return funType->hasEqualArgumentTypes(*_funAndFlag.first); + return funType->hasEqualParameterTypes(*_funAndFlag.first); }); if (it == overloads.end()) overloads.push_back(make_pair(funType, function->isImplemented())); @@ -404,7 +404,7 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& function, Func FunctionType functionType(function); FunctionType superType(super); - if (!functionType.hasEqualArgumentTypes(superType)) + if (!functionType.hasEqualParameterTypes(superType)) return; if (!function.annotation().superFunction) @@ -475,7 +475,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co for (auto const& it: externalDeclarations) for (size_t i = 0; i < it.second.size(); ++i) for (size_t j = i + 1; j < it.second.size(); ++j) - if (!it.second[i].second->hasEqualArgumentTypes(*it.second[j].second)) + if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second)) m_errorReporter.typeError( it.second[j].first->location(), "Function overload clash during conversion to external types for arguments." @@ -498,7 +498,12 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment) TupleType const& lhs = dynamic_cast<TupleType const&>(*type(_assignment.leftHandSide())); TupleType const& rhs = dynamic_cast<TupleType const&>(*type(_assignment.rightHandSide())); - bool fillRight = !lhs.components().empty() && (!lhs.components().back() || lhs.components().front()); + if (lhs.components().size() != rhs.components().size()) + { + solAssert(m_errorReporter.hasErrors(), ""); + return; + } + size_t storageToStorageCopies = 0; size_t toStorageCopies = 0; for (size_t i = 0; i < lhs.components().size(); ++i) @@ -506,10 +511,8 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment) ReferenceType const* ref = dynamic_cast<ReferenceType const*>(lhs.components()[i].get()); if (!ref || !ref->dataStoredIn(DataLocation::Storage) || ref->isPointer()) continue; - size_t rhsPos = fillRight ? i : rhs.components().size() - (lhs.components().size() - i); - solAssert(rhsPos < rhs.components().size(), ""); toStorageCopies++; - if (rhs.components()[rhsPos]->dataStoredIn(DataLocation::Storage)) + if (rhs.components()[i]->dataStoredIn(DataLocation::Storage)) storageToStorageCopies++; } if (storageToStorageCopies >= 1 && toStorageCopies >= 2) @@ -751,13 +754,6 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) return false; } -bool TypeChecker::visit(EnumDefinition const& _enum) -{ - if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface) - m_errorReporter.typeError(_enum.location(), "Enumerable cannot be declared in interfaces."); - return false; -} - void TypeChecker::visitManually( ModifierInvocation const& _modifier, vector<ContractDefinition const*> const& _bases @@ -817,6 +813,7 @@ void TypeChecker::visitManually( bool TypeChecker::visit(EventDefinition const& _eventDef) { + solAssert(_eventDef.visibility() > Declaration::Visibility::Internal, ""); unsigned numIndexed = 0; for (ASTPointer<VariableDeclaration> const& var: _eventDef.parameters()) { @@ -826,6 +823,15 @@ bool TypeChecker::visit(EventDefinition const& _eventDef) m_errorReporter.typeError(var->location(), "Type is required to live outside storage."); if (!type(*var)->interfaceType(false)) m_errorReporter.typeError(var->location(), "Internal or recursive type is not allowed as event parameter type."); + if ( + !_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) && + !typeSupportedByOldABIEncoder(*type(*var)) + ) + m_errorReporter.typeError( + var->location(), + "This type is only supported in the new experimental ABI encoder. " + "Use \"pragma experimental ABIEncoderV2;\" to enable the feature." + ); } if (_eventDef.isAnonymous() && numIndexed > 4) m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event."); @@ -857,6 +863,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) return size_t(-1); Declaration const* declaration = ref->second.declaration; solAssert(!!declaration, ""); + bool requiresStorage = ref->second.isSlot || ref->second.isOffset; if (auto var = dynamic_cast<VariableDeclaration const*>(declaration)) { if (var->isConstant()) @@ -864,7 +871,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) m_errorReporter.typeError(_identifier.location, "Constant variables not supported by inline assembly."); return size_t(-1); } - else if (ref->second.isSlot || ref->second.isOffset) + else if (requiresStorage) { if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage)) { @@ -896,6 +903,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) return size_t(-1); } } + else if (requiresStorage) + { + m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables."); + return size_t(-1); + } else if (_context == julia::IdentifierContext::LValue) { m_errorReporter.typeError(_identifier.location, "Only local variables can be assigned to in inline assembly."); @@ -927,15 +939,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly) }; solAssert(!_inlineAssembly.annotation().analysisInfo, ""); _inlineAssembly.annotation().analysisInfo = make_shared<assembly::AsmAnalysisInfo>(); - boost::optional<Error::Type> errorTypeForLoose = - m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050) ? - Error::Type::SyntaxError : - Error::Type::Warning; assembly::AsmAnalyzer analyzer( *_inlineAssembly.annotation().analysisInfo, m_errorReporter, m_evmVersion, - errorTypeForLoose, + Error::Type::SyntaxError, assembly::AsmFlavour::Loose, identifierAccess ); @@ -1038,7 +1046,10 @@ string createTupleDecl(vector<ASTPointer<VariableDeclaration>> const& _decls) vector<string> components; for (ASTPointer<VariableDeclaration> const& decl: _decls) if (decl) + { + solAssert(decl->annotation().type, ""); components.emplace_back(decl->annotation().type->toString(false) + " " + decl->name()); + } else components.emplace_back(); @@ -1056,6 +1067,9 @@ bool typeCanBeExpressed(vector<ASTPointer<VariableDeclaration>> const& decls) if (!decl) continue; + if (!decl->annotation().type) + return false; + if (auto functionType = dynamic_cast<FunctionType const*>(decl->annotation().type.get())) if ( functionType->kind() != FunctionType::Kind::Internal && @@ -1318,11 +1332,41 @@ bool TypeChecker::visit(Conditional const& _conditional) return false; } +void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& _expression) +{ + if (auto const* tupleExpression = dynamic_cast<TupleExpression const*>(&_expression)) + { + auto const* tupleType = dynamic_cast<TupleType const*>(&_type); + auto const& types = tupleType ? tupleType->components() : vector<TypePointer> { _type.shared_from_this() }; + + solAssert(tupleExpression->components().size() == types.size(), ""); + for (size_t i = 0; i < types.size(); i++) + if (types[i]) + { + solAssert(!!tupleExpression->components()[i], ""); + checkExpressionAssignment(*types[i], *tupleExpression->components()[i]); + } + } + else if (_type.category() == Type::Category::Mapping) + { + bool isLocalOrReturn = false; + if (auto const* identifier = dynamic_cast<Identifier const*>(&_expression)) + if (auto const *variableDeclaration = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration)) + if (variableDeclaration->isLocalOrReturn()) + isLocalOrReturn = true; + if (!isLocalOrReturn) + m_errorReporter.typeError(_expression.location(), "Mappings cannot be assigned to."); + } +} + bool TypeChecker::visit(Assignment const& _assignment) { requireLValue(_assignment.leftHandSide()); TypePointer t = type(_assignment.leftHandSide()); _assignment.annotation().type = t; + + checkExpressionAssignment(*t, _assignment.leftHandSide()); + if (TupleType const* tupleType = dynamic_cast<TupleType const*>(t.get())) { if (_assignment.assignmentOperator() != Token::Assign) @@ -1339,11 +1383,6 @@ bool TypeChecker::visit(Assignment const& _assignment) if (dynamic_cast<TupleType const*>(type(_assignment.rightHandSide()).get())) checkDoubleStorageAssignment(_assignment); } - else if (t->category() == Type::Category::Mapping) - { - m_errorReporter.typeError(_assignment.location(), "Mappings cannot be assigned to."); - _assignment.rightHandSide().accept(*this); - } else if (_assignment.assignmentOperator() == Token::Assign) expectType(_assignment.rightHandSide(), *t); else @@ -1742,22 +1781,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) m_errorReporter.typeError(arguments[i]->location(), "Invalid rational number (too large or division by zero)."); errored = true; } - if (!errored) - { - TypePointer encodingType; - if ( - argType->mobileType() && - argType->mobileType()->interfaceType(false) && - argType->mobileType()->interfaceType(false)->encodingType() - ) - encodingType = argType->mobileType()->interfaceType(false)->encodingType(); - // Structs are fine as long as ABIV2 is activated and we do not do packed encoding. - if (!encodingType || ( - dynamic_cast<StructType const*>(encodingType.get()) && - !(abiEncodeV2 && functionType->padArguments()) - )) - m_errorReporter.typeError(arguments[i]->location(), "This type cannot be encoded."); - } + if (!errored && !argType->fullEncodingType(false, abiEncodeV2, !functionType->padArguments())) + m_errorReporter.typeError(arguments[i]->location(), "This type cannot be encoded."); } else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) { diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 8dc6b376..b696de85 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -87,13 +87,15 @@ private: /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. /// Should only be called if the left hand side is tuple-typed. void checkDoubleStorageAssignment(Assignment const& _assignment); + // Checks whether the expression @arg _expression can be assigned from type @arg _type + // and reports an error, if not. + void checkExpressionAssignment(Type const& _type, Expression const& _expression); virtual void endVisit(InheritanceSpecifier const& _inheritance) override; virtual void endVisit(UsingForDirective const& _usingFor) override; virtual bool visit(StructDefinition const& _struct) override; virtual bool visit(FunctionDefinition const& _function) override; virtual bool visit(VariableDeclaration const& _variable) override; - virtual bool visit(EnumDefinition const& _enum) override; /// We need to do this manually because we want to pass the bases of the current contract in /// case this is a base constructor call. void visitManually(ModifierInvocation const& _modifier, std::vector<ContractDefinition const*> const& _bases); diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 7719d080..23797d52 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -347,15 +347,6 @@ string FunctionDefinition::externalSignature() const return FunctionType(*this).externalSignature(); } -string FunctionDefinition::fullyQualifiedName() const -{ - auto const* contract = dynamic_cast<ContractDefinition const*>(scope()); - solAssert(contract, "Enclosing scope of function definition was not set."); - - auto fname = name().empty() ? "<fallback>" : name(); - return sourceUnitName() + ":" + contract->name() + "." + fname; -} - FunctionDefinitionAnnotation& FunctionDefinition::annotation() const { if (!m_annotation) @@ -475,11 +466,6 @@ bool VariableDeclaration::isExternalCallableParameter() const return false; } -bool VariableDeclaration::canHaveAutoType() const -{ - return isLocalVariable() && !isCallableParameter(); -} - TypePointer VariableDeclaration::type() const { return annotation().type; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 9ed3b9aa..69c6fa05 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -206,7 +206,6 @@ public: bool isVisibleInDerivedContracts() const { return isVisibleInContract() && visibility() >= Visibility::Internal; } bool isVisibleAsLibraryMember() const { return visibility() >= Visibility::Internal; } - std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); } virtual bool isLValue() const { return false; } virtual bool isPartOfExternalInterface() const { return false; } @@ -406,6 +405,8 @@ public: /// Returns the fallback function or nullptr if no fallback function was specified. FunctionDefinition const* fallbackFunction() const; + std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); } + virtual TypePointer type() const override; virtual ContractDefinitionAnnotation& annotation() const override; @@ -619,7 +620,6 @@ public: std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; } std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); } Block const& body() const { solAssert(m_body, ""); return *m_body; } - std::string fullyQualifiedName() const; virtual bool isVisibleInContract() const override { return Declaration::isVisibleInContract() && !isConstructor() && !isFallback(); @@ -696,7 +696,6 @@ public: bool isExternalCallableParameter() const; /// @returns true if the type of the variable does not need to be specified, i.e. it is declared /// in the body of a function or modifier. - bool canHaveAutoType() const; bool isStateVariable() const { return m_isStateVariable; } bool isIndexed() const { return m_isIndexed; } bool isConstant() const { return m_isConstant; } diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index a26828a6..a8ede66a 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -325,9 +325,6 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node) std::vector<pair<string, Json::Value>> attributes = { make_pair("name", _node.name()), make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue), - // FIXME: remove with next breaking release - make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() <= StateMutability::View), - make_pair("payable", _node.isPayable()), make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())), make_pair("superFunction", idOrNull(_node.annotation().superFunction)), make_pair("visibility", Declaration::visibilityToString(_node.visibility())), @@ -418,11 +415,8 @@ bool ASTJsonConverter::visit(UserDefinedTypeName const& _node) bool ASTJsonConverter::visit(FunctionTypeName const& _node) { setJsonNode(_node, "FunctionTypeName", { - make_pair("payable", _node.isPayable()), make_pair("visibility", Declaration::visibilityToString(_node.visibility())), make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())), - // FIXME: remove with next breaking release - make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() <= StateMutability::View), make_pair("parameterTypes", toJson(*_node.parameterTypeList())), make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())), make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c85e0522..565d197a 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -169,15 +169,6 @@ pair<u256, unsigned> const* StorageOffsets::offset(size_t _index) const return nullptr; } -MemberList& MemberList::operator=(MemberList&& _other) -{ - solAssert(&_other != this, ""); - - m_memberTypes = move(_other.m_memberTypes); - m_storageOffsets = move(_other.m_storageOffsets); - return *this; -} - void MemberList::combine(MemberList const & _other) { m_memberTypes += _other.m_memberTypes; @@ -263,6 +254,17 @@ string Type::escapeIdentifier(string const& _identifier) return ret; } +string Type::identifier() const +{ + string ret = escapeIdentifier(richIdentifier()); + solAssert(ret.find_first_of("0123456789") != 0, "Identifier cannot start with a number."); + solAssert( + ret.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMONPQRSTUVWXYZ_$") == string::npos, + "Identifier contains invalid characters." + ); + return ret; +} + TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) { solAssert(Token::isElementaryTypeName(_type.token()), @@ -390,6 +392,27 @@ MemberList const& Type::members(ContractDefinition const* _currentScope) const return *m_members[_currentScope]; } +TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _packed) const +{ + TypePointer encodingType = mobileType(); + if (encodingType) + encodingType = encodingType->interfaceType(_inLibraryCall); + if (encodingType) + encodingType = encodingType->encodingType(); + if (auto structType = dynamic_cast<StructType const*>(encodingType.get())) + { + // Structs are fine in the following circumstances: + // - ABIv2 without packed encoding or, + // - storage struct for a library + if (!( + (_encoderV2 && !_packed) || + (structType->location() == DataLocation::Storage && _inLibraryCall) + )) + return TypePointer(); + } + return encodingType; +} + MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition const& _scope) { // Normalise data location of type. @@ -1125,7 +1148,14 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ string RationalNumberType::richIdentifier() const { - return "t_rational_" + m_value.numerator().str() + "_by_" + m_value.denominator().str(); + // rational seemingly will put the sign always on the numerator, + // but let just make it deterministic here. + bigint numerator = abs(m_value.numerator()); + bigint denominator = abs(m_value.denominator()); + if (m_value < 0) + return "t_rational_minus_" + numerator.str() + "_by_" + denominator.str(); + else + return "t_rational_" + numerator.str() + "_by_" + denominator.str(); } bool RationalNumberType::operator==(Type const& _other) const @@ -1850,7 +1880,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con continue; auto memberType = dynamic_cast<FunctionType const*>(member.type.get()); solAssert(!!memberType, "Override changes type."); - if (!memberType->hasEqualArgumentTypes(*functionType)) + if (!memberType->hasEqualParameterTypes(*functionType)) continue; functionWithEqualArgumentsFound = true; break; @@ -2274,16 +2304,14 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons { solAssert(!!_targetType, ""); TypePointers const& targetComponents = dynamic_cast<TupleType const&>(*_targetType).components(); - bool fillRight = !targetComponents.empty() && (!targetComponents.back() || targetComponents.front()); + solAssert(components().size() == targetComponents.size(), ""); TypePointers tempComponents(targetComponents.size()); - for (size_t i = 0; i < min(targetComponents.size(), components().size()); ++i) + for (size_t i = 0; i < targetComponents.size(); ++i) { - size_t si = fillRight ? i : components().size() - i - 1; - size_t ti = fillRight ? i : targetComponents.size() - i - 1; - if (components()[si] && targetComponents[ti]) + if (components()[i] && targetComponents[i]) { - tempComponents[ti] = components()[si]->closestTemporaryType(targetComponents[ti]); - solAssert(tempComponents[ti], ""); + tempComponents[i] = components()[i]->closestTemporaryType(targetComponents[i]); + solAssert(tempComponents[i], ""); } } return make_shared<TupleType>(tempComponents); @@ -2804,7 +2832,7 @@ bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes, TypePoin ); } -bool FunctionType::hasEqualArgumentTypes(FunctionType const& _other) const +bool FunctionType::hasEqualParameterTypes(FunctionType const& _other) const { if (m_parameterTypes.size() != _other.m_parameterTypes.size()) return false; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 474a6f33..1fa2b2f5 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -95,9 +95,7 @@ public: using MemberMap = std::vector<Member>; - MemberList() {} explicit MemberList(MemberMap const& _members): m_memberTypes(_members) {} - MemberList& operator=(MemberList&& _other); void combine(MemberList const& _other); TypePointer memberType(std::string const& _name) const { @@ -132,6 +130,8 @@ private: mutable std::unique_ptr<StorageOffsets> m_storageOffsets; }; +static_assert(std::is_nothrow_move_constructible<MemberList>::value, "MemberList should be noexcept move constructible"); + /** * Abstract base class that forms the root of the type hierarchy. */ @@ -172,7 +172,7 @@ public: /// only if they have the same identifier. /// The identifier should start with "t_". /// Will not contain any character which would be invalid as an identifier. - std::string identifier() const { return escapeIdentifier(richIdentifier()); } + std::string identifier() const; /// More complex identifier strings use "parentheses", where $_ is interpreted as as /// "opening parenthesis", _$ as "closing parenthesis", _$_ as "comma" and any $ that @@ -280,6 +280,11 @@ public: /// This for example returns address for contract types. /// If there is no such type, returns an empty shared pointer. virtual TypePointer encodingType() const { return TypePointer(); } + /// @returns the encoding type used under the given circumstances for the type of an expression + /// when used for e.g. abi.encode(...) or the empty pointer if the object + /// cannot be encoded. + /// This is different from encodingType since it takes implicit conversions into account. + TypePointer fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _packed) const; /// @returns a (simpler) type that is used when decoding this type in calldata. virtual TypePointer decodingType() const { return encodingType(); } /// @returns a type that will be used outside of Solidity for e.g. function signatures. @@ -1030,7 +1035,7 @@ public: /// expression the function is called on. bool canTakeArguments(TypePointers const& _arguments, TypePointer const& _selfType = TypePointer()) const; /// @returns true if the types of parameters are equal (doesn't check return parameter types) - bool hasEqualArgumentTypes(FunctionType const& _other) const; + bool hasEqualParameterTypes(FunctionType const& _other) const; /// @returns true if the ABI is used for this call (only meaningful for external calls) bool isBareCall() const; diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index b3f1bc7e..dda77958 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -228,7 +228,8 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure) if (type.numBytes() == 32) templ("body", "cleaned := value"); else if (type.numBytes() == 0) - templ("body", "cleaned := 0"); + // This is disallowed in the type system. + solAssert(false, ""); else { size_t numBits = type.numBytes() * 8; @@ -471,13 +472,8 @@ string ABIFunctions::abiEncodingFunction( bool _fromStack ) { - solUnimplementedAssert( - _to.mobileType() && - _to.mobileType()->interfaceType(_encodeAsLibraryTypes) && - _to.mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(), - "Encoding type \"" + _to.toString() + "\" not yet implemented." - ); - TypePointer toInterface = _to.mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(); + TypePointer toInterface = _to.fullEncodingType(_encodeAsLibraryTypes, true, false); + solUnimplementedAssert(toInterface, "Encoding type \"" + _to.toString() + "\" not yet implemented."); Type const& to = *toInterface; if (_from.category() == Type::Category::StringLiteral) @@ -886,13 +882,8 @@ string ABIFunctions::abiEncodingFunctionStruct( solAssert(member.type, ""); if (!member.type->canLiveOutsideStorage()) continue; - solUnimplementedAssert( - member.type->mobileType() && - member.type->mobileType()->interfaceType(_encodeAsLibraryTypes) && - member.type->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(), - "Encoding type \"" + member.type->toString() + "\" not yet implemented." - ); - auto memberTypeTo = member.type->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(); + TypePointer memberTypeTo = member.type->fullEncodingType(_encodeAsLibraryTypes, true, false); + solUnimplementedAssert(memberTypeTo, "Encoding type \"" + member.type->toString() + "\" not yet implemented."); auto memberTypeFrom = _from.memberType(member.name); solAssert(memberTypeFrom, ""); bool dynamicMember = memberTypeTo->isDynamicallyEncoded(); diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index d3afada5..55f1d252 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -46,19 +46,6 @@ void Compiler::compileContract( m_context.optimise(m_optimize, m_optimizeRuns); } -void Compiler::compileClone( - ContractDefinition const& _contract, - map<ContractDefinition const*, eth::Assembly const*> const& _contracts -) -{ - solAssert(!_contract.isLibrary(), ""); - ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize); - ContractCompiler cloneCompiler(&runtimeCompiler, m_context, m_optimize); - m_runtimeSub = cloneCompiler.compileClone(_contract, _contracts); - - m_context.optimise(m_optimize, m_optimizeRuns); -} - eth::AssemblyItem Compiler::functionEntryLabel(FunctionDefinition const& _function) const { return m_runtimeContext.functionEntryLabelIfExists(_function); diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index f6865d75..4028ae63 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -50,12 +50,6 @@ public: std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts, bytes const& _metadata ); - /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given - /// contract at runtime, but contains the full creation-time code. - void compileClone( - ContractDefinition const& _contract, - std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts - ); /// @returns Entire assembly. eth::Assembly const& assembly() const { return m_context.assembly(); } /// @returns The entire assembled object (with constructor). diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 3b1b4ec0..71b615b8 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -411,7 +411,7 @@ FunctionDefinition const& CompilerContext::resolveVirtualFunction( if ( function->name() == name && !function->isConstructor() && - FunctionType(*function).hasEqualArgumentTypes(functionType) + FunctionType(*function).hasEqualParameterTypes(functionType) ) return *function; solAssert(false, "Super function " + name + " not found."); diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 2d81a106..b30851fb 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -333,26 +333,19 @@ void CompilerUtils::encodeToMemory( ) { // stack: <v1> <v2> ... <vn> <mem> + bool const encoderV2 = m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2); TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes; solAssert(targetTypes.size() == _givenTypes.size(), ""); for (TypePointer& t: targetTypes) { - solUnimplementedAssert( - t->mobileType() && - t->mobileType()->interfaceType(_encodeAsLibraryTypes) && - t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(), - "Encoding type \"" + t->toString() + "\" not yet implemented." - ); - t = t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(); + TypePointer tEncoding = t->fullEncodingType(_encodeAsLibraryTypes, encoderV2, !_padToWordBoundaries); + solUnimplementedAssert(tEncoding, "Encoding type \"" + t->toString() + "\" not yet implemented."); + t = std::move(tEncoding); } if (_givenTypes.empty()) return; - else if ( - _padToWordBoundaries && - !_copyDynamicDataInPlace && - m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) - ) + else if (_padToWordBoundaries && !_copyDynamicDataInPlace && encoderV2) { // Use the new Yul-based encoding function auto stackHeightBefore = m_context.stackHeight(); @@ -954,20 +947,12 @@ void CompilerUtils::convertType( { TupleType const& sourceTuple = dynamic_cast<TupleType const&>(_typeOnStack); TupleType const& targetTuple = dynamic_cast<TupleType const&>(_targetType); - // fillRight: remove excess values at right side, !fillRight: remove eccess values at left side - bool fillRight = !targetTuple.components().empty() && ( - !targetTuple.components().back() || - targetTuple.components().front() - ); + solAssert(targetTuple.components().size() == sourceTuple.components().size(), ""); unsigned depth = sourceTuple.sizeOnStack(); for (size_t i = 0; i < sourceTuple.components().size(); ++i) { TypePointer sourceType = sourceTuple.components()[i]; - TypePointer targetType; - if (fillRight && i < targetTuple.components().size()) - targetType = targetTuple.components()[i]; - else if (!fillRight && targetTuple.components().size() + i >= sourceTuple.components().size()) - targetType = targetTuple.components()[targetTuple.components().size() - (sourceTuple.components().size() - i)]; + TypePointer targetType = targetTuple.components()[i]; if (!sourceType) { solAssert(!targetType, ""); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index bbb3db3d..f9493d6d 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -71,7 +71,11 @@ void ContractCompiler::compileContract( appendDelegatecallCheck(); initializeContext(_contract, _contracts); + // This generates the dispatch function for externally visible functions + // and adds the function to the compilation queue. Additionally internal functions, + // which are referenced directly or indirectly will be added. appendFunctionSelector(_contract); + // This processes the above populated queue until it is empty. appendMissingFunctions(); } @@ -90,27 +94,6 @@ size_t ContractCompiler::compileConstructor( } } -size_t ContractCompiler::compileClone( - ContractDefinition const& _contract, - map<ContractDefinition const*, eth::Assembly const*> const& _contracts -) -{ - initializeContext(_contract, _contracts); - - appendInitAndConstructorCode(_contract); - - //@todo determine largest return size of all runtime functions - auto runtimeSub = m_context.addSubroutine(cloneRuntime()); - - // stack contains sub size - m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY; - m_context << u256(0) << Instruction::RETURN; - - appendMissingFunctions(); - - return size_t(runtimeSub.data()); -} - void ContractCompiler::initializeContext( ContractDefinition const& _contract, map<ContractDefinition const*, eth::Assembly const*> const& _compiledContracts @@ -976,29 +959,6 @@ void ContractCompiler::compileExpression(Expression const& _expression, TypePoin CompilerUtils(m_context).convertType(*_expression.annotation().type, *_targetType); } -eth::AssemblyPointer ContractCompiler::cloneRuntime() const -{ - eth::Assembly a; - a << Instruction::CALLDATASIZE; - a << u256(0) << Instruction::DUP1 << Instruction::CALLDATACOPY; - //@todo adjust for larger return values, make this dynamic. - a << u256(0x20) << u256(0) << Instruction::CALLDATASIZE; - a << u256(0); - // this is the address which has to be substituted by the linker. - //@todo implement as special "marker" AssemblyItem. - a << u256("0xcafecafecafecafecafecafecafecafecafecafe"); - a << u256(eth::GasCosts::callGas(m_context.evmVersion()) + 10) << Instruction::GAS << Instruction::SUB; - a << Instruction::DELEGATECALL; - //Propagate error condition (if DELEGATECALL pushes 0 on stack). - a << Instruction::ISZERO; - a << Instruction::ISZERO; - eth::AssemblyItem afterTag = a.appendJumpI().tag(); - a << Instruction::INVALID << afterTag; - //@todo adjust for larger return values, make this dynamic. - a << u256(0x20) << u256(0) << Instruction::RETURN; - return make_shared<eth::Assembly>(a); -} - void ContractCompiler::popScopedVariables(ASTNode const* _node) { unsigned blockHeight = m_scopeStackHeight.at(m_modifierDepth).at(_node); diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h index 8516ec2c..5fa650b1 100644 --- a/libsolidity/codegen/ContractCompiler.h +++ b/libsolidity/codegen/ContractCompiler.h @@ -56,13 +56,6 @@ public: ContractDefinition const& _contract, std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts ); - /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given - /// contract at runtime, but contains the full creation-time code. - /// @returns the identifier of the runtime sub-assembly. - size_t compileClone( - ContractDefinition const& _contract, - std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts - ); private: /// Registers the non-function objects inside the contract with the context and stores the basic @@ -122,9 +115,6 @@ private: void appendStackVariableInitialisation(VariableDeclaration const& _variable); void compileExpression(Expression const& _expression, TypePointer const& _targetType = TypePointer()); - /// @returns the runtime assembly for clone contracts. - eth::AssemblyPointer cloneRuntime() const; - /// Frees the variables of a certain scope (to be used when leaving). void popScopedVariables(ASTNode const* _node); diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 17b50a38..88c1e56a 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -375,8 +375,14 @@ void SMTChecker::endVisit(Identifier const& _identifier) } else if (SSAVariable::isSupportedType(_identifier.annotation().type->category())) { - VariableDeclaration const& decl = dynamic_cast<VariableDeclaration const&>(*(_identifier.annotation().referencedDeclaration)); - defineExpr(_identifier, currentValue(decl)); + if (VariableDeclaration const* decl = dynamic_cast<VariableDeclaration const*>(_identifier.annotation().referencedDeclaration)) + defineExpr(_identifier, currentValue(*decl)); + else + // TODO: handle MagicVariableDeclaration here + m_errorReporter.warning( + _identifier.location(), + "Assertion checker does not yet support the type of this variable." + ); } else if (FunctionType const* fun = dynamic_cast<FunctionType const*>(_identifier.annotation().type.get())) { diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index d5580dd2..ea804cf5 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -57,7 +57,7 @@ bool AsmAnalyzer::operator()(Label const& _label) solAssert(!_label.name.empty(), ""); checkLooseFeature( _label.location, - "The use of labels is deprecated. Please use \"if\", \"switch\", \"for\" or function calls instead." + "The use of labels is disallowed. Please use \"if\", \"switch\", \"for\" or function calls instead." ); m_info.stackHeightInfo[&_label] = m_stackHeight; warnOnInstructions(solidity::Instruction::JUMPDEST, _label.location); @@ -68,7 +68,7 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) { checkLooseFeature( _instruction.location, - "The use of non-functional instructions is deprecated. Please use functional notation instead." + "The use of non-functional instructions is disallowed. Please use functional notation instead." ); auto const& info = instructionInfo(_instruction.instruction); m_stackHeight += info.ret - info.args; @@ -201,7 +201,7 @@ bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment) { checkLooseFeature( _assignment.location, - "The use of stack assignment is deprecated. Please use assignment in functional notation instead." + "The use of stack assignment is disallowed. Please use assignment in functional notation instead." ); bool success = checkAssignment(_assignment.variableName, size_t(-1)); m_info.stackHeightInfo[&_assignment] = m_stackHeight; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index aa33bad8..5cfd1758 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -191,6 +191,8 @@ bool CompilerStack::analyze() if (!resolver.performImports(*source->ast, sourceUnitsByName)) return false; + // This is the main name and type resolution loop. Needs to be run for every contract, because + // the special variables "this" and "super" must be set appropriately. for (Source const* source: m_sourceOrder) for (ASTPointer<ASTNode> const& node: source->ast->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) @@ -204,11 +206,15 @@ bool CompilerStack::analyze() // thus contracts can only conflict if declared in the same source file. This // already causes a double-declaration error elsewhere, so we do not report // an error here and instead silently drop any additional contracts we find. - if (m_contracts.find(contract->fullyQualifiedName()) == m_contracts.end()) m_contracts[contract->fullyQualifiedName()].contract = contract; } + // This cannot be done in the above loop, because cross-contract types couldn't be resolved. + // A good example is `LibraryName.TypeName x;`. + // + // Note: this does not resolve overloaded functions. In order to do that, types of arguments are needed, + // which is only done one step later. TypeChecker typeChecker(m_evmVersion, m_errorReporter); for (Source const* source: m_sourceOrder) for (ASTPointer<ASTNode> const& node: source->ast->nodes()) @@ -218,6 +224,7 @@ bool CompilerStack::analyze() if (noErrors) { + // Checks that can only be done when all types of all AST nodes are known. PostTypeChecker postTypeChecker(m_errorReporter); for (Source const* source: m_sourceOrder) if (!postTypeChecker.check(*source->ast)) @@ -226,6 +233,8 @@ bool CompilerStack::analyze() if (noErrors) { + // Control flow graph generator and analyzer. It can check for issues such as + // variable is used before it is assigned to. CFG cfg(m_errorReporter); for (Source const* source: m_sourceOrder) if (!cfg.constructFlow(*source->ast)) @@ -242,6 +251,7 @@ bool CompilerStack::analyze() if (noErrors) { + // Checks for common mistakes. Only generates warnings. StaticAnalyzer staticAnalyzer(m_errorReporter); for (Source const* source: m_sourceOrder) if (!staticAnalyzer.analyze(*source->ast)) @@ -250,6 +260,7 @@ bool CompilerStack::analyze() if (noErrors) { + // Check for state mutability in every function. vector<ASTPointer<ASTNode>> ast; for (Source const* source: m_sourceOrder) ast.push_back(source->ast); @@ -300,6 +311,7 @@ bool CompilerStack::compile() if (!parseAndAnalyze()) return false; + // Only compile contracts individually which have been requested. map<ContractDefinition const*, eth::Assembly const*> compiledContracts; for (Source const* source: m_sourceOrder) for (ASTPointer<ASTNode> const& node: source->ast->nodes()) @@ -317,7 +329,6 @@ void CompilerStack::link() { contract.second.object.link(m_libraries); contract.second.runtimeObject.link(m_libraries); - contract.second.cloneObject.link(m_libraries); } } @@ -396,11 +407,6 @@ eth::LinkerObject const& CompilerStack::runtimeObject(string const& _contractNam return contract(_contractName).runtimeObject; } -eth::LinkerObject const& CompilerStack::cloneObject(string const& _contractName) const -{ - return contract(_contractName).cloneObject; -} - /// FIXME: cache this string string CompilerStack::assemblyString(string const& _contractName, StringMap _sourceCodes) const { @@ -571,7 +577,7 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string for (auto const& node: _ast.nodes()) if (ImportDirective const* import = dynamic_cast<ImportDirective*>(node.get())) { - string importPath = absolutePath(import->path(), _sourcePath); + string importPath = dev::absolutePath(import->path(), _sourcePath); // The current value of `path` is the absolute path as seen from this source file. // We first have to apply remappings before we can store the actual absolute path // as seen globally. @@ -614,8 +620,8 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context for (auto const& redir: m_remappings) { - string context = sanitizePath(redir.context); - string prefix = sanitizePath(redir.prefix); + string context = dev::sanitizePath(redir.context); + string prefix = dev::sanitizePath(redir.prefix); // Skip if current context is closer if (context.length() < longestContext) @@ -632,7 +638,7 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context longestContext = context.length(); longestPrefix = prefix.length(); - bestMatchTarget = sanitizePath(redir.target); + bestMatchTarget = dev::sanitizePath(redir.target); } string path = bestMatchTarget; path.append(_path.begin() + longestPrefix, _path.end()); @@ -669,23 +675,6 @@ void CompilerStack::resolveImports() swap(m_sourceOrder, sourceOrder); } -string CompilerStack::absolutePath(string const& _path, string const& _reference) -{ - using path = boost::filesystem::path; - path p(_path); - // Anything that does not start with `.` is an absolute path. - if (p.begin() == p.end() || (*p.begin() != "." && *p.begin() != "..")) - return _path; - path result(_reference); - result.remove_filename(); - for (path::iterator it = p.begin(); it != p.end(); ++it) - if (*it == "..") - result = result.parent_path(); - else if (*it != ".") - result /= *it; - return result.generic_string(); -} - namespace { bool onlySafeExperimentalFeaturesActivated(set<ExperimentalFeature> const& features) @@ -755,23 +744,6 @@ void CompilerStack::compileContract( } _compiledContracts[compiledContract.contract] = &compiler->assembly(); - - try - { - if (!_contract.isLibrary()) - { - Compiler cloneCompiler(m_evmVersion, m_optimize, m_optimizeRuns); - cloneCompiler.compileClone(_contract, _compiledContracts); - compiledContract.cloneObject = cloneCompiler.assembledObject(); - } - } - catch (eth::AssemblyException const&) - { - // In some cases (if the constructor requests a runtime function), it is not - // possible to compile the clone. - - // TODO: Report error / warning - } } string const CompilerStack::lastContractName() const diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 0578ac86..2234a8c9 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -36,7 +36,6 @@ #include <json/json.h> #include <boost/noncopyable.hpp> -#include <boost/filesystem.hpp> #include <ostream> #include <string> @@ -190,12 +189,6 @@ public: /// @returns the runtime object for the contract. eth::LinkerObject const& runtimeObject(std::string const& _contractName) const; - /// @returns the bytecode of a contract that uses an already deployed contract via DELEGATECALL. - /// The returned bytes will contain a sequence of 20 bytes of the format "XXX...XXX" which have to - /// substituted by the actual address. Note that this sequence starts end ends in three X - /// characters but can contain anything in between. - eth::LinkerObject const& cloneObject(std::string const& _contractName) const; - /// @returns normal contract assembly items eth::AssemblyItems const* assemblyItems(std::string const& _contractName) const; @@ -258,7 +251,6 @@ private: std::shared_ptr<Compiler> compiler; eth::LinkerObject object; ///< Deployment object (includes the runtime sub-object). eth::LinkerObject runtimeObject; ///< Runtime object. - eth::LinkerObject cloneObject; ///< Clone object (deprecated). std::string metadata; ///< The metadata json that will be hashed into the chain. mutable std::unique_ptr<Json::Value const> abi; mutable std::unique_ptr<Json::Value const> userDocumentation; @@ -274,12 +266,6 @@ private: std::string applyRemapping(std::string const& _path, std::string const& _context); void resolveImports(); - /// @returns the absolute path corresponding to @a _path relative to @a _reference. - static std::string absolutePath(std::string const& _path, std::string const& _reference); - - /// Helper function to return path converted strings. - static std::string sanitizePath(std::string const& _path) { return boost::filesystem::path(_path).generic_string(); } - /// @returns true if the contract is requested to be compiled. bool isRequestedContract(ContractDefinition const& _contract) const; @@ -352,8 +338,9 @@ private: std::vector<Remapping> m_remappings; std::map<std::string const, Source> m_sources; std::shared_ptr<GlobalContext> m_globalContext; - std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>> m_scopes; std::vector<Source const*> m_sourceOrder; + /// This is updated during compilation. + std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>> m_scopes; std::map<std::string const, Contract> m_contracts; ErrorList m_errorList; ErrorReporter m_errorReporter; diff --git a/scripts/tests.sh b/scripts/tests.sh index 0a1fcdac..1c0fc590 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -30,7 +30,11 @@ set -e REPO_ROOT="$(dirname "$0")"/.. +WORKDIR=`mktemp -d` IPC_ENABLED=true +ALETH_PID= +CMDLINE_PID= + if [[ "$OSTYPE" == "darwin"* ]] then SMT_FLAGS="--no-smt" @@ -41,6 +45,49 @@ then fi fi +safe_kill() { + local PID=${1} + local NAME=${2:-${1}} + local n=1 + + # only proceed if $PID does exist + kill -0 $PID 2>/dev/null || return + + echo "Sending SIGTERM to ${NAME} (${PID}) ..." + kill $PID + + # wait until process terminated gracefully + while kill -0 $PID 2>/dev/null && [[ $n -le 4 ]]; do + echo "Waiting ($n) ..." + sleep 1 + n=$[n + 1] + done + + # process still alive? then hard-kill + if kill -0 $PID 2>/dev/null; then + echo "Sending SIGKILL to ${NAME} (${PID}) ..." + kill -9 $PID + fi +} + +cleanup() { + # ensure failing commands don't cause termination during cleanup (especially within safe_kill) + set +e + + if [[ "$IPC_ENABLED" = true ]] && [[ -n "${ALETH_PID}" ]] + then + safe_kill $ALETH_PID $ALETH_PATH + fi + if [[ -n "$CMDLINE_PID" ]] + then + safe_kill $CMDLINE_PID "Commandline tests" + fi + + echo "Cleaning up working directory ${WORKDIR} ..." + rm -rf "$WORKDIR" || true +} +trap cleanup INT TERM + if [ "$1" = --junit_report ] then if [ -z "$2" ] @@ -57,12 +104,13 @@ function printError() { echo "$(tput setaf 1)$1$(tput sgr0)"; } function printTask() { echo "$(tput bold)$(tput setaf 2)$1$(tput sgr0)"; } printTask "Running commandline tests..." -"$REPO_ROOT/test/cmdlineTests.sh" & -CMDLINE_PID=$! # Only run in parallel if this is run on CI infrastructure -if [ -z "$CI" ] +if [[ -n "$CI" ]] then - if ! wait $CMDLINE_PID + "$REPO_ROOT/test/cmdlineTests.sh" & + CMDLINE_PID=$! +else + if ! $REPO_ROOT/test/cmdlineTests.sh then printError "Commandline tests FAILED" exit 1 @@ -102,10 +150,10 @@ function download_aleth() # echos the PID function run_aleth() { - $ALETH_PATH --test -d "$1" >/dev/null 2>&1 & + $ALETH_PATH --test -d "${WORKDIR}" >/dev/null 2>&1 & echo $! # Wait until the IPC endpoint is available. - while [ ! -S "$1"/geth.ipc ] ; do sleep 1; done + while [ ! -S "${WORKDIR}/geth.ipc" ] ; do sleep 1; done sleep 2 } @@ -121,7 +169,7 @@ if [ "$IPC_ENABLED" = true ]; then download_aleth check_aleth - ALETH_PID=$(run_aleth /tmp/test) + ALETH_PID=$(run_aleth) fi progress="--show-progress" @@ -154,19 +202,15 @@ do log=--logger=JUNIT,test_suite,$log_directory/noopt_$vm.xml $testargs_no_opt fi fi - "$REPO_ROOT"/build/test/soltest $progress $log -- --testpath "$REPO_ROOT"/test "$optimize" --evm-version "$vm" $SMT_FLAGS $IPC_FLAGS --ipcpath /tmp/test/geth.ipc + "$REPO_ROOT"/build/test/soltest $progress $log -- --testpath "$REPO_ROOT"/test "$optimize" --evm-version "$vm" $SMT_FLAGS $IPC_FLAGS --ipcpath "${WORKDIR}/geth.ipc" done done -if ! wait $CMDLINE_PID +if [[ -n $CMDLINE_PID ]] && ! wait $CMDLINE_PID then printError "Commandline tests FAILED" + CMDLINE_PID= exit 1 fi -if [ "$IPC_ENABLED" = true ] -then - pkill "$ALETH_PID" || true - sleep 4 - pgrep "$ALETH_PID" && pkill -9 "$ALETH_PID" || true -fi +cleanup diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 6a768a00..429bd637 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -80,7 +80,6 @@ static string const g_strAstJson = "ast-json"; static string const g_strAstCompactJson = "ast-compact-json"; static string const g_strBinary = "bin"; static string const g_strBinaryRuntime = "bin-runtime"; -static string const g_strCloneBinary = "clone-bin"; static string const g_strCombinedJson = "combined-json"; static string const g_strCompactJSON = "compact-format"; static string const g_strContracts = "contracts"; @@ -128,7 +127,6 @@ static string const g_argAstCompactJson = g_strAstCompactJson; static string const g_argAstJson = g_strAstJson; static string const g_argBinary = g_strBinary; static string const g_argBinaryRuntime = g_strBinaryRuntime; -static string const g_argCloneBinary = g_strCloneBinary; static string const g_argCombinedJson = g_strCombinedJson; static string const g_argCompactJSON = g_strCompactJSON; static string const g_argGas = g_strGas; @@ -161,7 +159,6 @@ static set<string> const g_combinedJsonArgs g_strAst, g_strBinary, g_strBinaryRuntime, - g_strCloneBinary, g_strCompactJSON, g_strInterface, g_strMetadata, @@ -213,7 +210,6 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) g_argAstJson, g_argBinary, g_argBinaryRuntime, - g_argCloneBinary, g_argMetadata, g_argNatspecUser, g_argNatspecDev, @@ -237,16 +233,6 @@ void CommandLineInterface::handleBinary(string const& _contract) cout << m_compiler->object(_contract).toHex() << endl; } } - if (m_args.count(g_argCloneBinary)) - { - if (m_args.count(g_argOutputDir)) - createFile(m_compiler->filesystemFriendlyName(_contract) + ".clone_bin", m_compiler->cloneObject(_contract).toHex()); - else - { - cout << "Clone Binary: " << endl; - cout << m_compiler->cloneObject(_contract).toHex() << endl; - } - } if (m_args.count(g_argBinaryRuntime)) { if (m_args.count(g_argOutputDir)) @@ -275,7 +261,7 @@ void CommandLineInterface::handleBytecode(string const& _contract) { if (m_args.count(g_argOpcodes)) handleOpcode(_contract); - if (m_args.count(g_argBinary) || m_args.count(g_argCloneBinary) || m_args.count(g_argBinaryRuntime)) + if (m_args.count(g_argBinary) || m_args.count(g_argBinaryRuntime)) handleBinary(_contract); } @@ -416,11 +402,11 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() { if (!ignoreMissing) { - cerr << "\"" << infile << "\" is not found" << endl; + cerr << infile << " is not found." << endl; return false; } else - cerr << "\"" << infile << "\" is not found. Skipping." << endl; + cerr << infile << " is not found. Skipping." << endl; continue; } @@ -429,16 +415,16 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() { if (!ignoreMissing) { - cerr << "\"" << infile << "\" is not a valid file" << endl; + cerr << infile << " is not a valid file." << endl; return false; } else - cerr << "\"" << infile << "\" is not a valid file. Skipping." << endl; + cerr << infile << " is not a valid file. Skipping." << endl; continue; } - m_sourceCodes[infile.string()] = dev::readFileAsString(infile.string()); + m_sourceCodes[infile.generic_string()] = dev::readFileAsString(infile.string()); path = boost::filesystem::canonical(infile).string(); } m_allowedDirectories.push_back(boost::filesystem::path(path).remove_filename()); @@ -631,7 +617,6 @@ Allowed options)", (g_argOpcodes.c_str(), "Opcodes of the contracts.") (g_argBinary.c_str(), "Binary of the contracts in hex.") (g_argBinaryRuntime.c_str(), "Binary of the runtime part of the contracts in hex.") - (g_argCloneBinary.c_str(), "Binary of the clone contracts in hex.") (g_argAbi.c_str(), "ABI specification of the contracts.") (g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.") (g_argNatspecUser.c_str(), "Natspec user documentation of all contracts.") @@ -724,7 +709,7 @@ bool CommandLineInterface::processInput() return ReadCallback::Result{false, "Not a valid file."}; auto contents = dev::readFileAsString(canonicalPath.string()); - m_sourceCodes[path.string()] = contents; + m_sourceCodes[path.generic_string()] = contents; return ReadCallback::Result{true, contents}; } catch (Exception const& _exception) @@ -910,8 +895,6 @@ void CommandLineInterface::handleCombinedJSON() contractData[g_strBinary] = m_compiler->object(contractName).toHex(); if (requests.count(g_strBinaryRuntime)) contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex(); - if (requests.count(g_strCloneBinary)) - contractData[g_strCloneBinary] = m_compiler->cloneObject(contractName).toHex(); if (requests.count(g_strOpcodes)) contractData[g_strOpcodes] = solidity::disassemble(m_compiler->object(contractName).bytecode); if (requests.count(g_strAsm)) diff --git a/test/boostTest.cpp b/test/boostTest.cpp index f23355fd..d9e939eb 100644 --- a/test/boostTest.cpp +++ b/test/boostTest.cpp @@ -36,6 +36,7 @@ #pragma GCC diagnostic pop #include <test/Options.h> +#include <test/libsolidity/ASTJSONTest.h> #include <test/libsolidity/SyntaxTest.h> #include <boost/algorithm/string.hpp> @@ -131,6 +132,12 @@ test_suite* init_unit_test_suite( int /*argc*/, char* /*argv*/[] ) "syntaxTests", SyntaxTest::create ) > 0, "no syntax tests found"); + solAssert(registerTests( + master, + dev::test::Options::get().testPath / "libsolidity", + "ASTJSON", + ASTJSONTest::create + ) > 0, "no JSON AST tests found"); if (dev::test::Options::get().disableIPC) { for (auto suite: { diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index bc0ee786..7256386d 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -32,7 +32,7 @@ REPO_ROOT=$(cd $(dirname "$0")/.. && pwd) echo $REPO_ROOT SOLC="$REPO_ROOT/build/solc/solc" -FULLARGS="--optimize --ignore-missing --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc" +FULLARGS="--optimize --ignore-missing --combined-json abi,asm,ast,bin,bin-runtime,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc" echo "Checking that the bug list is up to date..." "$REPO_ROOT"/scripts/update_bugs_by_version.py @@ -94,6 +94,56 @@ printTask "Testing unknown options..." fi ) +# General helper function for testing SOLC behaviour, based on file name, compile opts, exit code, stdout and stderr. +# An failure is expected. +test_solc_file_input_failures() { + local filename="${1}" + local solc_args="${2}" + local stdout_expected="${3}" + local stderr_expected="${4}" + local stdout_path=`mktemp` + local stderr_path=`mktemp` + + set +e + "$SOLC" "${filename}" ${solc_args} 1>$stdout_path 2>$stderr_path + exitCode=$? + set -e + + if [[ $exitCode -eq 0 ]]; then + printError "Incorrect exit code. Expected failure (non-zero) but got success (0)." + rm -f $stdout_path $stderr_path + exit 1 + fi + + if [[ "$(cat $stdout_path)" != "${stdout_expected}" ]]; then + printError "Incorrect output on stderr received. Expected:" + echo -e "${stdout_expected}" + + printError "But got:" + cat $stdout_path + rm -f $stdout_path $stderr_path + exit 1 + fi + + if [[ "$(cat $stderr_path)" != "${stderr_expected}" ]]; then + printError "Incorrect output on stderr received. Expected:" + echo -e "${stderr_expected}" + + printError "But got:" + cat $stderr_path + rm -f $stdout_path $stderr_path + exit 1 + fi + + rm -f $stdout_path $stderr_path +} + +printTask "Testing passing files that are not found..." +test_solc_file_input_failures "file_not_found.sol" "" "" "\"file_not_found.sol\" is not found." + +printTask "Testing passing files that are not files..." +test_solc_file_input_failures "." "" "" "\".\" is not a valid file." + printTask "Compiling various other contracts and libraries..." ( cd "$REPO_ROOT"/test/compilationTests/ diff --git a/test/compilationTests/milestonetracker/RLP.sol b/test/compilationTests/milestonetracker/RLP.sol index e261bf23..e1f44457 100644 --- a/test/compilationTests/milestonetracker/RLP.sol +++ b/test/compilationTests/milestonetracker/RLP.sol @@ -381,19 +381,16 @@ library RLP { // we can write entire words, and just overwrite any excess. assembly { { - let i := 0 // Start at arr + 0x20 let words := div(add(btsLen, 31), 32) let rOffset := btsPtr let wOffset := add(tgt, 0x20) - tag_loop: - jumpi(end, eq(i, words)) + + // Start at arr + 0x20 + for { let i := 0 } not(eq(i, words)) { i := add(i, 1) } { let offset := mul(i, 0x20) mstore(add(wOffset, offset), mload(add(rOffset, offset))) - i := add(i, 1) } - jump(tag_loop) - end: mstore(add(tgt, add(0x20, mload(tgt))), 0) } } diff --git a/test/libdevcore/StringUtils.cpp b/test/libdevcore/StringUtils.cpp index 9ee93d02..94f1b753 100644 --- a/test/libdevcore/StringUtils.cpp +++ b/test/libdevcore/StringUtils.cpp @@ -81,6 +81,24 @@ BOOST_AUTO_TEST_CASE(test_alternatives_list) BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\", \"c\" or \"d\""); } +BOOST_AUTO_TEST_CASE(test_human_readable_join) +{ + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({})), ""); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a"})), "a"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b"})), "a, b"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b", "c"})), "a, b, c"); + + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({}), "; "), ""); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a"}), "; "), "a"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b"}), "; "), "a; b"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b", "c"}), "; "), "a; b; c"); + + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({}), "; ", " or "), ""); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a"}), "; ", " or "), "a"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b"}), "; ", " or "), "a or b"); + BOOST_CHECK_EQUAL(joinHumanReadable(vector<string>({"a", "b", "c"}), "; ", " or "), "a; b or c"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/Simplifier.cpp b/test/libjulia/Simplifier.cpp index 8ed8287a..e5b7e0d8 100644 --- a/test/libjulia/Simplifier.cpp +++ b/test/libjulia/Simplifier.cpp @@ -139,4 +139,14 @@ BOOST_AUTO_TEST_CASE(mod_and) ); } +BOOST_AUTO_TEST_CASE(not_applied) +{ + CHECK( + // The first argument of div is not constant. + // keccak256 is not movable. + "{ let a := div(keccak256(0, 0), 0) }", + "{ let a := div(keccak256(0, 0), 0) }" + ); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp deleted file mode 100644 index 482b05e6..00000000 --- a/test/libsolidity/ASTJSON.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see <http://www.gnu.org/licenses/>. -*/ -/** - * @author Christian <c@ethdev.com> - * @date 2016 - * Tests for the json ast output. - */ - -#include <test/Options.h> - -#include <libsolidity/interface/Exceptions.h> -#include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/ast/ASTJsonConverter.h> - -#include <boost/test/unit_test.hpp> - -#include <string> - -using namespace std; - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -BOOST_AUTO_TEST_SUITE(SolidityASTJSON) - -BOOST_AUTO_TEST_CASE(short_type_name) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() public { uint[] memory x; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["declarations"][0]; - BOOST_CHECK_EQUAL(varDecl["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeIdentifier"], "t_array$_t_uint256_$dyn_memory_ptr"); - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeString"], "uint256[]"); -} - -BOOST_AUTO_TEST_CASE(short_type_name_ref) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() public { uint[][] memory rows; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["declarations"][0]; - BOOST_CHECK_EQUAL(varDecl["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(varDecl["typeName"]["typeDescriptions"]["typeIdentifier"], "t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr"); - BOOST_CHECK_EQUAL(varDecl["typeName"]["typeDescriptions"]["typeString"], "uint256[][]"); -} - -BOOST_AUTO_TEST_CASE(long_type_name_binary_operation) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() public { uint a = 2 + 3; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][0]["body"]["statements"][0]["initialValue"]["commonType"]; - BOOST_CHECK_EQUAL(varDecl["typeIdentifier"], "t_rational_5_by_1"); - BOOST_CHECK_EQUAL(varDecl["typeString"], "int_const 5"); -} - -BOOST_AUTO_TEST_CASE(long_type_name_identifier) -{ - CompilerStack c; - c.addSource("a", "contract c { uint[] a; function f() public { uint[] storage b = a; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["nodes"][0]["nodes"][1]["body"]["statements"][0]["initialValue"]; - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeIdentifier"], "t_array$_t_uint256_$dyn_storage"); - BOOST_CHECK_EQUAL(varDecl["typeDescriptions"]["typeString"], "uint256[] storage ref"); -} - -BOOST_AUTO_TEST_CASE(documentation) -{ - CompilerStack c; - c.addSource("a", "/**This contract is empty*/ contract C {}"); - c.addSource("b", - "/**This contract is empty" - " and has a line-breaking comment.*/" - "contract C {}" - ); - c.addSource("c", - "contract C {" - " /** Some comment on Evt.*/ event Evt();" - " /** Some comment on mod.*/ modifier mod() { _; }" - " /** Some comment on fn.*/ function fn() public {}" - "}" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 0; - sourceIndices["b"] = 1; - sourceIndices["c"] = 2; - //same tests for non-legacy mode - Json::Value astJsonA = ASTJsonConverter(false, sourceIndices).toJson(c.ast("a")); - Json::Value documentationA = astJsonA["nodes"][0]["documentation"]; - BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); - Json::Value astJsonB = ASTJsonConverter(false, sourceIndices).toJson(c.ast("b")); - Json::Value documentationB = astJsonB["nodes"][0]["documentation"]; - BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); - Json::Value astJsonC = ASTJsonConverter(false, sourceIndices).toJson(c.ast("c")); - Json::Value documentationC0 = astJsonC["nodes"][0]["nodes"][0]["documentation"]; - Json::Value documentationC1 = astJsonC["nodes"][0]["nodes"][1]["documentation"]; - Json::Value documentationC2 = astJsonC["nodes"][0]["nodes"][2]["documentation"]; - BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); - BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); - BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); -} - - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} // end namespaces diff --git a/test/libsolidity/ASTJSON/array_type_name.json b/test/libsolidity/ASTJSON/array_type_name.json new file mode 100644 index 00000000..e3a3bea9 --- /dev/null +++ b/test/libsolidity/ASTJSON/array_type_name.json @@ -0,0 +1,76 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + }, + "id" : 5, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 4, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "constant" : false, + "id" : 3, + "name" : "i", + "nodeType" : "VariableDeclaration", + "scope" : 4, + "src" : "13:8:1", + "stateVariable" : true, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "13:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 2, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "13:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "scope" : 5, + "src" : "0:24:1" + } + ], + "src" : "0:25:1" +} diff --git a/test/libsolidity/ASTJSON/array_type_name.sol b/test/libsolidity/ASTJSON/array_type_name.sol new file mode 100644 index 00000000..202ecf02 --- /dev/null +++ b/test/libsolidity/ASTJSON/array_type_name.sol @@ -0,0 +1 @@ +contract C { uint[] i; } diff --git a/test/libsolidity/ASTJSON/array_type_name_legacy.json b/test/libsolidity/ASTJSON/array_type_name_legacy.json new file mode 100644 index 00000000..80feb344 --- /dev/null +++ b/test/libsolidity/ASTJSON/array_type_name_legacy.json @@ -0,0 +1,89 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "scope" : 5 + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "i", + "scope" : 4, + "stateVariable" : true, + "storageLocation" : "default", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "13:4:1" + } + ], + "id" : 2, + "name" : "ArrayTypeName", + "src" : "13:6:1" + } + ], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "13:8:1" + } + ], + "id" : 4, + "name" : "ContractDefinition", + "src" : "0:24:1" + } + ], + "id" : 5, + "name" : "SourceUnit", + "src" : "0:25:1" +} diff --git a/test/libsolidity/ASTJSON/documentation.json b/test/libsolidity/ASTJSON/documentation.json new file mode 100644 index 00000000..403d4e72 --- /dev/null +++ b/test/libsolidity/ASTJSON/documentation.json @@ -0,0 +1,180 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 1 + ] + }, + "id" : 2, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : "This contract is empty", + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 2, + "src" : "28:13:1" + } + ], + "src" : "28:14:1" +}, +{ + "absolutePath" : "b", + "exportedSymbols" : + { + "C" : + [ + 3 + ] + }, + "id" : 4, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : "This contract is empty\nand has a line-breaking comment.", + "fullyImplemented" : true, + "id" : 3, + "linearizedBaseContracts" : + [ + 3 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 4, + "src" : "62:13:2" + } + ], + "src" : "62:14:2" +}, +{ + "absolutePath" : "c", + "exportedSymbols" : + { + "C" : + [ + 15 + ] + }, + "id" : 16, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 15, + "linearizedBaseContracts" : + [ + 15 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "anonymous" : false, + "documentation" : "Some comment on Evt.", + "id" : 6, + "name" : "Evt", + "nodeType" : "EventDefinition", + "parameters" : + { + "id" : 5, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "51:2:3" + }, + "src" : "42:12:3" + }, + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "99:6:3", + "statements" : + [ + { + "id" : 8, + "nodeType" : "PlaceholderStatement", + "src" : "101:1:3" + } + ] + }, + "documentation" : "Some comment on mod.", + "id" : 10, + "name" : "mod", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "96:2:3" + }, + "src" : "84:21:3", + "visibility" : "internal" + }, + { + "body" : + { + "id" : 13, + "nodeType" : "Block", + "src" : "155:2:3", + "statements" : [] + }, + "documentation" : "Some comment on fn.", + "id" : 14, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "fn", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "145:2:3" + }, + "returnParameters" : + { + "id" : 12, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "155:0:3" + }, + "scope" : 15, + "src" : "134:23:3", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 16, + "src" : "0:159:3" + } + ], + "src" : "0:160:3" +} diff --git a/test/libsolidity/ASTJSON/documentation.sol b/test/libsolidity/ASTJSON/documentation.sol new file mode 100644 index 00000000..e65af9b4 --- /dev/null +++ b/test/libsolidity/ASTJSON/documentation.sol @@ -0,0 +1,17 @@ +// ---- SOURCE: a + +/**This contract is empty*/ contract C {} + +// ---- SOURCE: b + +/**This contract is empty + and has a line-breaking comment.*/ +contract C {} + +// ---- SOURCE: c + +contract C { + /** Some comment on Evt.*/ event Evt(); + /** Some comment on mod.*/ modifier mod() { _; } + /** Some comment on fn.*/ function fn() public {} +} diff --git a/test/libsolidity/ASTJSON/documentation_legacy.json b/test/libsolidity/ASTJSON/documentation_legacy.json new file mode 100644 index 00000000..5a890e50 --- /dev/null +++ b/test/libsolidity/ASTJSON/documentation_legacy.json @@ -0,0 +1,176 @@ +{ + "attributes" : + { + "absolutePath" : "c", + "exportedSymbols" : + { + "C" : + [ + 15 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 15 + ], + "name" : "C", + "scope" : 16 + }, + "children" : + [ + { + "attributes" : + { + "anonymous" : false, + "documentation" : "Some comment on Evt.", + "name" : "Evt" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 5, + "name" : "ParameterList", + "src" : "51:2:3" + } + ], + "id" : 6, + "name" : "EventDefinition", + "src" : "42:12:3" + }, + { + "attributes" : + { + "documentation" : "Some comment on mod.", + "name" : "mod", + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 7, + "name" : "ParameterList", + "src" : "96:2:3" + }, + { + "children" : + [ + { + "id" : 8, + "name" : "PlaceholderStatement", + "src" : "101:1:3" + } + ], + "id" : 9, + "name" : "Block", + "src" : "99:6:3" + } + ], + "id" : 10, + "name" : "ModifierDefinition", + "src" : "84:21:3" + }, + { + "attributes" : + { + "documentation" : "Some comment on fn.", + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "fn", + "scope" : 15, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 11, + "name" : "ParameterList", + "src" : "145:2:3" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 12, + "name" : "ParameterList", + "src" : "155:0:3" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 13, + "name" : "Block", + "src" : "155:2:3" + } + ], + "id" : 14, + "name" : "FunctionDefinition", + "src" : "134:23:3" + } + ], + "id" : 15, + "name" : "ContractDefinition", + "src" : "0:159:3" + } + ], + "id" : 16, + "name" : "SourceUnit", + "src" : "0:160:3" +} diff --git a/test/libsolidity/ASTJSON/enum_value.json b/test/libsolidity/ASTJSON/enum_value.json new file mode 100644 index 00000000..21afd9a7 --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value.json @@ -0,0 +1,57 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + }, + "id" : 5, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 4, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "canonicalName" : "C.E", + "id" : 3, + "members" : + [ + { + "id" : 1, + "name" : "A", + "nodeType" : "EnumValue", + "src" : "22:1:1" + }, + { + "id" : 2, + "name" : "B", + "nodeType" : "EnumValue", + "src" : "25:1:1" + } + ], + "name" : "E", + "nodeType" : "EnumDefinition", + "src" : "13:15:1" + } + ], + "scope" : 5, + "src" : "0:30:1" + } + ], + "src" : "0:31:1" +} diff --git a/test/libsolidity/ASTJSON/enum_value.sol b/test/libsolidity/ASTJSON/enum_value.sol new file mode 100644 index 00000000..ef0875fb --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value.sol @@ -0,0 +1 @@ +contract C { enum E { A, B } } diff --git a/test/libsolidity/ASTJSON/enum_value_legacy.json b/test/libsolidity/ASTJSON/enum_value_legacy.json new file mode 100644 index 00000000..d7782969 --- /dev/null +++ b/test/libsolidity/ASTJSON/enum_value_legacy.json @@ -0,0 +1,78 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 4 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 4 + ], + "name" : "C", + "scope" : 5 + }, + "children" : + [ + { + "attributes" : + { + "canonicalName" : "C.E", + "name" : "E" + }, + "children" : + [ + { + "attributes" : + { + "name" : "A" + }, + "id" : 1, + "name" : "EnumValue", + "src" : "22:1:1" + }, + { + "attributes" : + { + "name" : "B" + }, + "id" : 2, + "name" : "EnumValue", + "src" : "25:1:1" + } + ], + "id" : 3, + "name" : "EnumDefinition", + "src" : "13:15:1" + } + ], + "id" : 4, + "name" : "ContractDefinition", + "src" : "0:30:1" + } + ], + "id" : 5, + "name" : "SourceUnit", + "src" : "0:31:1" +} diff --git a/test/libsolidity/ASTJSON/event_definition.json b/test/libsolidity/ASTJSON/event_definition.json new file mode 100644 index 00000000..029062c3 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_definition.json @@ -0,0 +1,50 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 3 + ] + }, + "id" : 4, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 3, + "linearizedBaseContracts" : + [ + 3 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "anonymous" : false, + "documentation" : null, + "id" : 2, + "name" : "E", + "nodeType" : "EventDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "20:2:1" + }, + "src" : "13:10:1" + } + ], + "scope" : 4, + "src" : "0:25:1" + } + ], + "src" : "0:26:1" +} diff --git a/test/libsolidity/ASTJSON/event_definition.sol b/test/libsolidity/ASTJSON/event_definition.sol new file mode 100644 index 00000000..81b43c67 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_definition.sol @@ -0,0 +1 @@ +contract C { event E(); } diff --git a/test/libsolidity/ASTJSON/event_definition_legacy.json b/test/libsolidity/ASTJSON/event_definition_legacy.json new file mode 100644 index 00000000..f5967bf4 --- /dev/null +++ b/test/libsolidity/ASTJSON/event_definition_legacy.json @@ -0,0 +1,74 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 3 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 3 + ], + "name" : "C", + "scope" : 4 + }, + "children" : + [ + { + "attributes" : + { + "anonymous" : false, + "documentation" : null, + "name" : "E" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "20:2:1" + } + ], + "id" : 2, + "name" : "EventDefinition", + "src" : "13:10:1" + } + ], + "id" : 3, + "name" : "ContractDefinition", + "src" : "0:25:1" + } + ], + "id" : 4, + "name" : "SourceUnit", + "src" : "0:26:1" +} diff --git a/test/libsolidity/ASTJSON/function_type.json b/test/libsolidity/ASTJSON/function_type.json new file mode 100644 index 00000000..7b10f0dc --- /dev/null +++ b/test/libsolidity/ASTJSON/function_type.json @@ -0,0 +1,224 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 17 + ] + }, + "id" : 18, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 17, + "linearizedBaseContracts" : + [ + 17 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 15, + "nodeType" : "Block", + "src" : "120:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 16, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 6, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 16, + "src" : "24:44:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_payable$__$returns$_t_uint256_$", + "typeString" : "function () payable external returns (uint256)" + }, + "typeName" : + { + "id" : 5, + "nodeType" : "FunctionTypeName", + "parameterTypes" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "32:2:1" + }, + "returnParameterTypes" : + { + "id" : 4, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 3, + "name" : "", + "nodeType" : "VariableDeclaration", + "scope" : 16, + "src" : "61:4:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 2, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "61:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "60:6:1" + }, + "src" : "24:44:1", + "stateMutability" : "payable", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_payable$__$returns$_t_uint256_$", + "typeString" : "function () payable external returns (uint256)" + }, + "visibility" : "external" + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "23:46:1" + }, + "returnParameters" : + { + "id" : 14, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 13, + "name" : "", + "nodeType" : "VariableDeclaration", + "scope" : 16, + "src" : "79:40:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_view$__$returns$_t_uint256_$", + "typeString" : "function () view external returns (uint256)" + }, + "typeName" : + { + "id" : 12, + "nodeType" : "FunctionTypeName", + "parameterTypes" : + { + "id" : 8, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "87:2:1" + }, + "returnParameterTypes" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 10, + "name" : "", + "nodeType" : "VariableDeclaration", + "scope" : 16, + "src" : "113:4:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 9, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "113:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "112:6:1" + }, + "src" : "79:40:1", + "stateMutability" : "view", + "typeDescriptions" : + { + "typeIdentifier" : "t_function_external_view$__$returns$_t_uint256_$", + "typeString" : "function () view external returns (uint256)" + }, + "visibility" : "external" + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "78:41:1" + }, + "scope" : 17, + "src" : "13:109:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 18, + "src" : "0:124:1" + } + ], + "src" : "0:125:1" +} diff --git a/test/libsolidity/ASTJSON/function_type.sol b/test/libsolidity/ASTJSON/function_type.sol new file mode 100644 index 00000000..b63bcbf0 --- /dev/null +++ b/test/libsolidity/ASTJSON/function_type.sol @@ -0,0 +1 @@ +contract C { function f(function() external payable returns (uint) x) returns (function() external view returns (uint)) {} } diff --git a/test/libsolidity/ASTJSON/function_type_legacy.json b/test/libsolidity/ASTJSON/function_type_legacy.json new file mode 100644 index 00000000..952fd865 --- /dev/null +++ b/test/libsolidity/ASTJSON/function_type_legacy.json @@ -0,0 +1,265 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 17 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 17 + ], + "name" : "C", + "scope" : 18 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 17, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 16, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "function () payable external returns (uint256)", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "stateMutability" : "payable", + "type" : "function () payable external returns (uint256)", + "visibility" : "external" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "32:2:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "", + "scope" : 16, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 2, + "name" : "ElementaryTypeName", + "src" : "61:4:1" + } + ], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "61:4:1" + } + ], + "id" : 4, + "name" : "ParameterList", + "src" : "60:6:1" + } + ], + "id" : 5, + "name" : "FunctionTypeName", + "src" : "24:44:1" + } + ], + "id" : 6, + "name" : "VariableDeclaration", + "src" : "24:44:1" + } + ], + "id" : 7, + "name" : "ParameterList", + "src" : "23:46:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "", + "scope" : 16, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "function () view external returns (uint256)", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "stateMutability" : "view", + "type" : "function () view external returns (uint256)", + "visibility" : "external" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 8, + "name" : "ParameterList", + "src" : "87:2:1" + }, + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "", + "scope" : 16, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 9, + "name" : "ElementaryTypeName", + "src" : "113:4:1" + } + ], + "id" : 10, + "name" : "VariableDeclaration", + "src" : "113:4:1" + } + ], + "id" : 11, + "name" : "ParameterList", + "src" : "112:6:1" + } + ], + "id" : 12, + "name" : "FunctionTypeName", + "src" : "79:40:1" + } + ], + "id" : 13, + "name" : "VariableDeclaration", + "src" : "79:40:1" + } + ], + "id" : 14, + "name" : "ParameterList", + "src" : "78:41:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 15, + "name" : "Block", + "src" : "120:2:1" + } + ], + "id" : 16, + "name" : "FunctionDefinition", + "src" : "13:109:1" + } + ], + "id" : 17, + "name" : "ContractDefinition", + "src" : "0:124:1" + } + ], + "id" : 18, + "name" : "SourceUnit", + "src" : "0:125:1" +} diff --git a/test/libsolidity/ASTJSON/inheritance_specifier.json b/test/libsolidity/ASTJSON/inheritance_specifier.json new file mode 100644 index 00000000..edef8677 --- /dev/null +++ b/test/libsolidity/ASTJSON/inheritance_specifier.json @@ -0,0 +1,80 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C1" : + [ + 1 + ], + "C2" : + [ + 4 + ] + }, + "id" : 5, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C1", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 5, + "src" : "0:14:1" + }, + { + "baseContracts" : + [ + { + "arguments" : null, + "baseName" : + { + "contractScope" : null, + "id" : 2, + "name" : "C1", + "nodeType" : "UserDefinedTypeName", + "referencedDeclaration" : 1, + "src" : "30:2:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_contract$_C1_$1", + "typeString" : "contract C1" + } + }, + "id" : 3, + "nodeType" : "InheritanceSpecifier", + "src" : "30:2:1" + } + ], + "contractDependencies" : + [ + 1 + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 4, + "linearizedBaseContracts" : + [ + 4, + 1 + ], + "name" : "C2", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 5, + "src" : "15:20:1" + } + ], + "src" : "0:36:1" +} diff --git a/test/libsolidity/ASTJSON/inheritance_specifier.sol b/test/libsolidity/ASTJSON/inheritance_specifier.sol new file mode 100644 index 00000000..02dbf0c5 --- /dev/null +++ b/test/libsolidity/ASTJSON/inheritance_specifier.sol @@ -0,0 +1 @@ +contract C1 {} contract C2 is C1 {} diff --git a/test/libsolidity/ASTJSON/inheritance_specifier_legacy.json b/test/libsolidity/ASTJSON/inheritance_specifier_legacy.json new file mode 100644 index 00000000..0fcf2939 --- /dev/null +++ b/test/libsolidity/ASTJSON/inheritance_specifier_legacy.json @@ -0,0 +1,105 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C1" : + [ + 1 + ], + "C2" : + [ + 4 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C1", + "nodes" : + [ + null + ], + "scope" : 5 + }, + "id" : 1, + "name" : "ContractDefinition", + "src" : "0:14:1" + }, + { + "attributes" : + { + "contractDependencies" : + [ + 1 + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 4, + 1 + ], + "name" : "C2", + "nodes" : + [ + null + ], + "scope" : 5 + }, + "children" : + [ + { + "attributes" : + { + "arguments" : null + }, + "children" : + [ + { + "attributes" : + { + "contractScope" : null, + "name" : "C1", + "referencedDeclaration" : 1, + "type" : "contract C1" + }, + "id" : 2, + "name" : "UserDefinedTypeName", + "src" : "30:2:1" + } + ], + "id" : 3, + "name" : "InheritanceSpecifier", + "src" : "30:2:1" + } + ], + "id" : 4, + "name" : "ContractDefinition", + "src" : "15:20:1" + } + ], + "id" : 5, + "name" : "SourceUnit", + "src" : "0:36:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json new file mode 100644 index 00000000..fe3e73d2 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json @@ -0,0 +1,175 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + }, + "id" : 12, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 11, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "33:19:1", + "statements" : + [ + { + "assignments" : + [ + 4 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 4, + "name" : "a", + "nodeType" : "VariableDeclaration", + "scope" : 9, + "src" : "35:6:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 3, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "35:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 8, + "initialValue" : + { + "argumentTypes" : null, + "commonType" : + { + "typeIdentifier" : "t_rational_5_by_1", + "typeString" : "int_const 5" + }, + "id" : 7, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "leftExpression" : + { + "argumentTypes" : null, + "hexValue" : "32", + "id" : 5, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "44:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_2_by_1", + "typeString" : "int_const 2" + }, + "value" : "2" + }, + "nodeType" : "BinaryOperation", + "operator" : "+", + "rightExpression" : + { + "argumentTypes" : null, + "hexValue" : "33", + "id" : 6, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "48:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_3_by_1", + "typeString" : "int_const 3" + }, + "value" : "3" + }, + "src" : "44:5:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_5_by_1", + "typeString" : "int_const 5" + } + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:14:1" + } + ] + }, + "documentation" : null, + "id" : 10, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 11, + "src" : "13:39:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 12, + "src" : "0:54:1" + } + ], + "src" : "0:55:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation.sol b/test/libsolidity/ASTJSON/long_type_name_binary_operation.sol new file mode 100644 index 00000000..f07029d7 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation.sol @@ -0,0 +1 @@ +contract c { function f() public { uint a = 2 + 3; } } diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json new file mode 100644 index 00000000..d78d01ff --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json @@ -0,0 +1,207 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "scope" : 12 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 11, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 4 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "a", + "scope" : 9, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 3, + "name" : "ElementaryTypeName", + "src" : "35:4:1" + } + ], + "id" : 4, + "name" : "VariableDeclaration", + "src" : "35:6:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "commonType" : + { + "typeIdentifier" : "t_rational_5_by_1", + "typeString" : "int_const 5" + }, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "operator" : "+", + "type" : "int_const 5" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "32", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 2", + "value" : "2" + }, + "id" : 5, + "name" : "Literal", + "src" : "44:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "33", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 3", + "value" : "3" + }, + "id" : 6, + "name" : "Literal", + "src" : "48:1:1" + } + ], + "id" : 7, + "name" : "BinaryOperation", + "src" : "44:5:1" + } + ], + "id" : 8, + "name" : "VariableDeclarationStatement", + "src" : "35:14:1" + } + ], + "id" : 9, + "name" : "Block", + "src" : "33:19:1" + } + ], + "id" : 10, + "name" : "FunctionDefinition", + "src" : "13:39:1" + } + ], + "id" : 11, + "name" : "ContractDefinition", + "src" : "0:54:1" + } + ], + "id" : 12, + "name" : "SourceUnit", + "src" : "0:55:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.json b/test/libsolidity/ASTJSON/long_type_name_identifier.json new file mode 100644 index 00000000..0579967c --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_identifier.json @@ -0,0 +1,181 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 14 + ] + }, + "id" : 15, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 14, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "constant" : false, + "id" : 3, + "name" : "a", + "nodeType" : "VariableDeclaration", + "scope" : 14, + "src" : "13:8:1", + "stateVariable" : true, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "13:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 2, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "13:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + }, + { + "body" : + { + "id" : 12, + "nodeType" : "Block", + "src" : "43:25:1", + "statements" : + [ + { + "assignments" : + [ + 9 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 9, + "name" : "b", + "nodeType" : "VariableDeclaration", + "scope" : 12, + "src" : "45:16:1", + "stateVariable" : false, + "storageLocation" : "storage", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 7, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "45:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 8, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "45:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 11, + "initialValue" : + { + "argumentTypes" : null, + "id" : 10, + "name" : "a", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 3, + "src" : "64:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage", + "typeString" : "uint256[] storage ref" + } + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "45:20:1" + } + ] + }, + "documentation" : null, + "id" : 13, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 4, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:2:1" + }, + "returnParameters" : + { + "id" : 5, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "43:0:1" + }, + "scope" : 14, + "src" : "23:45:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 15, + "src" : "0:70:1" + } + ], + "src" : "0:71:1" +} diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.sol b/test/libsolidity/ASTJSON/long_type_name_identifier.sol new file mode 100644 index 00000000..f03f7a84 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_identifier.sol @@ -0,0 +1 @@ +contract c { uint[] a; function f() public { uint[] storage b = a; } } diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json new file mode 100644 index 00000000..a96ccef3 --- /dev/null +++ b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json @@ -0,0 +1,219 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 14 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "c", + "scope" : 15 + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "a", + "scope" : 14, + "stateVariable" : true, + "storageLocation" : "default", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "13:4:1" + } + ], + "id" : 2, + "name" : "ArrayTypeName", + "src" : "13:6:1" + } + ], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "13:8:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 14, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 4, + "name" : "ParameterList", + "src" : "33:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 5, + "name" : "ParameterList", + "src" : "43:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 9 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "b", + "scope" : 12, + "stateVariable" : false, + "storageLocation" : "storage", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 7, + "name" : "ElementaryTypeName", + "src" : "45:4:1" + } + ], + "id" : 8, + "name" : "ArrayTypeName", + "src" : "45:6:1" + } + ], + "id" : 9, + "name" : "VariableDeclaration", + "src" : "45:16:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 3, + "type" : "uint256[] storage ref", + "value" : "a" + }, + "id" : 10, + "name" : "Identifier", + "src" : "64:1:1" + } + ], + "id" : 11, + "name" : "VariableDeclarationStatement", + "src" : "45:20:1" + } + ], + "id" : 12, + "name" : "Block", + "src" : "43:25:1" + } + ], + "id" : 13, + "name" : "FunctionDefinition", + "src" : "23:45:1" + } + ], + "id" : 14, + "name" : "ContractDefinition", + "src" : "0:70:1" + } + ], + "id" : 15, + "name" : "SourceUnit", + "src" : "0:71:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_definition.json b/test/libsolidity/ASTJSON/modifier_definition.json new file mode 100644 index 00000000..95554f03 --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_definition.json @@ -0,0 +1,174 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + }, + "id" : 15, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 14, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 5, + "nodeType" : "Block", + "src" : "32:6:1", + "statements" : + [ + { + "id" : 4, + "nodeType" : "PlaceholderStatement", + "src" : "34:1:1" + } + ] + }, + "documentation" : null, + "id" : 6, + "name" : "M", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 3, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 2, + "name" : "i", + "nodeType" : "VariableDeclaration", + "scope" : 6, + "src" : "24:6:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "24:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "23:8:1" + }, + "src" : "13:25:1", + "visibility" : "internal" + }, + { + "body" : + { + "id" : 12, + "nodeType" : "Block", + "src" : "64:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 13, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + { + "arguments" : + [ + { + "argumentTypes" : null, + "hexValue" : "31", + "id" : 9, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "54:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_1_by_1", + "typeString" : "int_const 1" + }, + "value" : "1" + } + ], + "id" : 10, + "modifierName" : + { + "argumentTypes" : null, + "id" : 8, + "name" : "M", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 6, + "src" : "52:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_modifier$_t_uint256_$", + "typeString" : "modifier (uint256)" + } + }, + "nodeType" : "ModifierInvocation", + "src" : "52:4:1" + } + ], + "name" : "F", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "49:2:1" + }, + "returnParameters" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "64:0:1" + }, + "scope" : 14, + "src" : "39:27:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 15, + "src" : "0:68:1" + } + ], + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_definition.sol b/test/libsolidity/ASTJSON/modifier_definition.sol new file mode 100644 index 00000000..96474e0f --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_definition.sol @@ -0,0 +1 @@ +contract C { modifier M(uint i) { _; } function F() M(1) public {} } diff --git a/test/libsolidity/ASTJSON/modifier_definition_legacy.json b/test/libsolidity/ASTJSON/modifier_definition_legacy.json new file mode 100644 index 00000000..e1e797ba --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_definition_legacy.json @@ -0,0 +1,211 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "scope" : 15 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "name" : "M", + "visibility" : "internal" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "i", + "scope" : 6, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "24:4:1" + } + ], + "id" : 2, + "name" : "VariableDeclaration", + "src" : "24:6:1" + } + ], + "id" : 3, + "name" : "ParameterList", + "src" : "23:8:1" + }, + { + "children" : + [ + { + "id" : 4, + "name" : "PlaceholderStatement", + "src" : "34:1:1" + } + ], + "id" : 5, + "name" : "Block", + "src" : "32:6:1" + } + ], + "id" : 6, + "name" : "ModifierDefinition", + "src" : "13:25:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "name" : "F", + "scope" : 14, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 7, + "name" : "ParameterList", + "src" : "49:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 11, + "name" : "ParameterList", + "src" : "64:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 6, + "type" : "modifier (uint256)", + "value" : "M" + }, + "id" : 8, + "name" : "Identifier", + "src" : "52:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "31", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 1", + "value" : "1" + }, + "id" : 9, + "name" : "Literal", + "src" : "54:1:1" + } + ], + "id" : 10, + "name" : "ModifierInvocation", + "src" : "52:4:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 12, + "name" : "Block", + "src" : "64:2:1" + } + ], + "id" : 13, + "name" : "FunctionDefinition", + "src" : "39:27:1" + } + ], + "id" : 14, + "name" : "ContractDefinition", + "src" : "0:68:1" + } + ], + "id" : 15, + "name" : "SourceUnit", + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_invocation.json b/test/libsolidity/ASTJSON/modifier_invocation.json new file mode 100644 index 00000000..95554f03 --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_invocation.json @@ -0,0 +1,174 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + }, + "id" : 15, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 14, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 5, + "nodeType" : "Block", + "src" : "32:6:1", + "statements" : + [ + { + "id" : 4, + "nodeType" : "PlaceholderStatement", + "src" : "34:1:1" + } + ] + }, + "documentation" : null, + "id" : 6, + "name" : "M", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 3, + "nodeType" : "ParameterList", + "parameters" : + [ + { + "constant" : false, + "id" : 2, + "name" : "i", + "nodeType" : "VariableDeclaration", + "scope" : 6, + "src" : "24:6:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + }, + "typeName" : + { + "id" : 1, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "24:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "src" : "23:8:1" + }, + "src" : "13:25:1", + "visibility" : "internal" + }, + { + "body" : + { + "id" : 12, + "nodeType" : "Block", + "src" : "64:2:1", + "statements" : [] + }, + "documentation" : null, + "id" : 13, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + { + "arguments" : + [ + { + "argumentTypes" : null, + "hexValue" : "31", + "id" : 9, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "54:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_1_by_1", + "typeString" : "int_const 1" + }, + "value" : "1" + } + ], + "id" : 10, + "modifierName" : + { + "argumentTypes" : null, + "id" : 8, + "name" : "M", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 6, + "src" : "52:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_modifier$_t_uint256_$", + "typeString" : "modifier (uint256)" + } + }, + "nodeType" : "ModifierInvocation", + "src" : "52:4:1" + } + ], + "name" : "F", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 7, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "49:2:1" + }, + "returnParameters" : + { + "id" : 11, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "64:0:1" + }, + "scope" : 14, + "src" : "39:27:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 15, + "src" : "0:68:1" + } + ], + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/modifier_invocation.sol b/test/libsolidity/ASTJSON/modifier_invocation.sol new file mode 100644 index 00000000..96474e0f --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_invocation.sol @@ -0,0 +1 @@ +contract C { modifier M(uint i) { _; } function F() M(1) public {} } diff --git a/test/libsolidity/ASTJSON/modifier_invocation_legacy.json b/test/libsolidity/ASTJSON/modifier_invocation_legacy.json new file mode 100644 index 00000000..e1e797ba --- /dev/null +++ b/test/libsolidity/ASTJSON/modifier_invocation_legacy.json @@ -0,0 +1,211 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 14 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 14 + ], + "name" : "C", + "scope" : 15 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "name" : "M", + "visibility" : "internal" + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "i", + "scope" : 6, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint256", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 1, + "name" : "ElementaryTypeName", + "src" : "24:4:1" + } + ], + "id" : 2, + "name" : "VariableDeclaration", + "src" : "24:6:1" + } + ], + "id" : 3, + "name" : "ParameterList", + "src" : "23:8:1" + }, + { + "children" : + [ + { + "id" : 4, + "name" : "PlaceholderStatement", + "src" : "34:1:1" + } + ], + "id" : 5, + "name" : "Block", + "src" : "32:6:1" + } + ], + "id" : 6, + "name" : "ModifierDefinition", + "src" : "13:25:1" + }, + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "name" : "F", + "scope" : 14, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 7, + "name" : "ParameterList", + "src" : "49:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 11, + "name" : "ParameterList", + "src" : "64:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 6, + "type" : "modifier (uint256)", + "value" : "M" + }, + "id" : 8, + "name" : "Identifier", + "src" : "52:1:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "31", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 1", + "value" : "1" + }, + "id" : 9, + "name" : "Literal", + "src" : "54:1:1" + } + ], + "id" : 10, + "name" : "ModifierInvocation", + "src" : "52:4:1" + }, + { + "attributes" : + { + "statements" : + [ + null + ] + }, + "children" : [], + "id" : 12, + "name" : "Block", + "src" : "64:2:1" + } + ], + "id" : 13, + "name" : "FunctionDefinition", + "src" : "39:27:1" + } + ], + "id" : 14, + "name" : "ContractDefinition", + "src" : "0:68:1" + } + ], + "id" : 15, + "name" : "SourceUnit", + "src" : "0:69:1" +} diff --git a/test/libsolidity/ASTJSON/non_utf8.json b/test/libsolidity/ASTJSON/non_utf8.json new file mode 100644 index 00000000..307259e9 --- /dev/null +++ b/test/libsolidity/ASTJSON/non_utf8.json @@ -0,0 +1,122 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 8 + ] + }, + "id" : 9, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 8, + "linearizedBaseContracts" : + [ + 8 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 6, + "nodeType" : "Block", + "src" : "33:20:1", + "statements" : + [ + { + "assignments" : + [ + 3 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 3, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 6, + "src" : "35:5:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_string_memory_ptr", + "typeString" : "string" + }, + "typeName" : null, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 5, + "initialValue" : + { + "argumentTypes" : null, + "hexValue" : "ff", + "id" : 4, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "string", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "43:7:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_stringliteral_8b1a944cf13a9a1c08facb2c9e98623ef3254d2ddb48113885c3e8e97fec8db9", + "typeString" : "literal_string (contains invalid UTF-8 sequence at position 0)" + }, + "value" : null + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ] + }, + "documentation" : null, + "id" : 7, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 8, + "src" : "13:40:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 9, + "src" : "0:55:1" + } + ], + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/non_utf8.sol b/test/libsolidity/ASTJSON/non_utf8.sol new file mode 100644 index 00000000..b83f3d70 --- /dev/null +++ b/test/libsolidity/ASTJSON/non_utf8.sol @@ -0,0 +1 @@ +contract C { function f() public { var x = hex"ff"; } } diff --git a/test/libsolidity/ASTJSON/non_utf8_legacy.json b/test/libsolidity/ASTJSON/non_utf8_legacy.json new file mode 100644 index 00000000..b1f847f7 --- /dev/null +++ b/test/libsolidity/ASTJSON/non_utf8_legacy.json @@ -0,0 +1,155 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 8 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 8 + ], + "name" : "C", + "scope" : 9 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 8, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 3 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 6, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "string", + "typeName" : null, + "value" : null, + "visibility" : "internal" + }, + "children" : [], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "35:5:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "ff", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "string", + "type" : "literal_string (contains invalid UTF-8 sequence at position 0)", + "value" : null + }, + "id" : 4, + "name" : "Literal", + "src" : "43:7:1" + } + ], + "id" : 5, + "name" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ], + "id" : 6, + "name" : "Block", + "src" : "33:20:1" + } + ], + "id" : 7, + "name" : "FunctionDefinition", + "src" : "13:40:1" + } + ], + "id" : 8, + "name" : "ContractDefinition", + "src" : "0:55:1" + } + ], + "id" : 9, + "name" : "SourceUnit", + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/placeholder_statement.json b/test/libsolidity/ASTJSON/placeholder_statement.json new file mode 100644 index 00000000..496e1500 --- /dev/null +++ b/test/libsolidity/ASTJSON/placeholder_statement.json @@ -0,0 +1,64 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 3, + "nodeType" : "Block", + "src" : "24:6:1", + "statements" : + [ + { + "id" : 2, + "nodeType" : "PlaceholderStatement", + "src" : "26:1:1" + } + ] + }, + "documentation" : null, + "id" : 4, + "name" : "M", + "nodeType" : "ModifierDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "24:0:1" + }, + "src" : "13:17:1", + "visibility" : "internal" + } + ], + "scope" : 6, + "src" : "0:32:1" + } + ], + "src" : "0:33:1" +} diff --git a/test/libsolidity/ASTJSON/placeholder_statement.sol b/test/libsolidity/ASTJSON/placeholder_statement.sol new file mode 100644 index 00000000..cb2c0990 --- /dev/null +++ b/test/libsolidity/ASTJSON/placeholder_statement.sol @@ -0,0 +1 @@ +contract C { modifier M { _; } } diff --git a/test/libsolidity/ASTJSON/placeholder_statement_legacy.json b/test/libsolidity/ASTJSON/placeholder_statement_legacy.json new file mode 100644 index 00000000..a5582976 --- /dev/null +++ b/test/libsolidity/ASTJSON/placeholder_statement_legacy.json @@ -0,0 +1,87 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "name" : "M", + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "24:0:1" + }, + { + "children" : + [ + { + "id" : 2, + "name" : "PlaceholderStatement", + "src" : "26:1:1" + } + ], + "id" : 3, + "name" : "Block", + "src" : "24:6:1" + } + ], + "id" : 4, + "name" : "ModifierDefinition", + "src" : "13:17:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "0:32:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:33:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name.json b/test/libsolidity/ASTJSON/short_type_name.json new file mode 100644 index 00000000..502c1e31 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name.json @@ -0,0 +1,126 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 10 + ] + }, + "id" : 11, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 10, + "linearizedBaseContracts" : + [ + 10 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 8, + "nodeType" : "Block", + "src" : "33:20:1", + "statements" : + [ + { + "assignments" : + [ + 6 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 6, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 8, + "src" : "35:15:1", + "stateVariable" : false, + "storageLocation" : "memory", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_memory_ptr", + "typeString" : "uint256[]" + }, + "typeName" : + { + "baseType" : + { + "id" : 4, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "35:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 5, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "35:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 7, + "initialValue" : null, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ] + }, + "documentation" : null, + "id" : 9, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 10, + "src" : "13:40:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 11, + "src" : "0:55:1" + } + ], + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name.sol b/test/libsolidity/ASTJSON/short_type_name.sol new file mode 100644 index 00000000..533874ae --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name.sol @@ -0,0 +1 @@ +contract c { function f() public { uint[] memory x; } } diff --git a/test/libsolidity/ASTJSON/short_type_name_legacy.json b/test/libsolidity/ASTJSON/short_type_name_legacy.json new file mode 100644 index 00000000..761bcd3b --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_legacy.json @@ -0,0 +1,162 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 10 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 10 + ], + "name" : "c", + "scope" : 11 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 10, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 6 + ], + "initialValue" : null + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 8, + "stateVariable" : false, + "storageLocation" : "memory", + "type" : "uint256[]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 4, + "name" : "ElementaryTypeName", + "src" : "35:4:1" + } + ], + "id" : 5, + "name" : "ArrayTypeName", + "src" : "35:6:1" + } + ], + "id" : 6, + "name" : "VariableDeclaration", + "src" : "35:15:1" + } + ], + "id" : 7, + "name" : "VariableDeclarationStatement", + "src" : "35:15:1" + } + ], + "id" : 8, + "name" : "Block", + "src" : "33:20:1" + } + ], + "id" : 9, + "name" : "FunctionDefinition", + "src" : "13:40:1" + } + ], + "id" : 10, + "name" : "ContractDefinition", + "src" : "0:55:1" + } + ], + "id" : 11, + "name" : "SourceUnit", + "src" : "0:56:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.json b/test/libsolidity/ASTJSON/short_type_name_ref.json new file mode 100644 index 00000000..b0c3ad97 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_ref.json @@ -0,0 +1,138 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + }, + "id" : 12, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 11, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "33:25:1", + "statements" : + [ + { + "assignments" : + [ + 7 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 7, + "name" : "rows", + "nodeType" : "VariableDeclaration", + "scope" : 9, + "src" : "35:20:1", + "stateVariable" : false, + "storageLocation" : "memory", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_array$_t_uint256_$dyn_memory_$dyn_memory_ptr", + "typeString" : "uint256[][]" + }, + "typeName" : + { + "baseType" : + { + "baseType" : + { + "id" : 4, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "35:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + }, + "id" : 5, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "35:6:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_uint256_$dyn_storage_ptr", + "typeString" : "uint256[]" + } + }, + "id" : 6, + "length" : null, + "nodeType" : "ArrayTypeName", + "src" : "35:8:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_array$_t_array$_t_uint256_$dyn_storage_$dyn_storage_ptr", + "typeString" : "uint256[][]" + } + }, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 8, + "initialValue" : null, + "nodeType" : "VariableDeclarationStatement", + "src" : "35:20:1" + } + ] + }, + "documentation" : null, + "id" : 10, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "33:0:1" + }, + "scope" : 11, + "src" : "13:45:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 12, + "src" : "0:60:1" + } + ], + "src" : "0:61:1" +} diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.sol b/test/libsolidity/ASTJSON/short_type_name_ref.sol new file mode 100644 index 00000000..a808b982 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_ref.sol @@ -0,0 +1 @@ +contract c { function f() public { uint[][] memory rows; } } diff --git a/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json new file mode 100644 index 00000000..d426a384 --- /dev/null +++ b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json @@ -0,0 +1,175 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "c" : + [ + 11 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "c", + "scope" : 12 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 11, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "33:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 7 + ], + "initialValue" : null + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "rows", + "scope" : 9, + "stateVariable" : false, + "storageLocation" : "memory", + "type" : "uint256[][]", + "value" : null, + "visibility" : "internal" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[][]" + }, + "children" : + [ + { + "attributes" : + { + "length" : null, + "type" : "uint256[]" + }, + "children" : + [ + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 4, + "name" : "ElementaryTypeName", + "src" : "35:4:1" + } + ], + "id" : 5, + "name" : "ArrayTypeName", + "src" : "35:6:1" + } + ], + "id" : 6, + "name" : "ArrayTypeName", + "src" : "35:8:1" + } + ], + "id" : 7, + "name" : "VariableDeclaration", + "src" : "35:20:1" + } + ], + "id" : 8, + "name" : "VariableDeclarationStatement", + "src" : "35:20:1" + } + ], + "id" : 9, + "name" : "Block", + "src" : "33:25:1" + } + ], + "id" : 10, + "name" : "FunctionDefinition", + "src" : "13:45:1" + } + ], + "id" : 11, + "name" : "ContractDefinition", + "src" : "0:60:1" + } + ], + "id" : 12, + "name" : "SourceUnit", + "src" : "0:61:1" +} diff --git a/test/libsolidity/ASTJSON/smoke.json b/test/libsolidity/ASTJSON/smoke.json new file mode 100644 index 00000000..f5369bfc --- /dev/null +++ b/test/libsolidity/ASTJSON/smoke.json @@ -0,0 +1,33 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 1 + ] + }, + "id" : 2, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 2, + "src" : "0:13:1" + } + ], + "src" : "0:14:1" +} diff --git a/test/libsolidity/ASTJSON/smoke.sol b/test/libsolidity/ASTJSON/smoke.sol new file mode 100644 index 00000000..2dde0d20 --- /dev/null +++ b/test/libsolidity/ASTJSON/smoke.sol @@ -0,0 +1 @@ +contract C {} diff --git a/test/libsolidity/ASTJSON/smoke_legacy.json b/test/libsolidity/ASTJSON/smoke_legacy.json new file mode 100644 index 00000000..e01a3c9b --- /dev/null +++ b/test/libsolidity/ASTJSON/smoke_legacy.json @@ -0,0 +1,48 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 1 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "C", + "nodes" : + [ + null + ], + "scope" : 2 + }, + "id" : 1, + "name" : "ContractDefinition", + "src" : "0:13:1" + } + ], + "id" : 2, + "name" : "SourceUnit", + "src" : "0:14:1" +} diff --git a/test/libsolidity/ASTJSON/source_location.json b/test/libsolidity/ASTJSON/source_location.json new file mode 100644 index 00000000..8d8acb0f --- /dev/null +++ b/test/libsolidity/ASTJSON/source_location.json @@ -0,0 +1,160 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 11 + ] + }, + "id" : 12, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 11, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "body" : + { + "id" : 9, + "nodeType" : "Block", + "src" : "26:19:1", + "statements" : + [ + { + "assignments" : + [ + 3 + ], + "declarations" : + [ + { + "constant" : false, + "id" : 3, + "name" : "x", + "nodeType" : "VariableDeclaration", + "scope" : 9, + "src" : "28:5:1", + "stateVariable" : false, + "storageLocation" : "default", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint8", + "typeString" : "uint8" + }, + "typeName" : null, + "value" : null, + "visibility" : "internal" + } + ], + "id" : 5, + "initialValue" : + { + "argumentTypes" : null, + "hexValue" : "32", + "id" : 4, + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "kind" : "number", + "lValueRequested" : false, + "nodeType" : "Literal", + "src" : "36:1:1", + "subdenomination" : null, + "typeDescriptions" : + { + "typeIdentifier" : "t_rational_2_by_1", + "typeString" : "int_const 2" + }, + "value" : "2" + }, + "nodeType" : "VariableDeclarationStatement", + "src" : "28:9:1" + }, + { + "expression" : + { + "argumentTypes" : null, + "id" : 7, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "nodeType" : "UnaryOperation", + "operator" : "++", + "prefix" : false, + "src" : "39:3:1", + "subExpression" : + { + "argumentTypes" : null, + "id" : 6, + "name" : "x", + "nodeType" : "Identifier", + "overloadedDeclarations" : [], + "referencedDeclaration" : 3, + "src" : "39:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint8", + "typeString" : "uint8" + } + }, + "typeDescriptions" : + { + "typeIdentifier" : "t_uint8", + "typeString" : "uint8" + } + }, + "id" : 8, + "nodeType" : "ExpressionStatement", + "src" : "39:3:1" + } + ] + }, + "documentation" : null, + "id" : 10, + "implemented" : true, + "isConstructor" : false, + "modifiers" : [], + "name" : "f", + "nodeType" : "FunctionDefinition", + "parameters" : + { + "id" : 1, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "23:2:1" + }, + "returnParameters" : + { + "id" : 2, + "nodeType" : "ParameterList", + "parameters" : [], + "src" : "26:0:1" + }, + "scope" : 11, + "src" : "13:32:1", + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + } + ], + "scope" : 12, + "src" : "0:47:1" + } + ], + "src" : "0:48:1" +} diff --git a/test/libsolidity/ASTJSON/source_location.sol b/test/libsolidity/ASTJSON/source_location.sol new file mode 100644 index 00000000..1fcec2e6 --- /dev/null +++ b/test/libsolidity/ASTJSON/source_location.sol @@ -0,0 +1 @@ +contract C { function f() { var x = 2; x++; } } diff --git a/test/libsolidity/ASTJSON/source_location_legacy.json b/test/libsolidity/ASTJSON/source_location_legacy.json new file mode 100644 index 00000000..327cd6da --- /dev/null +++ b/test/libsolidity/ASTJSON/source_location_legacy.json @@ -0,0 +1,198 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 11 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 11 + ], + "name" : "C", + "scope" : 12 + }, + "children" : + [ + { + "attributes" : + { + "documentation" : null, + "implemented" : true, + "isConstructor" : false, + "modifiers" : + [ + null + ], + "name" : "f", + "scope" : 11, + "stateMutability" : "nonpayable", + "superFunction" : null, + "visibility" : "public" + }, + "children" : + [ + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 1, + "name" : "ParameterList", + "src" : "23:2:1" + }, + { + "attributes" : + { + "parameters" : + [ + null + ] + }, + "children" : [], + "id" : 2, + "name" : "ParameterList", + "src" : "26:0:1" + }, + { + "children" : + [ + { + "attributes" : + { + "assignments" : + [ + 3 + ] + }, + "children" : + [ + { + "attributes" : + { + "constant" : false, + "name" : "x", + "scope" : 9, + "stateVariable" : false, + "storageLocation" : "default", + "type" : "uint8", + "typeName" : null, + "value" : null, + "visibility" : "internal" + }, + "children" : [], + "id" : 3, + "name" : "VariableDeclaration", + "src" : "28:5:1" + }, + { + "attributes" : + { + "argumentTypes" : null, + "hexvalue" : "32", + "isConstant" : false, + "isLValue" : false, + "isPure" : true, + "lValueRequested" : false, + "subdenomination" : null, + "token" : "number", + "type" : "int_const 2", + "value" : "2" + }, + "id" : 4, + "name" : "Literal", + "src" : "36:1:1" + } + ], + "id" : 5, + "name" : "VariableDeclarationStatement", + "src" : "28:9:1" + }, + { + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "isConstant" : false, + "isLValue" : false, + "isPure" : false, + "lValueRequested" : false, + "operator" : "++", + "prefix" : false, + "type" : "uint8" + }, + "children" : + [ + { + "attributes" : + { + "argumentTypes" : null, + "overloadedDeclarations" : + [ + null + ], + "referencedDeclaration" : 3, + "type" : "uint8", + "value" : "x" + }, + "id" : 6, + "name" : "Identifier", + "src" : "39:1:1" + } + ], + "id" : 7, + "name" : "UnaryOperation", + "src" : "39:3:1" + } + ], + "id" : 8, + "name" : "ExpressionStatement", + "src" : "39:3:1" + } + ], + "id" : 9, + "name" : "Block", + "src" : "26:19:1" + } + ], + "id" : 10, + "name" : "FunctionDefinition", + "src" : "13:32:1" + } + ], + "id" : 11, + "name" : "ContractDefinition", + "src" : "0:47:1" + } + ], + "id" : 12, + "name" : "SourceUnit", + "src" : "0:48:1" +} diff --git a/test/libsolidity/ASTJSON/using_for_directive.json b/test/libsolidity/ASTJSON/using_for_directive.json new file mode 100644 index 00000000..33caabb4 --- /dev/null +++ b/test/libsolidity/ASTJSON/using_for_directive.json @@ -0,0 +1,87 @@ +{ + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ], + "L" : + [ + 1 + ] + }, + "id" : 6, + "nodeType" : "SourceUnit", + "nodes" : + [ + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "library", + "documentation" : null, + "fullyImplemented" : true, + "id" : 1, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "L", + "nodeType" : "ContractDefinition", + "nodes" : [], + "scope" : 6, + "src" : "0:12:1" + }, + { + "baseContracts" : [], + "contractDependencies" : [], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "id" : 5, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "nodeType" : "ContractDefinition", + "nodes" : + [ + { + "id" : 4, + "libraryName" : + { + "contractScope" : null, + "id" : 2, + "name" : "L", + "nodeType" : "UserDefinedTypeName", + "referencedDeclaration" : 1, + "src" : "32:1:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_contract$_L_$1", + "typeString" : "library L" + } + }, + "nodeType" : "UsingForDirective", + "src" : "26:17:1", + "typeName" : + { + "id" : 3, + "name" : "uint", + "nodeType" : "ElementaryTypeName", + "src" : "38:4:1", + "typeDescriptions" : + { + "typeIdentifier" : "t_uint256", + "typeString" : "uint256" + } + } + } + ], + "scope" : 6, + "src" : "13:32:1" + } + ], + "src" : "0:46:1" +} diff --git a/test/libsolidity/ASTJSON/using_for_directive.sol b/test/libsolidity/ASTJSON/using_for_directive.sol new file mode 100644 index 00000000..a882ad88 --- /dev/null +++ b/test/libsolidity/ASTJSON/using_for_directive.sol @@ -0,0 +1 @@ +library L {} contract C { using L for uint; } diff --git a/test/libsolidity/ASTJSON/using_for_directive_legacy.json b/test/libsolidity/ASTJSON/using_for_directive_legacy.json new file mode 100644 index 00000000..0827ef90 --- /dev/null +++ b/test/libsolidity/ASTJSON/using_for_directive_legacy.json @@ -0,0 +1,110 @@ +{ + "attributes" : + { + "absolutePath" : "a", + "exportedSymbols" : + { + "C" : + [ + 5 + ], + "L" : + [ + 1 + ] + } + }, + "children" : + [ + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "library", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 1 + ], + "name" : "L", + "nodes" : + [ + null + ], + "scope" : 6 + }, + "id" : 1, + "name" : "ContractDefinition", + "src" : "0:12:1" + }, + { + "attributes" : + { + "baseContracts" : + [ + null + ], + "contractDependencies" : + [ + null + ], + "contractKind" : "contract", + "documentation" : null, + "fullyImplemented" : true, + "linearizedBaseContracts" : + [ + 5 + ], + "name" : "C", + "scope" : 6 + }, + "children" : + [ + { + "children" : + [ + { + "attributes" : + { + "contractScope" : null, + "name" : "L", + "referencedDeclaration" : 1, + "type" : "library L" + }, + "id" : 2, + "name" : "UserDefinedTypeName", + "src" : "32:1:1" + }, + { + "attributes" : + { + "name" : "uint", + "type" : "uint256" + }, + "id" : 3, + "name" : "ElementaryTypeName", + "src" : "38:4:1" + } + ], + "id" : 4, + "name" : "UsingForDirective", + "src" : "26:17:1" + } + ], + "id" : 5, + "name" : "ContractDefinition", + "src" : "13:32:1" + } + ], + "id" : 6, + "name" : "SourceUnit", + "src" : "0:46:1" +} diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp new file mode 100644 index 00000000..05839c1f --- /dev/null +++ b/test/libsolidity/ASTJSONTest.cpp @@ -0,0 +1,201 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <test/libsolidity/ASTJSONTest.h> +#include <test/Options.h> +#include <libsolidity/ast/ASTJsonConverter.h> +#include <libsolidity/interface/CompilerStack.h> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/throw_exception.hpp> +#include <cctype> +#include <fstream> +#include <memory> +#include <stdexcept> + +using namespace dev; +using namespace solidity; +using namespace dev::solidity::test; +using namespace dev::solidity::test::formatting; +using namespace std; +namespace fs = boost::filesystem; +using namespace boost::unit_test; + +ASTJSONTest::ASTJSONTest(string const& _filename) +{ + if (!boost::algorithm::ends_with(_filename, ".sol")) + BOOST_THROW_EXCEPTION(runtime_error("Invalid test contract file name: \"" + _filename + "\".")); + + m_astFilename = _filename.substr(0, _filename.size() - 4) + ".json"; + m_legacyAstFilename = _filename.substr(0, _filename.size() - 4) + "_legacy.json"; + + ifstream file(_filename); + if (!file) + BOOST_THROW_EXCEPTION(runtime_error("Cannot open test contract: \"" + _filename + "\".")); + file.exceptions(ios::badbit); + + string sourceName; + string source; + string line; + string const sourceDelimiter("// ---- SOURCE: "); + string const delimiter("// ----"); + while (getline(file, line)) + { + if (boost::algorithm::starts_with(line, sourceDelimiter)) + { + if (!sourceName.empty()) + m_sources.emplace_back(sourceName, source); + + sourceName = line.substr(sourceDelimiter.size(), string::npos); + source = string(); + } + else if (!line.empty() && !boost::algorithm::starts_with(line, delimiter)) + source += line + "\n"; + } + + m_sources.emplace_back(sourceName.empty() ? "a" : sourceName, source); + + file.close(); + file.open(m_astFilename); + if (file) + { + string line; + while (getline(file, line)) + m_expectation += line + "\n"; + } + + file.close(); + file.open(m_legacyAstFilename); + if (file) + { + string line; + while (getline(file, line)) + m_expectationLegacy += line + "\n"; + } +} + +bool ASTJSONTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted) +{ + CompilerStack c; + + map<string, unsigned> sourceIndices; + for (size_t i = 0; i < m_sources.size(); i++) + { + c.addSource(m_sources[i].first, m_sources[i].second); + sourceIndices[m_sources[i].first] = i + 1; + } + + c.setEVMVersion(dev::test::Options::get().evmVersion()); + c.parseAndAnalyze(); + + for (size_t i = 0; i < m_sources.size(); i++) + { + ostringstream result; + ASTJsonConverter(false, sourceIndices).print(result, c.ast(m_sources[i].first)); + m_result += result.str(); + if (i != m_sources.size() - 1) + m_result += ","; + m_result += "\n"; + } + + bool resultsMatch = true; + + if (m_expectation != m_result) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; + { + istringstream stream(m_expectation); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; + { + istringstream stream(m_result); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + resultsMatch = false; + } + + for (size_t i = 0; i < m_sources.size(); i++) + { + ostringstream result; + ASTJsonConverter(true, sourceIndices).print(result, c.ast(m_sources[i].first)); + m_resultLegacy = result.str(); + if (i != m_sources.size() - 1) + m_resultLegacy += ","; + m_resultLegacy += "\n"; + } + + if (m_expectationLegacy != m_resultLegacy) + { + string nextIndentLevel = _linePrefix + " "; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result (legacy):" << endl; + { + istringstream stream(m_expectationLegacy); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + FormattedScope(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result (legacy):" << endl; + { + istringstream stream(m_resultLegacy); + string line; + while (getline(stream, line)) + _stream << nextIndentLevel << line << endl; + } + _stream << endl; + resultsMatch = false; + } + + return resultsMatch; +} + +void ASTJSONTest::printSource(ostream& _stream, string const& _linePrefix, bool const) const +{ + for (auto const& source: m_sources) + { + if (m_sources.size() > 1 || source.first != "a") + _stream << _linePrefix << "// ---- SOURCE: " << source.first << endl << endl; + stringstream stream(source.second); + string line; + while (getline(stream, line)) + _stream << _linePrefix << line << endl; + _stream << endl; + } +} + +void ASTJSONTest::printUpdatedExpectations(std::ostream&, std::string const&) const +{ + ofstream file(m_astFilename.c_str()); + if (!file) BOOST_THROW_EXCEPTION(runtime_error("Cannot write AST expectation to \"" + m_astFilename + "\".")); + file.exceptions(ios::badbit); + file << m_result; + file.flush(); + file.close(); + file.open(m_legacyAstFilename.c_str()); + if (!file) BOOST_THROW_EXCEPTION(runtime_error("Cannot write legacy AST expectation to \"" + m_legacyAstFilename + "\".")); + file << m_resultLegacy; + file.flush(); + file.close(); +} diff --git a/test/libsolidity/ASTJSONTest.h b/test/libsolidity/ASTJSONTest.h new file mode 100644 index 00000000..6f24bb60 --- /dev/null +++ b/test/libsolidity/ASTJSONTest.h @@ -0,0 +1,58 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include <test/libsolidity/FormattedScope.h> +#include <test/libsolidity/TestCase.h> + +#include <iosfwd> +#include <string> +#include <vector> +#include <utility> + +namespace dev +{ +namespace solidity +{ +namespace test +{ + +class ASTJSONTest: public TestCase +{ +public: + static std::unique_ptr<TestCase> create(std::string const& _filename) + { return std::unique_ptr<TestCase>(new ASTJSONTest(_filename)); } + ASTJSONTest(std::string const& _filename); + + virtual bool run(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) override; + + virtual void printSource(std::ostream& _stream, std::string const& _linePrefix = "", bool const _formatted = false) const override; + virtual void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix) const override; +private: + std::vector<std::pair<std::string, std::string>> m_sources; + std::string m_expectation; + std::string m_expectationLegacy; + std::string m_astFilename; + std::string m_legacyAstFilename; + std::string m_result; + std::string m_resultLegacy; +}; + +} +} +} diff --git a/test/libsolidity/ASTLegacyJSON.cpp b/test/libsolidity/ASTLegacyJSON.cpp deleted file mode 100644 index 69cb1bb9..00000000 --- a/test/libsolidity/ASTLegacyJSON.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see <http://www.gnu.org/licenses/>. -*/ -/** - * @author Christian <c@ethdev.com> - * @date 2016 - * Tests for the json ast output. - */ - -#include <test/Options.h> - -#include <libsolidity/interface/Exceptions.h> -#include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/ast/ASTJsonConverter.h> - -#include <boost/test/unit_test.hpp> - -#include <string> - -using namespace std; - -namespace dev -{ -namespace solidity -{ -namespace test -{ - -BOOST_AUTO_TEST_SUITE(SolidityASTLegacyJSON) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CompilerStack c; - c.addSource("a", "contract C {}"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); -} - -BOOST_AUTO_TEST_CASE(source_location) -{ - CompilerStack c; - c.addSource("a", "contract C { function f() { var x = 2; x++; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["name"], "SourceUnit"); - BOOST_CHECK_EQUAL(astJson["children"][0]["name"], "ContractDefinition"); - BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["name"], "FunctionDefinition"); - BOOST_CHECK_EQUAL(astJson["children"][0]["children"][0]["src"], "13:32:1"); - -} - -BOOST_AUTO_TEST_CASE(inheritance_specifier) -{ - CompilerStack c; - c.addSource("a", "contract C1 {} contract C2 is C1 {}"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - BOOST_CHECK_EQUAL(astJson["children"][1]["attributes"]["name"], "C2"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["name"], "InheritanceSpecifier"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["src"], "30:2:1"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["name"], "UserDefinedTypeName"); - BOOST_CHECK_EQUAL(astJson["children"][1]["children"][0]["children"][0]["attributes"]["name"], "C1"); -} - -BOOST_AUTO_TEST_CASE(using_for_directive) -{ - CompilerStack c; - c.addSource("a", "library L {} contract C { using L for uint; }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value usingFor = astJson["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(usingFor["name"], "UsingForDirective"); - BOOST_CHECK_EQUAL(usingFor["src"], "26:17:1"); - BOOST_CHECK_EQUAL(usingFor["children"][0]["name"], "UserDefinedTypeName"); - BOOST_CHECK_EQUAL(usingFor["children"][0]["attributes"]["name"], "L"); - BOOST_CHECK_EQUAL(usingFor["children"][1]["name"], "ElementaryTypeName"); - BOOST_CHECK_EQUAL(usingFor["children"][1]["attributes"]["name"], "uint"); -} - -BOOST_AUTO_TEST_CASE(enum_value) -{ - CompilerStack c; - c.addSource("a", "contract C { enum E { A, B } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value enumDefinition = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["name"], "EnumValue"); - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["attributes"]["name"], "A"); - BOOST_CHECK_EQUAL(enumDefinition["children"][0]["src"], "22:1:1"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["name"], "EnumValue"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["attributes"]["name"], "B"); - BOOST_CHECK_EQUAL(enumDefinition["children"][1]["src"], "25:1:1"); -} - -BOOST_AUTO_TEST_CASE(modifier_definition) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) public {} }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value modifier = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(modifier["name"], "ModifierDefinition"); - BOOST_CHECK_EQUAL(modifier["attributes"]["name"], "M"); - BOOST_CHECK_EQUAL(modifier["src"], "13:25:1"); -} - -BOOST_AUTO_TEST_CASE(modifier_invocation) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M(uint i) { _; } function F() M(1) public {} }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value modifier = astJson["children"][0]["children"][1]["children"][2]; - BOOST_CHECK_EQUAL(modifier["name"], "ModifierInvocation"); - BOOST_CHECK_EQUAL(modifier["src"], "52:4:1"); - BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["type"], "modifier (uint256)"); - BOOST_CHECK_EQUAL(modifier["children"][0]["attributes"]["value"], "M"); - BOOST_CHECK_EQUAL(modifier["children"][1]["attributes"]["value"], "1"); -} - -BOOST_AUTO_TEST_CASE(event_definition) -{ - CompilerStack c; - c.addSource("a", "contract C { event E(); }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value event = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(event["name"], "EventDefinition"); - BOOST_CHECK_EQUAL(event["attributes"]["name"], "E"); - BOOST_CHECK_EQUAL(event["src"], "13:10:1"); -} - -BOOST_AUTO_TEST_CASE(array_type_name) -{ - CompilerStack c; - c.addSource("a", "contract C { uint[] i; }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value arrayDecl = astJson["children"][0]["children"][0]["attributes"]; - BOOST_CHECK_EQUAL(arrayDecl["storageLocation"], "default"); - BOOST_CHECK_EQUAL(arrayDecl["type"], "uint256[]"); - Json::Value array = astJson["children"][0]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(array["name"], "ArrayTypeName"); - BOOST_CHECK_EQUAL(array["src"], "13:6:1"); -} - -BOOST_AUTO_TEST_CASE(short_type_name) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() public { uint[] memory x; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value arrayDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["type"], "uint256[]"); -} - -BOOST_AUTO_TEST_CASE(short_type_name_ref) -{ - CompilerStack c; - c.addSource("a", "contract c { function f() public { uint[][] memory rows; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value arrayDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["storageLocation"], "memory"); - BOOST_CHECK_EQUAL(arrayDecl["attributes"]["type"], "uint256[][]"); -} - -BOOST_AUTO_TEST_CASE(placeholder_statement) -{ - CompilerStack c; - c.addSource("a", "contract C { modifier M { _; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value placeholder = astJson["children"][0]["children"][0]["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(placeholder["name"], "PlaceholderStatement"); - BOOST_CHECK_EQUAL(placeholder["src"], "26:1:1"); -} - -BOOST_AUTO_TEST_CASE(non_utf8) -{ - CompilerStack c; - c.addSource("a", "contract C { function f() public { var x = hex\"ff\"; } }"); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value varDecl = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(varDecl["attributes"]["type"], "string"); - BOOST_CHECK_EQUAL(varDecl["attributes"]["typeName"], Json::nullValue); - Json::Value literal = astJson["children"][0]["children"][0]["children"][2]["children"][0]["children"][1]; - BOOST_CHECK_EQUAL(literal["name"], "Literal"); - BOOST_CHECK_EQUAL(literal["attributes"]["hexvalue"], "ff"); - BOOST_CHECK_EQUAL(literal["attributes"]["token"], "string"); - BOOST_CHECK_EQUAL(literal["attributes"]["value"], Json::nullValue); - BOOST_CHECK(literal["attributes"]["type"].asString().find("invalid") != string::npos); -} - -BOOST_AUTO_TEST_CASE(function_type) -{ - CompilerStack c; - c.addSource("a", - "contract C { function f(function() external payable returns (uint) x) " - "returns (function() external view returns (uint)) {} }" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 1; - Json::Value astJson = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value fun = astJson["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition"); - Json::Value argument = fun["children"][0]["children"][0]; - BOOST_CHECK_EQUAL(argument["name"], "VariableDeclaration"); - BOOST_CHECK_EQUAL(argument["attributes"]["name"], "x"); - BOOST_CHECK_EQUAL(argument["attributes"]["type"], "function () payable external returns (uint256)"); - Json::Value funType = argument["children"][0]; - BOOST_CHECK_EQUAL(funType["attributes"]["constant"], false); - BOOST_CHECK_EQUAL(funType["attributes"]["payable"], true); - BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); - Json::Value retval = fun["children"][1]["children"][0]; - BOOST_CHECK_EQUAL(retval["name"], "VariableDeclaration"); - BOOST_CHECK_EQUAL(retval["attributes"]["name"], ""); - BOOST_CHECK_EQUAL(retval["attributes"]["type"], "function () view external returns (uint256)"); - funType = retval["children"][0]; - BOOST_CHECK_EQUAL(funType["attributes"]["constant"], true); - BOOST_CHECK_EQUAL(funType["attributes"]["payable"], false); - BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external"); -} - -BOOST_AUTO_TEST_CASE(documentation) -{ - CompilerStack c; - c.addSource("a", "/**This contract is empty*/ contract C {}"); - c.addSource("b", - "/**This contract is empty" - " and has a line-breaking comment.*/" - "contract C {}" - ); - c.addSource("c", - "contract C {" - " /** Some comment on Evt.*/ event Evt();" - " /** Some comment on mod.*/ modifier mod() { _; }" - " /** Some comment on fn.*/ function fn() public {}" - "}" - ); - c.setEVMVersion(dev::test::Options::get().evmVersion()); - c.parseAndAnalyze(); - map<string, unsigned> sourceIndices; - sourceIndices["a"] = 0; - sourceIndices["b"] = 1; - sourceIndices["c"] = 2; - Json::Value astJsonA = ASTJsonConverter(true, sourceIndices).toJson(c.ast("a")); - Json::Value documentationA = astJsonA["children"][0]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationA, "This contract is empty"); - Json::Value astJsonB = ASTJsonConverter(true, sourceIndices).toJson(c.ast("b")); - Json::Value documentationB = astJsonB["children"][0]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationB, "This contract is empty and has a line-breaking comment."); - Json::Value astJsonC = ASTJsonConverter(true, sourceIndices).toJson(c.ast("c")); - Json::Value documentationC0 = astJsonC["children"][0]["children"][0]["attributes"]["documentation"]; - Json::Value documentationC1 = astJsonC["children"][0]["children"][1]["attributes"]["documentation"]; - Json::Value documentationC2 = astJsonC["children"][0]["children"][2]["attributes"]["documentation"]; - BOOST_CHECK_EQUAL(documentationC0, "Some comment on Evt."); - BOOST_CHECK_EQUAL(documentationC1, "Some comment on mod."); - BOOST_CHECK_EQUAL(documentationC2, "Some comment on fn."); -} - - -BOOST_AUTO_TEST_SUITE_END() - -} -} -} // end namespaces diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 14413ca0..fdb11504 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -40,7 +40,7 @@ class JSONInterfaceChecker public: JSONInterfaceChecker(): m_compilerStack() {} - void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) + void checkInterface(std::string const& _code, std::string const& _contractName, std::string const& _expectedInterfaceString) { m_compilerStack.reset(false); m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code); @@ -48,7 +48,7 @@ public: m_compilerStack.setOptimiserSettings(dev::test::Options::get().optimize); BOOST_REQUIRE_MESSAGE(m_compilerStack.parseAndAnalyze(), "Parsing contract failed"); - Json::Value generatedInterface = m_compilerStack.contractABI(m_compilerStack.lastContractName()); + Json::Value generatedInterface = m_compilerStack.contractABI(_contractName); Json::Value expectedInterface; BOOST_REQUIRE(jsonParseStrict(_expectedInterfaceString, expectedInterface)); BOOST_CHECK_MESSAGE( @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(basic_test) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(empty_contract) @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(empty_contract) )"; char const* interface = "[]"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(multiple_methods) @@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(multiple_params) @@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(multiple_params) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(multiple_methods_order) @@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(view_function) @@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(view_function) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(pure_function) @@ -358,7 +358,7 @@ BOOST_AUTO_TEST_CASE(pure_function) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(events) @@ -436,7 +436,7 @@ BOOST_AUTO_TEST_CASE(events) ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(events_anonymous) @@ -456,7 +456,7 @@ BOOST_AUTO_TEST_CASE(events_anonymous) ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(inherited) @@ -531,7 +531,7 @@ BOOST_AUTO_TEST_CASE(inherited) }])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "Derived", interface); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { @@ -575,7 +575,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(empty_name_return_parameter) @@ -609,7 +609,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) ] } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(constructor_abi) @@ -641,7 +641,7 @@ BOOST_AUTO_TEST_CASE(constructor_abi) "type": "constructor" } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(payable_constructor_abi) @@ -673,7 +673,7 @@ BOOST_AUTO_TEST_CASE(payable_constructor_abi) "type": "constructor" } ])"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(return_param_in_abi) @@ -719,7 +719,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(strings_and_arrays) @@ -748,7 +748,7 @@ BOOST_AUTO_TEST_CASE(strings_and_arrays) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(library_function) @@ -756,7 +756,7 @@ BOOST_AUTO_TEST_CASE(library_function) char const* sourceCode = R"( library test { struct StructType { uint a; } - function f(StructType storage b, uint[] storage c, test d) public returns (uint[] memory e, StructType storage f) {} + function f(StructType storage b, uint[] storage c, test d) public returns (uint[] memory e, StructType storage f) { f = f; } } )"; @@ -780,7 +780,7 @@ BOOST_AUTO_TEST_CASE(library_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(include_fallback_function) @@ -800,7 +800,7 @@ BOOST_AUTO_TEST_CASE(include_fallback_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(payable_function) @@ -834,7 +834,7 @@ BOOST_AUTO_TEST_CASE(payable_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(payable_fallback_function) @@ -854,7 +854,7 @@ BOOST_AUTO_TEST_CASE(payable_fallback_function) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(function_type) @@ -881,12 +881,12 @@ BOOST_AUTO_TEST_CASE(function_type) } ] )"; - checkInterface(sourceCode, interface); + checkInterface(sourceCode, "test", interface); } BOOST_AUTO_TEST_CASE(return_structs) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; contract C { struct S { uint a; T[] sub; } @@ -931,12 +931,12 @@ BOOST_AUTO_TEST_CASE(return_structs) "type" : "function" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "C", interface); } BOOST_AUTO_TEST_CASE(return_structs_with_contracts) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; contract C { struct S { C[] x; C y; } @@ -974,12 +974,13 @@ BOOST_AUTO_TEST_CASE(return_structs_with_contracts) "type": "function" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "C", interface); } BOOST_AUTO_TEST_CASE(event_structs) { - char const* text = R"( + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; contract C { struct S { uint a; T[] sub; bytes b; } struct T { uint[2] x; } @@ -1031,12 +1032,12 @@ BOOST_AUTO_TEST_CASE(event_structs) "type": "event" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "C", interface); } BOOST_AUTO_TEST_CASE(structs_in_libraries) { - char const* text = R"( + char const* sourceCode = R"( pragma experimental ABIEncoderV2; library L { struct S { uint a; T[] sub; bytes b; } @@ -1095,7 +1096,7 @@ BOOST_AUTO_TEST_CASE(structs_in_libraries) "type": "function" }] )"; - checkInterface(text, interface); + checkInterface(sourceCode, "L", interface); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e9e7c93b..a6c1372b 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1478,6 +1478,73 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); } +BOOST_AUTO_TEST_CASE(mapping_local_assignment) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + m = m2; + m[2] = 21; + + return (m1[1], m1[2], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(byte(42), byte(0), byte(0), byte(21))); +} + +BOOST_AUTO_TEST_CASE(mapping_local_tuple_assignment) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + uint8 v; + (m, v) = (m2, 21); + m[2] = v; + + return (m1[1], m1[2], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(byte(42), byte(0), byte(0), byte(21))); +} + +BOOST_AUTO_TEST_CASE(mapping_local_compound_assignment) +{ + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) m1; + mapping(uint8 => uint8) m2; + function f() public returns (uint8, uint8, uint8, uint8) { + mapping(uint8 => uint8) storage m = m1; + m[1] = 42; + + (m = m2)[2] = 21; + + return (m1[1], m1[2], m2[1], m2[2]); + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(byte(42), byte(0), byte(0), byte(21))); +} + + BOOST_AUTO_TEST_CASE(structs) { char const* sourceCode = R"( @@ -4510,6 +4577,50 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints) ABI_CHECK(callContractFunction("test()"), encodeArgs(1)); } +BOOST_AUTO_TEST_CASE(enum_referencing) +{ + char const* sourceCode = R"( + interface I { + enum Direction { A, B, Left, Right } + } + library L { + enum Direction { Left, Right } + function f() public pure returns (Direction) { + return Direction.Right; + } + function g() public pure returns (I.Direction) { + return I.Direction.Right; + } + } + contract C is I { + function f() public pure returns (Direction) { + return Direction.Right; + } + function g() public pure returns (I.Direction) { + return I.Direction.Right; + } + function h() public pure returns (L.Direction) { + return L.Direction.Right; + } + function x() public pure returns (L.Direction) { + return L.f(); + } + function y() public pure returns (I.Direction) { + return L.g(); + } + } + )"; + compileAndRun(sourceCode, 0, "L"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); + compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}}); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("x()"), encodeArgs(1)); + ABI_CHECK(callContractFunction("y()"), encodeArgs(3)); +} + BOOST_AUTO_TEST_CASE(inline_member_init) { char const* sourceCode = R"( @@ -8910,52 +9021,6 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) ABI_CHECK(callContractFunction("separator2()"), encodeArgs(u256(0))); } -BOOST_AUTO_TEST_CASE(inline_assembly_jumps) -{ - char const* sourceCode = R"( - contract C { - function f() public { - assembly { - let n := calldataload(4) - let a := 1 - let b := a - loop: - jumpi(loopend, eq(n, 0)) - a add swap1 - n := sub(n, 1) - jump(loop) - loopend: - mstore(0, a) - return(0, 0x20) - } - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f()", u256(5)), encodeArgs(u256(13))); - ABI_CHECK(callContractFunction("f()", u256(7)), encodeArgs(u256(34))); -} - -BOOST_AUTO_TEST_CASE(inline_assembly_function_access) -{ - char const* sourceCode = R"( - contract C { - uint public x; - function g(uint y) public { x = 2 * y; assembly { stop } } - function f(uint _x) public { - assembly { - _x - jump(g) - pop - } - } - } - )"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f(uint256)", u256(5)), encodeArgs()); - ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(10))); -} - BOOST_AUTO_TEST_CASE(inline_assembly_function_call) { char const* sourceCode = R"( @@ -11261,7 +11326,7 @@ BOOST_AUTO_TEST_CASE(invalid_instruction) contract C { function f() public { assembly { - invalid + invalid() } } } @@ -11688,19 +11753,10 @@ BOOST_AUTO_TEST_CASE(keccak256_assembly) ret := keccak256(0, 0) } } - function g() public pure returns (bytes32 ret) { - assembly { - 0 - 0 - keccak256 - =: ret - } - } } )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); - ABI_CHECK(callContractFunction("g()"), fromHex("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")); } BOOST_AUTO_TEST_CASE(multi_modifiers) @@ -12477,6 +12533,80 @@ BOOST_AUTO_TEST_CASE(abi_encode_with_signaturev2) ABI_CHECK(callContractFunction("f4()"), expectation); } +BOOST_AUTO_TEST_CASE(abi_encode_empty_string) +{ + char const* sourceCode = R"( + // Tests that this will not end up using a "bytes0" type + // (which would assert) + contract C { + function f() public pure returns (bytes memory, bytes memory) { + return (abi.encode(""), abi.encodePacked("")); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x40, 0xc0, + 0x60, 0x20, 0x00, 0x00, + 0x00 + )); +} + +BOOST_AUTO_TEST_CASE(abi_encode_empty_string_v2) +{ + char const* sourceCode = R"( + // Tests that this will not end up using a "bytes0" type + // (which would assert) + pragma experimental ABIEncoderV2; + contract C { + function f() public pure returns (bytes memory, bytes memory) { + return (abi.encode(""), abi.encodePacked("")); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x40, 0xa0, + 0x40, 0x20, 0x00, + 0x00 + )); +} + +BOOST_AUTO_TEST_CASE(abi_encode_rational) +{ + char const* sourceCode = R"( + // Tests that rational numbers (even negative ones) are encoded properly. + contract C { + function f() public pure returns (bytes memory) { + return abi.encode(1, -2); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x20, + 0x40, u256(1), u256(-2) + )); +} + +BOOST_AUTO_TEST_CASE(abi_encode_rational_v2) +{ + char const* sourceCode = R"( + // Tests that rational numbers (even negative ones) are encoded properly. + pragma experimental ABIEncoderV2; + contract C { + function f() public pure returns (bytes memory) { + return abi.encode(1, -2); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f()"), encodeArgs( + 0x20, + 0x40, u256(1), u256(-2) + )); +} + BOOST_AUTO_TEST_CASE(abi_encode_call) { char const* sourceCode = R"T( @@ -12547,50 +12677,6 @@ BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) } } -BOOST_AUTO_TEST_CASE(swap_peephole_optimisation) -{ - char const* sourceCode = R"( - contract C { - function lt(uint a, uint b) public returns (bool c) { - assembly { - a - b - swap1 - lt - =: c - } - } - function add(uint a, uint b) public returns (uint c) { - assembly { - a - b - swap1 - add - =: c - } - } - function div(uint a, uint b) public returns (uint c) { - assembly { - a - b - swap1 - div - =: c - } - } - } - )"; - compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(1))); - BOOST_CHECK(callContractFunction("lt(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(1), u256(2)) == encodeArgs(u256(3))); - BOOST_CHECK(callContractFunction("add(uint256,uint256)", u256(100), u256(200)) == encodeArgs(u256(300))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(2), u256(1)) == encodeArgs(u256(2))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(200), u256(10)) == encodeArgs(u256(20))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(1), u256(0)) == encodeArgs(u256(0))); - BOOST_CHECK(callContractFunction("div(uint256,uint256)", u256(0), u256(1)) == encodeArgs(u256(0))); -} - BOOST_AUTO_TEST_CASE(bitwise_shifting_constantinople) { if (!dev::test::Options::get().evmVersion().hasBitwiseShifting()) @@ -12599,26 +12685,17 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constantinople) contract C { function shl(uint a, uint b) public returns (uint c) { assembly { - a - b - shl - =: c + c := shl(b, a) } } function shr(uint a, uint b) public returns (uint c) { assembly { - a - b - shr - =: c + c := shr(b, a) } } function sar(uint a, uint b) public returns (uint c) { assembly { - a - b - sar - =: c + c := sar(b, a) } } } @@ -12646,10 +12723,7 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) function shl_1() public returns (bool) { uint c; assembly { - 1 - 2 - shl - =: c + c := shl(2, 1) } assert(c == 4); return true; @@ -12657,10 +12731,7 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) function shl_2() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 1 - shl - =: c + c := shl(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe); return true; @@ -12668,10 +12739,7 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) function shl_3() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 256 - shl - =: c + c := shl(256, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0); return true; @@ -12679,10 +12747,7 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) function shr_1() public returns (bool) { uint c; assembly { - 3 - 1 - shr - =: c + c := shr(1, 3) } assert(c == 1); return true; @@ -12690,10 +12755,7 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) function shr_2() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 1 - shr - =: c + c := shr(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); return true; @@ -12701,10 +12763,7 @@ BOOST_AUTO_TEST_CASE(bitwise_shifting_constants_constantinople) function shr_3() public returns (bool) { uint c; assembly { - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - 256 - shr - =: c + c := shr(256, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) } assert(c == 0); return true; diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index d025e65a..41814888 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -390,12 +390,10 @@ BOOST_AUTO_TEST_CASE(unsatisfied_version) BOOST_AUTO_TEST_CASE(returndatasize_as_variable) { char const* text = R"( - contract c { function f() public { uint returndatasize; assembly { returndatasize }}} + contract C { function f() public pure { uint returndatasize; returndatasize; assembly { pop(returndatasize()) }}} )"; vector<pair<Error::Type, std::string>> expectations(vector<pair<Error::Type, std::string>>{ - {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"}, - {Error::Type::Warning, "The use of non-functional instructions is deprecated."}, - {Error::Type::DeclarationError, "Unbalanced stack"} + {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"} }); if (!dev::test::Options::get().evmVersion().supportsReturndata()) expectations.emplace_back(make_pair(Error::Type::Warning, std::string("\"returndatasize\" instruction is only available for Byzantium-compatible"))); @@ -405,15 +403,13 @@ BOOST_AUTO_TEST_CASE(returndatasize_as_variable) BOOST_AUTO_TEST_CASE(create2_as_variable) { char const* text = R"( - contract c { function f() public { uint create2; assembly { create2(0, 0, 0, 0) } }} + contract c { function f() public { uint create2; create2; assembly { pop(create2(0, 0, 0, 0)) } }} )"; // This needs special treatment, because the message mentions the EVM version, // so cannot be run via isoltest. CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{ {Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"}, {Error::Type::Warning, "The \"create2\" instruction is not supported by the VM version"}, - {Error::Type::DeclarationError, "Unbalanced stack"}, - {Error::Type::Warning, "not supposed to return values"} })); } diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 98a3bba9..cc44b578 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -41,6 +41,7 @@ public: void checkNatspec( std::string const& _code, + std::string const& _contractName, std::string const& _expectedDocumentationString, bool _userDocumentation ) @@ -52,9 +53,9 @@ public: Json::Value generatedDocumentation; if (_userDocumentation) - generatedDocumentation = m_compilerStack.natspecUser(m_compilerStack.lastContractName()); + generatedDocumentation = m_compilerStack.natspecUser(_contractName); else - generatedDocumentation = m_compilerStack.natspecDev(m_compilerStack.lastContractName()); + generatedDocumentation = m_compilerStack.natspecDev(_contractName); Json::Value expectedDocumentation; jsonParseStrict(_expectedDocumentationString, expectedDocumentation); BOOST_CHECK_MESSAGE( @@ -93,7 +94,7 @@ BOOST_AUTO_TEST_CASE(user_basic_test) " \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}" "}}"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) @@ -119,8 +120,8 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) " \"mul(uint256)\":{ \"notice\": \"Multiplies `a` by 7\"}" "}}"; - checkNatspec(sourceCode, devNatspec, false); - checkNatspec(sourceCode, userNatspec, true); + checkNatspec(sourceCode, "test", devNatspec, false); + checkNatspec(sourceCode, "test", userNatspec, true); } BOOST_AUTO_TEST_CASE(user_multiline_comment) @@ -140,7 +141,7 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) " \"mul_and_add(uint256,uint256)\":{ \"notice\": \"Multiplies `a` by 7 and then adds `b`\"}" "}}"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(user_multiple_functions) @@ -171,7 +172,7 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions) " \"sub(int256)\":{ \"notice\": \"Subtracts 3 from `input`\"}" "}}"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(user_empty_contract) @@ -182,7 +183,7 @@ BOOST_AUTO_TEST_CASE(user_empty_contract) char const* natspec = "{\"methods\":{} }"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) @@ -201,8 +202,8 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) char const* devNatspec = "{\"methods\":{}}"; char const* userNatspec = "{\"methods\":{}}"; - checkNatspec(sourceCode, devNatspec, false); - checkNatspec(sourceCode, userNatspec, true); + checkNatspec(sourceCode, "test", devNatspec, false); + checkNatspec(sourceCode, "test", userNatspec, true); } BOOST_AUTO_TEST_CASE(dev_desc_after_nl) @@ -228,7 +229,7 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiple_params) @@ -253,7 +254,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace) @@ -276,7 +277,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params_mixed_whitespace) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) @@ -302,7 +303,7 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiple_functions) @@ -353,7 +354,7 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_return) @@ -381,7 +382,7 @@ BOOST_AUTO_TEST_CASE(dev_return) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) { @@ -411,7 +412,7 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } @@ -443,7 +444,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_multiline_comment) @@ -476,7 +477,7 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment) " }\n" "}}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_contract_no_doc) @@ -496,7 +497,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc) " }\n" "}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_contract_doc) @@ -520,7 +521,7 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc) " }\n" "}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(dev_author_at_function) @@ -546,7 +547,7 @@ BOOST_AUTO_TEST_CASE(dev_author_at_function) " }\n" "}"; - checkNatspec(sourceCode, natspec, false); + checkNatspec(sourceCode, "test", natspec, false); } BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) @@ -569,7 +570,7 @@ BOOST_AUTO_TEST_CASE(natspec_notice_without_tag) } )ABCDEF"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag) @@ -592,7 +593,7 @@ BOOST_AUTO_TEST_CASE(natspec_multiline_notice_without_tag) } )ABCDEF"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(empty_comment) @@ -608,7 +609,7 @@ BOOST_AUTO_TEST_CASE(empty_comment) } )ABCDEF"; - checkNatspec(sourceCode, natspec, true); + checkNatspec(sourceCode, "test", natspec, true); } BOOST_AUTO_TEST_CASE(dev_title_at_function_error) diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index b8b537e5..db0e3b66 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -157,6 +157,9 @@ BOOST_AUTO_TEST_CASE(type_identifiers) BOOST_CHECK_EQUAL(RationalNumberType(rational(7, 1)).identifier(), "t_rational_7_by_1"); BOOST_CHECK_EQUAL(RationalNumberType(rational(200, 77)).identifier(), "t_rational_200_by_77"); BOOST_CHECK_EQUAL(RationalNumberType(rational(2 * 200, 2 * 77)).identifier(), "t_rational_200_by_77"); + BOOST_CHECK_EQUAL(RationalNumberType(rational(-2 * 200, -2 * 77)).identifier(), "t_rational_200_by_77"); + BOOST_CHECK_EQUAL(RationalNumberType(rational(-2 * 200, 2 * 77)).identifier(), "t_rational_minus_200_by_77"); + BOOST_CHECK_EQUAL(RationalNumberType(rational(2 * 200, -2 * 77)).identifier(), "t_rational_minus_200_by_77"); BOOST_CHECK_EQUAL( StringLiteralType(Literal(SourceLocation{}, Token::StringLiteral, make_shared<string>("abc - def"))).identifier(), "t_stringliteral_196a9142ee0d40e274a6482393c762b16dd8315713207365e1e13d8d85b74fc4" diff --git a/test/libsolidity/syntaxTests/constants/assign_constant_function_value_050.sol b/test/libsolidity/syntaxTests/constants/assign_constant_function_value_050.sol deleted file mode 100644 index 2c92899d..00000000 --- a/test/libsolidity/syntaxTests/constants/assign_constant_function_value_050.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental "v0.5.0"; - -contract C { - function () pure returns (uint) x; - uint constant y = x(); -} -// ---- -// TypeError: (105-108): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol new file mode 100644 index 00000000..5fde497c --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol @@ -0,0 +1,10 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure returns (S storage) { + assembly { + } + } +} +// ---- +// TypeError: (87-88): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol index 65902cc8..0d3db856 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_fine.sol @@ -8,7 +8,7 @@ contract C { } function g(bool flag) internal returns (S storage c) { // control flow in assembly will not be analyzed for now, - // so this will not issue a warning + // so this will not issue an error assembly { if flag { sstore(c_slot, sload(s_slot)) @@ -17,7 +17,7 @@ contract C { } function h() internal returns (S storage c) { // any reference from assembly will be sufficient for now, - // so this will not issue a warning + // so this will not issue an error assembly { sstore(s_slot, sload(c_slot)) } diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_warn.sol deleted file mode 100644 index 09c13847..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_warn.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal pure returns (S storage) { - assembly { - } - } -} -// ---- -// Warning: (87-88): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol new file mode 100644 index 00000000..eb574c96 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_err.sol @@ -0,0 +1,52 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + do { + break; + c = s; + } while(false); + } + function g() internal view returns (S storage c) { + do { + if (s.f) { + continue; + c = s; + } + else { + } + } while(false); + } + function h() internal view returns (S storage c) { + do { + if (s.f) { + break; + } + else { + c = s; + } + } while(false); + } + function i() internal view returns (S storage c) { + do { + if (s.f) { + continue; + } + else { + c = s; + } + } while(false); + } + function j() internal view returns (S storage c) { + do { + continue; + c = s; + } while(false); + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (223-234): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (440-451): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (654-665): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (871-882): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol deleted file mode 100644 index 7d001c19..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol +++ /dev/null @@ -1,52 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - do { - break; - c = s; - } while(false); - } - function g() internal view returns (S storage c) { - do { - if (s.f) { - continue; - c = s; - } - else { - } - } while(false); - } - function h() internal view returns (S storage c) { - do { - if (s.f) { - break; - } - else { - c = s; - } - } while(false); - } - function i() internal view returns (S storage c) { - do { - if (s.f) { - continue; - } - else { - c = s; - } - } while(false); - } - function j() internal view returns (S storage c) { - do { - continue; - c = s; - } while(false); - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (223-234): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (440-451): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (654-665): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (871-882): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol new file mode 100644 index 00000000..0d266ccf --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_err.sol @@ -0,0 +1,14 @@ +contract C { + struct S { bool f; } + S s; + function f() internal pure returns (S storage) { return; } + function g() internal view returns (S storage c, S storage) { c = s; return; } + function h() internal view returns (S storage, S storage d) { d = s; return; } + function i() internal pure returns (S storage, S storage) { return; } +} +// ---- +// TypeError: (87-88): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (163-164): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (233-234): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (316-317): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (327-328): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol index 3a0a30ea..6d72e4ef 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_fine.sol @@ -2,5 +2,6 @@ contract C { struct S { bool f; } S s; function f() internal view returns (S storage c, S storage d) { c = s; d = s; return; } + function g() internal view returns (S storage, S storage) { return (s,s); } } // ---- diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_warn.sol deleted file mode 100644 index 0a5b2fbf..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/emptyReturn_warn.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal pure returns (S storage) { return; } - function g() internal view returns (S storage c, S storage) { c = s; return; } - function h() internal view returns (S storage, S storage d) { d = s; return; } - function i() internal pure returns (S storage, S storage) { return; } - function j() internal view returns (S storage, S storage) { return (s,s); } -} -// ---- -// Warning: (87-88): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (163-164): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (233-234): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (316-317): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (327-328): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol new file mode 100644 index 00000000..9aa580a4 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_err.sol @@ -0,0 +1,16 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + for(;; c = s) { + } + } + function g() internal view returns (S storage c) { + for(;;) { + c = s; + } + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (182-193): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_warn.sol deleted file mode 100644 index ba9a2440..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/for_warn.sol +++ /dev/null @@ -1,16 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - for(;; c = s) { - } - } - function g() internal view returns (S storage c) { - for(;;) { - c = s; - } - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (182-193): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol new file mode 100644 index 00000000..f3e55318 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_err.sol @@ -0,0 +1,18 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view returns (S storage c) { + if (flag) c = s; + } + function g(bool flag) internal returns (S storage c) { + if (flag) c = s; + else + { + if (!flag) c = s; + else s.f = true; + } + } +} +// ---- +// TypeError: (96-107): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (186-197): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_warn.sol deleted file mode 100644 index c257c252..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/if_warn.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f(bool flag) internal view returns (S storage c) { - if (flag) c = s; - } - function g(bool flag) internal returns (S storage c) { - if (flag) c = s; - else - { - if (!flag) c = s; - else s.f = true; - } - } -} -// ---- -// Warning: (96-107): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (186-197): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol new file mode 100644 index 00000000..a0047782 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol @@ -0,0 +1,22 @@ +contract C { + modifier revertIfNoReturn() { + _; + revert(); + } + modifier ifFlag(bool flag) { + if (flag) + _; + } + struct S { uint a; } + S s; + function f(bool flag) ifFlag(flag) internal view returns(S storage) { + return s; + } + + function g(bool flag) ifFlag(flag) revertIfNoReturn() internal view returns(S storage) { + return s; + } +} +// ---- +// TypeError: (249-250): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (367-368): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_warn.sol deleted file mode 100644 index 50c6dd99..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_warn.sol +++ /dev/null @@ -1,22 +0,0 @@ -contract C { - modifier revertIfNoReturn() { - _; - revert(); - } - modifier ifFlag(bool flag) { - if (flag) - _; - } - struct S { uint a; } - S s; - function f(bool flag) ifFlag(flag) internal view returns(S storage) { - return s; - } - - function g(bool flag) ifFlag(flag) revertIfNoReturn() internal view returns(S storage) { - return s; - } -} -// ---- -// Warning: (249-250): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (367-368): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol new file mode 100644 index 00000000..d0ad8245 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_err.sol @@ -0,0 +1,18 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + false && (c = s).f; + } + function g() internal view returns (S storage c) { + true || (c = s).f; + } + function h() internal view returns (S storage c) { + // expect error, although this is always fine + true && (false || (c = s).f); + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (176-187): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (264-275): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_warn.sol deleted file mode 100644 index 9f660f11..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/short_circuit_warn.sol +++ /dev/null @@ -1,18 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - false && (c = s).f; - } - function g() internal view returns (S storage c) { - true || (c = s).f; - } - function h() internal view returns (S storage c) { - // expect warning, although this is always fine - true && (false || (c = s).f); - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (176-187): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (264-275): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol new file mode 100644 index 00000000..6d10287b --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_err.sol @@ -0,0 +1,13 @@ +contract C { + struct S { bool f; } + S s; + function f(bool flag) internal view returns (S storage c) { + flag ? (c = s).f : false; + } + function g(bool flag) internal view returns (S storage c) { + flag ? false : (c = s).f; + } +} +// ---- +// TypeError: (96-107): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (200-211): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_warn.sol deleted file mode 100644 index 57561fbb..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/ternary_warn.sol +++ /dev/null @@ -1,13 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f(bool flag) internal view returns (S storage c) { - flag ? (c = s).f : false; - } - function g(bool flag) internal view returns (S storage c) { - flag ? false : (c = s).f; - } -} -// ---- -// Warning: (96-107): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. -// Warning: (200-211): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol new file mode 100644 index 00000000..e7b4fae7 --- /dev/null +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_err.sol @@ -0,0 +1,11 @@ +contract C { + struct S { bool f; } + S s; + function f() internal view returns (S storage c) { + while(false) { + c = s; + } + } +} +// ---- +// TypeError: (87-98): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_warn.sol deleted file mode 100644 index 26db892f..00000000 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/while_warn.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - struct S { bool f; } - S s; - function f() internal view returns (S storage c) { - while(false) { - c = s; - } - } -} -// ---- -// Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/emit_empty.sol b/test/libsolidity/syntaxTests/emit/emit_empty.sol index 819d88fe..819d88fe 100644 --- a/test/libsolidity/syntaxTests/emit_empty.sol +++ b/test/libsolidity/syntaxTests/emit/emit_empty.sol diff --git a/test/libsolidity/syntaxTests/emit_non_event.sol b/test/libsolidity/syntaxTests/emit/emit_non_event.sol index d5045ddf..d5045ddf 100644 --- a/test/libsolidity/syntaxTests/emit_non_event.sol +++ b/test/libsolidity/syntaxTests/emit/emit_non_event.sol diff --git a/test/libsolidity/syntaxTests/events/event_nested_array.sol b/test/libsolidity/syntaxTests/events/event_nested_array.sol new file mode 100644 index 00000000..70af63b6 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_nested_array.sol @@ -0,0 +1,5 @@ +contract c { + event E(uint[][]); +} +// ---- +// TypeError: (25-33): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_2.sol new file mode 100644 index 00000000..5825650e --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_nested_array_2.sol @@ -0,0 +1,4 @@ +contract c { + event E(uint[2][]); +} +// ---- diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol b/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol new file mode 100644 index 00000000..fd59e962 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_nested_array_in_struct.sol @@ -0,0 +1,6 @@ +contract c { + struct S { uint x; uint[][] arr; } + event E(S); +} +// ---- +// TypeError: (61-62): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct.sol b/test/libsolidity/syntaxTests/events/event_struct.sol new file mode 100644 index 00000000..c955dc5e --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_struct.sol @@ -0,0 +1,6 @@ +contract c { + struct S { uint a ; } + event E(S); +} +// ---- +// TypeError: (51-52): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol new file mode 100644 index 00000000..69ee5017 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol @@ -0,0 +1,6 @@ +contract c { + struct S { uint a ; } + event E(S indexed); +} +// ---- +// TypeError: (51-52): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol deleted file mode 100644 index 8d5df5bf..00000000 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/ancestor_V050.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma experimental "v0.5.0"; - -contract A { constructor(uint) public { } } -contract B is A(2) { constructor() public { } } -contract C is B { constructor() A(3) public { } } -// ---- -// DeclarationError: (156-160): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol b/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol deleted file mode 100644 index f9325f99..00000000 --- a/test/libsolidity/syntaxTests/inheritance/duplicated_constructor_call/base_V050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; - -contract A { constructor(uint) public { } } -contract B is A(2) { constructor() A(3) public { } } -// ---- -// DeclarationError: (110-114): Base constructor arguments given twice. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol index cbea8991..ac1f541e 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_invalid_argument_count.sol @@ -11,6 +11,6 @@ contract C { } // ---- // TypeError: (87-88): Expected 1 arguments but got 0. -// Warning: (87-90): Top-level expressions are not supposed to return values (this expression returns -1 values). Use ``pop()`` or assign them. +// SyntaxError: (87-90): Top-level expressions are not supposed to return values (this expression returns -1 values). Use ``pop()`` or assign them. // TypeError: (108-109): Expected 1 arguments but got 2. -// Warning: (108-115): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// SyntaxError: (108-115): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol index 5de492e1..150fb938 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/function_call_to_label.sol @@ -8,6 +8,6 @@ contract C { } } // ---- -// Warning: (63-64): The use of labels is deprecated. Please use "if", "switch", "for" or function calls instead. -// Warning: (63-64): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. +// SyntaxError: (63-64): The use of labels is disallowed. Please use "if", "switch", "for" or function calls instead. +// SyntaxError: (63-64): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. // TypeError: (73-74): Attempt to call label instead of function. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol new file mode 100644 index 00000000..ec23a263 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_offset.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + _offset + } + } +} +// ---- +// DeclarationError: (75-82): In variable names _slot and _offset can only be used as a suffix. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol new file mode 100644 index 00000000..d493a68a --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_empty_slot.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure { + assembly { + _slot + } + } +} +// ---- +// DeclarationError: (75-80): In variable names _slot and _offset can only be used as a suffix. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol new file mode 100644 index 00000000..9165654f --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/storage_reference_on_function.sol @@ -0,0 +1,9 @@ +contract C { + function f() pure public { + assembly { + let x := f_slot + } + } +} +// ---- +// TypeError: (84-90): The suffixes _offset and _slot can only be used on storage variables. diff --git a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol b/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol deleted file mode 100644 index af1babbc..00000000 --- a/test/libsolidity/syntaxTests/modifiers/modifiers_on_abstract_functions_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract C -{ - modifier only_owner() { _; } - function foo() only_owner public; - function bar() public only_owner; -} -// ---- -// SyntaxError: (80-113): Functions without implementation cannot have modifiers. -// SyntaxError: (118-151): Functions without implementation cannot have modifiers. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol deleted file mode 100644 index 27b1ea96..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/016_assignment_to_mapping.sol +++ /dev/null @@ -1,12 +0,0 @@ -contract test { - struct str { - mapping(uint=>uint) map; - } - str data; - function fun() public { - mapping(uint=>uint) storage a = data.map; - data.map = a; - } -} -// ---- -// TypeError: (172-184): Mappings cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/166_assigning_state_to_const_variable_050.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/166_assigning_state_to_const_variable_050.sol deleted file mode 100644 index dc0a6e63..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/166_assigning_state_to_const_variable_050.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma experimental "v0.5.0"; - -contract C { - address constant x = msg.sender; -} -// ---- -// TypeError: (69-79): Initial value for constant variable has to be compile-time constant. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/352_callcode_deprecated_v050.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/352_callcode_deprecated_v050.sol deleted file mode 100644 index c0e29b38..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/352_callcode_deprecated_v050.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - address(0x12).callcode; - } -} -// ---- -// TypeError: (85-107): "callcode" has been deprecated in favour of "delegatecall". diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol index 273e1844..e9599f4b 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/373_inline_assembly_unbalanced_positive_stack.sol @@ -6,5 +6,5 @@ contract test { } } // ---- -// Warning: (73-74): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// SyntaxError: (73-74): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. // DeclarationError: (59-84): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol index bda090b4..342afc46 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/374_inline_assembly_unbalanced_negative_stack.sol @@ -6,5 +6,5 @@ contract test { } } // ---- -// Warning: (73-76): The use of non-functional instructions is deprecated. Please use functional notation instead. +// SyntaxError: (73-76): The use of non-functional instructions is disallowed. Please use functional notation instead. // DeclarationError: (59-86): Unbalanced stack at the end of a block: 1 missing item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol index 4cda64e7..ca1e15a9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/375_inline_assembly_unbalanced_two_stack_load.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract c { uint8 x; function f() public { @@ -6,4 +5,4 @@ contract c { } } // ---- -// TypeError: (105-106): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. +// TypeError: (75-76): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol index d6dcc4d0..0032f99e 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/376_inline_assembly_in_modifier.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { modifier m { uint a = 1; @@ -11,4 +10,4 @@ contract test { } } // ---- -// Warning: (152-181): Function state mutability can be restricted to pure +// Warning: (122-151): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol index 9a2065e2..3dfb458a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/377_inline_assembly_storage.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { uint x = 1; function f() public { @@ -8,4 +7,4 @@ contract test { } } // ---- -// TypeError: (119-120): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. +// TypeError: (89-90): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol index b99179ef..b9b92d47 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/378_inline_assembly_storage_in_modifiers.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { uint x = 1; modifier m { @@ -11,4 +10,4 @@ contract test { } } // ---- -// TypeError: (110-111): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. +// TypeError: (80-81): Only local variables are supported. To access storage variables, use the _slot and _offset suffixes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol index 866232dd..c8928804 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/379_inline_assembly_constant_assign.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { uint constant x = 1; function f() public { @@ -8,4 +7,4 @@ contract test { } } // ---- -// TypeError: (128-129): Constant variables not supported by inline assembly. +// TypeError: (98-99): Constant variables not supported by inline assembly. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol index a41858a0..03ff9166 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/380_inline_assembly_constant_access.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { uint constant x = 1; function f() public { @@ -8,4 +7,4 @@ contract test { } } // ---- -// TypeError: (137-138): Constant variables not supported by inline assembly. +// TypeError: (107-108): Constant variables not supported by inline assembly. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol index 93004ef6..877f5783 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/381_inline_assembly_local_variable_access_out_of_functions.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() public { uint a; @@ -8,4 +7,4 @@ contract test { } } // ---- -// DeclarationError: (144-145): Cannot access local Solidity variables from inside an inline assembly function. +// DeclarationError: (114-115): Cannot access local Solidity variables from inside an inline assembly function. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol index 913ea725..65d614a3 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/382_inline_assembly_local_variable_access_out_of_functions_storage_ptr.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { uint[] r; function f() public { @@ -9,4 +8,4 @@ contract test { } } // ---- -// DeclarationError: (172-180): Cannot access local Solidity variables from inside an inline assembly function. +// DeclarationError: (142-150): Cannot access local Solidity variables from inside an inline assembly function. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol index 7528f355..abe9067a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/383_inline_assembly_storage_variable_access_out_of_functions.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { uint a; function f() pure public { diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol index d95fd978..9e324ce1 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/385_inline_assembly_calldata_variables.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract C { function f(bytes bytesAsCalldata) external { assembly { @@ -7,4 +6,4 @@ contract C { } } // ---- -// TypeError: (132-147): Call data elements cannot be accessed directly. Copy to a local variable first or use "calldataload" or "calldatacopy" with manually determined offsets and sizes. +// TypeError: (102-117): Call data elements cannot be accessed directly. Copy to a local variable first or use "calldataload" or "calldatacopy" with manually determined offsets and sizes. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/386_inline_assembly_050_literals_on_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/386_inline_assembly_050_literals_on_stack.sol deleted file mode 100644 index a5f0f96c..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/386_inline_assembly_050_literals_on_stack.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() pure public { - assembly { - 1 - } - } -} -// ---- -// SyntaxError: (105-106): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. -// DeclarationError: (91-116): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol index 7b68c60b..62fe7171 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/387_inline_assembly_literals_on_stack.sol @@ -6,5 +6,5 @@ contract C { } } // ---- -// Warning: (75-76): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// SyntaxError: (75-76): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. // DeclarationError: (61-86): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/388_inline_assembly_050_bare_instructions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/388_inline_assembly_050_bare_instructions.sol deleted file mode 100644 index 4a7aca8a..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/388_inline_assembly_050_bare_instructions.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() view public { - assembly { - address - pop - } - } -} -// ---- -// SyntaxError: (105-112): The use of non-functional instructions is deprecated. Please use functional notation instead. -// SyntaxError: (125-128): The use of non-functional instructions is deprecated. Please use functional notation instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol index c44412cf..7315d5d1 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/389_inline_assembly_bare_instructions.sol @@ -7,5 +7,5 @@ contract C { } } // ---- -// Warning: (75-82): The use of non-functional instructions is deprecated. Please use functional notation instead. -// Warning: (95-98): The use of non-functional instructions is deprecated. Please use functional notation instead. +// SyntaxError: (75-82): The use of non-functional instructions is disallowed. Please use functional notation instead. +// SyntaxError: (95-98): The use of non-functional instructions is disallowed. Please use functional notation instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/390_inline_assembly_050_labels.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/390_inline_assembly_050_labels.sol deleted file mode 100644 index 77a73ebc..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/390_inline_assembly_050_labels.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() pure public { - assembly { - label: - } - } -} -// ---- -// SyntaxError: (105-110): The use of labels is deprecated. Please use "if", "switch", "for" or function calls instead. -// SyntaxError: (105-110): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol index 15bd6660..0d7bacb4 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/391_inline_assembly_labels.sol @@ -6,5 +6,5 @@ contract C { } } // ---- -// Warning: (75-80): The use of labels is deprecated. Please use "if", "switch", "for" or function calls instead. -// Warning: (75-80): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. +// SyntaxError: (75-80): The use of labels is disallowed. Please use "if", "switch", "for" or function calls instead. +// SyntaxError: (75-80): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/392_inline_assembly_050_jump.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/392_inline_assembly_050_jump.sol deleted file mode 100644 index 0c98ada1..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/392_inline_assembly_050_jump.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() pure public { - assembly { - jump(2) - } - } -} -// ---- -// SyntaxError: (105-112): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol index c3c82ce8..6cb35d6d 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/393_inline_assembly_jump.sol @@ -6,5 +6,4 @@ contract C { } } // ---- -// Warning: (75-82): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. -// TypeError: (75-82): Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// SyntaxError: (75-82): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/394_inline_assembly_050_leave_items_on_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/394_inline_assembly_050_leave_items_on_stack.sol deleted file mode 100644 index f72fe741..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/394_inline_assembly_050_leave_items_on_stack.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - function f() pure public { - assembly { - mload(0) - } - } -} -// ---- -// SyntaxError: (105-113): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. -// DeclarationError: (91-123): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol index 56043ccf..8538a2a0 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/395_inline_assembly_leave_items_on_stack.sol @@ -6,5 +6,5 @@ contract C { } } // ---- -// Warning: (75-83): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. +// SyntaxError: (75-83): Top-level expressions are not supposed to return values (this expression returns 1 value). Use ``pop()`` or assign them. // DeclarationError: (61-93): Unbalanced stack at the end of a block: 1 surplus item(s). diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol index 5513817d..1533e7ff 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/422_interface_enums.sol @@ -2,4 +2,3 @@ interface I { enum A { B, C } } // ---- -// TypeError: (18-33): Enumerable cannot be declared in interfaces. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/564_events_without_emit_deprecated_v050.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/564_events_without_emit_deprecated_v050.sol deleted file mode 100644 index e148d65a..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/564_events_without_emit_deprecated_v050.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma experimental "v0.5.0"; -contract C { - event e(); - function f() public { - e(); - } -} -// ---- -// TypeError: (92-95): Event invocations have to be prefixed by "emit". diff --git a/test/libsolidity/syntaxTests/parsing/enum_from_interface.sol b/test/libsolidity/syntaxTests/parsing/enum_from_interface.sol new file mode 100644 index 00000000..0fe0fbae --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_from_interface.sol @@ -0,0 +1,9 @@ +interface I { + enum Direction { Left, Right } +} + +contract D { + function f() public pure returns (I.Direction) { + return I.Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_from_interface_in_library.sol b/test/libsolidity/syntaxTests/parsing/enum_from_interface_in_library.sol new file mode 100644 index 00000000..8d9003eb --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_from_interface_in_library.sol @@ -0,0 +1,12 @@ +interface I { + enum Direction { Left, Right } +} + +library L { + function f() public pure returns (I.Direction) { + return I.Direction.Left; + } + function g() internal pure returns (I.Direction) { + return I.Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_from_library.sol b/test/libsolidity/syntaxTests/parsing/enum_from_library.sol new file mode 100644 index 00000000..ab762a82 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_from_library.sol @@ -0,0 +1,9 @@ +library L { + enum Direction { Left, Right } +} + +contract D { + function f() public pure returns (L.Direction) { + return L.Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_inheritance_contract.sol b/test/libsolidity/syntaxTests/parsing/enum_inheritance_contract.sol new file mode 100644 index 00000000..e5b98352 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_inheritance_contract.sol @@ -0,0 +1,9 @@ +contract C { + enum Direction { Left, Right } +} + +contract D is C { + function f() public pure returns (Direction) { + return Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/parsing/enum_inheritance_interface.sol b/test/libsolidity/syntaxTests/parsing/enum_inheritance_interface.sol new file mode 100644 index 00000000..75858744 --- /dev/null +++ b/test/libsolidity/syntaxTests/parsing/enum_inheritance_interface.sol @@ -0,0 +1,9 @@ +interface I { + enum Direction { Left, Right } +} + +contract D is I { + function f() public pure returns (Direction) { + return Direction.Left; + } +} diff --git a/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol new file mode 100644 index 00000000..3cff3a9a --- /dev/null +++ b/test/libsolidity/syntaxTests/tupleAssignments/double_storage_crash.sol @@ -0,0 +1,11 @@ +// This used to crash in certain compiler versions. +contract CrashContract { + struct S { uint a; } + S x; + function f() public { + (x, x) = 1(x, x); + } +} +// ---- +// TypeError: (170-177): Type is not callable +// TypeError: (170-177): Type tuple() is not implicitly convertible to expected type tuple(struct CrashContract.S storage ref,struct CrashContract.S storage ref). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol b/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol deleted file mode 100644 index 902d8b98..00000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_left.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - struct S { uint a; uint b; } - S x; S y; - function f() public { - (,x, y) = (1, 2, y, x); - } -} -// ---- -// TypeError: (89-101): Type tuple(int_const 1,int_const 2,struct C.S storage ref,struct C.S storage ref) is not implicitly convertible to expected type tuple(,struct C.S storage ref,struct C.S storage ref). -// Warning: (79-101): This assignment performs two copies to storage. Since storage copies do not first copy to a temporary location, one of them might be overwritten before the second is executed and thus may have unexpected effects. It is safer to perform the copies separately or assign to storage pointers first. diff --git a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol b/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol deleted file mode 100644 index 51556aab..00000000 --- a/test/libsolidity/syntaxTests/tupleAssignments/err_multiple_storage_storage_copies_fill_right.sol +++ /dev/null @@ -1,10 +0,0 @@ -contract C { - struct S { uint a; uint b; } - S x; S y; - function f() public { - (x, y, ) = (y, x, 1, 2); - } -} -// ---- -// TypeError: (90-102): Type tuple(struct C.S storage ref,struct C.S storage ref,int_const 1,int_const 2) is not implicitly convertible to expected type tuple(struct C.S storage ref,struct C.S storage ref,). -// Warning: (79-102): This assignment performs two copies to storage. Since storage copies do not first copy to a temporary location, one of them might be overwritten before the second is executed and thus may have unexpected effects. It is safer to perform the copies separately or assign to storage pointers first. diff --git a/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol b/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol index ae722391..32b381bb 100644 --- a/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol +++ b/test/libsolidity/syntaxTests/tupleAssignments/error_fill.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract C { function f() public pure returns (uint, uint, bytes32) { uint a; @@ -8,5 +7,5 @@ contract C { } } // ---- -// TypeError: (133-136): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(uint256,). -// TypeError: (147-150): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(,bytes32). +// TypeError: (103-106): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(uint256,). +// TypeError: (117-120): Type tuple(uint256,uint256,bytes32) is not implicitly convertible to expected type tuple(,bytes32). diff --git a/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol b/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol index bbf21d7e..f14641cb 100644 --- a/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol +++ b/test/libsolidity/syntaxTests/tupleAssignments/large_component_count.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract C { function g() public pure returns ( uint, diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol new file mode 100644 index 00000000..a329c91e --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_local.sol @@ -0,0 +1,11 @@ +contract test { + mapping(uint=>uint) map; + function fun() public view { + mapping(uint=>uint) storage a = map; + mapping(uint=>uint) storage b = map; + b = a; + (b) = a; + (b, b) = (a, a); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol new file mode 100644 index 00000000..1323afe6 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_state_variable.sol @@ -0,0 +1,14 @@ +contract test { + mapping(uint=>uint) map; + function fun() public { + mapping(uint=>uint) storage a = map; + map = a; + (map) = a; + (map, map) = (a, a); + } +} +// ---- +// TypeError: (126-129): Mappings cannot be assigned to. +// TypeError: (144-147): Mappings cannot be assigned to. +// TypeError: (163-166): Mappings cannot be assigned to. +// TypeError: (168-171): Mappings cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol new file mode 100644 index 00000000..b89241ed --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/assignment_struct.sol @@ -0,0 +1,17 @@ +contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() public { + mapping(uint=>uint) storage a = data.map; + data.map = a; + (data.map) = a; + (data.map, data.map) = (a, a); + } +} +// ---- +// TypeError: (172-180): Mappings cannot be assigned to. +// TypeError: (195-203): Mappings cannot be assigned to. +// TypeError: (219-227): Mappings cannot be assigned to. +// TypeError: (229-237): Mappings cannot be assigned to. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_external.sol new file mode 100644 index 00000000..85121241 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_external.sol @@ -0,0 +1,7 @@ +contract C { + function f() external pure returns (mapping(uint=>uint) storage m) { + } +} +// ---- +// TypeError: (53-82): Type is required to live outside storage. +// TypeError: (53-82): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol new file mode 100644 index 00000000..a46003f8 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_internal.sol @@ -0,0 +1,21 @@ +// This should be allowed in a future release. +contract C { + mapping(uint=>uint) m; + function f() internal view returns (mapping(uint=>uint) storage) { + return m; + } + function g() private view returns (mapping(uint=>uint) storage) { + return m; + } + function h() internal view returns (mapping(uint=>uint) storage r) { + r = m; + } + function i() private view returns (mapping(uint=>uint) storage r) { + (r,r) = (m,m); + } +} +// ---- +// TypeError: (127-146): Type is required to live outside storage. +// TypeError: (221-240): Type is required to live outside storage. +// TypeError: (316-345): Type is required to live outside storage. +// TypeError: (409-438): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public.sol new file mode 100644 index 00000000..383fa797 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_return_public.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns (mapping(uint=>uint) storage m) { + } +} +// ---- +// TypeError: (51-80): Type is required to live outside storage. +// TypeError: (51-80): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/var_type_suggest.sol b/test/libsolidity/syntaxTests/types/var_type_suggest.sol index 176fab96..cc35fdd6 100644 --- a/test/libsolidity/syntaxTests/types/var_type_suggest.sol +++ b/test/libsolidity/syntaxTests/types/var_type_suggest.sol @@ -12,6 +12,10 @@ contract C { var myblockhash = block.blockhash; var (a, b) = (2, "troi"); var (x,, z) = h(); + var (c, d) = (""); + var (k, l) = (2); + var (m, n) = 1; + var (o, p) = ""; } } // ---- @@ -21,3 +25,11 @@ contract C { // SyntaxError: (293-326): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. // SyntaxError: (336-360): Use of the "var" keyword is disallowed. Use explicit declaration `(uint8 a, string memory b) = ...´ instead. // SyntaxError: (370-387): Use of the "var" keyword is disallowed. Use explicit declaration `(uint256 x, , uint256 z) = ...´ instead. +// TypeError: (397-414): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (397-414): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// TypeError: (424-440): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (424-440): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// TypeError: (450-464): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (450-464): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. +// TypeError: (474-489): Different number of components on the left hand side (2) than on the right hand side (1). +// SyntaxError: (474-489): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly_jump_no_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly_jump_no_restrict_warning.sol deleted file mode 100644 index 418be561..00000000 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly_jump_no_restrict_warning.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract C { - function k() public { - assembly { jump(2) } - } -} -// ---- -// Warning: (58-65): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/assembly_jump_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/assembly_jump_view_fail.sol deleted file mode 100644 index c1729db7..00000000 --- a/test/libsolidity/syntaxTests/viewPureChecker/assembly_jump_view_fail.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract C { - function k() public view { - assembly { jump(2) } - } -} -// ---- -// Warning: (63-70): Jump instructions and labels are low-level EVM features that can lead to incorrect stack access. Because of that they are discouraged. Please consider using "switch", "if" or "for" statements instead. -// TypeError: (63-70): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_external.sol index 3f0a9aca..ed409e58 100644 --- a/test/libsolidity/syntaxTests/visibility/interface/function_external050.sol +++ b/test/libsolidity/syntaxTests/visibility/interface/function_external.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; interface I { function f() external; } diff --git a/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol b/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol deleted file mode 100644 index e0c04095..00000000 --- a/test/libsolidity/syntaxTests/visibility/interface/function_public050.sol +++ /dev/null @@ -1,6 +0,0 @@ -pragma experimental "v0.5.0"; -interface I { - function f() public; -} -// ---- -// TypeError: (45-65): Functions in interfaces must be declared external. diff --git a/test/tools/CMakeLists.txt b/test/tools/CMakeLists.txt index 257b4f24..d6df0ac8 100644 --- a/test/tools/CMakeLists.txt +++ b/test/tools/CMakeLists.txt @@ -3,5 +3,5 @@ target_link_libraries(solfuzzer PRIVATE libsolc evmasm ${Boost_PROGRAM_OPTIONS_L add_executable(isoltest isoltest.cpp ../Options.cpp ../libsolidity/TestCase.cpp ../libsolidity/SyntaxTest.cpp ../libsolidity/AnalysisFramework.cpp ../libsolidity/SolidityExecutionFramework.cpp ../ExecutionFramework.cpp - ../RPCSession.cpp) + ../RPCSession.cpp ../libsolidity/ASTJSONTest.cpp) target_link_libraries(isoltest PRIVATE libsolc solidity evmasm ${Boost_PROGRAM_OPTIONS_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index bd4b0db9..ad6b456d 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -18,6 +18,7 @@ #include <libdevcore/CommonIO.h> #include <test/libsolidity/AnalysisFramework.h> #include <test/libsolidity/SyntaxTest.h> +#include <test/libsolidity/ASTJSONTest.h> #include <boost/algorithm/string.hpp> #include <boost/algorithm/string/replace.hpp> @@ -44,8 +45,8 @@ namespace fs = boost::filesystem; struct TestStats { int successCount; - int runCount; - operator bool() const { return successCount == runCount; } + int testCount; + operator bool() const { return successCount == testCount; } }; class TestTool @@ -87,13 +88,15 @@ private: Request handleResponse(bool const _exception); TestCase::TestCaseCreator m_testCaseCreator; - bool const m_formatted; + bool const m_formatted = false; string const m_name; fs::path const m_path; unique_ptr<TestCase> m_test; + static bool m_exitRequested; }; string TestTool::editor; +bool TestTool::m_exitRequested = false; TestTool::Result TestTool::process() { @@ -194,7 +197,7 @@ TestStats TestTool::processPath( std::queue<fs::path> paths; paths.push(_path); int successCount = 0; - int runCount = 0; + int testCount = 0; while (!paths.empty()) { @@ -211,10 +214,15 @@ TestStats TestTool::processPath( if (fs::is_directory(entry.path()) || TestCase::isTestFilename(entry.path().filename())) paths.push(currentPath / entry.path().filename()); } + else if (m_exitRequested) + { + ++testCount; + paths.pop(); + } else { + ++testCount; TestTool testTool(_testCaseCreator, currentPath.string(), fullpath, _formatted); - ++runCount; auto result = testTool.process(); switch(result) @@ -224,10 +232,12 @@ TestStats TestTool::processPath( switch(testTool.handleResponse(result == Result::Exception)) { case Request::Quit: - return { successCount, runCount }; + paths.pop(); + m_exitRequested = true; + break; case Request::Rerun: cout << "Re-running test case..." << endl; - --runCount; + --testCount; break; case Request::Skip: paths.pop(); @@ -242,7 +252,7 @@ TestStats TestTool::processPath( } } - return { successCount, runCount }; + return { successCount, testCount }; } @@ -336,22 +346,53 @@ Allowed options)", } } + TestStats global_stats { 0, 0 }; + fs::path syntaxTestPath = testPath / "libsolidity" / "syntaxTests"; if (fs::exists(syntaxTestPath) && fs::is_directory(syntaxTestPath)) { auto stats = TestTool::processPath(SyntaxTest::create, testPath / "libsolidity", "syntaxTests", formatted); - cout << endl << "Summary: "; + cout << endl << "Syntax Test Summary: "; FormattedScope(cout, formatted, {BOLD, stats ? GREEN : RED}) << - stats.successCount << "/" << stats.runCount; - cout << " tests successful." << endl; + stats.successCount << "/" << stats.testCount; + cout << " tests successful." << endl << endl; - return stats ? 0 : 1; + global_stats.testCount += stats.testCount; + global_stats.successCount += stats.successCount; } else { cerr << "Syntax tests not found. Use the --testpath argument." << endl; return 1; } + + fs::path astJsonTestPath = testPath / "libsolidity" / "ASTJSON"; + + if (fs::exists(astJsonTestPath) && fs::is_directory(astJsonTestPath)) + { + auto stats = TestTool::processPath(ASTJSONTest::create, testPath / "libsolidity", "ASTJSON", formatted); + + cout << endl << "JSON AST Test Summary: "; + FormattedScope(cout, formatted, {BOLD, stats ? GREEN : RED}) << + stats.successCount << "/" << stats.testCount; + cout << " tests successful." << endl << endl; + + global_stats.testCount += stats.testCount; + global_stats.successCount += stats.successCount; + } + else + { + cerr << "JSON AST tests not found." << endl; + return 1; + } + + cout << endl << "Summary: "; + FormattedScope(cout, formatted, {BOLD, global_stats ? GREEN : RED}) << + global_stats.successCount << "/" << global_stats.testCount; + cout << " tests successful." << endl; + + + return global_stats ? 0 : 1; } |