mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into HEAD
This commit is contained in:
commit
e16811e79f
20
Changelog.md
20
Changelog.md
@ -4,20 +4,30 @@ Breaking Changes:
|
||||
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
|
||||
* Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type.
|
||||
|
||||
|
||||
### 0.7.4 (unreleased)
|
||||
|
||||
|
||||
### 0.7.3 (2020-10-07)
|
||||
|
||||
Important Bugfixes:
|
||||
* Code Generator: Properly cleanup after copying dynamic-array to storage for packed types.
|
||||
|
||||
Compiler Features:
|
||||
* Code generator: Implemented events with function type as one of its indexed parameters.
|
||||
* General: Option to stop compilation after parsing stage. Can be used with ``solc --stop-after parsing``
|
||||
* Optimizer: Optimize ``exp`` when base is ``-1``.
|
||||
* SMTChecker: Support ``addmod`` and ``mulmod``.
|
||||
* SMTChecker: Support array slices.
|
||||
* SMTChecker: Support type conversions.
|
||||
* Optimizer: Optimize ``exp`` when base is -1.
|
||||
* Code generator: Implemented events with function type as one of its indexed parameters.
|
||||
* General: Option to stop compilation after parsing stage. Can be used with ``solc --stop-after parsing``
|
||||
|
||||
|
||||
Bugfixes:
|
||||
* Fixed internal compiler errors for certain contracts involving the ``new`` expression.
|
||||
* JSON AST: Fix internal error when using ``--ast-json`` on a function with memory arguments in ABIEncoderV2 contracts.
|
||||
* Type Checker: Add missing checks for calls using types incompatible with ABIEncoderV1 in modules where ABIEncoderV2 is not enabled.
|
||||
* Type Checker: Fix internal compiler error when calling `.push(<arg>)` for a storage array with a nested mapping.
|
||||
|
||||
### 0.7.3 (unreleased)
|
||||
|
||||
|
||||
### 0.7.2 (2020-09-28)
|
||||
|
||||
|
110
appveyor.yml
110
appveyor.yml
@ -1,110 +0,0 @@
|
||||
#------------------------------------------------------------------------------
|
||||
# Appveyor configuration file for solidity.
|
||||
#
|
||||
# The documentation for solidity is hosted at:
|
||||
#
|
||||
# http://solidity.readthedocs.org
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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/>
|
||||
#
|
||||
# (c) 2016 solidity contributors.
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
branches:
|
||||
only:
|
||||
- release
|
||||
- develop
|
||||
configuration:
|
||||
- Release
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
# This is used for pushing to solidity-test-bytecodes
|
||||
priv_key:
|
||||
secure: yYGwg4rhCdHfwuv2mFjaNEDwAx3IKUbp0D5fMGpaKefnfk+BiMS5bqSHRiOj91PZ91P9pUk2Vu+eNuS4hTFCf1zFGfrOhlJ4Ij0xSyU5m/LQr590Mo+f7W94Xc8ubgo6j2hp9qH/szTqTzmAkmxKO5TLlWjVzVny2t/s5o5UprLS1/MdzDNLjpVNXR03oKfdWUV9a2l6+PejXCbqyUCagh6BByZqeAPbDcil6eAfxu4EPX83Fuurof+KqFzIWycBG5qK1pTipn2pxiA0QKuUrD8y8VNL0S23NTgxoxSp7nPVMd3K0qRSzPM5lrqS7Z8i3evkVwPbuhu0gSiV08jGVahH2snQ3JGYsH2D4KmVn/xiVBeJ0lRplYlfZF0GUu7iJ+DDxi6wBPhW9A25/NyD/mx7Ub2dLheyWi8AjdSCzhfRD+4We8FQQeHRo3Q0kAohFmlCXdXhrcwOOloId8r6xYwg+hWxHTt2Oe9CKwXfmiPjgl/Gd6lYgLpyyfJ8drQ6tjO/pybLEa10v74qYNdVW5LaLIsRUM9Jm/FDVTrOGYtPndi87mF+/tBJIaXXNz0EMl5xvsKW0SBfUMV49zoDDKZZgWyO9U/cfViEUi7Sdn9QLsBWLZfSgBQNkq3WGZVKPq58OxEWT9dUghQHlSVh2qWF/NUx0TRBjiJl9JM56ENTMD00y18eDcXNCeLLVYB+R1axabUPdXivrO+BrWQK94IWxKEJ+YYN8WVJWAO5T/EBDKwgiXGneePwJ75WP7XCLtuYxqjC+CeW3xBVCzCEeZB/VVBvt7fhmtcoeZZ6tAS10h0yY5WWZ/EUVorj+c/FrMm7Nlpcrd1p4hciffePSLVg+yvy9/xTuM9trYWMgj4xcDQbYsaeItHO2Z3EiUoCgNdUw6rONiNwS/XBApWhCcklWm0/g62h2gOa7/hnKG6p2omQzYw+cOzWbF9+DBzoTSXXZXqbUshVee+CD+iYJKleGYSdbMdM89HW4HyskHk6HgM1ggE8CsgD1pMhXtqLTYZBlvsZCBkHPkD9NhGD2DtrNOmJOW8xwkL2/Il6roDF4n856XNdsjvd++rvQoKr58SkyApCJeCo3sfVres0W22g+7If2b2kWC4/DphrFkeaceFzJOctBUrwstvQBXIVOcadU978A3E7jvTaMR4JL9kC/iPOUVNjNRNM/gNvTlf3CIyMMszFeftjEBGnCZaSpht2RtNapRQQb6QPkOP88nufQVZq/TP1ECmvdTUWJ7kSnAupu6u8oH2x2IIm/KKeIwSYU5rGxjRb36DwgXCHcwfRYo3VNorwTeZGj4q1TSM9PuvgzNg//gKZW6VRa+HdNm/40ZGpDsOrr55tOBqfpq9k5RmevqW/OMZS3xUuArKdYLQY75t9eWcbHSgFN2ZY1KEdyEEvVKgs6Q4lEnSSulGxroRxTU5BOoA0V4tCeCUoSPD3FB93WsO9fBPzNsqOuBtDdIkApefzc1pT38uKpmVfggKUsoWUdqMXAWqCDWr2uw9EE900RJpEY6mIEWhkcro5LAMwaqByOGpqFFUkH+UWTC102eVHEmjxKpC6c6cSzoKKU6Ckd+jVRFO7TvmVe1MKCwjXj8lcAfAM2gQ+XehtrQdIBhAmCrnzurfz2u9tKVdpiADC1ig+kMs1/HX2713LYVXzDKdk+duQ94SVtGv9F2Iv+KN5oq4UFgll6VGt7GHsJOrYYf/wrOfB09IkpmjNygvcpmmSdcXXF8ulDD6KHTGEGUlFwLOpEwKx+zX2ZvviStHhN8KsoTKSVSueDmSSI63HdTS7FxfrHJc1yAzsdqEN5g5eV/z2Fn34qy64mdFSAZMF5zsbWZYFpc9ef3llF5aRcuD90JWT2VC7rB2jeGEtiwGkDlqKzxqRvJk06wTK6+n5RncN66bDaksulOPJMAR/bRW7dinV8T6yIvybuhqDetxJQP6eyAnW4xr1YxIAG4BXGZV6XAPTgOG2oGvMdncxkcLQHXVu07x39ySqP/m2MBxn0zF3DmaqrSPIRMhS8gG3d/23Jux3YHDEOBHjdJSdwqs5F5+QBFPV2rmJnpcSoW4d3M119XI20L914c62R7wY4e6+qmi3ydQU9g6p8psZgaE3TuMsyzX3k4C30nC/3gWT+zl253NjZwfbzIdHu5LWNDY9kEHtKzLP
|
||||
# NB: Appveyor cache is disabled, because it is proving very unreliable.
|
||||
# We can re-enable it when we find a way to mitigate the unreliability
|
||||
# issues. Have automated builds be reliable is the more important thing.
|
||||
#cache: build
|
||||
#
|
||||
# In case we'd need a RDP detail to login into appveyor
|
||||
#init:
|
||||
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
install:
|
||||
- ps: if ($env:priv_key) {
|
||||
$fileContent = "-----BEGIN RSA PRIVATE KEY-----`n";
|
||||
$fileContent += $env:priv_key.Replace(' ', "`n");
|
||||
$fileContent += "`n-----END RSA PRIVATE KEY-----`n";
|
||||
Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent
|
||||
}
|
||||
- ps: $prerelease = "nightly."
|
||||
- ps: $prerelease += Get-Date -format "yyyy.M.d"
|
||||
- ps: if($env:appveyor_repo_branch -eq 'release') { Set-Content prerelease.txt $null } else { Set-Content prerelease.txt $prerelease }
|
||||
- scripts/install_deps.bat
|
||||
- set ETHEREUM_DEPS_PATH=%APPVEYOR_BUILD_FOLDER%\deps\install
|
||||
before_build:
|
||||
- if not exist build mkdir build
|
||||
- cd build
|
||||
- cmake -G "Visual Studio 15 2017 Win64" .. -DTESTS=On -DBoost_USE_STATIC_RUNTIME=OFF
|
||||
build_script:
|
||||
- msbuild solidity.sln /p:Configuration=%CONFIGURATION% /m:%NUMBER_OF_PROCESSORS% /v:minimal
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- scripts\release.bat %CONFIGURATION% 2017
|
||||
- ps: $bytecodedir = git show -s --format="%cd-%H" --date="format:%Y-%m-%d-%H-%M"
|
||||
|
||||
test_script:
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION%
|
||||
- soltest.exe --show-progress -- --testpath %APPVEYOR_BUILD_FOLDER%\test --no-smt
|
||||
# Skip bytecode compare if private key is not available
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- ps: if ($env:priv_key -and -not $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) {
|
||||
scripts\bytecodecompare\storebytecode.bat $Env:CONFIGURATION $bytecodedir
|
||||
}
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\build\test\%CONFIGURATION%
|
||||
|
||||
artifacts:
|
||||
- path: solidity-windows.zip
|
||||
name: solidity-windows-zip
|
||||
|
||||
# This is the deploy target for Windows which generates ZIPs per commit.
|
||||
# We are in agreement that generating ZIPs per commit for the develop
|
||||
# branch is probably just noise, so we only run this deployment target
|
||||
# on 'release'.
|
||||
#
|
||||
# See https://www.appveyor.com/docs/deployment/github for information
|
||||
# on GitHub Releases in Appveyor.
|
||||
#
|
||||
# You need to generate a GitHub personal access token for Appveyor
|
||||
# See https://github.com/settings/tokens for more information on that.
|
||||
# The token you generate there (in an encrypted form) is what is
|
||||
# passed to this deployment target in the 'auth_token' parameter
|
||||
# below.
|
||||
|
||||
deploy:
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: HPjiugbDSCsEFTphj/qwHuSw80/BV1xWoSvj95CPmtb16Ukh2VQbLVB7iFtZSans
|
||||
artifact: solidity-windows-zip
|
||||
on:
|
||||
branch: release
|
||||
appveyor_repo_tag: true
|
||||
|
||||
notifications:
|
||||
- provider: GitHubPullRequest
|
||||
on_build_success: false
|
||||
on_build_failure: false
|
||||
on_build_status_changed: false
|
@ -1,4 +1,11 @@
|
||||
[
|
||||
{
|
||||
"name": "DynamicArrayCleanup",
|
||||
"summary": "When assigning a dynamically-sized array with types of size at most 16 bytes in storage causing the assigned array to shrink, some parts of deleted slots were not zeroed out.",
|
||||
"description": "Consider a dynamically-sized array in storage whose base-type is small enough such that multiple values can be packed into a single slot, such as `uint128[]`. Let us define its length to be `l`. When this array gets assigned from another array with a smaller length, say `m`, the slots between elements `m` and `l` have to be cleaned by zeroing them out. However, this cleaning was not performed properly. Specifically, after the slot corresponding to `m`, only the first packed value was cleaned up. If this array gets resized to a length larger than `m`, the indices corresponding to the unclean parts of the slot contained the original value, instead of 0. The resizing here is performed by assigning to the array `length`, by a `push()` or via inline assembly. You are not affected if you are only using `.push(<arg>)` or if you assign a value (even zero) to the new elements after increasing the length of the array.",
|
||||
"fixed": "0.7.3",
|
||||
"severity": "medium"
|
||||
},
|
||||
{
|
||||
"name": "FreeFunctionRedefinition",
|
||||
"summary": "The compiler does not flag an error when two or more free functions with the same name and parameter types are defined in a source unit or when an imported free function alias shadows another free function with a different name but identical parameter types.",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"0.1.0": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -19,6 +20,7 @@
|
||||
},
|
||||
"0.1.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -37,6 +39,7 @@
|
||||
},
|
||||
"0.1.2": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -55,6 +58,7 @@
|
||||
},
|
||||
"0.1.3": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -73,6 +77,7 @@
|
||||
},
|
||||
"0.1.4": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
"ZeroFunctionSelector",
|
||||
@ -92,6 +97,7 @@
|
||||
},
|
||||
"0.1.5": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
"ZeroFunctionSelector",
|
||||
@ -111,6 +117,7 @@
|
||||
},
|
||||
"0.1.6": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
@ -132,6 +139,7 @@
|
||||
},
|
||||
"0.1.7": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"ExpExponentCleanup",
|
||||
"NestedArrayFunctionCallDecoder",
|
||||
@ -153,6 +161,7 @@
|
||||
},
|
||||
"0.2.0": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"ExpExponentCleanup",
|
||||
@ -175,6 +184,7 @@
|
||||
},
|
||||
"0.2.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"ExpExponentCleanup",
|
||||
@ -197,6 +207,7 @@
|
||||
},
|
||||
"0.2.2": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"ExpExponentCleanup",
|
||||
@ -219,6 +230,7 @@
|
||||
},
|
||||
"0.3.0": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -243,6 +255,7 @@
|
||||
},
|
||||
"0.3.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -266,6 +279,7 @@
|
||||
},
|
||||
"0.3.2": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -289,6 +303,7 @@
|
||||
},
|
||||
"0.3.3": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -311,6 +326,7 @@
|
||||
},
|
||||
"0.3.4": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -333,6 +349,7 @@
|
||||
},
|
||||
"0.3.5": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -355,6 +372,7 @@
|
||||
},
|
||||
"0.3.6": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -375,6 +393,7 @@
|
||||
},
|
||||
"0.4.0": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -395,6 +414,7 @@
|
||||
},
|
||||
"0.4.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -415,6 +435,7 @@
|
||||
},
|
||||
"0.4.10": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -434,6 +455,7 @@
|
||||
},
|
||||
"0.4.11": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -452,6 +474,7 @@
|
||||
},
|
||||
"0.4.12": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -469,6 +492,7 @@
|
||||
},
|
||||
"0.4.13": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -486,6 +510,7 @@
|
||||
},
|
||||
"0.4.14": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -502,6 +527,7 @@
|
||||
},
|
||||
"0.4.15": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -517,6 +543,7 @@
|
||||
},
|
||||
"0.4.16": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -534,6 +561,7 @@
|
||||
},
|
||||
"0.4.17": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -552,6 +580,7 @@
|
||||
},
|
||||
"0.4.18": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -569,6 +598,7 @@
|
||||
},
|
||||
"0.4.19": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -587,6 +617,7 @@
|
||||
},
|
||||
"0.4.2": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -606,6 +637,7 @@
|
||||
},
|
||||
"0.4.20": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -624,6 +656,7 @@
|
||||
},
|
||||
"0.4.21": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -642,6 +675,7 @@
|
||||
},
|
||||
"0.4.22": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -660,6 +694,7 @@
|
||||
},
|
||||
"0.4.23": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -677,6 +712,7 @@
|
||||
},
|
||||
"0.4.24": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -694,6 +730,7 @@
|
||||
},
|
||||
"0.4.25": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -709,6 +746,7 @@
|
||||
},
|
||||
"0.4.26": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -721,6 +759,7 @@
|
||||
},
|
||||
"0.4.3": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -739,6 +778,7 @@
|
||||
},
|
||||
"0.4.4": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
"privateCanBeOverridden",
|
||||
@ -756,6 +796,7 @@
|
||||
},
|
||||
"0.4.5": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -776,6 +817,7 @@
|
||||
},
|
||||
"0.4.6": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -795,6 +837,7 @@
|
||||
},
|
||||
"0.4.7": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -814,6 +857,7 @@
|
||||
},
|
||||
"0.4.8": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -833,6 +877,7 @@
|
||||
},
|
||||
"0.4.9": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -852,6 +897,7 @@
|
||||
},
|
||||
"0.5.0": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -867,6 +913,7 @@
|
||||
},
|
||||
"0.5.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -882,6 +929,7 @@
|
||||
},
|
||||
"0.5.10": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -893,6 +941,7 @@
|
||||
},
|
||||
"0.5.11": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -903,6 +952,7 @@
|
||||
},
|
||||
"0.5.12": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -913,6 +963,7 @@
|
||||
},
|
||||
"0.5.13": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -923,6 +974,7 @@
|
||||
},
|
||||
"0.5.14": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
@ -935,6 +987,7 @@
|
||||
},
|
||||
"0.5.15": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
@ -946,6 +999,7 @@
|
||||
},
|
||||
"0.5.16": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
@ -956,6 +1010,7 @@
|
||||
},
|
||||
"0.5.17": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
@ -965,6 +1020,7 @@
|
||||
},
|
||||
"0.5.2": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -980,6 +1036,7 @@
|
||||
},
|
||||
"0.5.3": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -995,6 +1052,7 @@
|
||||
},
|
||||
"0.5.4": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -1010,6 +1068,7 @@
|
||||
},
|
||||
"0.5.5": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -1027,6 +1086,7 @@
|
||||
},
|
||||
"0.5.6": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -1044,6 +1104,7 @@
|
||||
},
|
||||
"0.5.7": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -1059,6 +1120,7 @@
|
||||
},
|
||||
"0.5.8": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -1073,6 +1135,7 @@
|
||||
},
|
||||
"0.5.9": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
"TupleAssignmentMultiStackSlotComponents",
|
||||
"MemoryArrayCreationOverflow",
|
||||
@ -1086,6 +1149,7 @@
|
||||
},
|
||||
"0.6.0": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
@ -1097,6 +1161,7 @@
|
||||
},
|
||||
"0.6.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
@ -1106,19 +1171,26 @@
|
||||
"released": "2020-01-02"
|
||||
},
|
||||
"0.6.10": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup"
|
||||
],
|
||||
"released": "2020-06-11"
|
||||
},
|
||||
"0.6.11": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup"
|
||||
],
|
||||
"released": "2020-07-07"
|
||||
},
|
||||
"0.6.12": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup"
|
||||
],
|
||||
"released": "2020-07-22"
|
||||
},
|
||||
"0.6.2": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
@ -1129,6 +1201,7 @@
|
||||
},
|
||||
"0.6.3": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
@ -1139,6 +1212,7 @@
|
||||
},
|
||||
"0.6.4": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
@ -1149,6 +1223,7 @@
|
||||
},
|
||||
"0.6.5": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck",
|
||||
@ -1158,6 +1233,7 @@
|
||||
},
|
||||
"0.6.6": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck"
|
||||
@ -1166,6 +1242,7 @@
|
||||
},
|
||||
"0.6.7": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"MissingEscapingInFormatting",
|
||||
"ArraySliceDynamicallyEncodedBaseType",
|
||||
"ImplicitConstructorCallvalueCheck"
|
||||
@ -1173,27 +1250,39 @@
|
||||
"released": "2020-05-04"
|
||||
},
|
||||
"0.6.8": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup"
|
||||
],
|
||||
"released": "2020-05-14"
|
||||
},
|
||||
"0.6.9": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"UsingForCalldata"
|
||||
],
|
||||
"released": "2020-06-04"
|
||||
},
|
||||
"0.7.0": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup"
|
||||
],
|
||||
"released": "2020-07-28"
|
||||
},
|
||||
"0.7.1": {
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup",
|
||||
"FreeFunctionRedefinition"
|
||||
],
|
||||
"released": "2020-09-02"
|
||||
},
|
||||
"0.7.2": {
|
||||
"bugs": [],
|
||||
"bugs": [
|
||||
"DynamicArrayCleanup"
|
||||
],
|
||||
"released": "2020-09-28"
|
||||
},
|
||||
"0.7.3": {
|
||||
"bugs": [],
|
||||
"released": "2020-10-07"
|
||||
}
|
||||
}
|
@ -167,7 +167,7 @@ void ImmutableValidator::analyseVariableReference(VariableDeclaration const& _va
|
||||
|
||||
// If this is not an ordinary assignment, we write and read at the same time.
|
||||
bool write = _expression.annotation().willBeWrittenTo;
|
||||
bool read = !_expression.annotation().willBeWrittenTo || !*_expression.annotation().lValueOfOrdinaryAssignment;
|
||||
bool read = !_expression.annotation().willBeWrittenTo || !_expression.annotation().lValueOfOrdinaryAssignment;
|
||||
if (write)
|
||||
{
|
||||
if (!m_currentConstructor)
|
||||
|
@ -1420,7 +1420,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
{
|
||||
requireLValue(
|
||||
*component,
|
||||
*_tuple.annotation().lValueOfOrdinaryAssignment
|
||||
_tuple.annotation().lValueOfOrdinaryAssignment
|
||||
);
|
||||
types.push_back(type(*component));
|
||||
}
|
||||
@ -1534,6 +1534,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
|
||||
_operation.annotation().isConstant = false;
|
||||
_operation.annotation().isPure = !modifying && *_operation.subExpression().annotation().isPure;
|
||||
_operation.annotation().isLValue = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2178,6 +2179,52 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
m_errorReporter.typeError(errorId, paramArgMap[i]->location(), description);
|
||||
}
|
||||
}
|
||||
|
||||
TypePointers const& returnParameterTypes = _functionType->returnParameterTypes();
|
||||
bool isLibraryCall = (_functionType->kind() == FunctionType::Kind::DelegateCall);
|
||||
bool callRequiresABIEncoding =
|
||||
// ABIEncode/ABIDecode calls not included because they should have been already validated
|
||||
// at this point and they have variadic arguments so they need special handling.
|
||||
_functionType->kind() == FunctionType::Kind::DelegateCall ||
|
||||
_functionType->kind() == FunctionType::Kind::External ||
|
||||
_functionType->kind() == FunctionType::Kind::Creation ||
|
||||
_functionType->kind() == FunctionType::Kind::Event;
|
||||
|
||||
if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
|
||||
{
|
||||
solAssert(!isVariadic, "");
|
||||
solAssert(parameterTypes.size() == arguments.size(), "");
|
||||
solAssert(!_functionType->isBareCall(), "");
|
||||
solAssert(*_functionCall.annotation().kind == FunctionCallKind::FunctionCall, "");
|
||||
|
||||
for (size_t i = 0; i < parameterTypes.size(); ++i)
|
||||
{
|
||||
solAssert(parameterTypes[i], "");
|
||||
|
||||
if (!typeSupportedByOldABIEncoder(*parameterTypes[i], isLibraryCall))
|
||||
m_errorReporter.typeError(
|
||||
2443_error,
|
||||
paramArgMap[i]->location(),
|
||||
"The type of this parameter, " + parameterTypes[i]->toString(true) + ", "
|
||||
"is only supported in ABIEncoderV2. "
|
||||
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
|
||||
);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < returnParameterTypes.size(); ++i)
|
||||
{
|
||||
solAssert(returnParameterTypes[i], "");
|
||||
|
||||
if (!typeSupportedByOldABIEncoder(*returnParameterTypes[i], isLibraryCall))
|
||||
m_errorReporter.typeError(
|
||||
2428_error,
|
||||
_functionCall.location(),
|
||||
"The type of return parameter " + toString(i + 1) + ", " + returnParameterTypes[i]->toString(true) + ", "
|
||||
"is only supported in ABIEncoderV2. "
|
||||
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
@ -2345,6 +2392,7 @@ bool TypeChecker::visit(FunctionCallOptions const& _functionCallOptions)
|
||||
|
||||
_functionCallOptions.annotation().isPure = false;
|
||||
_functionCallOptions.annotation().isConstant = false;
|
||||
_functionCallOptions.annotation().isLValue = false;
|
||||
|
||||
auto expressionFunctionType = dynamic_cast<FunctionType const*>(type(_functionCallOptions.expression()));
|
||||
if (!expressionFunctionType)
|
||||
@ -2477,6 +2525,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
solAssert(!!type, "Type name not resolved.");
|
||||
|
||||
_newExpression.annotation().isConstant = false;
|
||||
_newExpression.annotation().isLValue = false;
|
||||
|
||||
if (auto contractName = dynamic_cast<UserDefinedTypeName const*>(&_newExpression.typeName()))
|
||||
{
|
||||
@ -2537,7 +2586,10 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
_newExpression.annotation().isPure = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_newExpression.annotation().isPure = false;
|
||||
m_errorReporter.fatalTypeError(8807_error, _newExpression.location(), "Contract or array type expected.");
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
||||
@ -2720,6 +2772,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
||||
)
|
||||
annotation.isPure = *_memberAccess.expression().annotation().isPure;
|
||||
}
|
||||
else
|
||||
annotation.isLValue = false;
|
||||
}
|
||||
else if (exprType->category() == Type::Category::Module)
|
||||
{
|
||||
@ -3015,6 +3069,7 @@ vector<Declaration const*> TypeChecker::cleanOverloadedDeclarations(
|
||||
bool TypeChecker::visit(Identifier const& _identifier)
|
||||
{
|
||||
IdentifierAnnotation& annotation = _identifier.annotation();
|
||||
|
||||
if (!annotation.referencedDeclaration)
|
||||
{
|
||||
annotation.overloadedDeclarations = cleanOverloadedDeclarations(_identifier, annotation.candidateDeclarations);
|
||||
|
@ -253,7 +253,8 @@ struct ExpressionAnnotation: ASTAnnotation
|
||||
bool willBeWrittenTo = false;
|
||||
/// Whether the expression is an lvalue that is only assigned.
|
||||
/// Would be false for --, ++, delete, +=, -=, ....
|
||||
SetOnce<bool> lValueOfOrdinaryAssignment;
|
||||
/// Only relevant if isLvalue == true
|
||||
bool lValueOfOrdinaryAssignment;
|
||||
|
||||
/// Types and - if given - names of arguments if the expr. is a function
|
||||
/// that is called, used for overload resolution
|
||||
|
@ -313,46 +313,4 @@ private:
|
||||
std::function<void(ASTNode const&)> m_onEndVisit;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility class that visits the AST in depth-first order and calls a function on each node and each edge.
|
||||
* Child nodes are only visited if the node callback of the parent returns true.
|
||||
* The node callback of a parent is called before any edge or node callback involving the children.
|
||||
* The edge callbacks of all children are called before the edge callback of the parent.
|
||||
* This way, the node callback can be used as an initializing callback and the edge callbacks can be
|
||||
* used to compute a "reduce" function.
|
||||
*/
|
||||
class ASTReduce: public ASTConstVisitor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a new ASTReduce object with the given callback functions.
|
||||
* @param _onNode called for each node, before its child edges and nodes, should return true to descend deeper
|
||||
* @param _onEdge called for each edge with (parent, child)
|
||||
*/
|
||||
ASTReduce(
|
||||
std::function<bool(ASTNode const&)> _onNode,
|
||||
std::function<void(ASTNode const&, ASTNode const&)> _onEdge
|
||||
): m_onNode(std::move(_onNode)), m_onEdge(std::move(_onEdge))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
bool visitNode(ASTNode const& _node) override
|
||||
{
|
||||
m_parents.push_back(&_node);
|
||||
return m_onNode(_node);
|
||||
}
|
||||
void endVisitNode(ASTNode const& _node) override
|
||||
{
|
||||
m_parents.pop_back();
|
||||
if (!m_parents.empty())
|
||||
m_onEdge(*m_parents.back(), _node);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<ASTNode const*> m_parents;
|
||||
std::function<bool(ASTNode const&)> m_onNode;
|
||||
std::function<void(ASTNode const&, ASTNode const&)> m_onEdge;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -290,7 +290,10 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
|
||||
// stack: target_ref target_data_end source_data_pos target_data_pos_updated source_data_end
|
||||
_context << Instruction::POP << Instruction::SWAP1 << Instruction::POP;
|
||||
// stack: target_ref target_data_end target_data_pos_updated
|
||||
utils.clearStorageLoop(targetBaseType);
|
||||
if (targetBaseType->storageBytes() < 32)
|
||||
utils.clearStorageLoop(TypeProvider::uint256());
|
||||
else
|
||||
utils.clearStorageLoop(targetBaseType);
|
||||
_context << Instruction::POP;
|
||||
}
|
||||
);
|
||||
@ -922,6 +925,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
||||
|
||||
void ArrayUtils::clearStorageLoop(TypePointer _type) const
|
||||
{
|
||||
solAssert(_type->storageBytes() >= 32, "");
|
||||
m_context.callLowLevelFunction(
|
||||
"$clearStorageLoop_" + _type->identifier(),
|
||||
2,
|
||||
|
@ -42,93 +42,6 @@ using namespace solidity::evmasm;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
|
||||
GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimation(
|
||||
AssemblyItems const& _items,
|
||||
vector<ASTNode const*> const& _ast
|
||||
) const
|
||||
{
|
||||
solAssert(std::count(_ast.begin(), _ast.end(), nullptr) == 0, "");
|
||||
map<SourceLocation, GasConsumption> particularCosts;
|
||||
|
||||
ControlFlowGraph cfg(_items);
|
||||
for (BasicBlock const& block: cfg.optimisedBlocks())
|
||||
{
|
||||
solAssert(!!block.startState, "");
|
||||
GasMeter meter(block.startState->copy(), m_evmVersion);
|
||||
auto const end = _items.begin() + static_cast<ptrdiff_t>(block.end);
|
||||
for (auto iter = _items.begin() + static_cast<ptrdiff_t>(block.begin); iter != end; ++iter)
|
||||
particularCosts[iter->location()] += meter.estimateMax(*iter);
|
||||
}
|
||||
|
||||
set<ASTNode const*> finestNodes = finestNodesAtLocation(_ast);
|
||||
ASTGasConsumptionSelfAccumulated gasCosts;
|
||||
auto onNode = [&](ASTNode const& _node)
|
||||
{
|
||||
if (!finestNodes.count(&_node))
|
||||
return true;
|
||||
gasCosts[&_node][0] = gasCosts[&_node][1] = particularCosts[_node.location()];
|
||||
return true;
|
||||
};
|
||||
auto onEdge = [&](ASTNode const& _parent, ASTNode const& _child)
|
||||
{
|
||||
gasCosts[&_parent][1] += gasCosts[&_child][1];
|
||||
};
|
||||
ASTReduce folder(onNode, onEdge);
|
||||
for (ASTNode const* ast: _ast)
|
||||
ast->accept(folder);
|
||||
|
||||
return gasCosts;
|
||||
}
|
||||
|
||||
map<ASTNode const*, GasMeter::GasConsumption> GasEstimator::breakToStatementLevel(
|
||||
ASTGasConsumptionSelfAccumulated const& _gasCosts,
|
||||
vector<ASTNode const*> const& _roots
|
||||
)
|
||||
{
|
||||
solAssert(std::count(_roots.begin(), _roots.end(), nullptr) == 0, "");
|
||||
// first pass: statementDepth[node] is the distance from the deepend statement to node
|
||||
// in direction of the tree root (or undefined if not possible)
|
||||
map<ASTNode const*, int> statementDepth;
|
||||
auto onNodeFirstPass = [&](ASTNode const& _node)
|
||||
{
|
||||
if (dynamic_cast<Statement const*>(&_node))
|
||||
statementDepth[&_node] = 0;
|
||||
return true;
|
||||
};
|
||||
auto onEdgeFirstPass = [&](ASTNode const& _parent, ASTNode const& _child)
|
||||
{
|
||||
if (statementDepth.count(&_child))
|
||||
statementDepth[&_parent] = max(statementDepth[&_parent], statementDepth[&_child] + 1);
|
||||
};
|
||||
ASTReduce firstPass(onNodeFirstPass, onEdgeFirstPass);
|
||||
for (ASTNode const* node: _roots)
|
||||
node->accept(firstPass);
|
||||
|
||||
// we use the location of a node if
|
||||
// - its statement depth is 0 or
|
||||
// - its statement depth is undefined but the parent's statement depth is at least 1
|
||||
map<ASTNode const*, GasConsumption> gasCosts;
|
||||
auto onNodeSecondPass = [&](ASTNode const& _node)
|
||||
{
|
||||
return statementDepth.count(&_node);
|
||||
};
|
||||
auto onEdgeSecondPass = [&](ASTNode const& _parent, ASTNode const& _child)
|
||||
{
|
||||
bool useNode = false;
|
||||
if (statementDepth.count(&_child))
|
||||
useNode = statementDepth[&_child] == 0;
|
||||
else
|
||||
useNode = statementDepth.count(&_parent) && statementDepth.at(&_parent) > 0;
|
||||
if (useNode)
|
||||
gasCosts[&_child] = _gasCosts.at(&_child)[1];
|
||||
};
|
||||
ASTReduce secondPass(onNodeSecondPass, onEdgeSecondPass);
|
||||
for (ASTNode const* node: _roots)
|
||||
node->accept(secondPass);
|
||||
// gasCosts should only contain non-overlapping locations
|
||||
return gasCosts;
|
||||
}
|
||||
|
||||
GasEstimator::GasConsumption GasEstimator::functionalEstimation(
|
||||
AssemblyItems const& _items,
|
||||
string const& _signature
|
||||
|
@ -48,22 +48,6 @@ public:
|
||||
|
||||
explicit GasEstimator(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {}
|
||||
|
||||
/// Estimates the gas consumption for every assembly item in the given assembly and stores
|
||||
/// it by source location.
|
||||
/// @returns a mapping from each AST node to a pair of its particular and syntactically accumulated gas costs.
|
||||
ASTGasConsumptionSelfAccumulated structuralEstimation(
|
||||
evmasm::AssemblyItems const& _items,
|
||||
std::vector<ASTNode const*> const& _ast
|
||||
) const;
|
||||
/// @returns a mapping from nodes with non-overlapping source locations to gas consumptions such that
|
||||
/// the following source locations are part of the mapping:
|
||||
/// 1. source locations of statements that do not contain other statements
|
||||
/// 2. maximal source locations that do not overlap locations coming from the first rule
|
||||
static ASTGasConsumption breakToStatementLevel(
|
||||
ASTGasConsumptionSelfAccumulated const& _gasCosts,
|
||||
std::vector<ASTNode const*> const& _roots
|
||||
);
|
||||
|
||||
/// @returns the estimated gas consumption by the (public or external) function with the
|
||||
/// given signature. If no signature is given, estimates the maximum gas usage.
|
||||
GasConsumption functionalEstimation(
|
||||
|
@ -101,9 +101,9 @@ void OptimiserSuite::run(
|
||||
|
||||
OptimiserSuite suite(_dialect, reservedIdentifiers, Debug::None, ast);
|
||||
|
||||
// Some steps depend on properties ensured by FunctionHoister, FunctionGrouper and
|
||||
// Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and
|
||||
// ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely.
|
||||
suite.runSequence("fgo", ast);
|
||||
suite.runSequence("hfgo", ast);
|
||||
|
||||
// Now the user-supplied part
|
||||
suite.runSequence(_optimisationSequence, ast);
|
||||
|
@ -1638,18 +1638,6 @@ void CommandLineInterface::handleAst(string const& _argStr)
|
||||
vector<ASTNode const*> asts;
|
||||
for (auto const& sourceCode: m_sourceCodes)
|
||||
asts.push_back(&m_compiler->ast(sourceCode.first));
|
||||
map<ASTNode const*, evmasm::GasMeter::GasConsumption> gasCosts;
|
||||
for (auto const& contract: m_compiler->contractNames())
|
||||
if (m_compiler->compilationSuccessful())
|
||||
if (auto const* assemblyItems = m_compiler->runtimeAssemblyItems(contract))
|
||||
{
|
||||
auto ret = GasEstimator::breakToStatementLevel(
|
||||
GasEstimator(m_evmVersion).structuralEstimation(*assemblyItems, asts),
|
||||
asts
|
||||
);
|
||||
for (auto const& it: ret)
|
||||
gasCosts[it.first] += it.second;
|
||||
}
|
||||
|
||||
bool legacyFormat = !m_args.count(g_argAstCompactJson);
|
||||
if (m_args.count(g_argOutputDir))
|
||||
|
@ -49,14 +49,6 @@ public:
|
||||
m_compiler.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
|
||||
m_compiler.setEVMVersion(m_evmVersion);
|
||||
BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
|
||||
|
||||
AssemblyItems const* items = m_compiler.runtimeAssemblyItems(m_compiler.lastContractName());
|
||||
ASTNode const& sourceUnit = m_compiler.ast("");
|
||||
BOOST_REQUIRE(items != nullptr);
|
||||
m_gasCosts = GasEstimator::breakToStatementLevel(
|
||||
GasEstimator(solidity::test::CommonOptions::get().evmVersion()).structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})),
|
||||
{&sourceUnit}
|
||||
);
|
||||
}
|
||||
|
||||
void testCreationTimeGas(string const& _sourceCode, u256 const& _tolerance = u256(0))
|
||||
@ -118,43 +110,10 @@ public:
|
||||
gas += i != 0 ? GasCosts::txDataNonZeroGas(evmVersion) : GasCosts::txDataZeroGas;
|
||||
return gas;
|
||||
}
|
||||
|
||||
protected:
|
||||
map<ASTNode const*, evmasm::GasMeter::GasConsumption> m_gasCosts;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(GasMeterTests, GasMeterTestFramework)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract test {
|
||||
bytes x;
|
||||
function f(uint a) public returns (uint b) {
|
||||
for (; a < 200; ++a) {
|
||||
x.push(0x09);
|
||||
b = a * a;
|
||||
}
|
||||
return f(a - 1);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compile(sourceCode);
|
||||
for (auto first = m_gasCosts.cbegin(); first != m_gasCosts.cend(); ++first)
|
||||
{
|
||||
auto second = first;
|
||||
for (++second; second != m_gasCosts.cend(); ++second)
|
||||
if (first->first->location().intersects(second->first->location()))
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(false, "Source locations should not overlap!");
|
||||
langutil::SourceReferenceFormatter formatter(cout);
|
||||
|
||||
formatter.printSourceLocation(&first->first->location());
|
||||
formatter.printSourceLocation(&second->first->location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(simple_contract)
|
||||
{
|
||||
// Tests a simple "deploy contract" code without constructor. The actual contract is not relevant.
|
||||
|
@ -633,8 +633,8 @@ BOOST_AUTO_TEST_CASE(optimise_multi_stores)
|
||||
)";
|
||||
compileBothVersions(sourceCode);
|
||||
compareVersions("f()");
|
||||
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 9);
|
||||
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 8);
|
||||
BOOST_CHECK_EQUAL(numInstructions(m_nonOptimizedBytecode, Instruction::SSTORE), 8);
|
||||
BOOST_CHECK_EQUAL(numInstructions(m_optimizedBytecode, Instruction::SSTORE), 7);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(optimise_constant_to_codecopy)
|
||||
|
@ -0,0 +1,23 @@
|
||||
// Test to see if cleanup is performed properly during array copying
|
||||
contract C {
|
||||
uint128[] x;
|
||||
function f() public returns(bool) {
|
||||
x.push(42); x.push(42); x.push(42); x.push(42);
|
||||
uint128[] memory y = new uint128[](1);
|
||||
y[0] = 23;
|
||||
x = y;
|
||||
assembly { sstore(x.slot, 4) }
|
||||
|
||||
assert(x[0] == 23);
|
||||
assert(x[1] == 0);
|
||||
|
||||
assert(x[2] == 0);
|
||||
// Issue 9832: the cleanup was only performed for the first packed type leaving the rest of
|
||||
// the slot dirty.
|
||||
assert(x[3] == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> true
|
@ -0,0 +1,48 @@
|
||||
// Issue 9832: Test to see if cleanup is performed properly after array copying
|
||||
contract C {
|
||||
uint40[] x;
|
||||
function f() public returns(bool) {
|
||||
|
||||
x.push(42); x.push(42); x.push(42); x.push(42);
|
||||
x.push(42); x.push(42); x.push(42); x.push(42);
|
||||
x.push(42); x.push(42); x.push(42); x.push(42);
|
||||
x.push(42); x.push(42); x.push(42); x.push(42);
|
||||
x.push(42); x.push(42); x.push(42); x.push(42);
|
||||
|
||||
uint40[] memory y = new uint40[](1);
|
||||
y[0] = 23;
|
||||
x = y;
|
||||
|
||||
assembly { sstore(x.slot, 20) }
|
||||
|
||||
assert(x[0] == 23);
|
||||
assert(x[1] == 0);
|
||||
assert(x[2] == 0);
|
||||
assert(x[3] == 0);
|
||||
|
||||
assert(x[4] == 0);
|
||||
assert(x[5] == 0);
|
||||
assert(x[6] == 0);
|
||||
assert(x[7] == 0);
|
||||
|
||||
assert(x[8] == 0);
|
||||
assert(x[9] == 0);
|
||||
assert(x[10] == 0);
|
||||
assert(x[11] == 0);
|
||||
|
||||
assert(x[12] == 0);
|
||||
assert(x[13] == 0);
|
||||
assert(x[14] == 0);
|
||||
assert(x[15] == 0);
|
||||
|
||||
assert(x[16] == 0);
|
||||
assert(x[17] == 0);
|
||||
assert(x[18] == 0);
|
||||
assert(x[19] == 0);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// f() -> true
|
@ -0,0 +1,21 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function set(Item storage _item) external view {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
L.Item item;
|
||||
|
||||
function foo() public view {
|
||||
L.set(item);
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,20 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
constructor(Item memory _item) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
new C(C.Item(5));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2443: (B:71-80): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,20 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function set(uint _x, string memory _y, Item memory _item, bool _z) external view {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
C(0x00).set({_item: C.Item(50), _z: false, _y: "abc", _x: 30});
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,22 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get(Item memory _item) external {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
C c = new C();
|
||||
function(C.Item memory) external ptr = c.get;
|
||||
ptr(C.Item(5));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2443: (B:146-155): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,16 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
function f() external view returns (string[] memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract D {
|
||||
function g() public view {
|
||||
C(0x00).f();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,20 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get() external view returns(Item memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
C(0x00).get();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,20 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint[] y;
|
||||
}
|
||||
|
||||
function get() external view returns(Item memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
C(0x00).get();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,19 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
event E(Item _value);
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
emit L.E(L.Item(42));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2443: (B:74-84): The type of this parameter, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,21 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get(Item storage _item) external view {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
L.Item item;
|
||||
|
||||
function foo() public view {
|
||||
L.get(item);
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,20 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get() external view returns(Item memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
L.get();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2428: (B:70-77): The type of return parameter 1, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,13 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
function get() public view returns (uint[][] memory) {}
|
||||
|
||||
function test() public view returns (bool) {
|
||||
uint[][] memory x = this.get();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// Warning 2072: (166-183): Unused local variable.
|
@ -0,0 +1,13 @@
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
function get() public view returns (uint[][] memory) {}
|
||||
|
||||
function test() public view returns (bool) {
|
||||
uint[][] memory x = this.get();
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: <byzantium
|
||||
// ----
|
||||
// TypeError 9574: (166-196): Type inaccessible dynamic type is not implicitly convertible to expected type uint256[] memory[] memory.
|
@ -0,0 +1,21 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
constructor(Item memory _item) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
new C(C.Item(5));
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,23 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get(Item memory _item) external {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
C c = new C();
|
||||
function(C.Item memory) external ptr = c.get;
|
||||
ptr(C.Item(5));
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,17 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
function f() external view returns (string[] memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract D {
|
||||
function g() public view {
|
||||
C(0x00).f();
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,21 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get() external view returns(Item memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
C(0x00).get();
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,21 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract C {
|
||||
struct Item {
|
||||
uint[] y;
|
||||
}
|
||||
|
||||
function get() external view returns(Item memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
C(0x00).get();
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,20 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
event E(Item _value);
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
emit L.E(L.Item(42));
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,25 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get(Item memory _item) external {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public {
|
||||
// NOTE: This test checks a case that is currently not possible (pointer to an external
|
||||
// library function) but it might become possible in the future.
|
||||
function(L.Item memory) external ptr = L.get;
|
||||
ptr(L.Item(5));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 9574: (B:269-313): Type function (struct L.Item memory) is not implicitly convertible to expected type function (struct L.Item memory) external.
|
@ -0,0 +1,21 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
library L {
|
||||
struct Item {
|
||||
uint x;
|
||||
}
|
||||
|
||||
function get() external view returns(Item memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "A";
|
||||
|
||||
contract Test {
|
||||
function foo() public view {
|
||||
L.get();
|
||||
}
|
||||
}
|
||||
// ----
|
@ -0,0 +1,30 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
struct Data {
|
||||
bool flag;
|
||||
}
|
||||
|
||||
contract A {
|
||||
function get() public view returns (Data memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract B {
|
||||
modifier validate() {
|
||||
A(0x00).get();
|
||||
_;
|
||||
}
|
||||
}
|
||||
==== Source: C ====
|
||||
import "B";
|
||||
|
||||
contract C is B {
|
||||
function foo()
|
||||
public
|
||||
validate()
|
||||
{}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
@ -0,0 +1,32 @@
|
||||
==== Source: A ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
struct Data {
|
||||
bool flag;
|
||||
}
|
||||
|
||||
contract A {
|
||||
function get() public view returns (Data memory) {}
|
||||
}
|
||||
==== Source: B ====
|
||||
import "A";
|
||||
|
||||
contract B {
|
||||
modifier validate() {
|
||||
A(0x00).get();
|
||||
_;
|
||||
}
|
||||
}
|
||||
==== Source: C ====
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "B";
|
||||
|
||||
contract C is B {
|
||||
function foo()
|
||||
public
|
||||
validate()
|
||||
{}
|
||||
}
|
||||
// ----
|
||||
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.
|
11
test/libsolidity/syntaxTests/lvalues/lvalue_not_set.sol
Normal file
11
test/libsolidity/syntaxTests/lvalues/lvalue_not_set.sol
Normal file
@ -0,0 +1,11 @@
|
||||
contract C {
|
||||
function foo(uint x) public
|
||||
{
|
||||
// Used to cause an ICE
|
||||
uint p = new uint[] = x;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError 4247: (100-110): Expression has to be an lvalue.
|
||||
// TypeError 7407: (113-114): Type uint256 is not implicitly convertible to expected type function (uint256) pure returns (uint256[] memory).
|
||||
// TypeError 9574: (91-114): Type function (uint256) pure returns (uint256[] memory) is not implicitly convertible to expected type uint256.
|
Loading…
Reference in New Issue
Block a user