aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-12-15 19:16:32 +0800
committerchriseth <c@ethdev.com>2016-12-15 19:16:56 +0800
commit822622cf5bf23e79a6e2292cb837d1a39ca1c419 (patch)
treee668cf9a257bab10e77469ba725e630bc8f3b0a5
parent2dabbdf06f414750ef0425c664f861aeb3e470b8 (diff)
parent3a692e3df9b62852c951adece42f6d12b2d4a44a (diff)
downloaddexon-solidity-822622cf5bf23e79a6e2292cb837d1a39ca1c419.tar.gz
dexon-solidity-822622cf5bf23e79a6e2292cb837d1a39ca1c419.tar.zst
dexon-solidity-822622cf5bf23e79a6e2292cb837d1a39ca1c419.zip
Merge remote-tracking branch 'origin/develop' into release
-rw-r--r--.travis.yml10
-rw-r--r--CMakeLists.txt2
-rw-r--r--Changelog.md19
-rw-r--r--appveyor.yml10
-rw-r--r--cmake/EthCompilerSettings.cmake3
-rw-r--r--docs/conf.py4
-rw-r--r--docs/contracts.rst6
-rw-r--r--docs/contributing.rst15
-rw-r--r--docs/control-structures.rst83
-rw-r--r--docs/grammar.txt (renamed from libsolidity/grammar.txt)14
-rw-r--r--docs/installing-solidity.rst15
-rw-r--r--docs/introduction-to-smart-contracts.rst2
-rw-r--r--docs/miscellaneous.rst206
-rw-r--r--docs/style-guide.rst81
-rw-r--r--docs/types.rst76
-rw-r--r--libdevcore/Common.h11
-rw-r--r--libdevcore/JSON.h8
-rw-r--r--libdevcore/SwarmHash.cpp12
-rw-r--r--libdevcore/SwarmHash.h5
-rw-r--r--libdevcore/UTF8.cpp2
-rw-r--r--libdevcore/UTF8.h10
-rw-r--r--libevmasm/Assembly.cpp24
-rw-r--r--libevmasm/Assembly.h15
-rw-r--r--libevmasm/AssemblyItem.cpp8
-rw-r--r--libevmasm/AssemblyItem.h10
-rw-r--r--libevmasm/BlockDeduplicator.cpp8
-rw-r--r--libevmasm/BlockDeduplicator.h8
-rw-r--r--libevmasm/CommonSubexpressionEliminator.cpp8
-rw-r--r--libevmasm/CommonSubexpressionEliminator.h8
-rw-r--r--libevmasm/ConstantOptimiser.cpp8
-rw-r--r--libevmasm/ConstantOptimiser.h8
-rw-r--r--libevmasm/ControlFlowGraph.cpp8
-rw-r--r--libevmasm/ControlFlowGraph.h8
-rw-r--r--libevmasm/EVMSchedule.h8
-rw-r--r--libevmasm/Exceptions.h8
-rw-r--r--libevmasm/ExpressionClasses.cpp22
-rw-r--r--libevmasm/ExpressionClasses.h8
-rw-r--r--libevmasm/GasMeter.cpp8
-rw-r--r--libevmasm/GasMeter.h8
-rw-r--r--libevmasm/Instruction.cpp8
-rw-r--r--libevmasm/Instruction.h8
-rw-r--r--libevmasm/KnownState.cpp8
-rw-r--r--libevmasm/KnownState.h8
-rw-r--r--libevmasm/LinkerObject.cpp8
-rw-r--r--libevmasm/LinkerObject.h8
-rw-r--r--libevmasm/PathGasMeter.cpp8
-rw-r--r--libevmasm/PathGasMeter.h8
-rw-r--r--libevmasm/PeepholeOptimiser.cpp201
-rw-r--r--libevmasm/PeepholeOptimiser.h8
-rw-r--r--libevmasm/SemanticInformation.cpp8
-rw-r--r--libevmasm/SemanticInformation.h8
-rw-r--r--libevmasm/SourceLocation.h8
-rw-r--r--liblll/CodeFragment.cpp57
-rw-r--r--liblll/Compiler.cpp8
-rw-r--r--liblll/Parser.cpp4
-rw-r--r--libsolidity/analysis/ConstantEvaluator.cpp8
-rw-r--r--libsolidity/analysis/ConstantEvaluator.h8
-rw-r--r--libsolidity/analysis/DeclarationContainer.cpp8
-rw-r--r--libsolidity/analysis/DeclarationContainer.h8
-rw-r--r--libsolidity/analysis/DocStringAnalyser.cpp8
-rw-r--r--libsolidity/analysis/DocStringAnalyser.h8
-rw-r--r--libsolidity/analysis/GlobalContext.cpp8
-rw-r--r--libsolidity/analysis/GlobalContext.h8
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp8
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.h8
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp8
-rw-r--r--libsolidity/analysis/ReferencesResolver.h8
-rw-r--r--libsolidity/analysis/SemVerHandler.cpp8
-rw-r--r--libsolidity/analysis/SemVerHandler.h8
-rw-r--r--libsolidity/analysis/StaticAnalyzer.cpp78
-rw-r--r--libsolidity/analysis/StaticAnalyzer.h72
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp8
-rw-r--r--libsolidity/analysis/SyntaxChecker.h8
-rw-r--r--libsolidity/analysis/TypeChecker.cpp15
-rw-r--r--libsolidity/analysis/TypeChecker.h8
-rw-r--r--libsolidity/ast/AST.cpp17
-rw-r--r--libsolidity/ast/AST.h12
-rw-r--r--libsolidity/ast/ASTAnnotations.cpp8
-rw-r--r--libsolidity/ast/ASTAnnotations.h10
-rw-r--r--libsolidity/ast/ASTForward.h8
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp43
-rw-r--r--libsolidity/ast/ASTJsonConverter.h9
-rw-r--r--libsolidity/ast/ASTPrinter.cpp8
-rw-r--r--libsolidity/ast/ASTPrinter.h8
-rw-r--r--libsolidity/ast/ASTUtils.cpp8
-rw-r--r--libsolidity/ast/ASTUtils.h8
-rw-r--r--libsolidity/ast/ASTVisitor.h8
-rw-r--r--libsolidity/ast/AST_accept.h8
-rw-r--r--libsolidity/ast/Types.cpp50
-rw-r--r--libsolidity/ast/Types.h12
-rw-r--r--libsolidity/codegen/ArrayUtils.cpp19
-rw-r--r--libsolidity/codegen/ArrayUtils.h8
-rw-r--r--libsolidity/codegen/Compiler.cpp18
-rw-r--r--libsolidity/codegen/Compiler.h11
-rw-r--r--libsolidity/codegen/CompilerContext.cpp19
-rw-r--r--libsolidity/codegen/CompilerContext.h12
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp118
-rw-r--r--libsolidity/codegen/CompilerUtils.h37
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp12
-rw-r--r--libsolidity/codegen/ContractCompiler.h8
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp132
-rw-r--r--libsolidity/codegen/ExpressionCompiler.h14
-rw-r--r--libsolidity/codegen/LValue.cpp26
-rw-r--r--libsolidity/codegen/LValue.h8
-rw-r--r--libsolidity/formal/Why3Translator.cpp8
-rw-r--r--libsolidity/formal/Why3Translator.h8
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp8
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.h8
-rw-r--r--libsolidity/inlineasm/AsmData.h8
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp8
-rw-r--r--libsolidity/inlineasm/AsmParser.h8
-rw-r--r--libsolidity/inlineasm/AsmStack.cpp8
-rw-r--r--libsolidity/inlineasm/AsmStack.h8
-rw-r--r--libsolidity/interface/CompilerStack.cpp135
-rw-r--r--libsolidity/interface/CompilerStack.h30
-rw-r--r--libsolidity/interface/Exceptions.cpp8
-rw-r--r--libsolidity/interface/Exceptions.h8
-rw-r--r--libsolidity/interface/GasEstimator.cpp8
-rw-r--r--libsolidity/interface/GasEstimator.h8
-rw-r--r--libsolidity/interface/InterfaceHandler.h8
-rw-r--r--libsolidity/interface/SourceReferenceFormatter.cpp8
-rw-r--r--libsolidity/interface/SourceReferenceFormatter.h8
-rw-r--r--libsolidity/interface/Utils.h8
-rw-r--r--libsolidity/interface/Version.cpp8
-rw-r--r--libsolidity/interface/Version.h8
-rw-r--r--libsolidity/parsing/DocStringParser.h8
-rw-r--r--libsolidity/parsing/Parser.cpp8
-rw-r--r--libsolidity/parsing/Parser.h8
-rw-r--r--libsolidity/parsing/ParserBase.cpp8
-rw-r--r--libsolidity/parsing/ParserBase.h8
-rw-r--r--libsolidity/parsing/Scanner.cpp15
-rw-r--r--libsolidity/parsing/Scanner.h12
-rw-r--r--libsolidity/parsing/Token.cpp8
-rw-r--r--libsolidity/parsing/Token.h12
-rw-r--r--scripts/Dockerfile12
-rwxr-xr-xscripts/install_deps.sh6
-rwxr-xr-xscripts/isolateTests.py24
-rwxr-xr-xscripts/isolate_tests.py44
-rwxr-xr-xscripts/tests.sh9
-rwxr-xr-xscripts/travis-emscripten/build_emscripten.sh4
-rw-r--r--solc/CommandLineInterface.cpp349
-rw-r--r--solc/CommandLineInterface.h9
-rw-r--r--solc/jsonCompiler.cpp9
-rw-r--r--solc/main.cpp8
-rw-r--r--test/CMakeLists.txt3
-rw-r--r--test/ExecutionFramework.cpp153
-rw-r--r--test/ExecutionFramework.h296
-rw-r--r--test/RPCSession.cpp8
-rw-r--r--test/RPCSession.h8
-rw-r--r--test/TestHelper.cpp13
-rw-r--r--test/TestHelper.h10
-rw-r--r--test/boostTest.cpp8
-rw-r--r--test/contracts/AuctionRegistrar.cpp16
-rw-r--r--test/contracts/FixedFeeRegistrar.cpp12
-rw-r--r--test/contracts/Wallet.cpp12
-rw-r--r--test/libdevcore/SwarmHash.cpp24
-rw-r--r--test/libevmasm/SourceLocation.cpp8
-rw-r--r--test/liblll/EndToEndTest.cpp279
-rw-r--r--test/liblll/ExecutionFramework.cpp33
-rw-r--r--test/liblll/ExecutionFramework.h73
-rw-r--r--test/liblll/Parser.cpp181
-rw-r--r--test/libsolidity/ASTJSON.cpp8
-rw-r--r--test/libsolidity/Assembly.cpp12
-rw-r--r--test/libsolidity/ErrorCheck.cpp34
-rw-r--r--test/libsolidity/ErrorCheck.h32
-rw-r--r--test/libsolidity/GasMeter.cpp11
-rw-r--r--test/libsolidity/Imports.cpp8
-rw-r--r--test/libsolidity/InlineAssembly.cpp8
-rw-r--r--test/libsolidity/SemVerMatcher.cpp8
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp149
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp1709
-rw-r--r--test/libsolidity/SolidityExecutionFramework.cpp116
-rw-r--r--test/libsolidity/SolidityExecutionFramework.h255
-rw-r--r--test/libsolidity/SolidityExpressionCompiler.cpp134
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp1713
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp352
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp149
-rw-r--r--test/libsolidity/SolidityParser.cpp742
-rw-r--r--test/libsolidity/SolidityScanner.cpp8
-rw-r--r--test/libsolidity/SolidityTypes.cpp8
180 files changed, 6409 insertions, 3165 deletions
diff --git a/.travis.yml b/.travis.yml
index 2748c460..2160d175 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,22 +6,22 @@
# http://solidity.readthedocs.org
#
# ------------------------------------------------------------------------------
-# This file is part of cpp-ethereum.
+# This file is part of solidity.
#
-# cpp-ethereum is free software: you can redistribute it and/or modify
+# 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.
#
-# cpp-ethereum is distributed in the hope that it will be useful,
+# 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>
+# along with solidity. If not, see <http://www.gnu.org/licenses/>
#
-# (c) 2016 cpp-ethereum contributors.
+# (c) 2016 solidity contributors.
#------------------------------------------------------------------------------
language: cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 992ce392..ee66eebd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ include(EthPolicy)
eth_policy()
# project name and version should be set after cmake_policy CMP0048
-set(PROJECT_VERSION "0.4.6")
+set(PROJECT_VERSION "0.4.7")
project(solidity VERSION ${PROJECT_VERSION})
# Let's find our dependencies
diff --git a/Changelog.md b/Changelog.md
index eb1e5e72..096c72d4 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,7 +1,24 @@
+### 0.4.7 (2016-12-15)
+
+Features:
+ * Bitshift operators.
+ * Type checker: Warn when ``msg.value`` is used in non-payable function.
+ * Code generator: Inject the Swarm hash of a metadata file into the bytecode.
+ * Code generator: Replace expensive memcpy precompile by simple assembly loop.
+ * Optimizer: Some dead code elimination.
+
+Bugfixes:
+ * Code generator: throw if calling the identity precompile failed during memory (array) copying.
+ * Type checker: string literals that are not valid UTF-8 cannot be converted to string type
+ * Code generator: any non-zero value given as a boolean argument is now converted into 1.
+ * AST Json Converter: replace ``VariableDefinitionStatement`` nodes with ``VariableDeclarationStatement``
+ * AST Json Converter: fix the camel case in ``ElementaryTypeNameExpression``
+ * AST Json Converter: replace ``public`` field with ``visibility`` in the function definition nodes
+
### 0.4.6 (2016-11-22)
Bugfixes:
- * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs
+ * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs (introduced in 0.4.5)
### 0.4.5 (2016-11-21)
diff --git a/appveyor.yml b/appveyor.yml
index 5d6dcb20..85fb36f2 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -9,22 +9,22 @@
# sockets unconditionally at the time of writing.
#
# ------------------------------------------------------------------------------
-# This file is part of cpp-ethereum.
+# This file is part of solidity.
#
-# cpp-ethereum is free software: you can redistribute it and/or modify
+# 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.
#
-# cpp-ethereum is distributed in the hope that it will be useful,
+# 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>
+# along with solidity. If not, see <http://www.gnu.org/licenses/>
#
-# (c) 2016 cpp-ethereum contributors.
+# (c) 2016 solidity contributors.
#------------------------------------------------------------------------------
branches:
diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake
index 0c307288..c734423b 100644
--- a/cmake/EthCompilerSettings.cmake
+++ b/cmake/EthCompilerSettings.cmake
@@ -155,6 +155,9 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
if (EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --memory-init-file 0 -O3 -s LINKABLE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s NO_EXIT_RUNTIME=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_DYNAMIC_EXECUTION=1")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_FILESYSTEM=1 -s AGGRESSIVE_VARIABLE_ELIMINATION=1")
add_definitions(-DETH_EMSCRIPTEN=1)
endif()
endif()
diff --git a/docs/conf.py b/docs/conf.py
index bf0accb9..2bc79fd9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -56,9 +56,9 @@ copyright = '2016, Ethereum'
# built documents.
#
# The short X.Y version.
-version = '0.4.6'
+version = '0.4.7'
# The full version, including alpha/beta/rc tags.
-release = '0.4.6-develop'
+release = '0.4.7-develop'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 7f8ace44..e82b7495 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -721,8 +721,10 @@ Details are given in the following example.
NameReg(config.lookup(1)).register(name);
}
- // Functions can be overridden, both local and
- // message-based function calls take these overrides
+ // Functions can be overridden by another function with the same name and
+ // the same number/types of inputs. If the overriding function has different
+ // types of output parameters, that causes an error.
+ // Both local and message-based function calls take these overrides
// into account.
function kill() {
if (msg.sender == owner) {
diff --git a/docs/contributing.rst b/docs/contributing.rst
index 111fb932..42204d5c 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -59,3 +59,18 @@ for this project. Also, even though we do CI testing, please test your code and
ensure that it builds locally before submitting a pull request.
Thank you for your help!
+
+Running the compiler tests
+==========================
+
+Solidity includes different types of tests. They are included in the application
+called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode.
+
+To run ``cpp-ethereum`` in testing mode: ``eth --test -d /tmp/testeth``.
+
+To run the tests: ``soltest -- --ipcpath /tmp/testeth/geth.ipc``.
+
+To run a subset of tests, filters can be used:
+``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc``, where ``TestName`` can be a wildcard ``*``.
+
+Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests.
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index f57e7936..0802c085 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -2,12 +2,62 @@
Expressions and Control Structures
##################################
+.. index:: ! parameter, parameter;input, parameter;output
+
+Input Parameters and Output Parameters
+======================================
+
+As in Javascript, functions may take parameters as input;
+unlike in Javascript and C, they may also return arbitrary number of
+parameters as output.
+
+Input Parameters
+----------------
+
+The input parameters are declared the same way as variables are. As an
+exception, unused parameters can omit the variable name.
+For example, suppose we want our contract to
+accept one kind of external calls with two integers, we would write
+something like::
+
+ contract Simple {
+ function taker(uint _a, uint _b) {
+ // do something with _a and _b.
+ }
+ }
+
+Output Parameters
+-----------------
+
+The output parameters can be declared with the same syntax after the
+``returns`` keyword. For example, suppose we wished to return two results:
+the sum and the product of the two given integers, then we would
+write::
+
+ contract Simple {
+ function arithmetics(uint _a, uint _b) returns (uint o_sum, uint o_product) {
+ o_sum = _a + _b;
+ o_product = _a * _b;
+ }
+ }
+
+The names of output parameters can be omitted.
+The output values can also be specified using ``return`` statements.
+The ``return`` statements are also capable of returning multiple
+values, see :ref:`multi-return`.
+Return parameters are initialized to zero; if they are not explicitly
+set, they stay to be zero.
+
+Input parameters and output parameters can be used as expressions in
+the function body. There, they are also usable in the left-hand side
+of assignment.
+
.. index:: if, else, while, do/while, for, break, continue, return, switch, goto
Control Structures
===================
-Most of the control structures from C or JavaScript are available in Solidity
+Most of the control structures from JavaScript are available in Solidity
except for ``switch`` and ``goto``. So
there is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with
the usual semantics known from C or JavaScript.
@@ -16,7 +66,17 @@ Parentheses can *not* be omitted for conditionals, but curly brances can be omit
around single-statement bodies.
Note that there is no type conversion from non-boolean to boolean types as
-there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid Solidity.
+there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid
+Solidity.
+
+.. _multi-return:
+
+Returning Multiple Values
+-------------------------
+
+When a function has multiple output parameters, ``return (v0, v1, ...,
+vn)`` can return multiple values. The number of components must be
+the same as the number of output parameters.
.. index:: ! function;call, function;internal, function;external
@@ -322,17 +382,18 @@ In the following example, we show how ``throw`` can be used to easily revert an
}
}
-Currently, there are situations, where exceptions happen automatically in Solidity:
+Currently, Solidity automatically generates a runtime exception in the following situations:
1. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``).
-2. If you access a fixed-length ``bytesN`` at a too large or negative index.
-3. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``.
-4. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly").
-5. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
-6. If you convert a value too big or negative into an enum type.
-7. If you perform an external function call targeting a contract that contains no code.
-8. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function).
-9. If your contract receives Ether via a public accessor function.
+1. If you access a fixed-length ``bytesN`` at a too large or negative index.
+1. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``.
+1. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly").
+1. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``).
+1. If you shift by a negative amount.
+1. If you convert a value too big or negative into an enum type.
+1. If you perform an external function call targeting a contract that contains no code.
+1. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function).
+1. If your contract receives Ether via a public accessor function.
Internally, Solidity performs an "invalid jump" when an exception is thrown and thus causes the EVM to revert all changes made to the state. The reason for this is that there is no safe way to continue execution, because an expected effect did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction (or at least call) without effect.
diff --git a/libsolidity/grammar.txt b/docs/grammar.txt
index c8bc3aed..d15fbaf7 100644
--- a/libsolidity/grammar.txt
+++ b/docs/grammar.txt
@@ -1,7 +1,7 @@
SourceUnit = (PragmaDirective | ImportDirective | ContractDefinition)*
// Pragma actually parses anything up to the trailing ';' to be fully forward-compatible.
-PragmaDirective = 'pragma' Identifier Expression ';'
+PragmaDirective = 'pragma' Identifier ([^;]+) ';'
ImportDirective = 'import' StringLiteral ('as' Identifier)? ';'
| 'import' ('*' | Identifier) ('as' Identifier)? 'from' StringLiteral ';'
@@ -22,7 +22,7 @@ StructDefinition = 'struct' Identifier '{'
( VariableDeclaration ';' (VariableDeclaration ';')* )? '}'
ModifierDefinition = 'modifier' Identifier ParameterList? Block
FunctionDefinition = 'function' Identifier? ParameterList
- ( FunctionCall | Identifier | 'constant' |' payable' | 'external' | 'public' | 'internal' | 'private' )*
+ ( FunctionCall | Identifier | 'constant' | 'payable' | 'external' | 'public' | 'internal' | 'private' )*
( 'returns' ParameterList )? Block
EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';'
@@ -44,7 +44,7 @@ FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant
StorageLocation = 'memory' | 'storage'
Block = '{' Statement* '}'
-Statement = IfStatement | WhileStatement | ForStatement | Block |
+Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
( DoWhileStatement | PlaceholderStatement | Continue | Break | Return |
Throw | SimpleStatement ) ';'
@@ -54,6 +54,7 @@ WhileStatement = 'while' '(' Expression ')' Statement
PlaceholderStatement = '_'
SimpleStatement = VariableDefinition | ExpressionStatement
ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement
+InlineAssemblyStatement = 'assembly' InlineAssemblyBlock
DoWhileStatement = 'do' Statement 'while' '(' Expression ')'
Continue = 'continue'
Break = 'break'
@@ -108,3 +109,10 @@ Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' |
Fixed = 'fixed' | 'fixed0x8' | 'fixed0x16' | 'fixed0x24' | 'fixed0x32' | 'fixed0x40' | 'fixed0x48' | 'fixed0x56' | 'fixed0x64' | 'fixed0x72' | 'fixed0x80' | 'fixed0x88' | 'fixed0x96' | 'fixed0x104' | 'fixed0x112' | 'fixed0x120' | 'fixed0x128' | 'fixed0x136' | 'fixed0x144' | 'fixed0x152' | 'fixed0x160' | 'fixed0x168' | 'fixed0x176' | 'fixed0x184' | 'fixed0x192' | 'fixed0x200' | 'fixed0x208' | 'fixed0x216' | 'fixed0x224' | 'fixed0x232' | 'fixed0x240' | 'fixed0x248' | 'fixed0x256' | 'fixed8x8' | 'fixed8x16' | 'fixed8x24' | 'fixed8x32' | 'fixed8x40' | 'fixed8x48' | 'fixed8x56' | 'fixed8x64' | 'fixed8x72' | 'fixed8x80' | 'fixed8x88' | 'fixed8x96' | 'fixed8x104' | 'fixed8x112' | 'fixed8x120' | 'fixed8x128' | 'fixed8x136' | 'fixed8x144' | 'fixed8x152' | 'fixed8x160' | 'fixed8x168' | 'fixed8x176' | 'fixed8x184' | 'fixed8x192' | 'fixed8x200' | 'fixed8x208' | 'fixed8x216' | 'fixed8x224' | 'fixed8x232' | 'fixed8x240' | 'fixed8x248' | 'fixed16x8' | 'fixed16x16' | 'fixed16x24' | 'fixed16x32' | 'fixed16x40' | 'fixed16x48' | 'fixed16x56' | 'fixed16x64' | 'fixed16x72' | 'fixed16x80' | 'fixed16x88' | 'fixed16x96' | 'fixed16x104' | 'fixed16x112' | 'fixed16x120' | 'fixed16x128' | 'fixed16x136' | 'fixed16x144' | 'fixed16x152' | 'fixed16x160' | 'fixed16x168' | 'fixed16x176' | 'fixed16x184' | 'fixed16x192' | 'fixed16x200' | 'fixed16x208' | 'fixed16x216' | 'fixed16x224' | 'fixed16x232' | 'fixed16x240' | 'fixed24x8' | 'fixed24x16' | 'fixed24x24' | 'fixed24x32' | 'fixed24x40' | 'fixed24x48' | 'fixed24x56' | 'fixed24x64' | 'fixed24x72' | 'fixed24x80' | 'fixed24x88' | 'fixed24x96' | 'fixed24x104' | 'fixed24x112' | 'fixed24x120' | 'fixed24x128' | 'fixed24x136' | 'fixed24x144' | 'fixed24x152' | 'fixed24x160' | 'fixed24x168' | 'fixed24x176' | 'fixed24x184' | 'fixed24x192' | 'fixed24x200' | 'fixed24x208' | 'fixed24x216' | 'fixed24x224' | 'fixed24x232' | 'fixed32x8' | 'fixed32x16' | 'fixed32x24' | 'fixed32x32' | 'fixed32x40' | 'fixed32x48' | 'fixed32x56' | 'fixed32x64' | 'fixed32x72' | 'fixed32x80' | 'fixed32x88' | 'fixed32x96' | 'fixed32x104' | 'fixed32x112' | 'fixed32x120' | 'fixed32x128' | 'fixed32x136' | 'fixed32x144' | 'fixed32x152' | 'fixed32x160' | 'fixed32x168' | 'fixed32x176' | 'fixed32x184' | 'fixed32x192' | 'fixed32x200' | 'fixed32x208' | 'fixed32x216' | 'fixed32x224' | 'fixed40x8' | 'fixed40x16' | 'fixed40x24' | 'fixed40x32' | 'fixed40x40' | 'fixed40x48' | 'fixed40x56' | 'fixed40x64' | 'fixed40x72' | 'fixed40x80' | 'fixed40x88' | 'fixed40x96' | 'fixed40x104' | 'fixed40x112' | 'fixed40x120' | 'fixed40x128' | 'fixed40x136' | 'fixed40x144' | 'fixed40x152' | 'fixed40x160' | 'fixed40x168' | 'fixed40x176' | 'fixed40x184' | 'fixed40x192' | 'fixed40x200' | 'fixed40x208' | 'fixed40x216' | 'fixed48x8' | 'fixed48x16' | 'fixed48x24' | 'fixed48x32' | 'fixed48x40' | 'fixed48x48' | 'fixed48x56' | 'fixed48x64' | 'fixed48x72' | 'fixed48x80' | 'fixed48x88' | 'fixed48x96' | 'fixed48x104' | 'fixed48x112' | 'fixed48x120' | 'fixed48x128' | 'fixed48x136' | 'fixed48x144' | 'fixed48x152' | 'fixed48x160' | 'fixed48x168' | 'fixed48x176' | 'fixed48x184' | 'fixed48x192' | 'fixed48x200' | 'fixed48x208' | 'fixed56x8' | 'fixed56x16' | 'fixed56x24' | 'fixed56x32' | 'fixed56x40' | 'fixed56x48' | 'fixed56x56' | 'fixed56x64' | 'fixed56x72' | 'fixed56x80' | 'fixed56x88' | 'fixed56x96' | 'fixed56x104' | 'fixed56x112' | 'fixed56x120' | 'fixed56x128' | 'fixed56x136' | 'fixed56x144' | 'fixed56x152' | 'fixed56x160' | 'fixed56x168' | 'fixed56x176' | 'fixed56x184' | 'fixed56x192' | 'fixed56x200' | 'fixed64x8' | 'fixed64x16' | 'fixed64x24' | 'fixed64x32' | 'fixed64x40' | 'fixed64x48' | 'fixed64x56' | 'fixed64x64' | 'fixed64x72' | 'fixed64x80' | 'fixed64x88' | 'fixed64x96' | 'fixed64x104' | 'fixed64x112' | 'fixed64x120' | 'fixed64x128' | 'fixed64x136' | 'fixed64x144' | 'fixed64x152' | 'fixed64x160' | 'fixed64x168' | 'fixed64x176' | 'fixed64x184' | 'fixed64x192' | 'fixed72x8' | 'fixed72x16' | 'fixed72x24' | 'fixed72x32' | 'fixed72x40' | 'fixed72x48' | 'fixed72x56' | 'fixed72x64' | 'fixed72x72' | 'fixed72x80' | 'fixed72x88' | 'fixed72x96' | 'fixed72x104' | 'fixed72x112' | 'fixed72x120' | 'fixed72x128' | 'fixed72x136' | 'fixed72x144' | 'fixed72x152' | 'fixed72x160' | 'fixed72x168' | 'fixed72x176' | 'fixed72x184' | 'fixed80x8' | 'fixed80x16' | 'fixed80x24' | 'fixed80x32' | 'fixed80x40' | 'fixed80x48' | 'fixed80x56' | 'fixed80x64' | 'fixed80x72' | 'fixed80x80' | 'fixed80x88' | 'fixed80x96' | 'fixed80x104' | 'fixed80x112' | 'fixed80x120' | 'fixed80x128' | 'fixed80x136' | 'fixed80x144' | 'fixed80x152' | 'fixed80x160' | 'fixed80x168' | 'fixed80x176' | 'fixed88x8' | 'fixed88x16' | 'fixed88x24' | 'fixed88x32' | 'fixed88x40' | 'fixed88x48' | 'fixed88x56' | 'fixed88x64' | 'fixed88x72' | 'fixed88x80' | 'fixed88x88' | 'fixed88x96' | 'fixed88x104' | 'fixed88x112' | 'fixed88x120' | 'fixed88x128' | 'fixed88x136' | 'fixed88x144' | 'fixed88x152' | 'fixed88x160' | 'fixed88x168' | 'fixed96x8' | 'fixed96x16' | 'fixed96x24' | 'fixed96x32' | 'fixed96x40' | 'fixed96x48' | 'fixed96x56' | 'fixed96x64' | 'fixed96x72' | 'fixed96x80' | 'fixed96x88' | 'fixed96x96' | 'fixed96x104' | 'fixed96x112' | 'fixed96x120' | 'fixed96x128' | 'fixed96x136' | 'fixed96x144' | 'fixed96x152' | 'fixed96x160' | 'fixed104x8' | 'fixed104x16' | 'fixed104x24' | 'fixed104x32' | 'fixed104x40' | 'fixed104x48' | 'fixed104x56' | 'fixed104x64' | 'fixed104x72' | 'fixed104x80' | 'fixed104x88' | 'fixed104x96' | 'fixed104x104' | 'fixed104x112' | 'fixed104x120' | 'fixed104x128' | 'fixed104x136' | 'fixed104x144' | 'fixed104x152' | 'fixed112x8' | 'fixed112x16' | 'fixed112x24' | 'fixed112x32' | 'fixed112x40' | 'fixed112x48' | 'fixed112x56' | 'fixed112x64' | 'fixed112x72' | 'fixed112x80' | 'fixed112x88' | 'fixed112x96' | 'fixed112x104' | 'fixed112x112' | 'fixed112x120' | 'fixed112x128' | 'fixed112x136' | 'fixed112x144' | 'fixed120x8' | 'fixed120x16' | 'fixed120x24' | 'fixed120x32' | 'fixed120x40' | 'fixed120x48' | 'fixed120x56' | 'fixed120x64' | 'fixed120x72' | 'fixed120x80' | 'fixed120x88' | 'fixed120x96' | 'fixed120x104' | 'fixed120x112' | 'fixed120x120' | 'fixed120x128' | 'fixed120x136' | 'fixed128x8' | 'fixed128x16' | 'fixed128x24' | 'fixed128x32' | 'fixed128x40' | 'fixed128x48' | 'fixed128x56' | 'fixed128x64' | 'fixed128x72' | 'fixed128x80' | 'fixed128x88' | 'fixed128x96' | 'fixed128x104' | 'fixed128x112' | 'fixed128x120' | 'fixed128x128' | 'fixed136x8' | 'fixed136x16' | 'fixed136x24' | 'fixed136x32' | 'fixed136x40' | 'fixed136x48' | 'fixed136x56' | 'fixed136x64' | 'fixed136x72' | 'fixed136x80' | 'fixed136x88' | 'fixed136x96' | 'fixed136x104' | 'fixed136x112' | 'fixed136x120' | 'fixed144x8' | 'fixed144x16' | 'fixed144x24' | 'fixed144x32' | 'fixed144x40' | 'fixed144x48' | 'fixed144x56' | 'fixed144x64' | 'fixed144x72' | 'fixed144x80' | 'fixed144x88' | 'fixed144x96' | 'fixed144x104' | 'fixed144x112' | 'fixed152x8' | 'fixed152x16' | 'fixed152x24' | 'fixed152x32' | 'fixed152x40' | 'fixed152x48' | 'fixed152x56' | 'fixed152x64' | 'fixed152x72' | 'fixed152x80' | 'fixed152x88' | 'fixed152x96' | 'fixed152x104' | 'fixed160x8' | 'fixed160x16' | 'fixed160x24' | 'fixed160x32' | 'fixed160x40' | 'fixed160x48' | 'fixed160x56' | 'fixed160x64' | 'fixed160x72' | 'fixed160x80' | 'fixed160x88' | 'fixed160x96' | 'fixed168x8' | 'fixed168x16' | 'fixed168x24' | 'fixed168x32' | 'fixed168x40' | 'fixed168x48' | 'fixed168x56' | 'fixed168x64' | 'fixed168x72' | 'fixed168x80' | 'fixed168x88' | 'fixed176x8' | 'fixed176x16' | 'fixed176x24' | 'fixed176x32' | 'fixed176x40' | 'fixed176x48' | 'fixed176x56' | 'fixed176x64' | 'fixed176x72' | 'fixed176x80' | 'fixed184x8' | 'fixed184x16' | 'fixed184x24' | 'fixed184x32' | 'fixed184x40' | 'fixed184x48' | 'fixed184x56' | 'fixed184x64' | 'fixed184x72' | 'fixed192x8' | 'fixed192x16' | 'fixed192x24' | 'fixed192x32' | 'fixed192x40' | 'fixed192x48' | 'fixed192x56' | 'fixed192x64' | 'fixed200x8' | 'fixed200x16' | 'fixed200x24' | 'fixed200x32' | 'fixed200x40' | 'fixed200x48' | 'fixed200x56' | 'fixed208x8' | 'fixed208x16' | 'fixed208x24' | 'fixed208x32' | 'fixed208x40' | 'fixed208x48' | 'fixed216x8' | 'fixed216x16' | 'fixed216x24' | 'fixed216x32' | 'fixed216x40' | 'fixed224x8' | 'fixed224x16' | 'fixed224x24' | 'fixed224x32' | 'fixed232x8' | 'fixed232x16' | 'fixed232x24' | 'fixed240x8' | 'fixed240x16' | 'fixed248x8'
Ufixed = 'ufixed' | 'ufixed0x8' | 'ufixed0x16' | 'ufixed0x24' | 'ufixed0x32' | 'ufixed0x40' | 'ufixed0x48' | 'ufixed0x56' | 'ufixed0x64' | 'ufixed0x72' | 'ufixed0x80' | 'ufixed0x88' | 'ufixed0x96' | 'ufixed0x104' | 'ufixed0x112' | 'ufixed0x120' | 'ufixed0x128' | 'ufixed0x136' | 'ufixed0x144' | 'ufixed0x152' | 'ufixed0x160' | 'ufixed0x168' | 'ufixed0x176' | 'ufixed0x184' | 'ufixed0x192' | 'ufixed0x200' | 'ufixed0x208' | 'ufixed0x216' | 'ufixed0x224' | 'ufixed0x232' | 'ufixed0x240' | 'ufixed0x248' | 'ufixed0x256' | 'ufixed8x8' | 'ufixed8x16' | 'ufixed8x24' | 'ufixed8x32' | 'ufixed8x40' | 'ufixed8x48' | 'ufixed8x56' | 'ufixed8x64' | 'ufixed8x72' | 'ufixed8x80' | 'ufixed8x88' | 'ufixed8x96' | 'ufixed8x104' | 'ufixed8x112' | 'ufixed8x120' | 'ufixed8x128' | 'ufixed8x136' | 'ufixed8x144' | 'ufixed8x152' | 'ufixed8x160' | 'ufixed8x168' | 'ufixed8x176' | 'ufixed8x184' | 'ufixed8x192' | 'ufixed8x200' | 'ufixed8x208' | 'ufixed8x216' | 'ufixed8x224' | 'ufixed8x232' | 'ufixed8x240' | 'ufixed8x248' | 'ufixed16x8' | 'ufixed16x16' | 'ufixed16x24' | 'ufixed16x32' | 'ufixed16x40' | 'ufixed16x48' | 'ufixed16x56' | 'ufixed16x64' | 'ufixed16x72' | 'ufixed16x80' | 'ufixed16x88' | 'ufixed16x96' | 'ufixed16x104' | 'ufixed16x112' | 'ufixed16x120' | 'ufixed16x128' | 'ufixed16x136' | 'ufixed16x144' | 'ufixed16x152' | 'ufixed16x160' | 'ufixed16x168' | 'ufixed16x176' | 'ufixed16x184' | 'ufixed16x192' | 'ufixed16x200' | 'ufixed16x208' | 'ufixed16x216' | 'ufixed16x224' | 'ufixed16x232' | 'ufixed16x240' | 'ufixed24x8' | 'ufixed24x16' | 'ufixed24x24' | 'ufixed24x32' | 'ufixed24x40' | 'ufixed24x48' | 'ufixed24x56' | 'ufixed24x64' | 'ufixed24x72' | 'ufixed24x80' | 'ufixed24x88' | 'ufixed24x96' | 'ufixed24x104' | 'ufixed24x112' | 'ufixed24x120' | 'ufixed24x128' | 'ufixed24x136' | 'ufixed24x144' | 'ufixed24x152' | 'ufixed24x160' | 'ufixed24x168' | 'ufixed24x176' | 'ufixed24x184' | 'ufixed24x192' | 'ufixed24x200' | 'ufixed24x208' | 'ufixed24x216' | 'ufixed24x224' | 'ufixed24x232' | 'ufixed32x8' | 'ufixed32x16' | 'ufixed32x24' | 'ufixed32x32' | 'ufixed32x40' | 'ufixed32x48' | 'ufixed32x56' | 'ufixed32x64' | 'ufixed32x72' | 'ufixed32x80' | 'ufixed32x88' | 'ufixed32x96' | 'ufixed32x104' | 'ufixed32x112' | 'ufixed32x120' | 'ufixed32x128' | 'ufixed32x136' | 'ufixed32x144' | 'ufixed32x152' | 'ufixed32x160' | 'ufixed32x168' | 'ufixed32x176' | 'ufixed32x184' | 'ufixed32x192' | 'ufixed32x200' | 'ufixed32x208' | 'ufixed32x216' | 'ufixed32x224' | 'ufixed40x8' | 'ufixed40x16' | 'ufixed40x24' | 'ufixed40x32' | 'ufixed40x40' | 'ufixed40x48' | 'ufixed40x56' | 'ufixed40x64' | 'ufixed40x72' | 'ufixed40x80' | 'ufixed40x88' | 'ufixed40x96' | 'ufixed40x104' | 'ufixed40x112' | 'ufixed40x120' | 'ufixed40x128' | 'ufixed40x136' | 'ufixed40x144' | 'ufixed40x152' | 'ufixed40x160' | 'ufixed40x168' | 'ufixed40x176' | 'ufixed40x184' | 'ufixed40x192' | 'ufixed40x200' | 'ufixed40x208' | 'ufixed40x216' | 'ufixed48x8' | 'ufixed48x16' | 'ufixed48x24' | 'ufixed48x32' | 'ufixed48x40' | 'ufixed48x48' | 'ufixed48x56' | 'ufixed48x64' | 'ufixed48x72' | 'ufixed48x80' | 'ufixed48x88' | 'ufixed48x96' | 'ufixed48x104' | 'ufixed48x112' | 'ufixed48x120' | 'ufixed48x128' | 'ufixed48x136' | 'ufixed48x144' | 'ufixed48x152' | 'ufixed48x160' | 'ufixed48x168' | 'ufixed48x176' | 'ufixed48x184' | 'ufixed48x192' | 'ufixed48x200' | 'ufixed48x208' | 'ufixed56x8' | 'ufixed56x16' | 'ufixed56x24' | 'ufixed56x32' | 'ufixed56x40' | 'ufixed56x48' | 'ufixed56x56' | 'ufixed56x64' | 'ufixed56x72' | 'ufixed56x80' | 'ufixed56x88' | 'ufixed56x96' | 'ufixed56x104' | 'ufixed56x112' | 'ufixed56x120' | 'ufixed56x128' | 'ufixed56x136' | 'ufixed56x144' | 'ufixed56x152' | 'ufixed56x160' | 'ufixed56x168' | 'ufixed56x176' | 'ufixed56x184' | 'ufixed56x192' | 'ufixed56x200' | 'ufixed64x8' | 'ufixed64x16' | 'ufixed64x24' | 'ufixed64x32' | 'ufixed64x40' | 'ufixed64x48' | 'ufixed64x56' | 'ufixed64x64' | 'ufixed64x72' | 'ufixed64x80' | 'ufixed64x88' | 'ufixed64x96' | 'ufixed64x104' | 'ufixed64x112' | 'ufixed64x120' | 'ufixed64x128' | 'ufixed64x136' | 'ufixed64x144' | 'ufixed64x152' | 'ufixed64x160' | 'ufixed64x168' | 'ufixed64x176' | 'ufixed64x184' | 'ufixed64x192' | 'ufixed72x8' | 'ufixed72x16' | 'ufixed72x24' | 'ufixed72x32' | 'ufixed72x40' | 'ufixed72x48' | 'ufixed72x56' | 'ufixed72x64' | 'ufixed72x72' | 'ufixed72x80' | 'ufixed72x88' | 'ufixed72x96' | 'ufixed72x104' | 'ufixed72x112' | 'ufixed72x120' | 'ufixed72x128' | 'ufixed72x136' | 'ufixed72x144' | 'ufixed72x152' | 'ufixed72x160' | 'ufixed72x168' | 'ufixed72x176' | 'ufixed72x184' | 'ufixed80x8' | 'ufixed80x16' | 'ufixed80x24' | 'ufixed80x32' | 'ufixed80x40' | 'ufixed80x48' | 'ufixed80x56' | 'ufixed80x64' | 'ufixed80x72' | 'ufixed80x80' | 'ufixed80x88' | 'ufixed80x96' | 'ufixed80x104' | 'ufixed80x112' | 'ufixed80x120' | 'ufixed80x128' | 'ufixed80x136' | 'ufixed80x144' | 'ufixed80x152' | 'ufixed80x160' | 'ufixed80x168' | 'ufixed80x176' | 'ufixed88x8' | 'ufixed88x16' | 'ufixed88x24' | 'ufixed88x32' | 'ufixed88x40' | 'ufixed88x48' | 'ufixed88x56' | 'ufixed88x64' | 'ufixed88x72' | 'ufixed88x80' | 'ufixed88x88' | 'ufixed88x96' | 'ufixed88x104' | 'ufixed88x112' | 'ufixed88x120' | 'ufixed88x128' | 'ufixed88x136' | 'ufixed88x144' | 'ufixed88x152' | 'ufixed88x160' | 'ufixed88x168' | 'ufixed96x8' | 'ufixed96x16' | 'ufixed96x24' | 'ufixed96x32' | 'ufixed96x40' | 'ufixed96x48' | 'ufixed96x56' | 'ufixed96x64' | 'ufixed96x72' | 'ufixed96x80' | 'ufixed96x88' | 'ufixed96x96' | 'ufixed96x104' | 'ufixed96x112' | 'ufixed96x120' | 'ufixed96x128' | 'ufixed96x136' | 'ufixed96x144' | 'ufixed96x152' | 'ufixed96x160' | 'ufixed104x8' | 'ufixed104x16' | 'ufixed104x24' | 'ufixed104x32' | 'ufixed104x40' | 'ufixed104x48' | 'ufixed104x56' | 'ufixed104x64' | 'ufixed104x72' | 'ufixed104x80' | 'ufixed104x88' | 'ufixed104x96' | 'ufixed104x104' | 'ufixed104x112' | 'ufixed104x120' | 'ufixed104x128' | 'ufixed104x136' | 'ufixed104x144' | 'ufixed104x152' | 'ufixed112x8' | 'ufixed112x16' | 'ufixed112x24' | 'ufixed112x32' | 'ufixed112x40' | 'ufixed112x48' | 'ufixed112x56' | 'ufixed112x64' | 'ufixed112x72' | 'ufixed112x80' | 'ufixed112x88' | 'ufixed112x96' | 'ufixed112x104' | 'ufixed112x112' | 'ufixed112x120' | 'ufixed112x128' | 'ufixed112x136' | 'ufixed112x144' | 'ufixed120x8' | 'ufixed120x16' | 'ufixed120x24' | 'ufixed120x32' | 'ufixed120x40' | 'ufixed120x48' | 'ufixed120x56' | 'ufixed120x64' | 'ufixed120x72' | 'ufixed120x80' | 'ufixed120x88' | 'ufixed120x96' | 'ufixed120x104' | 'ufixed120x112' | 'ufixed120x120' | 'ufixed120x128' | 'ufixed120x136' | 'ufixed128x8' | 'ufixed128x16' | 'ufixed128x24' | 'ufixed128x32' | 'ufixed128x40' | 'ufixed128x48' | 'ufixed128x56' | 'ufixed128x64' | 'ufixed128x72' | 'ufixed128x80' | 'ufixed128x88' | 'ufixed128x96' | 'ufixed128x104' | 'ufixed128x112' | 'ufixed128x120' | 'ufixed128x128' | 'ufixed136x8' | 'ufixed136x16' | 'ufixed136x24' | 'ufixed136x32' | 'ufixed136x40' | 'ufixed136x48' | 'ufixed136x56' | 'ufixed136x64' | 'ufixed136x72' | 'ufixed136x80' | 'ufixed136x88' | 'ufixed136x96' | 'ufixed136x104' | 'ufixed136x112' | 'ufixed136x120' | 'ufixed144x8' | 'ufixed144x16' | 'ufixed144x24' | 'ufixed144x32' | 'ufixed144x40' | 'ufixed144x48' | 'ufixed144x56' | 'ufixed144x64' | 'ufixed144x72' | 'ufixed144x80' | 'ufixed144x88' | 'ufixed144x96' | 'ufixed144x104' | 'ufixed144x112' | 'ufixed152x8' | 'ufixed152x16' | 'ufixed152x24' | 'ufixed152x32' | 'ufixed152x40' | 'ufixed152x48' | 'ufixed152x56' | 'ufixed152x64' | 'ufixed152x72' | 'ufixed152x80' | 'ufixed152x88' | 'ufixed152x96' | 'ufixed152x104' | 'ufixed160x8' | 'ufixed160x16' | 'ufixed160x24' | 'ufixed160x32' | 'ufixed160x40' | 'ufixed160x48' | 'ufixed160x56' | 'ufixed160x64' | 'ufixed160x72' | 'ufixed160x80' | 'ufixed160x88' | 'ufixed160x96' | 'ufixed168x8' | 'ufixed168x16' | 'ufixed168x24' | 'ufixed168x32' | 'ufixed168x40' | 'ufixed168x48' | 'ufixed168x56' | 'ufixed168x64' | 'ufixed168x72' | 'ufixed168x80' | 'ufixed168x88' | 'ufixed176x8' | 'ufixed176x16' | 'ufixed176x24' | 'ufixed176x32' | 'ufixed176x40' | 'ufixed176x48' | 'ufixed176x56' | 'ufixed176x64' | 'ufixed176x72' | 'ufixed176x80' | 'ufixed184x8' | 'ufixed184x16' | 'ufixed184x24' | 'ufixed184x32' | 'ufixed184x40' | 'ufixed184x48' | 'ufixed184x56' | 'ufixed184x64' | 'ufixed184x72' | 'ufixed192x8' | 'ufixed192x16' | 'ufixed192x24' | 'ufixed192x32' | 'ufixed192x40' | 'ufixed192x48' | 'ufixed192x56' | 'ufixed192x64' | 'ufixed200x8' | 'ufixed200x16' | 'ufixed200x24' | 'ufixed200x32' | 'ufixed200x40' | 'ufixed200x48' | 'ufixed200x56' | 'ufixed208x8' | 'ufixed208x16' | 'ufixed208x24' | 'ufixed208x32' | 'ufixed208x40' | 'ufixed208x48' | 'ufixed216x8' | 'ufixed216x16' | 'ufixed216x24' | 'ufixed216x32' | 'ufixed216x40' | 'ufixed224x8' | 'ufixed224x16' | 'ufixed224x24' | 'ufixed224x32' | 'ufixed232x8' | 'ufixed232x16' | 'ufixed232x24' | 'ufixed240x8' | 'ufixed240x16' | 'ufixed248x8'
+
+InlineAssemblyBlock = '{' AssemblyItem* '}'
+
+AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | NumberLiteral | StringLiteral | HexLiteral
+AssemblyLocalBinding = 'let' Identifier ':=' FunctionalAssemblyExpression
+AssemblyAssignment = Identifier ':=' FunctionalAssemblyExpression | '=:' Identifier
+FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')'
diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst
index ec40e822..ef38705c 100644
--- a/docs/installing-solidity.rst
+++ b/docs/installing-solidity.rst
@@ -44,6 +44,21 @@ To install it, simply use
Details about the usage of the Node.js package can be found in the
`solc-js repository <https://github.com/ethereum/solc-js>`_.
+Docker
+======
+
+We provide up to date docker builds for the compiler. The ``stable``
+repository contains released versions while the ``nightly``
+repository contains potentially unstable changes in the develop branch.
+
+.. code:: bash
+
+ docker run ethereum/solc:stable solc --version
+
+Currenty, the docker image only contains the compiler executable,
+so you have to do some additional work to link in the source and
+output directories.
+
Binary Packages
===============
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index 4a3de441..aee1e03b 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -433,7 +433,7 @@ Logs
====
It is possible to store data in a specially indexed data structure
-that maps all they way up to the block level. This feature called **logs**
+that maps all the way up to the block level. This feature called **logs**
is used by Solidity in order to implement **events**.
Contracts cannot access log data after it has been created, but they
can be efficiently accessed from outside the blockchain.
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 0b3eed38..4a9dad87 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -56,6 +56,8 @@ So for the following contract snippet::
The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``.
+.. index: memory layout
+
****************
Layout in Memory
****************
@@ -72,7 +74,69 @@ Solidity always places new objects at the free memory pointer and memory is neve
.. warning::
There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifecycle, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one shouldn't expect the free memory to be zeroed out.
-.. index: memory layout
+
+.. index: calldata layout
+
+*******************
+Layout of Call Data
+*******************
+
+When a Solidity contract is deployed and when it is called from an
+account, the input data is assumed to be in the format in `the ABI
+specification
+<https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI>`_. The
+ABI specification requires arguments to be padded to multiples of 32
+bytes. The internal function calls use a different convention.
+
+
+.. index: variable cleanup
+
+*********************************
+Internals - Cleaning Up Variables
+*********************************
+
+When a value is shorter than 256-bit, in some cases the remaining bits
+must be cleaned.
+The Solidity compiler is designed to clean such remaining bits before any operations
+that might be adversely affected by the potential garbage in the remaining bits.
+For example, before writing a value to the memory, the remaining bits need
+to be cleared because the memory contents can be used for computing
+hashes or sent as the data of a message call. Similarly, before
+storing a value in the storage, the remaining bits need to be cleaned
+because otherwise the garbled value can be observed.
+
+On the other hand, we do not clean the bits if the immediately
+following operation is not affected. For instance, since any non-zero
+value is considered ``true`` by ``JUMPI`` instruction, we do not clean
+the boolean values before they are used as the condition for
+``JUMPI``.
+
+In addition to the design principle above, the Solidity compiler
+cleans input data when it is loaded onto the stack.
+
+Different types have different rules for cleaning up invalid values:
+
++---------------+---------------+-------------------+
+|Type |Valid Values |Invalid Values Mean|
++===============+===============+===================+
+|enum of n |0 until n - 1 |exception |
+|members | | |
++---------------+---------------+-------------------+
+|bool |0 or 1 |1 |
++---------------+---------------+-------------------+
+|signed integers|sign-extended |currently silently |
+| |word |wraps; in the |
+| | |future exceptions |
+| | |will be thrown |
+| | | |
+| | | |
++---------------+---------------+-------------------+
+|unsigned |higher bits |currently silently |
+|integers |zeroed |wraps; in the |
+| | |future exceptions |
+| | |will be thrown |
++---------------+---------------+-------------------+
+
*****************
Esoteric Features
@@ -221,6 +285,142 @@ Either add ``--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"`` to
If ``solc`` is called with the option ``--link``, all input files are interpreted to be unlinked binaries (hex-encoded) in the ``__LibraryName____``-format given above and are linked in-place (if the input is read from stdin, it is written to stdout). All options except ``--libraries`` are ignored (including ``-o``) in this case.
+*****************
+Contract Metadata
+*****************
+
+The Solidity compiler automatically generates a JSON file, the
+contract metadata, that contains information about the current contract.
+It can be used to query the compiler version, the sources used, the ABI
+and NatSpec documentation in order to more safely interact with the contract
+and to verify its source code.
+
+The compiler appends a Swarm hash of the metadata file to the end of the
+bytecode (for details, see below) of each contract, so that you can retrieve
+the file in an authenticated way without having to resort to a centralized
+data provider.
+
+Of course, you have to publish the metadata file to Swarm (or some other service)
+so that others can access it. The file can be output by using ``solc --metadata``
+and the file will be called ``ContractName_meta.json``.
+It will contain Swarm references to the source code, so you have to upload
+all source files and the metadata file.
+
+The metadata file has the following format. The example below is presented in a
+human-readable way. Properly formatted metadata should use quotes correctly,
+reduce whitespace to a minimum and sort the keys of all objects to arrive at a
+unique formatting.
+Comments are of course also not permitted and used here only for explanatory purposes.
+
+.. code-block:: none
+
+ {
+ // Required: The version of the metadata format
+ version: "1",
+ // Required: Source code language, basically selects a "sub-version"
+ // of the specification
+ language: "Solidity",
+ // Required: Details about the compiler, contents are specific
+ // to the language.
+ compiler: {
+ // Required for Solidity: Version of the compiler
+ version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
+ // Optional: Hash of the compiler binary which produced this output
+ keccak256: "0x123..."
+ },
+ // Required: Compilation source files/source units, keys are file names
+ sources:
+ {
+ "myFile.sol": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x123...",
+ // Required (unless "content" is used, see below): Sorted URL(s)
+ // to the source file, protocol is more or less arbitrary, but a
+ // Swarm URL is recommended
+ "urls": [ "bzzr://56ab..." ]
+ },
+ "mortal": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x234...",
+ // Required (unless "url" is used): literal contents of the source file
+ "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
+ }
+ },
+ // Required: Compiler settings
+ settings:
+ {
+ // Required for Solidity: Sorted list of remappings
+ remappings: [ ":g/dir" ],
+ // Optional: Optimizer settings (enabled defaults to false)
+ optimizer: {
+ enabled: true,
+ runs: 500
+ },
+ // Required for Solidity: File and name of the contract or library this
+ // metadata is created for.
+ compilationTarget: {
+ "myFile.sol": "MyContract"
+ },
+ // Required for Solidity: Addresses for libraries used
+ libraries: {
+ "MyLib": "0x123123..."
+ }
+ },
+ // Required: Generated information about the contract.
+ output:
+ {
+ // Required: ABI definition of the contract
+ abi: [ ... ],
+ // Required: NatSpec user documentation of the contract
+ userdoc: [ ... ],
+ // Required: NatSpec developer documentation of the contract
+ devdoc: [ ... ],
+ }
+ }
+
+
+Encoding of the Metadata Hash in the Bytecode
+=============================================
+
+Because we might support other ways to retrieve the metadata file in the future,
+the mapping ``{"bzzr0": <Swarm hash>}`` is stored
+[CBOR](https://tools.ietf.org/html/rfc7049)-encoded. Since the beginning of that
+encoding is not easy to find, its length is added in a two-byte big-endian
+encoding. The current version of the Solidity compiler thus adds the following
+to the end of the deployed bytecode::
+
+ 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
+
+So in order to retrieve the data, the end of the deployed bytecode can be checked
+to match that pattern and use the Swarm hash to retrieve the file.
+
+Usage for Automatic Interface Generation and NatSpec
+====================================================
+
+The metadata is used in the following way: A component that wants to interact
+with a contract (e.g. Mist) retrieves the code of the contract, from that
+the Swarm hash of a file which is then retrieved.
+That file is JSON-decoded into a structure like above.
+
+The component can then use the ABI to automatically generate a rudimentary
+user interface for the contract.
+
+Furthermore, Mist can use the userdoc to display a confirmation message to the user
+whenever they interact with the contract.
+
+Usage for Source Code Verification
+==================================
+
+In order to verify the compilation, sources can be retrieved from Swarm
+via the link in the metadata file.
+The compiler of the correct version (which is checked to be part of the "official" compilers)
+is invoked on that input with the specified settings. The resulting
+bytecode is compared to the data of the creation transaction or CREATE opcode data.
+This automatically verifies the metadata since its hash is part of the bytecode.
+Excess data corresponds to the constructor input data, which should be decoded
+according to the interface and presented to the user.
+
+
***************
Tips and Tricks
***************
@@ -363,10 +563,10 @@ Reserved Keywords
These keywords are reserved in Solidity. They might become part of the syntax in the future:
-``abstract``, ``after``, ``case``, ``catch``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``,
+``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``, ``null``,
``of``, ``pure``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``, ``view``.
Language Grammar
================
-The entire language grammar is `available here <https://github.com/ethereum/solidity/blob/release/libsolidity/grammar.txt>`_.
+.. literalinclude:: grammar.txt
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index 272a1b31..9aae3d7b 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -150,6 +150,74 @@ No::
...
}
+Order of Functions
+==================
+
+Ordering helps readers identify which functions they can call and to find the constructor and fallback definitions easier.
+
+Functions should be grouped according to their visibility and ordered:
+
+- constructor
+- fallback function (if exists)
+- external
+- public
+- internal
+- private
+
+Within a grouping, place the `constant` functions last.
+
+Yes::
+
+ contract A {
+ function A() {
+ ...
+ }
+
+ function() {
+ ...
+ }
+
+ // External functions
+ // ...
+
+ // External functions that are constant
+ // ...
+
+ // Public functions
+ // ...
+
+ // Internal functions
+ // ...
+
+ // Private functions
+ // ...
+ }
+
+No::
+
+ contract A {
+
+ // External functions
+ // ...
+
+ // Private functions
+ // ...
+
+ // Public functions
+ // ...
+
+ function A() {
+ ...
+ }
+
+ function() {
+ ...
+ }
+
+ // Internal functions
+ // ...
+ }
+
Whitespace in Expressions
=========================
@@ -194,6 +262,19 @@ No::
y = 2;
long_variable = 3;
+Don't include a whitespace in the fallback function:
+
+Yes::
+
+ function() {
+ ...
+ }
+
+No::
+
+ function () {
+ ...
+ }
Control Structures
==================
diff --git a/docs/types.rst b/docs/types.rst
index b22ad7d4..069a9190 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -52,12 +52,17 @@ Operators:
* Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``)
* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation)
-* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation)
+* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift)
Division always truncates (it just maps to the DIV opcode of the EVM), but it does not truncate if both
operators are :ref:`literals<rational_literals>` (or literal expressions).
-Division by zero and modulus with zero throws an exception.
+Division by zero and modulus with zero throws a runtime exception.
+
+The result of a shift operation is the type of the left operand. The
+expression ``x << y`` is equivalent to ``x * 2**y`` and ``x >> y`` is
+equivalent to ``x / 2**y``. This means that shifting negative numbers
+sign extends. Shifting by a negative amount throws a runtime exception.
.. index:: address, balance, send, call, callcode, delegatecall
@@ -136,9 +141,13 @@ Fixed-size byte arrays
Operators:
* Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``)
-* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation)
+* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift)
* Index access: If ``x`` is of type ``bytesI``, then ``x[k]`` for ``0 <= k < I`` returns the ``k`` th byte (read-only).
+The shifting operator works with any integer type as right operand (but will
+return the type of the left operand), which denotes the number of bits to shift by.
+Shifting by a negative amount will cause a runtime exception.
+
Members:
* ``.length`` yields the fixed length of the byte array (read-only).
@@ -169,9 +178,18 @@ Fixed Point Numbers
Rational and Integer Literals
-----------------------------
-All number literals retain arbitrary precision until they are converted to a non-literal type (i.e. by
-using them together with a non-literal type). This means that computations do not overflow but also
-divisions do not truncate.
+Integer literals are formed from a sequence of numbers in the range 0-9.
+They are interpreted as decimals. For example, ``69`` means sixty nine.
+Octal literals do not exist in Solidity and leading zeros are ignored.
+For example, ``0100`` means one hundred.
+
+Decimal literals are formed by a ``.`` with at least one number on
+one side. Examples include ``1.``, ``.1`` and ``1.3``.
+
+Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. by
+using them together with a non-literal expression).
+This means that computations do not overflow and divisions do not truncate
+in number literal expressions.
For example, ``(2**800 + 1) - 2**800`` results in the constant ``1`` (of type ``uint8``)
although intermediate results would not even fit the machine word size. Furthermore, ``.5 * 8`` results
@@ -185,12 +203,20 @@ In ``var x = 1/4;``, ``x`` will receive the type ``ufixed0x8`` while in ``var x
the type ``ufixed0x256`` because ``1/3`` is not finitely representable in binary and will thus be
approximated.
-Any operator that can be applied to integers can also be applied to literal expressions as
+Any operator that can be applied to integers can also be applied to number literal expressions as
long as the operands are integers. If any of the two is fractional, bit operations are disallowed
and exponentiation is disallowed if the exponent is fractional (because that might result in
a non-rational number).
.. note::
+ Solidity has a number literal type for each rational number.
+ Integer literals and rational number literals belong to number literal types.
+ Moreover, all number literal expressions (i.e. the expressions that
+ contain only number literals and operators) belong to number literal
+ types. So the number literal expressions `1 + 2` and `2 + 1` both
+ belong to the same number literal type for the rational number three.
+
+.. note::
Most finite decimal fractions like ``5.3743`` are not finitely representable in binary. The correct type
for ``5.3743`` is ``ufixed8x248`` because that allows to best approximate the number. If you want to
use the number together with types like ``ufixed`` (i.e. ``ufixed128x128``), you have to explicitly
@@ -200,7 +226,7 @@ a non-rational number).
Division on integer literals used to truncate in earlier versions, but it will now convert into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``.
.. note::
- Literal expressions are converted to a permanent type as soon as they are used with other
+ Number literal expressions are converted into a non-literal type as soon as they are used with non-literal
expressions. Even though we know that the value of the
expression assigned to ``b`` in the following example evaluates to an integer, it still
uses fixed point types (and not rational number literals) in between and so the code
@@ -216,7 +242,7 @@ a non-rational number).
String Literals
---------------
-String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``.
+String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; `"foo"`` represents three bytes not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``.
String literals support escape characters, such as ``\n``, ``\xNN`` and ``\uNNNN``. ``\xNN`` takes a hex value and inserts the appropriate byte, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 sequence.
@@ -312,12 +338,19 @@ If external function types are used outside of the context of Solidity,
they are treated as the ``function`` type, which encodes the address
followed by the function identifier together in a single ``bytes24`` type.
+Note that public functions of the current contract can be used both as an
+internal and as an external function. To use ``f`` as an internal function,
+just use ``f``, if you want to use its external form, use ``this.f``.
+
Example that shows how to use internal function types::
+ pragma solidity ^0.4.5;
+
library ArrayUtils {
// internal functions can be used in internal library functions because
// they will be part of the same code context
function map(uint[] memory self, function (uint) returns (uint) f)
+ internal
returns (uint[] memory r)
{
r = new uint[](self.length);
@@ -327,8 +360,9 @@ Example that shows how to use internal function types::
}
function reduce(
uint[] memory self,
- function (uint) returns (uint) f
+ function (uint x, uint y) returns (uint) f
)
+ internal
returns (uint r)
{
r = self[0];
@@ -336,7 +370,7 @@ Example that shows how to use internal function types::
r = f(r, self[i]);
}
}
- function range(uint length) returns (uint[] memory r) {
+ function range(uint length) internal returns (uint[] memory r) {
r = new uint[](length);
for (uint i = 0; i < r.length; i++) {
r[i] = i;
@@ -346,7 +380,7 @@ Example that shows how to use internal function types::
contract Pyramid {
using ArrayUtils for *;
- function pyramid(uint l) return (uint) {
+ function pyramid(uint l) returns (uint) {
return ArrayUtils.range(l).map(square).reduce(sum);
}
function square(uint x) internal returns (uint) {
@@ -359,14 +393,16 @@ Example that shows how to use internal function types::
Another example that uses external function types::
+ pragma solidity ^0.4.5;
+
contract Oracle {
struct Request {
bytes data;
- function(bytes) external callback;
+ function(bytes memory) external callback;
}
Request[] requests;
event NewRequest(uint);
- function query(bytes data, function(bytes) external callback) {
+ function query(bytes data, function(bytes memory) external callback) {
requests.push(Request(data, callback));
NewRequest(requests.length - 1);
}
@@ -377,12 +413,12 @@ Another example that uses external function types::
}
contract OracleUser {
- Oracle constant oracle = 0x1234567; // known contract
+ Oracle constant oracle = Oracle(0x1234567); // known contract
function buySomething() {
- oracle.query("USD", oracleResponse);
+ oracle.query("USD", this.oracleResponse);
}
function oracleResponse(bytes response) {
- if (msg.sender != oracle) throw;
+ if (msg.sender != address(oracle)) throw;
// Use the data
}
}
@@ -729,9 +765,9 @@ assigning it to a local variable, as in
Mappings
========
-Mapping types are declared as ``mapping _KeyType => _ValueType``, where
-``_KeyType`` can be almost any type except for a mapping and ``_ValueType``
-can actually be any type, including mappings.
+Mapping types are declared as ``mapping _KeyType => _ValueType``.
+Here ``_KeyType`` can be almost any type except for a mapping, a dynamically sized array, a contract, an enum and a struct.
+``_ValueType`` can actually be any type, including mappings.
Mappings can be seen as hashtables which are virtually initialized such that
every possible key exists and is mapped to a value whose byte-representation is
diff --git a/libdevcore/Common.h b/libdevcore/Common.h
index d65cfeac..225f38ac 100644
--- a/libdevcore/Common.h
+++ b/libdevcore/Common.h
@@ -135,6 +135,17 @@ inline u256 s2u(s256 _u)
return u256(c_end + _u);
}
+inline std::ostream& operator<<(std::ostream& os, bytes const& _bytes)
+{
+ std::ostringstream ss;
+ ss << std::hex;
+ std::copy(_bytes.begin(), _bytes.end(), std::ostream_iterator<int>(ss, ","));
+ std::string result = ss.str();
+ result.pop_back();
+ os << "[" + result + "]";
+ return os;
+}
+
template <size_t n> inline u256 exp10()
{
return exp10<n - 1>() * u256(10);
diff --git a/libdevcore/JSON.h b/libdevcore/JSON.h
index 7876dfb2..9f7d9a03 100644
--- a/libdevcore/JSON.h
+++ b/libdevcore/JSON.h
@@ -27,14 +27,14 @@
namespace dev
{
-/// Serialise the JSON object (@a _input) with identation
-std::string jsonPrettyPrint(Json::Value const& _input)
+/// Serialise the JSON object (@a _input) with indentation
+inline std::string jsonPrettyPrint(Json::Value const& _input)
{
return Json::StyledWriter().write(_input);
}
-/// Serialise theJ SON object (@a _input) without identation
-std::string jsonCompactPrint(Json::Value const& _input)
+/// Serialise the JSON object (@a _input) without indentation
+inline std::string jsonCompactPrint(Json::Value const& _input)
{
Json::FastWriter writer;
writer.omitEndingLineFeed();
diff --git a/libdevcore/SwarmHash.cpp b/libdevcore/SwarmHash.cpp
index e7b844eb..aa98eafd 100644
--- a/libdevcore/SwarmHash.cpp
+++ b/libdevcore/SwarmHash.cpp
@@ -38,13 +38,14 @@ h256 swarmHashSimple(bytesConstRef _data, size_t _size)
return keccak256(toLittleEndian(_size) + _data.toBytes());
}
-h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length)
+h256 swarmHashIntermediate(string const& _input, size_t _offset, size_t _length)
{
+ bytesConstRef ref;
+ bytes innerNodes;
if (_length <= 0x1000)
- return swarmHashSimple(bytesConstRef(_input.data() + _offset, _length), _length);
+ ref = bytesConstRef(_input).cropped(_offset, _length);
else
{
- bytes innerNodes;
size_t maxRepresentedSize = 0x1000;
while (maxRepresentedSize * (0x1000 / 32) < _length)
maxRepresentedSize *= (0x1000 / 32);
@@ -53,11 +54,12 @@ h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length)
size_t size = std::min(maxRepresentedSize, _length - i);
innerNodes += swarmHashIntermediate(_input, _offset + i, size).asBytes();
}
- return swarmHashSimple(bytesConstRef(&innerNodes), _length);
+ ref = bytesConstRef(&innerNodes);
}
+ return swarmHashSimple(ref, _length);
}
-h256 dev::swarmHash(bytes const& _input)
+h256 dev::swarmHash(string const& _input)
{
return swarmHashIntermediate(_input, 0, _input.size());
}
diff --git a/libdevcore/SwarmHash.h b/libdevcore/SwarmHash.h
index 925509ab..f474ce11 100644
--- a/libdevcore/SwarmHash.h
+++ b/libdevcore/SwarmHash.h
@@ -20,12 +20,13 @@
#pragma once
#include <libdevcore/FixedHash.h>
-#include <libdevcore/Common.h>
+
+#include <string>
namespace dev
{
/// Compute the "swarm hash" of @a _data
-h256 swarmHash(bytes const& _data);
+h256 swarmHash(std::string const& _data);
}
diff --git a/libdevcore/UTF8.cpp b/libdevcore/UTF8.cpp
index d742fe66..1c7ed17c 100644
--- a/libdevcore/UTF8.cpp
+++ b/libdevcore/UTF8.cpp
@@ -28,7 +28,7 @@ namespace dev
{
-bool validate(std::string const& _input, size_t& _invalidPosition)
+bool validateUTF8(std::string const& _input, size_t& _invalidPosition)
{
const size_t length = _input.length();
bool valid = true;
diff --git a/libdevcore/UTF8.h b/libdevcore/UTF8.h
index 3e39273c..753914e3 100644
--- a/libdevcore/UTF8.h
+++ b/libdevcore/UTF8.h
@@ -29,7 +29,13 @@ namespace dev
{
/// Validate an input for UTF8 encoding
-/// @returns true if it is invalid and the first invalid position in invalidPosition
-bool validate(std::string const& _input, size_t& _invalidPosition);
+/// @returns false if it is invalid and the first invalid position in invalidPosition
+bool validateUTF8(std::string const& _input, size_t& _invalidPosition);
+
+inline bool validateUTF8(std::string const& _input)
+{
+ size_t invalidPos;
+ return validateUTF8(_input, invalidPos);
+}
}
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index c394afa2..a9ca24dc 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Assembly.cpp
* @author Gav Wood <i@gavwood.com>
@@ -331,13 +331,12 @@ map<u256, u256> Assembly::optimiseInternal(bool _enable, bool _isCreation, size_
}
map<u256, u256> tagReplacements;
- unsigned total = 0;
- for (unsigned count = 1; count > 0; total += count)
+ for (unsigned count = 1; count > 0;)
{
count = 0;
PeepholeOptimiser peepOpt(m_items);
- if (peepOpt.optimise())
+ while (peepOpt.optimise())
count++;
if (!_enable)
@@ -399,7 +398,7 @@ map<u256, u256> Assembly::optimiseInternal(bool _enable, bool _isCreation, size_
}
if (_enable)
- total += ConstantOptimisationMethod::optimiseConstants(
+ ConstantOptimisationMethod::optimiseConstants(
_isCreation,
_isCreation ? 1 : _runs,
*this,
@@ -433,7 +432,7 @@ LinkerObject const& Assembly::assemble() const
unsigned bytesPerTag = dev::bytesRequired(bytesRequiredForCode);
byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag;
- unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1;
+ unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1 + m_auxiliaryData.size();
for (auto const& sub: m_subs)
bytesRequiredIncludingData += sub->assemble().bytecode.size();
@@ -526,8 +525,10 @@ LinkerObject const& Assembly::assemble() const
}
}
- if (!dataRef.empty() && !subRef.empty())
+ if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty())
+ // Append a STOP just to be sure.
ret.bytecode.push_back(0);
+
for (size_t i = 0; i < m_subs.size(); ++i)
{
auto references = subRef.equal_range(i);
@@ -569,6 +570,9 @@ LinkerObject const& Assembly::assemble() const
}
ret.bytecode += dataItem.second;
}
+
+ ret.bytecode += m_auxiliaryData;
+
for (unsigned pos: sizeRef)
{
bytesRef r(ret.bytecode.data() + pos, bytesPerDataRef);
diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h
index f3c56610..9e7f9f7b 100644
--- a/libevmasm/Assembly.h
+++ b/libevmasm/Assembly.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
@@ -71,6 +71,9 @@ public:
AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMPI); return ret; }
AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); }
+ /// Appends @a _data literally to the very end of the bytecode.
+ void appendAuxiliaryDataToEnd(bytes const& _data) { m_auxiliaryData += _data; }
+
template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
AssemblyItems const& items() const { return m_items; }
AssemblyItem const& back() const { return m_items.back(); }
@@ -125,10 +128,12 @@ private:
Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const;
protected:
- // 0 is reserved for exception
+ /// 0 is reserved for exception
unsigned m_usedTags = 1;
AssemblyItems m_items;
std::map<h256, bytes> m_data;
+ /// Data that is appended to the very end of the contract.
+ bytes m_auxiliaryData;
std::vector<std::shared_ptr<Assembly>> m_subs;
std::map<h256, std::string> m_strings;
std::map<h256, std::string> m_libraries; ///< Identifiers of libraries to be linked.
diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp
index 7bd93eaf..54e38de8 100644
--- a/libevmasm/AssemblyItem.cpp
+++ b/libevmasm/AssemblyItem.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Assembly.cpp
* @author Gav Wood <i@gavwood.com>
diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h
index 1a2fb1e6..b5bd3ed8 100644
--- a/libevmasm/AssemblyItem.h
+++ b/libevmasm/AssemblyItem.h
@@ -1,20 +1,20 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
-/** @file Assembly.h
+/** @file AssemblyItem.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp
index 18b595cd..d21be07e 100644
--- a/libevmasm/BlockDeduplicator.cpp
+++ b/libevmasm/BlockDeduplicator.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file BlockDeduplicator.cpp
diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h
index 5ecab7f3..797c2476 100644
--- a/libevmasm/BlockDeduplicator.h
+++ b/libevmasm/BlockDeduplicator.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file BlockDeduplicator.h
diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp
index 0797dd29..6294e579 100644
--- a/libevmasm/CommonSubexpressionEliminator.cpp
+++ b/libevmasm/CommonSubexpressionEliminator.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file CommonSubexpressionEliminator.cpp
diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h
index f6c43c57..83fc9732 100644
--- a/libevmasm/CommonSubexpressionEliminator.h
+++ b/libevmasm/CommonSubexpressionEliminator.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file CommonSubexpressionEliminator.h
diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp
index 27f630f5..f4a50c2d 100644
--- a/libevmasm/ConstantOptimiser.cpp
+++ b/libevmasm/ConstantOptimiser.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ConstantOptimiser.cpp
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h
index e75eff38..b35b2a69 100644
--- a/libevmasm/ConstantOptimiser.h
+++ b/libevmasm/ConstantOptimiser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ConstantOptimiser.cpp
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp
index d4801562..86f16d48 100644
--- a/libevmasm/ControlFlowGraph.cpp
+++ b/libevmasm/ControlFlowGraph.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ControlFlowGraph.cpp
diff --git a/libevmasm/ControlFlowGraph.h b/libevmasm/ControlFlowGraph.h
index 78998262..ebef543f 100644
--- a/libevmasm/ControlFlowGraph.h
+++ b/libevmasm/ControlFlowGraph.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ControlFlowGraph.h
diff --git a/libevmasm/EVMSchedule.h b/libevmasm/EVMSchedule.h
index 02a34b16..f882f006 100644
--- a/libevmasm/EVMSchedule.h
+++ b/libevmasm/EVMSchedule.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file EVMSchedule.h
* @author Gav <i@gavwood.com>
diff --git a/libevmasm/Exceptions.h b/libevmasm/Exceptions.h
index 03b8afde..06b0ac78 100644
--- a/libevmasm/Exceptions.h
+++ b/libevmasm/Exceptions.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Exceptions.h
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp
index cf5e6a0e..d5ccd7e3 100644
--- a/libevmasm/ExpressionClasses.cpp
+++ b/libevmasm/ExpressionClasses.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ExpressionClasses.cpp
@@ -245,22 +245,25 @@ Rules::Rules()
// invariants involving known constants
{{Instruction::ADD, {X, 0}}, [=]{ return X; }},
+ {{Instruction::SUB, {X, 0}}, [=]{ return X; }},
{{Instruction::MUL, {X, 1}}, [=]{ return X; }},
{{Instruction::DIV, {X, 1}}, [=]{ return X; }},
{{Instruction::SDIV, {X, 1}}, [=]{ return X; }},
{{Instruction::OR, {X, 0}}, [=]{ return X; }},
{{Instruction::XOR, {X, 0}}, [=]{ return X; }},
{{Instruction::AND, {X, ~u256(0)}}, [=]{ return X; }},
+ {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::MUL, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::DIV, {X, 0}}, [=]{ return u256(0); }},
+ {{Instruction::DIV, {0, X}}, [=]{ return u256(0); }},
{{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::MOD, {0, X}}, [=]{ return u256(0); }},
- {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::OR, {X, ~u256(0)}}, [=]{ return ~u256(0); }},
{{Instruction::EQ, {X, 0}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; } },
// operations involving an expression and itself
{{Instruction::AND, {X, X}}, [=]{ return X; }},
{{Instruction::OR, {X, X}}, [=]{ return X; }},
+ {{Instruction::XOR, {X, X}}, [=]{ return u256(0); }},
{{Instruction::SUB, {X, X}}, [=]{ return u256(0); }},
{{Instruction::EQ, {X, X}}, [=]{ return u256(1); }},
{{Instruction::LT, {X, X}}, [=]{ return u256(0); }},
@@ -270,6 +273,11 @@ Rules::Rules()
{{Instruction::MOD, {X, X}}, [=]{ return u256(0); }},
{{Instruction::NOT, {{Instruction::NOT, {X}}}}, [=]{ return X; }},
+ {{Instruction::XOR, {{{X}, {Instruction::XOR, {X, Y}}}}}, [=]{ return Y; }},
+ {{Instruction::OR, {{{X}, {Instruction::AND, {X, Y}}}}}, [=]{ return X; }},
+ {{Instruction::AND, {{{X}, {Instruction::OR, {X, Y}}}}}, [=]{ return X; }},
+ {{Instruction::AND, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return u256(0); }},
+ {{Instruction::OR, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return ~u256(0); }},
};
// Double negation of opcodes with binary result
for (auto const& op: vector<Instruction>{
@@ -287,6 +295,10 @@ Rules::Rules()
{Instruction::ISZERO, {{Instruction::ISZERO, {{Instruction::ISZERO, {X}}}}}},
[=]() -> Pattern { return {Instruction::ISZERO, {X}}; }
});
+ m_rules.push_back({
+ {Instruction::ISZERO, {{Instruction::XOR, {X, Y}}}},
+ [=]() -> Pattern { return { Instruction::EQ, {X, Y} }; }
+ });
// Associative operations
for (auto const& opFun: vector<pair<Instruction,function<u256(u256 const&,u256 const&)>>>{
{Instruction::ADD, plus<u256>()},
diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h
index 4bfd7d24..11a698dd 100644
--- a/libevmasm/ExpressionClasses.h
+++ b/libevmasm/ExpressionClasses.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ExpressionClasses.h
diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp
index da8b41e3..21db3565 100644
--- a/libevmasm/GasMeter.cpp
+++ b/libevmasm/GasMeter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file GasMeter.cpp
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h
index ff127909..0bc10f1f 100644
--- a/libevmasm/GasMeter.h
+++ b/libevmasm/GasMeter.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file GasMeter.cpp
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp
index 2aaa6f1d..5244a91f 100644
--- a/libevmasm/Instruction.cpp
+++ b/libevmasm/Instruction.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Instruction.cpp
* @author Gav Wood <i@gavwood.com>
diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h
index 0b06a677..c7fad1c5 100644
--- a/libevmasm/Instruction.h
+++ b/libevmasm/Instruction.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Instruction.h
* @author Gav Wood <i@gavwood.com>
diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp
index 0b6e0ac5..6e3130dd 100644
--- a/libevmasm/KnownState.cpp
+++ b/libevmasm/KnownState.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file KnownState.cpp
diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h
index c1c602dc..fd6a26c1 100644
--- a/libevmasm/KnownState.h
+++ b/libevmasm/KnownState.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file KnownState.h
diff --git a/libevmasm/LinkerObject.cpp b/libevmasm/LinkerObject.cpp
index ceb864a1..93e4067c 100644
--- a/libevmasm/LinkerObject.cpp
+++ b/libevmasm/LinkerObject.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file LinkerObject.cpp
* @author Christian R <c@ethdev.com>
diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h
index 83d2bd7e..d3ec3e97 100644
--- a/libevmasm/LinkerObject.h
+++ b/libevmasm/LinkerObject.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Assembly.h
* @author Gav Wood <i@gavwood.com>
diff --git a/libevmasm/PathGasMeter.cpp b/libevmasm/PathGasMeter.cpp
index 2113008b..c56e2f8b 100644
--- a/libevmasm/PathGasMeter.cpp
+++ b/libevmasm/PathGasMeter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file PathGasMeter.cpp
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h
index 1ada460a..0a0fe5d0 100644
--- a/libevmasm/PathGasMeter.h
+++ b/libevmasm/PathGasMeter.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file PathGasMeter.cpp
* @author Christian <c@ethdev.com>
diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp
index f42dba48..b96b0295 100644
--- a/libevmasm/PeepholeOptimiser.cpp
+++ b/libevmasm/PeepholeOptimiser.cpp
@@ -1,21 +1,21 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
- * @file PeepholeOptimiser.h
+ * @file PeepholeOptimiser.cpp
* Performs local optimising code changes to assembly.
*/
@@ -30,60 +30,131 @@ using namespace dev;
// TODO: Extend this to use the tools from ExpressionClasses.cpp
-struct Identity
+struct OptimiserState
+{
+ AssemblyItems const& items;
+ size_t i;
+ std::back_insert_iterator<AssemblyItems> out;
+};
+
+template <class Method, size_t Arguments>
+struct ApplyRule
+{
+};
+template <class Method>
+struct ApplyRule<Method, 3>
{
- static size_t windowSize() { return 1; }
- static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
+ static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
{
- *_out = *_in;
- return true;
+ return Method::applySimple(_in[0], _in[1], _in[2], _out);
+ }
+};
+template <class Method>
+struct ApplyRule<Method, 2>
+{
+ static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
+ {
+ return Method::applySimple(_in[0], _in[1], _out);
+ }
+};
+template <class Method>
+struct ApplyRule<Method, 1>
+{
+ static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
+ {
+ return Method::applySimple(_in[0], _out);
}
};
-struct PushPop
+template <class Method, size_t WindowSize>
+struct SimplePeepholeOptimizerMethod
{
- static size_t windowSize() { return 2; }
- static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems>)
+ static bool apply(OptimiserState& _state)
{
- auto t = _in[0].type();
- if (_in[1] == Instruction::POP && (
- SemanticInformation::isDupInstruction(_in[0]) ||
- t == Push || t == PushString || t == PushTag || t == PushSub ||
- t == PushSubSize || t == PushProgramSize || t == PushData || t == PushLibraryAddress
- ))
+ if (
+ _state.i + WindowSize <= _state.items.size() &&
+ ApplyRule<Method, WindowSize>::applyRule(_state.items.begin() + _state.i, _state.out)
+ )
+ {
+ _state.i += WindowSize;
return true;
+ }
else
return false;
}
};
-struct DoubleSwap
+struct Identity: SimplePeepholeOptimizerMethod<Identity, 1>
{
- static size_t windowSize() { return 2; }
- static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems>)
+ static bool applySimple(AssemblyItem const& _item, std::back_insert_iterator<AssemblyItems> _out)
{
- if (_in[0] == _in[1] && SemanticInformation::isSwapInstruction(_in[0]))
- return true;
- else
- return false;
+ *_out = _item;
+ return true;
}
};
-struct JumpToNext
+struct PushPop: SimplePeepholeOptimizerMethod<PushPop, 2>
{
- static size_t windowSize() { return 3; }
- static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
+ static bool applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator<AssemblyItems>)
+ {
+ auto t = _push.type();
+ return _pop == Instruction::POP && (
+ SemanticInformation::isDupInstruction(_push) ||
+ t == Push || t == PushString || t == PushTag || t == PushSub ||
+ t == PushSubSize || t == PushProgramSize || t == PushData || t == PushLibraryAddress
+ );
+ }
+};
+
+struct OpPop: SimplePeepholeOptimizerMethod<OpPop, 2>
+{
+ static bool applySimple(
+ AssemblyItem const& _op,
+ AssemblyItem const& _pop,
+ std::back_insert_iterator<AssemblyItems> _out
+ )
+ {
+ if (_pop == Instruction::POP && _op.type() == Operation)
+ {
+ Instruction instr = _op.instruction();
+ if (instructionInfo(instr).ret == 1 && !instructionInfo(instr).sideEffects)
+ {
+ for (int j = 0; j < instructionInfo(instr).args; j++)
+ *_out = Instruction::POP;
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+struct DoubleSwap: SimplePeepholeOptimizerMethod<DoubleSwap, 2>
+{
+ static size_t applySimple(AssemblyItem const& _s1, AssemblyItem const& _s2, std::back_insert_iterator<AssemblyItems>)
+ {
+ return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1);
+ }
+};
+
+struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext, 3>
+{
+ static size_t applySimple(
+ AssemblyItem const& _pushTag,
+ AssemblyItem const& _jump,
+ AssemblyItem const& _tag,
+ std::back_insert_iterator<AssemblyItems> _out
+ )
{
if (
- _in[0].type() == PushTag &&
- (_in[1] == Instruction::JUMP || _in[1] == Instruction::JUMPI) &&
- _in[2].type() == Tag &&
- _in[0].data() == _in[2].data()
+ _pushTag.type() == PushTag &&
+ (_jump == Instruction::JUMP || _jump == Instruction::JUMPI) &&
+ _tag.type() == Tag &&
+ _pushTag.data() == _tag.data()
)
{
- if (_in[1] == Instruction::JUMPI)
- *_out = AssemblyItem(Instruction::POP, _in[1].location());
- *_out = _in[2];
+ if (_jump == Instruction::JUMPI)
+ *_out = AssemblyItem(Instruction::POP, _jump.location());
+ *_out = _tag;
return true;
}
else
@@ -91,19 +162,23 @@ struct JumpToNext
}
};
-struct TagConjunctions
+struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions, 3>
{
- static size_t windowSize() { return 3; }
- static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
+ static bool applySimple(
+ AssemblyItem const& _pushTag,
+ AssemblyItem const& _pushConstant,
+ AssemblyItem const& _and,
+ std::back_insert_iterator<AssemblyItems> _out
+ )
{
if (
- _in[0].type() == PushTag &&
- _in[2] == Instruction::AND &&
- _in[1].type() == Push &&
- (_in[1].data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF)
+ _pushTag.type() == PushTag &&
+ _and == Instruction::AND &&
+ _pushConstant.type() == Push &&
+ (_pushConstant.data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF)
)
{
- *_out = _in[0];
+ *_out = _pushTag;
return true;
}
else
@@ -111,11 +186,35 @@ struct TagConjunctions
}
};
-struct OptimiserState
+/// Removes everything after a JUMP (or similar) until the next JUMPDEST.
+struct UnreachableCode
{
- AssemblyItems const& items;
- size_t i;
- std::back_insert_iterator<AssemblyItems> out;
+ static bool apply(OptimiserState& _state)
+ {
+ auto it = _state.items.begin() + _state.i;
+ auto end = _state.items.end();
+ if (it == end)
+ return false;
+ if (
+ it[0] != Instruction::JUMP &&
+ it[0] != Instruction::RETURN &&
+ it[0] != Instruction::STOP &&
+ it[0] != Instruction::SUICIDE
+ )
+ return false;
+
+ size_t i = 1;
+ while (it + i != end && it[i].type() != Tag)
+ i++;
+ if (i > 1)
+ {
+ *_state.out = it[0];
+ _state.i += i;
+ return true;
+ }
+ else
+ return false;
+ }
};
void applyMethods(OptimiserState&)
@@ -126,9 +225,7 @@ void applyMethods(OptimiserState&)
template <typename Method, typename... OtherMethods>
void applyMethods(OptimiserState& _state, Method, OtherMethods... _other)
{
- if (_state.i + Method::windowSize() <= _state.items.size() && Method::apply(_state.items.begin() + _state.i, _state.out))
- _state.i += Method::windowSize();
- else
+ if (!Method::apply(_state))
applyMethods(_state, _other...);
}
@@ -136,7 +233,7 @@ bool PeepholeOptimiser::optimise()
{
OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)};
while (state.i < m_items.size())
- applyMethods(state, PushPop(), DoubleSwap(), JumpToNext(), TagConjunctions(), Identity());
+ applyMethods(state, PushPop(), OpPop(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity());
if (m_optimisedItems.size() < m_items.size())
{
m_items = std::move(m_optimisedItems);
diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h
index 372e49c5..a74cc8b3 100644
--- a/libevmasm/PeepholeOptimiser.h
+++ b/libevmasm/PeepholeOptimiser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file PeepholeOptimiser.h
diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp
index ea579b83..23a00d95 100644
--- a/libevmasm/SemanticInformation.cpp
+++ b/libevmasm/SemanticInformation.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file SemanticInformation.cpp
diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h
index 0eda5ed5..5b02061f 100644
--- a/libevmasm/SemanticInformation.h
+++ b/libevmasm/SemanticInformation.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file SemanticInformation.h
diff --git a/libevmasm/SourceLocation.h b/libevmasm/SourceLocation.h
index b8f073bb..b42c3aa9 100644
--- a/libevmasm/SourceLocation.h
+++ b/libevmasm/SourceLocation.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris Karapetsas <lefteris@ethdev.com>
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp
index d757dcf1..af7d7f0a 100644
--- a/liblll/CodeFragment.cpp
+++ b/liblll/CodeFragment.cpp
@@ -91,15 +91,11 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
{
auto it = _s.vars.find(s);
if (it == _s.vars.end())
- {
- bool ok;
- tie(it, ok) = _s.vars.insert(make_pair(s, make_pair(_s.stackSize, 32)));
- _s.stackSize += 32;
- }
+ error<InvalidName>(std::string("Symbol not found: ") + s);
m_asm.append((u256)it->second.first);
}
else
- error<BareSymbol>();
+ error<BareSymbol>(s);
break;
}
@@ -111,7 +107,9 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS
m_asm.append((u256)i);
break;
}
- default: break;
+ default:
+ error<CompilerException>("Unexpected fragment type");
+ break;
}
}
@@ -177,11 +175,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
{
auto it = _s.vars.find(n);
if (it == _s.vars.end())
- {
- bool ok;
- tie(it, ok) = _s.vars.insert(make_pair(n, make_pair(_s.stackSize, 32)));
- _s.stackSize += 32;
- }
+ error<InvalidName>(std::string("Symbol not found: ") + s);
return it->second.first;
};
@@ -278,42 +272,43 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
bytes data;
for (auto const& i: _t)
{
- if (ii == 1)
+ if (ii == 0)
+ {
+ ii++;
+ continue;
+ }
+ else if (ii == 1)
{
pos = CodeFragment(i, _s);
if (pos.m_asm.deposit() != 1)
error<InvalidDeposit>();
}
- else if (ii == 2 && !i.tag() && i.which() == sp::utree_type::string_type)
+ else if (i.tag() != 0)
+ {
+ error<InvalidLiteral>();
+ }
+ else if (i.which() == sp::utree_type::string_type)
{
auto sr = i.get<sp::basic_string<boost::iterator_range<char const*>, sp::utree_type::string_type>>();
- data = bytes((byte const*)sr.begin(), (byte const*)sr.end());
+ data.insert(data.end(), (byte const *)sr.begin(), (byte const*)sr.end());
}
- else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::any_type)
+ else if (i.which() == sp::utree_type::any_type)
{
bigint bi = *i.get<bigint*>();
if (bi < 0)
error<IntegerOutOfRange>();
- else if (bi > bigint(u256(0) - 1))
- {
- if (ii == 2 && _t.size() == 3)
- {
- // One big int - allow it as hex.
- data.resize(bytesRequired(bi));
- toBigEndian(bi, data);
- }
- else
- error<IntegerOutOfRange>();
- }
else
{
- data.resize(data.size() + 32);
- *(h256*)(&data.back() - 31) = (u256)bi;
+ bytes tmp = toCompactBigEndian(bi);
+ data.insert(data.end(), tmp.begin(), tmp.end());
}
}
- else if (ii)
+ else
+ {
error<InvalidLiteral>();
- ++ii;
+ }
+
+ ii++;
}
m_asm.append((u256)data.size());
m_asm.append(Instruction::DUP1);
diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp
index 4008022f..cd909f34 100644
--- a/liblll/Compiler.cpp
+++ b/liblll/Compiler.cpp
@@ -100,11 +100,17 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v
string dev::eth::parseLLL(string const& _src)
{
sp::utree o;
+
try
{
parseTreeLLL(_src, o);
}
- catch (...) {}
+ catch (...)
+ {
+ killBigints(o);
+ return string();
+ }
+
ostringstream ret;
debugOutAST(ret, o);
killBigints(o);
diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp
index 219d4f54..ad5e1885 100644
--- a/liblll/Parser.cpp
+++ b/liblll/Parser.cpp
@@ -100,7 +100,7 @@ void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out)
qi::rule<it, string()> str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"';
qi::rule<it, string()> strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))];
qi::rule<it, symbol_type()> symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))];
- qi::rule<it, string()> intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]];
+ qi::rule<it, string()> intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> +qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]];
qi::rule<it, sp::utree()> integer = intstr[qi::_val = px::construct<sp::any_ptr>(px::new_<bigint>(qi::_1))];
qi::rule<it, space_type, sp::utree()> atom = integer[qi::_val = qi::_1] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1];
qi::rule<it, space_type, sp::utree::list_type()> seq = '{' > *element > '}';
@@ -109,7 +109,7 @@ void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out)
qi::rule<it, space_type, sp::utree::list_type()> mstore = '[' > element > ']' > -qi::lit(":") > element;
qi::rule<it, space_type, sp::utree::list_type()> sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element;
qi::rule<it, space_type, sp::utree::list_type()> calldataload = qi::lit("$") > element;
- qi::rule<it, space_type, sp::utree::list_type()> list = '(' > *element > ')';
+ qi::rule<it, space_type, sp::utree::list_type()> list = '(' > +element > ')';
qi::rule<it, space_type, sp::utree()> extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | seq[tagNode<5>()] | calldataload[tagNode<6>()];
element = atom | list | extra;
diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp
index bdd8f61e..7057eab7 100644
--- a/libsolidity/analysis/ConstantEvaluator.cpp
+++ b/libsolidity/analysis/ConstantEvaluator.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h
index f311efbf..9ec04ebe 100644
--- a/libsolidity/analysis/ConstantEvaluator.h
+++ b/libsolidity/analysis/ConstantEvaluator.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/DeclarationContainer.cpp b/libsolidity/analysis/DeclarationContainer.cpp
index 042b7a6a..1599b83a 100644
--- a/libsolidity/analysis/DeclarationContainer.cpp
+++ b/libsolidity/analysis/DeclarationContainer.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/DeclarationContainer.h b/libsolidity/analysis/DeclarationContainer.h
index 5862f7a5..9c7c89e7 100644
--- a/libsolidity/analysis/DeclarationContainer.h
+++ b/libsolidity/analysis/DeclarationContainer.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp
index 4f75f03d..58261144 100644
--- a/libsolidity/analysis/DocStringAnalyser.cpp
+++ b/libsolidity/analysis/DocStringAnalyser.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/DocStringAnalyser.h b/libsolidity/analysis/DocStringAnalyser.h
index cdf297e3..bfc8befc 100644
--- a/libsolidity/analysis/DocStringAnalyser.h
+++ b/libsolidity/analysis/DocStringAnalyser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp
index d075949e..e46868be 100644
--- a/libsolidity/analysis/GlobalContext.cpp
+++ b/libsolidity/analysis/GlobalContext.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/GlobalContext.h b/libsolidity/analysis/GlobalContext.h
index 482391d3..4ed08711 100644
--- a/libsolidity/analysis/GlobalContext.h
+++ b/libsolidity/analysis/GlobalContext.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 26d38cfe..2a33a501 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h
index 89b9818b..68c3ffa1 100644
--- a/libsolidity/analysis/NameAndTypeResolver.h
+++ b/libsolidity/analysis/NameAndTypeResolver.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index a0768a34..66bf1d0e 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h
index bfaef2e1..caa3a78f 100644
--- a/libsolidity/analysis/ReferencesResolver.h
+++ b/libsolidity/analysis/ReferencesResolver.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/analysis/SemVerHandler.cpp b/libsolidity/analysis/SemVerHandler.cpp
index c7b212b2..42186396 100644
--- a/libsolidity/analysis/SemVerHandler.cpp
+++ b/libsolidity/analysis/SemVerHandler.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <chris@ethereum.org>
diff --git a/libsolidity/analysis/SemVerHandler.h b/libsolidity/analysis/SemVerHandler.h
index e3b642db..fae0a764 100644
--- a/libsolidity/analysis/SemVerHandler.h
+++ b/libsolidity/analysis/SemVerHandler.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <chris@ethereum.org>
diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp
new file mode 100644
index 00000000..c39f874e
--- /dev/null
+++ b/libsolidity/analysis/StaticAnalyzer.cpp
@@ -0,0 +1,78 @@
+/*
+ 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 Federico Bond <federicobond@gmail.com>
+ * @date 2016
+ * Static analyzer and checker.
+ */
+
+#include <libsolidity/analysis/StaticAnalyzer.h>
+#include <memory>
+#include <libsolidity/ast/AST.h>
+
+using namespace std;
+using namespace dev;
+using namespace dev::solidity;
+
+
+bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit)
+{
+ _sourceUnit.accept(*this);
+ return Error::containsOnlyWarnings(m_errors);
+}
+
+bool StaticAnalyzer::visit(ContractDefinition const& _contract)
+{
+ m_library = _contract.isLibrary();
+ return true;
+}
+
+void StaticAnalyzer::endVisit(ContractDefinition const&)
+{
+ m_library = false;
+}
+
+bool StaticAnalyzer::visit(FunctionDefinition const& _function)
+{
+ m_nonPayablePublic = _function.isPublic() && !_function.isPayable();
+ return true;
+}
+
+void StaticAnalyzer::endVisit(FunctionDefinition const&)
+{
+ m_nonPayablePublic = false;
+}
+
+bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
+{
+ if (m_nonPayablePublic && !m_library)
+ if (MagicType const* type = dynamic_cast<MagicType const*>(_memberAccess.expression().annotation().type.get()))
+ if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "value")
+ warning(_memberAccess.location(), "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?");
+
+ return true;
+}
+
+void StaticAnalyzer::warning(SourceLocation const& _location, string const& _description)
+{
+ auto err = make_shared<Error>(Error::Type::Warning);
+ *err <<
+ errinfo_sourceLocation(_location) <<
+ errinfo_comment(_description);
+
+ m_errors.push_back(err);
+}
diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h
new file mode 100644
index 00000000..b6cf783e
--- /dev/null
+++ b/libsolidity/analysis/StaticAnalyzer.h
@@ -0,0 +1,72 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Federico Bond <federicobond@gmail.com>
+ * @date 2016
+ * Static analyzer and checker.
+ */
+
+#pragma once
+
+#include <libsolidity/analysis/TypeChecker.h>
+#include <libsolidity/ast/Types.h>
+#include <libsolidity/ast/ASTAnnotations.h>
+#include <libsolidity/ast/ASTForward.h>
+#include <libsolidity/ast/ASTVisitor.h>
+
+namespace dev
+{
+namespace solidity
+{
+
+
+/**
+ * The module that performs static analysis on the AST.
+ */
+class StaticAnalyzer: private ASTConstVisitor
+{
+public:
+ /// @param _errors the reference to the list of errors and warnings to add them found during static analysis.
+ explicit StaticAnalyzer(ErrorList& _errors): m_errors(_errors) {}
+
+ /// Performs static analysis on the given source unit and all of its sub-nodes.
+ /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings
+ bool analyze(SourceUnit const& _sourceUnit);
+
+private:
+ /// Adds a new warning to the list of errors.
+ void warning(SourceLocation const& _location, std::string const& _description);
+
+ virtual bool visit(ContractDefinition const& _contract) override;
+ virtual void endVisit(ContractDefinition const& _contract) override;
+
+ virtual bool visit(FunctionDefinition const& _function) override;
+ virtual void endVisit(FunctionDefinition const& _function) override;
+
+ virtual bool visit(MemberAccess const& _memberAccess) override;
+
+ ErrorList& m_errors;
+
+ /// Flag that indicates whether the current contract definition is a library.
+ bool m_library = false;
+
+ /// Flag that indicates whether a public function does not contain the "payable" modifier.
+ bool m_nonPayablePublic = false;
+};
+
+}
+}
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index dbaa15ed..0a4943fe 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libsolidity/analysis/SyntaxChecker.h>
diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h
index ac8ed872..c24bae09 100644
--- a/libsolidity/analysis/SyntaxChecker.h
+++ b/libsolidity/analysis/SyntaxChecker.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 8b6d45e2..e414e27c 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -1529,6 +1529,8 @@ bool TypeChecker::visit(Identifier const& _identifier)
!!annotation.referencedDeclaration,
"Referenced declaration is null after overload resolution."
);
+ auto variableDeclaration = dynamic_cast<VariableDeclaration const*>(annotation.referencedDeclaration);
+ annotation.isConstant = variableDeclaration != nullptr && variableDeclaration->isConstant();
annotation.isLValue = annotation.referencedDeclaration->isLValue();
annotation.type = annotation.referencedDeclaration->type();
if (!annotation.type)
@@ -1612,7 +1614,10 @@ void TypeChecker::requireLValue(Expression const& _expression)
{
_expression.annotation().lValueRequested = true;
_expression.accept(*this);
- if (!_expression.annotation().isLValue)
+
+ if (_expression.annotation().isConstant)
+ typeError(_expression.location(), "Cannot assign to a constant variable.");
+ else if (!_expression.annotation().isLValue)
typeError(_expression.location(), "Expression has to be an lvalue.");
}
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index 5874bb50..143b15b2 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 305668e7..3cd1dfbe 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -63,6 +63,15 @@ SourceUnitAnnotation& SourceUnit::annotation() const
return static_cast<SourceUnitAnnotation&>(*m_annotation);
}
+string Declaration::sourceUnitName() const
+{
+ solAssert(!!m_scope, "");
+ ASTNode const* scope = m_scope;
+ while (dynamic_cast<Declaration const*>(scope) && dynamic_cast<Declaration const*>(scope)->m_scope)
+ scope = dynamic_cast<Declaration const*>(scope)->m_scope;
+ return dynamic_cast<SourceUnit const&>(*scope).annotation().path;
+}
+
ImportAnnotation& ImportDirective::annotation() const
{
if (!m_annotation)
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index a2b70fe9..ab4be1ea 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -158,6 +158,10 @@ public:
ASTNode const* scope() const { return m_scope; }
void setScope(ASTNode const* _scope) { m_scope = _scope; }
+ /// @returns the source name this declaration is present in.
+ /// Can be combined with annotation().canonicalName to form a globally unique name.
+ std::string sourceUnitName() const;
+
virtual bool isLValue() const { return false; }
virtual bool isPartOfExternalInterface() const { return false; }
diff --git a/libsolidity/ast/ASTAnnotations.cpp b/libsolidity/ast/ASTAnnotations.cpp
index 416e6b44..0f958a38 100644
--- a/libsolidity/ast/ASTAnnotations.cpp
+++ b/libsolidity/ast/ASTAnnotations.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h
index 2a192e47..9c4c3ae8 100644
--- a/libsolidity/ast/ASTAnnotations.h
+++ b/libsolidity/ast/ASTAnnotations.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -154,6 +154,8 @@ struct ExpressionAnnotation: ASTAnnotation
{
/// Inferred type of the expression.
TypePointer type;
+ /// Whether the expression is a constant variable
+ bool isConstant = false;
/// Whether it is an LValue (i.e. something that can be assigned to).
bool isLValue = false;
/// Whether the expression is used in a context where the LValue is actually required.
diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h
index 52bbf396..cfeeaa58 100644
--- a/libsolidity/ast/ASTForward.h
+++ b/libsolidity/ast/ASTForward.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index 37dfd3c6..abaad0fd 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
@@ -24,6 +24,7 @@
#include <boost/algorithm/string/join.hpp>
#include <libdevcore/UTF8.h>
#include <libsolidity/ast/AST.h>
+#include <libsolidity/interface/Exceptions.h>
using namespace std;
@@ -173,9 +174,9 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
{
addJsonNode(_node, "FunctionDefinition", {
make_pair("name", _node.name()),
- make_pair("public", _node.isPublic()),
make_pair("constant", _node.isDeclaredConst()),
- make_pair("payable", _node.isPayable())
+ make_pair("payable", _node.isPayable()),
+ make_pair("visibility", visibility(_node.visibility()))
}, true);
return true;
}
@@ -228,13 +229,9 @@ bool ASTJsonConverter::visit(UserDefinedTypeName const& _node)
bool ASTJsonConverter::visit(FunctionTypeName const& _node)
{
- string visibility = "internal";
- if (_node.visibility() == Declaration::Visibility::External)
- visibility = "external";
-
addJsonNode(_node, "FunctionTypeName", {
make_pair("payable", _node.isPayable()),
- make_pair("visibility", visibility),
+ make_pair("visibility", visibility(_node.visibility())),
make_pair("constant", _node.isDeclaredConst())
}, true);
return true;
@@ -318,7 +315,7 @@ bool ASTJsonConverter::visit(Throw const& _node)
bool ASTJsonConverter::visit(VariableDeclarationStatement const& _node)
{
- addJsonNode(_node, "VariableDefinitionStatement", {}, true);
+ addJsonNode(_node, "VariableDeclarationStatement", {}, true);
return true;
}
@@ -407,7 +404,7 @@ bool ASTJsonConverter::visit(Identifier const& _node)
bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node)
{
- addJsonNode(_node, "ElementaryTypenameExpression", {
+ addJsonNode(_node, "ElementaryTypeNameExpression", {
make_pair("value", _node.typeName().toString()),
make_pair("type", type(_node))
});
@@ -417,9 +414,8 @@ bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node)
bool ASTJsonConverter::visit(Literal const& _node)
{
char const* tokenString = Token::toString(_node.token());
- size_t invalidPos = 0;
Json::Value value{_node.value()};
- if (!dev::validate(_node.value(), invalidPos))
+ if (!dev::validateUTF8(_node.value()))
value = Json::nullValue;
Token::Value subdenomination = Token::Value(_node.subDenomination());
addJsonNode(_node, "Literal", {
@@ -657,6 +653,23 @@ void ASTJsonConverter::process()
processed = true;
}
+string ASTJsonConverter::visibility(Declaration::Visibility const& _visibility)
+{
+ switch (_visibility)
+ {
+ case Declaration::Visibility::Private:
+ return "private";
+ case Declaration::Visibility::Internal:
+ return "internal";
+ case Declaration::Visibility::Public:
+ return "public";
+ case Declaration::Visibility::External:
+ return "external";
+ default:
+ BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown declaration visibility."));
+ }
+}
+
string ASTJsonConverter::type(Expression const& _expression)
{
return _expression.annotation().type ? _expression.annotation().type->toString() : "Unknown";
diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h
index 0a71779c..49f23f99 100644
--- a/libsolidity/ast/ASTJsonConverter.h
+++ b/libsolidity/ast/ASTJsonConverter.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
@@ -152,6 +152,7 @@ private:
bool _hasChildren
);
std::string sourceLocationToString(SourceLocation const& _location) const;
+ std::string visibility(Declaration::Visibility const& _visibility);
std::string type(Expression const& _expression);
std::string type(VariableDeclaration const& _varDecl);
inline void goUp()
diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp
index 053b9b82..23eb3b64 100644
--- a/libsolidity/ast/ASTPrinter.cpp
+++ b/libsolidity/ast/ASTPrinter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/ASTPrinter.h b/libsolidity/ast/ASTPrinter.h
index 9f88a1fd..4a37f17f 100644
--- a/libsolidity/ast/ASTPrinter.h
+++ b/libsolidity/ast/ASTPrinter.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp
index e9b70b62..7d180490 100644
--- a/libsolidity/ast/ASTUtils.cpp
+++ b/libsolidity/ast/ASTUtils.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h
index 237537ec..f7cacf3e 100644
--- a/libsolidity/ast/ASTUtils.h
+++ b/libsolidity/ast/ASTUtils.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h
index e72afe69..20be634b 100644
--- a/libsolidity/ast/ASTVisitor.h
+++ b/libsolidity/ast/ASTVisitor.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h
index f521e092..7c1c64b0 100644
--- a/libsolidity/ast/AST_accept.h
+++ b/libsolidity/ast/AST_accept.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 4488398f..03ff8471 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -251,6 +251,19 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
return members;
}
+bool isValidShiftAndAmountType(Token::Value _operator, Type const& _shiftAmountType)
+{
+ // Disable >>> here.
+ if (_operator == Token::SHR)
+ return false;
+ else if (IntegerType const* otherInt = dynamic_cast<decltype(otherInt)>(&_shiftAmountType))
+ return !otherInt->isAddress();
+ else if (RationalNumberType const* otherRat = dynamic_cast<decltype(otherRat)>(&_shiftAmountType))
+ return otherRat->integerType() && !otherRat->integerType()->isSigned();
+ else
+ return false;
+}
+
IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier):
m_bits(_bits), m_modifier(_modifier)
{
@@ -340,6 +353,17 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe
_other->category() != category()
)
return TypePointer();
+ if (Token::isShiftOp(_operator))
+ {
+ // Shifts are not symmetric with respect to the type
+ if (isAddress())
+ return TypePointer();
+ if (isValidShiftAndAmountType(_operator, *_other))
+ return shared_from_this();
+ else
+ return TypePointer();
+ }
+
auto commonType = Type::commonType(shared_from_this(), _other); //might be a integer or fixed point
if (!commonType)
return TypePointer();
@@ -879,7 +903,8 @@ bool StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (auto arrayType = dynamic_cast<ArrayType const*>(&_convertTo))
return
arrayType->isByteArray() &&
- !(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer());
+ !(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer()) &&
+ !(arrayType->isString() && !isValidUTF8());
else
return false;
}
@@ -895,7 +920,7 @@ std::string StringLiteralType::toString(bool) const
{
size_t invalidSequence;
- if (!dev::validate(m_value, invalidSequence))
+ if (!dev::validateUTF8(m_value, invalidSequence))
return "literal_string (contains invalid UTF-8 sequence at position " + dev::toString(invalidSequence) + ")";
return "literal_string \"" + m_value + "\"";
@@ -906,6 +931,11 @@ TypePointer StringLiteralType::mobileType() const
return make_shared<ArrayType>(DataLocation::Memory, true);
}
+bool StringLiteralType::isValidUTF8() const
+{
+ return dev::validateUTF8(m_value);
+}
+
shared_ptr<FixedBytesType> FixedBytesType::smallestTypeForLiteral(string const& _literal)
{
if (_literal.length() <= 32)
@@ -948,6 +978,14 @@ TypePointer FixedBytesType::unaryOperatorResult(Token::Value _operator) const
TypePointer FixedBytesType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
{
+ if (Token::isShiftOp(_operator))
+ {
+ if (isValidShiftAndAmountType(_operator, *_other))
+ return shared_from_this();
+ else
+ return TypePointer();
+ }
+
auto commonType = dynamic_pointer_cast<FixedBytesType const>(Type::commonType(shared_from_this(), _other));
if (!commonType)
return TypePointer();
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 34fcfc82..26e2b8f2 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -425,6 +425,8 @@ public:
virtual std::string toString(bool) const override;
virtual TypePointer mobileType() const override;
+ bool isValidUTF8() const;
+
std::string const& value() const { return m_value; }
private:
@@ -1115,6 +1117,8 @@ public:
virtual std::string toString(bool _short) const override;
+ Kind kind() const { return m_kind; }
+
private:
Kind m_kind;
};
diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp
index b5f5cd8e..352c7177 100644
--- a/libsolidity/codegen/ArrayUtils.cpp
+++ b/libsolidity/codegen/ArrayUtils.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -200,7 +200,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
else if (sourceBaseType->isValueType())
CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false);
else
- solAssert(false, "Copying of type " + _sourceType.toString(false) + " to storage not yet supported.");
+ solUnimplemented("Copying of type " + _sourceType.toString(false) + " to storage not yet supported.");
// stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] <source_value>...
solAssert(
2 + byteOffsetSize + sourceBaseType->sizeOnStack() <= 16,
@@ -335,9 +335,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord
if (baseSize > 1)
m_context << u256(baseSize) << Instruction::MUL;
// stack: <target> <source> <size>
- //@TODO do not use ::CALL if less than 32 bytes?
m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4;
- utils.memoryCopy();
+ // We can resort to copying full 32 bytes only if
+ // - the length is known to be a multiple of 32 or
+ // - we will pad to full 32 bytes later anyway.
+ if (((baseSize % 32) == 0) || _padToWordBoundaries)
+ utils.memoryCopy32();
+ else
+ utils.memoryCopy();
m_context << Instruction::SWAP1 << Instruction::POP;
// stack: <target> <size>
diff --git a/libsolidity/codegen/ArrayUtils.h b/libsolidity/codegen/ArrayUtils.h
index 53d36c14..d0ba2892 100644
--- a/libsolidity/codegen/ArrayUtils.h
+++ b/libsolidity/codegen/ArrayUtils.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp
index 54639515..44264a07 100644
--- a/libsolidity/codegen/Compiler.cpp
+++ b/libsolidity/codegen/Compiler.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -30,11 +30,13 @@ using namespace dev::solidity;
void Compiler::compileContract(
ContractDefinition const& _contract,
- std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts
+ std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts,
+ bytes const& _metadata
)
{
ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
runtimeCompiler.compileContract(_contract, _contracts);
+ m_runtimeContext.appendAuxiliaryData(_metadata);
// This might modify m_runtimeContext because it can access runtime functions at
// creation time.
@@ -42,12 +44,6 @@ void Compiler::compileContract(
m_runtimeSub = creationCompiler.compileConstructor(_contract, _contracts);
m_context.optimise(m_optimize, m_optimizeRuns);
-
- if (_contract.isLibrary())
- {
- solAssert(m_runtimeSub != size_t(-1), "");
- m_context.injectVersionStampIntoSub(m_runtimeSub);
- }
}
void Compiler::compileClone(
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index 4a87de0e..eef078c1 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -42,7 +42,8 @@ public:
void compileContract(
ContractDefinition const& _contract,
- std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
+ 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.
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index c76db2a6..c14ab845 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -202,6 +202,8 @@ void CompilerContext::appendInlineAssembly(
return false;
unsigned stackDepth = _localVariables.end() - it;
int stackDiff = _assembly.deposit() - startStackHeight + stackDepth;
+ if (_context == assembly::CodeGenerator::IdentifierContext::LValue)
+ stackDiff -= 1;
if (stackDiff < 1 || stackDiff > 16)
BOOST_THROW_EXCEPTION(
CompilerError() <<
@@ -217,14 +219,7 @@ void CompilerContext::appendInlineAssembly(
return true;
};
- solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), "");
-}
-
-void CompilerContext::injectVersionStampIntoSub(size_t _subIndex)
-{
- eth::Assembly& sub = m_asm->sub(_subIndex);
- sub.injectStart(Instruction::POP);
- sub.injectStart(fromBigEndian<u256>(binaryVersion()));
+ solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), "Failed to assemble inline assembly block.");
}
FunctionDefinition const& CompilerContext::resolveVirtualFunction(
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 8ccbddfd..80671528 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -152,8 +152,8 @@ public:
std::map<std::string, std::string> const& _replacements = std::map<std::string, std::string>{}
);
- /// Prepends "PUSH <compiler version number> POP"
- void injectVersionStampIntoSub(size_t _subIndex);
+ /// Appends arbitrary data to the end of the bytecode.
+ void appendAuxiliaryData(bytes const& _data) { m_asm->appendAuxiliaryDataToEnd(_data); }
void optimise(bool _fullOptimsation, unsigned _runs = 200) { m_asm->optimise(_fullOptimsation, true, _runs); }
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index bfe5386b..7d382aba 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -298,21 +298,73 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type)
m_context << Instruction::SWAP1 << Instruction::POP;
}
+void CompilerUtils::memoryCopyPrecompile()
+{
+ // Stack here: size target source
+
+ m_context.appendInlineAssembly(R"(
+ {
+ let words := div(add(len, 31), 32)
+ let cost := add(15, mul(3, words))
+ jumpi(invalidJumpLabel, iszero(call(cost, $identityContractAddress, 0, src, len, dst, len)))
+ }
+ )",
+ { "len", "dst", "src" },
+ map<string, string> {
+ { "$identityContractAddress", toString(identityContractAddress) }
+ }
+ );
+ m_context << Instruction::POP << Instruction::POP << Instruction::POP;
+}
+
+void CompilerUtils::memoryCopy32()
+{
+ // Stack here: size target source
+
+ m_context.appendInlineAssembly(R"(
+ {
+ jumpi(end, eq(len, 0))
+ start:
+ mstore(dst, mload(src))
+ jumpi(end, iszero(gt(len, 32)))
+ dst := add(dst, 32)
+ src := add(src, 32)
+ len := sub(len, 32)
+ jump(start)
+ end:
+ }
+ )",
+ { "len", "dst", "src" }
+ );
+ m_context << Instruction::POP << Instruction::POP << Instruction::POP;
+}
+
void CompilerUtils::memoryCopy()
{
// Stack here: size target source
- // stack for call: outsize target size source value contract gas
- //@TODO do not use ::CALL if less than 32 bytes?
- m_context << Instruction::DUP3 << Instruction::SWAP1;
- m_context << u256(0) << u256(identityContractAddress);
- // compute gas costs
- m_context << u256(32) << Instruction::DUP5 << u256(31) << Instruction::ADD;
- static unsigned c_identityGas = 15;
- static unsigned c_identityWordGas = 3;
- m_context << Instruction::DIV << u256(c_identityWordGas) << Instruction::MUL;
- m_context << u256(c_identityGas) << Instruction::ADD;
- m_context << Instruction::CALL;
- m_context << Instruction::POP; // ignore return value
+
+ m_context.appendInlineAssembly(R"(
+ {
+ // copy 32 bytes at once
+ start32:
+ jumpi(end32, lt(len, 32))
+ mstore(dst, mload(src))
+ dst := add(dst, 32)
+ src := add(src, 32)
+ len := sub(len, 32)
+ jump(start32)
+ end32:
+
+ // copy the remainder (0 < len < 32)
+ let mask := sub(exp(256, sub(32, len)), 1)
+ let srcpart := and(mload(src), not(mask))
+ let dstpart := and(mload(dst), mask)
+ mstore(dst, or(srcpart, dstpart))
+ }
+ )",
+ { "len", "dst", "src" }
+ );
+ m_context << Instruction::POP << Instruction::POP << Instruction::POP;
}
void CompilerUtils::splitExternalFunctionType(bool _leftAligned)
@@ -358,7 +410,7 @@ void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function)
Instruction::OR;
}
-void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded)
+void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded, bool _chopSignBits)
{
// For a type extension, we need to remove all higher-order bits that we might have ignored in
// previous operations.
@@ -370,6 +422,12 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
Type::Category targetTypeCategory = _targetType.category();
bool enumOverflowCheckPending = (targetTypeCategory == Type::Category::Enum || stackTypeCategory == Type::Category::Enum);
+ bool chopSignBitsPending = _chopSignBits && targetTypeCategory == Type::Category::Integer;
+ if (chopSignBitsPending)
+ {
+ const IntegerType& targetIntegerType = dynamic_cast<const IntegerType &>(_targetType);
+ chopSignBitsPending = targetIntegerType.isSigned();
+ }
switch (stackTypeCategory)
{
@@ -482,6 +540,14 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
cleanHigherOrderBits(typeOnStack);
else if (_cleanupNeeded)
cleanHigherOrderBits(targetType);
+ if (chopSignBitsPending)
+ {
+ if (typeOnStack.numBits() < 256)
+ m_context
+ << ((u256(1) << typeOnStack.numBits()) - 1)
+ << Instruction::AND;
+ chopSignBitsPending = false;
+ }
}
}
break;
@@ -724,10 +790,15 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
default:
// All other types should not be convertible to non-equal types.
solAssert(_typeOnStack == _targetType, "Invalid type conversion requested.");
+ if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32)
+ m_context
+ << ((u256(1) << (8 * _targetType.storageBytes())) - 1)
+ << Instruction::AND;
break;
}
solAssert(!enumOverflowCheckPending, "enum overflow checking missing.");
+ solAssert(!chopSignBitsPending, "forgot to chop the sign bits.");
}
void CompilerUtils::pushZeroValue(Type const& _type)
@@ -881,9 +952,9 @@ void CompilerUtils::storeStringData(bytesConstRef _data)
}
}
-unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries)
+unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWords)
{
- unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries);
+ unsigned numBytes = _type.calldataEncodedSize(_padToWords);
bool isExternalFunctionType = false;
if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
if (funType->location() == FunctionType::Location::External)
@@ -906,6 +977,8 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda
if (leftAligned)
m_context << shiftFactor << Instruction::MUL;
}
+ if (_fromCalldata)
+ convertType(_type, _type, true);
return numBytes;
}
@@ -920,16 +993,17 @@ void CompilerUtils::cleanHigherOrderBits(IntegerType const& _typeOnStack)
m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << Instruction::AND;
}
-unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const
+unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords)
{
- unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries);
+ unsigned numBytes = _type.calldataEncodedSize(_padToWords);
bool leftAligned = _type.category() == Type::Category::FixedBytes;
if (numBytes == 0)
m_context << Instruction::POP;
else
{
solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested.");
- if (numBytes != 32 && !leftAligned && !_padToWordBoundaries)
+ convertType(_type, _type, true);
+ if (numBytes != 32 && !leftAligned && !_padToWords)
// shift the value accordingly before storing
m_context << (u256(1) << ((32 - numBytes) * 8)) << Instruction::MUL;
}
diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h
index 8e4033d6..b9ed6757 100644
--- a/libsolidity/codegen/CompilerUtils.h
+++ b/libsolidity/codegen/CompilerUtils.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -52,13 +52,13 @@ public:
/// @param _offset offset in memory (or calldata)
/// @param _type data type to load
/// @param _fromCalldata if true, load from calldata, not from memory
- /// @param _padToWordBoundaries if true, assume the data is padded to word (32 byte) boundaries
+ /// @param _padToWords if true, assume the data is padded to full words (32 bytes)
/// @returns the number of bytes consumed in memory.
unsigned loadFromMemory(
unsigned _offset,
Type const& _type = IntegerType(256),
bool _fromCalldata = false,
- bool _padToWordBoundaries = false
+ bool _padToWords = false
);
/// Dynamic version of @see loadFromMemory, expects the memory offset on the stack.
/// Stack pre: memory_offset
@@ -66,7 +66,7 @@ public:
void loadFromMemoryDynamic(
Type const& _type,
bool _fromCalldata = false,
- bool _padToWordBoundaries = true,
+ bool _padToWords = true,
bool _keepUpdatedMemoryOffset = true
);
/// Stores a 256 bit integer from stack in memory.
@@ -76,11 +76,11 @@ public:
/// Dynamic version of @see storeInMemory, expects the memory offset below the value on the stack
/// and also updates that. For reference types, only copies the data pointer. Fails for
/// non-memory-references.
- /// @param _padToWordBoundaries if true, adds zeros to pad to multiple of 32 bytes. Array elements
+ /// @param _padToWords if true, adds zeros to pad to multiple of 32 bytes. Array elements
/// are always padded (except for byte arrays), regardless of this parameter.
/// Stack pre: memory_offset value...
/// Stack post: (memory_offset+length)
- void storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries = true);
+ void storeInMemoryDynamic(Type const& _type, bool _padToWords = true);
/// Copies values (of types @a _givenTypes) given on the stack to a location in memory given
/// at the stack top, encoding them according to the ABI as the given types @a _targetTypes.
@@ -88,7 +88,7 @@ public:
/// Stack pre: <v1> <v2> ... <vn> <memptr>
/// Stack post: <memptr_updated>
/// Does not touch the memory-free pointer.
- /// @param _padToWordBoundaries if false, all values are concatenated without padding.
+ /// @param _padToWords if false, all values are concatenated without padding.
/// @param _copyDynamicDataInPlace if true, dynamic types is stored (without length)
/// together with fixed-length data.
/// @param _encodeAsLibraryTypes if true, encodes for a library function, e.g. does not
@@ -98,7 +98,7 @@ public:
void encodeToMemory(
TypePointers const& _givenTypes = {},
TypePointers const& _targetTypes = {},
- bool _padToWordBoundaries = true,
+ bool _padToWords = true,
bool _copyDynamicDataInPlace = false,
bool _encodeAsLibraryTypes = false
);
@@ -112,6 +112,14 @@ public:
/// Uses a CALL to the identity contract to perform a memory-to-memory copy.
/// Stack pre: <size> <target> <source>
/// Stack post:
+ void memoryCopyPrecompile();
+ /// Copies full 32 byte words in memory (regions cannot overlap), i.e. may copy more than length.
+ /// Stack pre: <size> <target> <source>
+ /// Stack post:
+ void memoryCopy32();
+ /// Copies data in memory (regions cannot overlap).
+ /// Stack pre: <size> <target> <source>
+ /// Stack post:
void memoryCopy();
/// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true)
@@ -130,7 +138,8 @@ public:
/// if a reference type is converted from calldata or storage to memory.
/// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be
/// necessary.
- void convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false);
+ /// If @a _chopSignBits, the function resets the signed bits out of the width of the signed integer.
+ void convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false, bool _chopSignBits = false);
/// Creates a zero-value for the given type and puts it onto the stack. This might allocate
/// memory for memory references.
@@ -184,9 +193,9 @@ private:
void cleanHigherOrderBits(IntegerType const& _typeOnStack);
/// Prepares the given type for storing in memory by shifting it if necessary.
- unsigned prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const;
+ unsigned prepareMemoryStore(Type const& _type, bool _padToWords);
/// Loads type from memory assuming memory offset is on stack top.
- unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries);
+ unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWords);
CompilerContext& m_context;
};
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 8d60d6b3..a0f196bc 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -583,7 +583,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
// lvalue context
auto variable = dynamic_cast<VariableDeclaration const*>(decl);
solAssert(
- !!variable || !m_context.isLocalVariable(variable),
+ !!variable && m_context.isLocalVariable(variable),
"Can only assign to stack variables in inline assembly."
);
unsigned size = variable->type()->sizeOnStack();
@@ -862,8 +862,6 @@ void ContractCompiler::appendModifierOrFunctionCode()
CompilerUtils::sizeOnStack(modifier.parameters()) +
CompilerUtils::sizeOnStack(modifier.localVariables());
codeBlock = &modifier.body();
-
- codeBlock = &modifier.body();
}
}
diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h
index 10febcf7..38c1e045 100644
--- a/libsolidity/codegen/ContractCompiler.h
+++ b/libsolidity/codegen/ContractCompiler.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 7a328528..a7fb8408 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -197,21 +197,39 @@ bool ExpressionCompiler::visit(Conditional const& _condition)
bool ExpressionCompiler::visit(Assignment const& _assignment)
{
CompilerContext::LocationSetter locationSetter(m_context, _assignment);
+ Token::Value op = _assignment.assignmentOperator();
+ Token::Value binOp = op == Token::Assign ? op : Token::AssignmentToBinaryOp(op);
+ Type const& leftType = *_assignment.leftHandSide().annotation().type;
+ if (leftType.category() == Type::Category::Tuple)
+ {
+ solAssert(*_assignment.annotation().type == TupleType(), "");
+ solAssert(op == Token::Assign, "");
+ }
+ else
+ solAssert(*_assignment.annotation().type == leftType, "");
+ bool cleanupNeeded = false;
+ if (op != Token::Assign)
+ cleanupNeeded = cleanupNeededForOp(leftType.category(), binOp);
_assignment.rightHandSide().accept(*this);
// Perform some conversion already. This will convert storage types to memory and literals
// to their actual type, but will not convert e.g. memory to storage.
- TypePointer type = _assignment.rightHandSide().annotation().type->closestTemporaryType(
- _assignment.leftHandSide().annotation().type
- );
- utils().convertType(*_assignment.rightHandSide().annotation().type, *type);
+ TypePointer rightIntermediateType;
+ if (op != Token::Assign && Token::isShiftOp(binOp))
+ rightIntermediateType = _assignment.rightHandSide().annotation().type->mobileType();
+ else
+ rightIntermediateType = _assignment.rightHandSide().annotation().type->closestTemporaryType(
+ _assignment.leftHandSide().annotation().type
+ );
+ utils().convertType(*_assignment.rightHandSide().annotation().type, *rightIntermediateType, cleanupNeeded);
_assignment.leftHandSide().accept(*this);
solAssert(!!m_currentLValue, "LValue not retrieved.");
- Token::Value op = _assignment.assignmentOperator();
- if (op != Token::Assign) // compound assignment
+ if (op == Token::Assign)
+ m_currentLValue->storeValue(*rightIntermediateType, _assignment.location());
+ else // compound assignment
{
- solUnimplementedAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types.");
+ solAssert(leftType.isValueType(), "Compound operators only available for value types.");
unsigned lvalueSize = m_currentLValue->sizeOnStack();
unsigned itemSize = _assignment.annotation().type->sizeOnStack();
if (lvalueSize > 0)
@@ -221,7 +239,15 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
// value lvalue_ref value lvalue_ref
}
m_currentLValue->retrieveValue(_assignment.location(), true);
- appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.annotation().type);
+ utils().convertType(leftType, leftType, cleanupNeeded);
+
+ if (Token::isShiftOp(binOp))
+ appendShiftOperatorCode(binOp, leftType, *rightIntermediateType);
+ else
+ {
+ solAssert(leftType == *rightIntermediateType, "");
+ appendOrdinaryBinaryOperatorCode(binOp, leftType);
+ }
if (lvalueSize > 0)
{
solAssert(itemSize + lvalueSize <= 16, "Stack too deep, try removing local variables.");
@@ -229,8 +255,8 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
for (unsigned i = 0; i < itemSize; ++i)
m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP;
}
+ m_currentLValue->storeValue(*_assignment.annotation().type, _assignment.location());
}
- m_currentLValue->storeValue(*type, _assignment.location());
m_currentLValue.reset();
return false;
}
@@ -351,20 +377,19 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
Expression const& leftExpression = _binaryOperation.leftExpression();
Expression const& rightExpression = _binaryOperation.rightExpression();
solAssert(!!_binaryOperation.annotation().commonType, "");
- Type const& commonType = *_binaryOperation.annotation().commonType;
+ TypePointer const& commonType = _binaryOperation.annotation().commonType;
Token::Value const c_op = _binaryOperation.getOperator();
if (c_op == Token::And || c_op == Token::Or) // special case: short-circuiting
appendAndOrOperatorCode(_binaryOperation);
- else if (commonType.category() == Type::Category::RationalNumber)
- m_context << commonType.literalValue(nullptr);
+ else if (commonType->category() == Type::Category::RationalNumber)
+ m_context << commonType->literalValue(nullptr);
else
{
- bool cleanupNeeded = false;
- if (Token::isCompareOp(c_op))
- cleanupNeeded = true;
- if (commonType.category() == Type::Category::Integer && (c_op == Token::Div || c_op == Token::Mod))
- cleanupNeeded = true;
+ bool cleanupNeeded = cleanupNeededForOp(commonType->category(), c_op);
+
+ TypePointer leftTargetType = commonType;
+ TypePointer rightTargetType = Token::isShiftOp(c_op) ? rightExpression.annotation().type->mobileType() : commonType;
// for commutative operators, push the literal as late as possible to allow improved optimization
auto isLiteral = [](Expression const& _e)
@@ -375,21 +400,24 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
if (swap)
{
leftExpression.accept(*this);
- utils().convertType(*leftExpression.annotation().type, commonType, cleanupNeeded);
+ utils().convertType(*leftExpression.annotation().type, *leftTargetType, cleanupNeeded);
rightExpression.accept(*this);
- utils().convertType(*rightExpression.annotation().type, commonType, cleanupNeeded);
+ utils().convertType(*rightExpression.annotation().type, *rightTargetType, cleanupNeeded);
}
else
{
rightExpression.accept(*this);
- utils().convertType(*rightExpression.annotation().type, commonType, cleanupNeeded);
+ utils().convertType(*rightExpression.annotation().type, *rightTargetType, cleanupNeeded);
leftExpression.accept(*this);
- utils().convertType(*leftExpression.annotation().type, commonType, cleanupNeeded);
+ utils().convertType(*leftExpression.annotation().type, *leftTargetType, cleanupNeeded);
}
- if (Token::isCompareOp(c_op))
- appendCompareOperatorCode(c_op, commonType);
+ if (Token::isShiftOp(c_op))
+ // shift only cares about the signedness of both sides
+ appendShiftOperatorCode(c_op, *leftTargetType, *rightTargetType);
+ else if (Token::isCompareOp(c_op))
+ appendCompareOperatorCode(c_op, *commonType);
else
- appendOrdinaryBinaryOperatorCode(c_op, commonType);
+ appendOrdinaryBinaryOperatorCode(c_op, *commonType);
}
// do not visit the child nodes, we already did that explicitly
@@ -1252,7 +1280,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal)
case Type::Category::StringLiteral:
break; // will be done during conversion
default:
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now."));
+ solUnimplemented("Only integer, boolean and string literals implemented for now.");
}
}
@@ -1326,8 +1354,6 @@ void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token::Value _operator
appendArithmeticOperatorCode(_operator, _type);
else if (Token::isBitOp(_operator))
appendBitOperatorCode(_operator);
- else if (Token::isShiftOp(_operator))
- appendShiftOperatorCode(_operator);
else
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown binary operator."));
}
@@ -1390,17 +1416,45 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator)
}
}
-void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
+void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type const& _valueType, Type const& _shiftAmountType)
{
- BOOST_THROW_EXCEPTION(UnimplementedFeatureError() << errinfo_comment("Shift operators not yet implemented."));
+ // stack: shift_amount value_to_shift
+
+ bool c_valueSigned = false;
+ if (auto valueType = dynamic_cast<IntegerType const*>(&_valueType))
+ c_valueSigned = valueType->isSigned();
+ else
+ solAssert(dynamic_cast<FixedBytesType const*>(&_valueType), "Only integer and fixed bytes type supported for shifts.");
+
+ // The amount can be a RationalNumberType too.
+ bool c_amountSigned = false;
+ if (auto amountType = dynamic_cast<RationalNumberType const*>(&_shiftAmountType))
+ {
+ // This should be handled by the type checker.
+ solAssert(amountType->integerType(), "");
+ solAssert(!amountType->integerType()->isSigned(), "");
+ }
+ else if (auto amountType = dynamic_cast<IntegerType const*>(&_shiftAmountType))
+ c_amountSigned = amountType->isSigned();
+ else
+ solAssert(false, "Invalid shift amount type.");
+
+ // shift by negative amount throws exception
+ if (c_amountSigned)
+ {
+ m_context << u256(0) << Instruction::DUP3 << Instruction::SLT;
+ m_context.appendConditionalJumpTo(m_context.errorTag());
+ }
+
switch (_operator)
{
case Token::SHL:
+ m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::MUL;
break;
case Token::SAR:
+ m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_valueSigned ? Instruction::SDIV : Instruction::DIV);
break;
case Token::SHR:
- break;
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown shift operator."));
}
@@ -1688,6 +1742,16 @@ void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression)
setLValue<StorageItem>(_expression, *_expression.annotation().type);
}
+bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _op)
+{
+ if (Token::isCompareOp(_op) || Token::isShiftOp(_op))
+ return true;
+ else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod))
+ return true;
+ else
+ return false;
+}
+
CompilerUtils ExpressionCompiler::utils()
{
return CompilerUtils(m_context);
diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h
index f4ce1fec..d0a8ac15 100644
--- a/libsolidity/codegen/ExpressionCompiler.h
+++ b/libsolidity/codegen/ExpressionCompiler.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -91,7 +91,7 @@ private:
void appendArithmeticOperatorCode(Token::Value _operator, Type const& _type);
void appendBitOperatorCode(Token::Value _operator);
- void appendShiftOperatorCode(Token::Value _operator);
+ void appendShiftOperatorCode(Token::Value _operator, Type const& _valueType, Type const& _shiftAmountType);
/// @}
/// Appends code to call a function of the given type with the given arguments.
@@ -117,6 +117,10 @@ private:
template <class _LValueType, class... _Arguments>
void setLValue(Expression const& _expression, _Arguments const&... _arguments);
+ /// @returns true if the operator applied to the given type requires a cleanup prior to the
+ /// operation.
+ bool cleanupNeededForOp(Type::Category _type, Token::Value _op);
+
/// @returns the CompilerUtils object containing the current context.
CompilerUtils utils();
diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp
index 2ec7f800..b9e141d8 100644
--- a/libsolidity/codegen/LValue.cpp
+++ b/libsolidity/codegen/LValue.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -216,6 +216,8 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const
{
CompilerUtils utils(m_context);
+ solAssert(m_dataType, "");
+
// stack: value storage_key storage_offset
if (m_dataType->isValueType())
{
@@ -228,6 +230,11 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
m_context << Instruction::POP;
if (!_move)
m_context << Instruction::DUP2 << Instruction::SWAP1;
+
+ m_context << Instruction::SWAP1;
+ utils.convertType(_sourceType, *m_dataType, true);
+ m_context << Instruction::SWAP1;
+
m_context << Instruction::SSTORE;
}
else
@@ -248,6 +255,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
// stack: value storage_ref cleared_value multiplier value
if (FunctionType const* fun = dynamic_cast<decltype(fun)>(m_dataType))
{
+ solAssert(_sourceType == *m_dataType, "function item stored but target is not equal to source");
if (fun->location() == FunctionType::Location::External)
// Combine the two-item function type into a single stack slot.
utils.combineExternalFunctionType(false);
@@ -257,19 +265,17 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
Instruction::AND;
}
else if (m_dataType->category() == Type::Category::FixedBytes)
+ {
+ solAssert(_sourceType.category() == Type::Category::FixedBytes, "source not fixed bytes");
m_context
<< (u256(0x1) << (256 - 8 * dynamic_cast<FixedBytesType const&>(*m_dataType).numBytes()))
<< Instruction::SWAP1 << Instruction::DIV;
+ }
else
{
solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type.");
// remove the higher order bits
- m_context
- << (u256(1) << (8 * (32 - m_dataType->storageBytes())))
- << Instruction::SWAP1
- << Instruction::DUP2
- << Instruction::MUL
- << Instruction::DIV;
+ utils.convertType(_sourceType, *m_dataType, true, true);
}
m_context << Instruction::MUL << Instruction::OR;
// stack: value storage_ref updated_value
diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h
index a2f979db..f8b68362 100644
--- a/libsolidity/codegen/LValue.h
+++ b/libsolidity/codegen/LValue.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp
index 5934d593..2903a4e3 100644
--- a/libsolidity/formal/Why3Translator.cpp
+++ b/libsolidity/formal/Why3Translator.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h
index 4fdac385..03f3bf9c 100644
--- a/libsolidity/formal/Why3Translator.h
+++ b/libsolidity/formal/Why3Translator.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index 771f1042..43c3b27a 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h
index b1fafe15..bd71812e 100644
--- a/libsolidity/inlineasm/AsmCodeGen.h
+++ b/libsolidity/inlineasm/AsmCodeGen.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h
index d6abf67f..d622ff54 100644
--- a/libsolidity/inlineasm/AsmData.h
+++ b/libsolidity/inlineasm/AsmData.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index 8d2c2ed4..ef3da255 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index 0a9d51d5..8b56ab90 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmStack.cpp b/libsolidity/inlineasm/AsmStack.cpp
index 11c6e28f..b8e0e857 100644
--- a/libsolidity/inlineasm/AsmStack.cpp
+++ b/libsolidity/inlineasm/AsmStack.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/inlineasm/AsmStack.h b/libsolidity/inlineasm/AsmStack.h
index 521f5fe7..1543cb2a 100644
--- a/libsolidity/inlineasm/AsmStack.h
+++ b/libsolidity/inlineasm/AsmStack.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index f1eb2614..4095844f 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -32,13 +32,18 @@
#include <libsolidity/analysis/NameAndTypeResolver.h>
#include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/analysis/DocStringAnalyser.h>
+#include <libsolidity/analysis/StaticAnalyzer.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <libsolidity/codegen/Compiler.h>
#include <libsolidity/interface/InterfaceHandler.h>
#include <libsolidity/formal/Why3Translator.h>
#include <libevmasm/Exceptions.h>
-#include <libdevcore/SHA3.h>
+
+#include <libdevcore/SwarmHash.h>
+#include <libdevcore/JSON.h>
+
+#include <json/json.h>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
@@ -79,6 +84,8 @@ void CompilerStack::reset(bool _keepSources)
{
m_sources.clear();
}
+ m_optimize = false;
+ m_optimizeRuns = 200;
m_globalContext.reset();
m_sourceOrder.clear();
m_contracts.clear();
@@ -139,7 +146,7 @@ bool CompilerStack::parse()
}
}
if (!Error::containsOnlyWarnings(m_errors))
- // errors while parsing. sould stop before type checking
+ // errors while parsing. should stop before type checking
return false;
resolveImports();
@@ -196,6 +203,15 @@ bool CompilerStack::parse()
m_contracts[contract->name()].contract = contract;
}
+
+ if (noErrors)
+ {
+ StaticAnalyzer staticAnalyzer(m_errors);
+ for (Source const* source: m_sourceOrder)
+ if (!staticAnalyzer.analyze(*source->ast))
+ noErrors = false;
+ }
+
m_parseSuccessful = noErrors;
return m_parseSuccessful;
}
@@ -217,32 +233,37 @@ vector<string> CompilerStack::contractNames() const
}
-bool CompilerStack::compile(bool _optimize, unsigned _runs)
+bool CompilerStack::compile(bool _optimize, unsigned _runs, map<string, h160> const& _libraries)
{
if (!m_parseSuccessful)
if (!parse())
return false;
+ m_optimize = _optimize;
+ m_optimizeRuns = _runs;
+ m_libraries = _libraries;
+
map<ContractDefinition const*, eth::Assembly const*> compiledContracts;
for (Source const* source: m_sourceOrder)
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
if (auto contract = dynamic_cast<ContractDefinition const*>(node.get()))
- compileContract(_optimize, _runs, *contract, compiledContracts);
+ compileContract(*contract, compiledContracts);
+ this->link();
return true;
}
-bool CompilerStack::compile(string const& _sourceCode, bool _optimize)
+bool CompilerStack::compile(string const& _sourceCode, bool _optimize, unsigned _runs)
{
- return parse(_sourceCode) && compile(_optimize);
+ return parse(_sourceCode) && compile(_optimize, _runs);
}
-void CompilerStack::link(const std::map<string, h160>& _libraries)
+void CompilerStack::link()
{
for (auto& contract: m_contracts)
{
- contract.second.object.link(_libraries);
- contract.second.runtimeObject.link(_libraries);
- contract.second.cloneObject.link(_libraries);
+ contract.second.object.link(m_libraries);
+ contract.second.runtimeObject.link(m_libraries);
+ contract.second.cloneObject.link(m_libraries);
}
}
@@ -356,20 +377,28 @@ Json::Value const& CompilerStack::metadata(string const& _contractName, Document
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+ return metadata(contract(_contractName), _type);
+}
+
+Json::Value const& CompilerStack::metadata(Contract const& _contract, DocumentationType _type) const
+{
+ if (!m_parseSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
+ solAssert(_contract.contract, "");
std::unique_ptr<Json::Value const>* doc;
- Contract const& currentContract = contract(_contractName);
// checks wheather we already have the documentation
switch (_type)
{
case DocumentationType::NatspecUser:
- doc = &currentContract.userDocumentation;
+ doc = &_contract.userDocumentation;
break;
case DocumentationType::NatspecDev:
- doc = &currentContract.devDocumentation;
+ doc = &_contract.devDocumentation;
break;
case DocumentationType::ABIInterface:
- doc = &currentContract.interface;
+ doc = &_contract.interface;
break;
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type."));
@@ -377,11 +406,19 @@ Json::Value const& CompilerStack::metadata(string const& _contractName, Document
// caches the result
if (!*doc)
- doc->reset(new Json::Value(InterfaceHandler::documentation(*currentContract.contract, _type)));
+ doc->reset(new Json::Value(InterfaceHandler::documentation(*_contract.contract, _type)));
return *(*doc);
}
+string const& CompilerStack::onChainMetadata(string const& _contractName) const
+{
+ if (!m_parseSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
+ return contract(_contractName).onChainMetadata;
+}
+
Scanner const& CompilerStack::scanner(string const& _sourceName) const
{
return *source(_sourceName).scanner;
@@ -572,8 +609,6 @@ string CompilerStack::absolutePath(string const& _path, string const& _reference
}
void CompilerStack::compileContract(
- bool _optimize,
- unsigned _runs,
ContractDefinition const& _contract,
map<ContractDefinition const*, eth::Assembly const*>& _compiledContracts
)
@@ -581,19 +616,28 @@ void CompilerStack::compileContract(
if (_compiledContracts.count(&_contract) || !_contract.annotation().isFullyImplemented)
return;
for (auto const* dependency: _contract.annotation().contractDependencies)
- compileContract(_optimize, _runs, *dependency, _compiledContracts);
+ compileContract(*dependency, _compiledContracts);
- shared_ptr<Compiler> compiler = make_shared<Compiler>(_optimize, _runs);
- compiler->compileContract(_contract, _compiledContracts);
+ shared_ptr<Compiler> compiler = make_shared<Compiler>(m_optimize, m_optimizeRuns);
Contract& compiledContract = m_contracts.at(_contract.name());
+ string onChainMetadata = createOnChainMetadata(compiledContract);
+ bytes cborEncodedMetadata =
+ // CBOR-encoding of {"bzzr0": dev::swarmHash(onChainMetadata)}
+ bytes{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} +
+ dev::swarmHash(onChainMetadata).asBytes();
+ solAssert(cborEncodedMetadata.size() <= 0xffff, "Metadata too large");
+ // 16-bit big endian length
+ cborEncodedMetadata += toCompactBigEndian(cborEncodedMetadata.size(), 2);
+ compiler->compileContract(_contract, _compiledContracts, cborEncodedMetadata);
compiledContract.compiler = compiler;
compiledContract.object = compiler->assembledObject();
compiledContract.runtimeObject = compiler->runtimeObject();
+ compiledContract.onChainMetadata = onChainMetadata;
_compiledContracts[compiledContract.contract] = &compiler->assembly();
try
{
- Compiler cloneCompiler(_optimize, _runs);
+ Compiler cloneCompiler(m_optimize, m_optimizeRuns);
cloneCompiler.compileClone(_contract, _compiledContracts);
compiledContract.cloneObject = cloneCompiler.assembledObject();
}
@@ -637,6 +681,47 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co
return it->second;
}
+string CompilerStack::createOnChainMetadata(Contract const& _contract) const
+{
+ Json::Value meta;
+ meta["version"] = 1;
+ meta["language"] = "Solidity";
+ meta["compiler"]["version"] = VersionString;
+
+ meta["sources"] = Json::objectValue;
+ for (auto const& s: m_sources)
+ {
+ solAssert(s.second.scanner, "Scanner not available");
+ meta["sources"][s.first]["keccak256"] =
+ "0x" + toHex(dev::keccak256(s.second.scanner->source()).asBytes());
+ meta["sources"][s.first]["urls"] = Json::arrayValue;
+ meta["sources"][s.first]["urls"].append(
+ "bzzr://" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes())
+ );
+ }
+ meta["settings"]["optimizer"]["enabled"] = m_optimize;
+ meta["settings"]["optimizer"]["runs"] = m_optimizeRuns;
+ meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] =
+ _contract.contract->annotation().canonicalName;
+
+ meta["settings"]["remappings"] = Json::arrayValue;
+ set<string> remappings;
+ for (auto const& r: m_remappings)
+ remappings.insert(r.context + ":" + r.prefix + "=" + r.target);
+ for (auto const& r: remappings)
+ meta["settings"]["remappings"].append(r);
+
+ meta["settings"]["libraries"] = Json::objectValue;
+ for (auto const& library: m_libraries)
+ meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes());
+
+ meta["output"]["abi"] = metadata(_contract, DocumentationType::ABIInterface);
+ meta["output"]["userdoc"] = metadata(_contract, DocumentationType::NatspecUser);
+ meta["output"]["devdoc"] = metadata(_contract, DocumentationType::NatspecDev);
+
+ return jsonCompactPrint(meta);
+}
+
string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) const
{
string ret;
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 1fd30c4d..f98a457a 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -113,13 +113,14 @@ public:
/// Compiles the source units that were previously added and parsed.
/// @returns false on error.
- bool compile(bool _optimize = false, unsigned _runs = 200);
+ bool compile(
+ bool _optimize = false,
+ unsigned _runs = 200,
+ std::map<std::string, h160> const& _libraries = std::map<std::string, h160>{}
+ );
/// Parses and compiles the given source code.
/// @returns false on error.
- bool compile(std::string const& _sourceCode, bool _optimize = false);
-
- /// Inserts the given addresses into the linker objects of all compiled contracts.
- void link(std::map<std::string, h160> const& _libraries);
+ bool compile(std::string const& _sourceCode, bool _optimize = false, unsigned _runs = 200);
/// Tries to translate all source files into a language suitable for formal analysis.
/// @param _errors list to store errors - defaults to the internal error list.
@@ -170,6 +171,7 @@ public:
/// @param type The type of the documentation to get.
/// Can be one of 4 types defined at @c DocumentationType
Json::Value const& metadata(std::string const& _contractName, DocumentationType _type) const;
+ std::string const& onChainMetadata(std::string const& _contractName) const;
/// @returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& scanner(std::string const& _sourceName = "") const;
@@ -213,6 +215,7 @@ private:
eth::LinkerObject object;
eth::LinkerObject runtimeObject;
eth::LinkerObject cloneObject;
+ std::string onChainMetadata; ///< The metadata json that will be hashed into the chain.
mutable std::unique_ptr<Json::Value const> interface;
mutable std::unique_ptr<Json::Value const> userDocumentation;
mutable std::unique_ptr<Json::Value const> devDocumentation;
@@ -233,16 +236,18 @@ private:
std::string absolutePath(std::string const& _path, std::string const& _reference) const;
/// Compile a single contract and put the result in @a _compiledContracts.
void compileContract(
- bool _optimize,
- unsigned _runs,
ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*>& _compiledContracts
);
+ void link();
+
Contract const& contract(std::string const& _contractName = "") const;
Source const& source(std::string const& _sourceName = "") const;
+ std::string createOnChainMetadata(Contract const& _contract) const;
std::string computeSourceMapping(eth::AssemblyItems const& _items) const;
+ Json::Value const& metadata(Contract const&, DocumentationType _type) const;
struct Remapping
{
@@ -252,6 +257,9 @@ private:
};
ReadFileCallback m_readFile;
+ bool m_optimize = false;
+ unsigned m_optimizeRuns = 200;
+ std::map<std::string, h160> m_libraries;
/// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum
/// "context:prefix=target"
std::vector<Remapping> m_remappings;
diff --git a/libsolidity/interface/Exceptions.cpp b/libsolidity/interface/Exceptions.cpp
index 6d72520b..90a680b4 100644
--- a/libsolidity/interface/Exceptions.cpp
+++ b/libsolidity/interface/Exceptions.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Liana <liana@ethdev.com>
diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h
index c651548a..81716c41 100644
--- a/libsolidity/interface/Exceptions.h
+++ b/libsolidity/interface/Exceptions.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp
index 1c804b78..852b392c 100644
--- a/libsolidity/interface/GasEstimator.cpp
+++ b/libsolidity/interface/GasEstimator.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/GasEstimator.h b/libsolidity/interface/GasEstimator.h
index 518e58e4..bf63df96 100644
--- a/libsolidity/interface/GasEstimator.h
+++ b/libsolidity/interface/GasEstimator.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/InterfaceHandler.h b/libsolidity/interface/InterfaceHandler.h
index d4f2eaf4..b7e1bb00 100644
--- a/libsolidity/interface/InterfaceHandler.h
+++ b/libsolidity/interface/InterfaceHandler.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/libsolidity/interface/SourceReferenceFormatter.cpp
index f09d2d45..7730a99a 100644
--- a/libsolidity/interface/SourceReferenceFormatter.cpp
+++ b/libsolidity/interface/SourceReferenceFormatter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/libsolidity/interface/SourceReferenceFormatter.h
index 2b908c46..7034f4ab 100644
--- a/libsolidity/interface/SourceReferenceFormatter.h
+++ b/libsolidity/interface/SourceReferenceFormatter.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/Utils.h b/libsolidity/interface/Utils.h
index eef8c917..0027759c 100644
--- a/libsolidity/interface/Utils.h
+++ b/libsolidity/interface/Utils.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp
index 0dca1ced..ff66f039 100644
--- a/libsolidity/interface/Version.cpp
+++ b/libsolidity/interface/Version.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/interface/Version.h b/libsolidity/interface/Version.h
index fea73997..5b07b3f4 100644
--- a/libsolidity/interface/Version.h
+++ b/libsolidity/interface/Version.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/parsing/DocStringParser.h b/libsolidity/parsing/DocStringParser.h
index f67b8bbd..c7f81c55 100644
--- a/libsolidity/parsing/DocStringParser.h
+++ b/libsolidity/parsing/DocStringParser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 02b7d5e0..f02a4a45 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 9295a7fa..79d1d1d4 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp
index 2abf58cc..87d47f4b 100644
--- a/libsolidity/parsing/ParserBase.cpp
+++ b/libsolidity/parsing/ParserBase.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
index 9705228f..dfb7cab7 100644
--- a/libsolidity/parsing/ParserBase.h
+++ b/libsolidity/parsing/ParserBase.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp
index 603f3e42..3623f23f 100644
--- a/libsolidity/parsing/Scanner.cpp
+++ b/libsolidity/parsing/Scanner.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
This file is derived from the file "scanner.cc", which was part of the
V8 project. The original copyright header follows:
@@ -327,7 +327,12 @@ Token::Value Scanner::scanMultiLineDocComment()
if (isLineTerminator(m_char))
{
skipWhitespace();
- if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/')
+ if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '*')
+ { // it is unknown if this leads to the end of the comment
+ addCommentLiteralChar('*');
+ advance();
+ }
+ else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/')
{ // skip first '*' in subsequent lines
if (charsAdded)
addCommentLiteralChar('\n');
diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h
index 36cba112..d6b48c6f 100644
--- a/libsolidity/parsing/Scanner.h
+++ b/libsolidity/parsing/Scanner.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
This file is derived from the file "scanner.h", which was part of the
V8 project. The original copyright header follows:
@@ -80,6 +80,8 @@ public:
void reset() { m_position = 0; }
+ std::string const& source() const { return m_source; }
+
///@{
///@name Error printing helper functions
/// Functions that help pretty-printing parse errors
@@ -102,6 +104,8 @@ public:
explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); }
+ std::string source() const { return m_source.source(); }
+
/// Resets the scanner as if newly constructed with _source and _sourceName as input.
void reset(CharStream const& _source, std::string const& _sourceName);
/// Resets scanner to the start of input.
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
index 0ab97988..66312f69 100644
--- a/libsolidity/parsing/Token.cpp
+++ b/libsolidity/parsing/Token.cpp
@@ -25,20 +25,20 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-// Modifications as part of cpp-ethereum under the following license:
+// Modifications as part of solidity under the following license:
//
-// cpp-ethereum is free software: you can redistribute it and/or modify
+// 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.
//
-// cpp-ethereum is distributed in the hope that it will be useful,
+// 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// along with solidity. If not, see <http://www.gnu.org/licenses/>.
#include <map>
#include <libsolidity/parsing/Token.h>
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 5dd42992..c6d050bb 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -25,20 +25,20 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-// Modifications as part of cpp-ethereum under the following license:
+// Modifications as part of solidity under the following license:
//
-// cpp-ethereum is free software: you can redistribute it and/or modify
+// 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.
//
-// cpp-ethereum is distributed in the hope that it will be useful,
+// 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// along with solidity. If not, see <http://www.gnu.org/licenses/>.
#pragma once
@@ -147,7 +147,6 @@ namespace solidity
K(Const, "constant", 0) \
K(Continue, "continue", 0) \
K(Contract, "contract", 0) \
- K(Default, "default", 0) \
K(Do, "do", 0) \
K(Else, "else", 0) \
K(Enum, "enum", 0) \
@@ -208,7 +207,6 @@ namespace solidity
T(TypesEnd, NULL, 0) /* used as type enum end marker */ \
\
/* Literals */ \
- K(NullLiteral, "null", 0) \
K(TrueLiteral, "true", 0) \
K(FalseLiteral, "false", 0) \
T(Number, NULL, 0) \
@@ -223,12 +221,14 @@ namespace solidity
K(After, "after", 0) \
K(Case, "case", 0) \
K(Catch, "catch", 0) \
+ K(Default, "default", 0) \
K(Final, "final", 0) \
K(In, "in", 0) \
K(Inline, "inline", 0) \
K(Interface, "interface", 0) \
K(Let, "let", 0) \
K(Match, "match", 0) \
+ K(NullLiteral, "null", 0) \
K(Of, "of", 0) \
K(Pure, "pure", 0) \
K(Relocatable, "relocatable", 0) \
diff --git a/scripts/Dockerfile b/scripts/Dockerfile
new file mode 100644
index 00000000..20140556
--- /dev/null
+++ b/scripts/Dockerfile
@@ -0,0 +1,12 @@
+FROM alpine
+MAINTAINER chriseth <chris@ethereum.org>
+
+RUN \
+ apk --no-cache --update add build-base cmake boost-dev git && \
+ sed -i -E -e 's/include <sys\/poll.h>/include <poll.h>/' /usr/include/boost/asio/detail/socket_types.hpp && \
+ git clone --depth 1 --recursive -b release https://github.com/ethereum/solidity && \
+ cd /solidity && cmake -DCMAKE_BUILD_TYPE=Release -DTESTS=0 -DSTATIC_LINKING=1 && \
+ cd /solidity && make solc && install -s solc/solc /usr/bin && \
+ cd / && rm -rf solidity && \
+ apk del sed build-base git make cmake gcc g++ musl-dev curl-dev boost-dev && \
+ rm -rf /var/cache/apk/*
diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh
index c9f82769..255176ab 100755
--- a/scripts/install_deps.sh
+++ b/scripts/install_deps.sh
@@ -83,12 +83,6 @@ case $(uname -s) in
;;
10.12)
echo "Installing solidity dependencies on macOS 10.12 Sierra."
- echo ""
- echo "NOTE - You are in unknown territory with this preview OS."
- echo "Even Homebrew doesn't have official support yet, and there are"
- echo "known issues (see https://github.com/ethereum/webthree-umbrella/issues/614)."
- echo "If you would like to partner with us to work through these issues, that"
- echo "would be fantastic. Please just comment on that issue. Thanks!"
;;
*)
echo "Unsupported macOS version."
diff --git a/scripts/isolateTests.py b/scripts/isolateTests.py
deleted file mode 100755
index fed779d3..00000000
--- a/scripts/isolateTests.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-#
-# This script reads C++ source files and writes all
-# multi-line strings into individual files.
-# This can be used to extract the Solidity test cases
-# into files for e.g. fuzz testing as
-# scripts/isolateTests.py tests/libsolidity/SolidityEndToEndTest.cpp
-
-import sys
-lines = sys.stdin.read().split('\n')
-inside = False
-tests = []
-for l in lines:
- if inside:
- if l.strip().endswith(')";'):
- inside = False
- else:
- tests[-1] += l + '\n'
- else:
- if l.strip().endswith('R"('):
- inside = True
- tests += ['']
-for i in range(len(tests)):
- open('test%d.sol' % i, 'w').write(tests[i])
diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py
new file mode 100755
index 00000000..91900aa6
--- /dev/null
+++ b/scripts/isolate_tests.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+#
+# This script reads C++ source files and writes all
+# multi-line strings into individual files.
+# This can be used to extract the Solidity test cases
+# into files for e.g. fuzz testing as
+# scripts/isolate_tests.py test/libsolidity/*
+
+import sys
+
+
+def extract_cases(path):
+ lines = open(path).read().splitlines()
+
+ inside = False
+ tests = []
+
+ for l in lines:
+ if inside:
+ if l.strip().endswith(')";'):
+ inside = False
+ else:
+ tests[-1] += l + '\n'
+ else:
+ if l.strip().endswith('R"('):
+ inside = True
+ tests += ['']
+
+ return tests
+
+
+def write_cases(tests, start=0):
+ for i, test in enumerate(tests, start=start):
+ open('test%d.sol' % i, 'w').write(test)
+
+
+if __name__ == '__main__':
+ files = sys.argv[1:]
+
+ i = 0
+ for path in files:
+ cases = extract_cases(path)
+ write_cases(cases, start=i)
+ i += len(cases)
diff --git a/scripts/tests.sh b/scripts/tests.sh
index 5da427d4..dfbda734 100755
--- a/scripts/tests.sh
+++ b/scripts/tests.sh
@@ -65,9 +65,14 @@ $ETH_PATH --test -d /tmp/test &
# The node needs to get a little way into its startup sequence before the IPC
# is available and is ready for the unit-tests to start talking to it.
while [ ! -S /tmp/test/geth.ipc ]; do sleep 2; done
+echo "--> IPC available."
-# And then run the Solidity unit-tests, pointing to that IPC endpoint.
-"$REPO_ROOT"/build/test/soltest -- --ipcpath /tmp/test/geth.ipc
+# And then run the Solidity unit-tests (once without optimization, once with),
+# pointing to that IPC endpoint.
+echo "--> Running tests without optimizer..."
+ "$REPO_ROOT"/build/test/soltest -- --ipcpath /tmp/test/geth.ipc && \
+ echo "--> Running tests WITH optimizer..." && \
+ "$REPO_ROOT"/build/test/soltest -- --optimize --ipcpath /tmp/test/geth.ipc
ERROR_CODE=$?
pkill eth || true
sleep 4
diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh
index f5374a33..a6eb01a0 100755
--- a/scripts/travis-emscripten/build_emscripten.sh
+++ b/scripts/travis-emscripten/build_emscripten.sh
@@ -95,4 +95,8 @@ emmake make -j 4
cd ..
cp build/solc/soljson.js ./
+OUTPUT_SIZE=`ls -la build/solc/soljson.js`
+
+echo "Emscripten output size: ${OUTPUT_SIZE}"
+
echo -en 'travis_fold:end:compiling_solidity\\r'
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 7b23f886..e322455b 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
@@ -65,36 +65,83 @@ namespace dev
namespace solidity
{
-static string const g_argAbiStr = "abi";
-static string const g_argSignatureHashes = "hashes";
-static string const g_argGas = "gas";
-static string const g_argAsmStr = "asm";
-static string const g_argAsmJsonStr = "asm-json";
-static string const g_argAstStr = "ast";
-static string const g_argAstJson = "ast-json";
-static string const g_argBinaryStr = "bin";
-static string const g_argRuntimeBinaryStr = "bin-runtime";
-static string const g_argCloneBinaryStr = "clone-bin";
-static string const g_argOpcodesStr = "opcodes";
-static string const g_argNatspecDevStr = "devdoc";
-static string const g_argNatspecUserStr = "userdoc";
-static string const g_argAddStandard = "add-std";
-static string const g_stdinFileName = "<stdin>";
+static string const g_strAbi = "abi";
+static string const g_strAddStandard = "add-std";
+static string const g_strAsm = "asm";
+static string const g_strAsmJson = "asm-json";
+static string const g_strAssemble = "assemble";
+static string const g_strAst = "ast";
+static string const g_strAstJson = "ast-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_strContracts = "contracts";
+static string const g_strFormal = "formal";
+static string const g_strGas = "gas";
+static string const g_strHelp = "help";
+static string const g_strInputFile = "input-file";
+static string const g_strInterface = "interface";
+static string const g_strLibraries = "libraries";
+static string const g_strLink = "link";
+static string const g_strMetadata = "metadata";
+static string const g_strNatspecDev = "devdoc";
+static string const g_strNatspecUser = "userdoc";
+static string const g_strOpcodes = "opcodes";
+static string const g_strOptimize = "optimize";
+static string const g_strOptimizeRuns = "optimize-runs";
+static string const g_strOutputDir = "output-dir";
+static string const g_strSignatureHashes = "hashes";
+static string const g_strSources = "sources";
+static string const g_strSourceList = "sourceList";
+static string const g_strSrcMap = "srcmap";
+static string const g_strSrcMapRuntime = "srcmap-runtime";
+static string const g_strVersion = "version";
+static string const g_stdinFileNameStr = "<stdin>";
+
+static string const g_argAbi = g_strAbi;
+static string const g_argAddStandard = g_strAddStandard;
+static string const g_argAsm = g_strAsm;
+static string const g_argAsmJson = g_strAsmJson;
+static string const g_argAssemble = g_strAssemble;
+static string const g_argAst = g_strAst;
+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_argFormal = g_strFormal;
+static string const g_argGas = g_strGas;
+static string const g_argHelp = g_strHelp;
+static string const g_argInputFile = g_strInputFile;
+static string const g_argLibraries = g_strLibraries;
+static string const g_argLink = g_strLink;
+static string const g_argMetadata = g_strMetadata;
+static string const g_argNatspecDev = g_strNatspecDev;
+static string const g_argNatspecUser = g_strNatspecUser;
+static string const g_argOpcodes = g_strOpcodes;
+static string const g_argOptimize = g_strOptimize;
+static string const g_argOptimizeRuns = g_strOptimizeRuns;
+static string const g_argOutputDir = g_strOutputDir;
+static string const g_argSignatureHashes = g_strSignatureHashes;
+static string const g_argVersion = g_strVersion;
+static string const g_stdinFileName = g_stdinFileNameStr;
/// Possible arguments to for --combined-json
static set<string> const g_combinedJsonArgs{
- "bin",
- "bin-runtime",
- "clone-bin",
- "srcmap",
- "srcmap-runtime",
- "opcodes",
- "abi",
- "interface",
- "asm",
- "ast",
- "userdoc",
- "devdoc"
+ g_strAbi,
+ g_strAsm,
+ g_strAst,
+ g_strBinary,
+ g_strBinaryRuntime,
+ g_strCloneBinary,
+ g_strInterface,
+ g_strMetadata,
+ g_strNatspecUser,
+ g_strNatspecDev,
+ g_strOpcodes,
+ g_strSrcMap,
+ g_strSrcMapRuntime
};
static void version()
@@ -112,21 +159,22 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args)
{
if (_args.count(g_argGas))
return true;
- if (_args.count("output-dir"))
+ if (_args.count(g_argOutputDir))
return false;
for (string const& arg: {
- g_argAbiStr,
- g_argSignatureHashes,
- g_argNatspecUserStr,
+ g_argAbi,
+ g_argAsm,
+ g_argAsmJson,
g_argAstJson,
- g_argNatspecDevStr,
- g_argAsmStr,
- g_argAsmJsonStr,
- g_argOpcodesStr,
- g_argBinaryStr,
- g_argRuntimeBinaryStr,
- g_argCloneBinaryStr,
- string("formal")
+ g_argBinary,
+ g_argBinaryRuntime,
+ g_argCloneBinary,
+ g_argFormal,
+ g_argMetadata,
+ g_argNatspecUser,
+ g_argNatspecDev,
+ g_argOpcodes,
+ g_argSignatureHashes
})
if (_args.count(arg))
return true;
@@ -135,9 +183,9 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args)
void CommandLineInterface::handleBinary(string const& _contract)
{
- if (m_args.count(g_argBinaryStr))
+ if (m_args.count(g_argBinary))
{
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(_contract + ".bin", m_compiler->object(_contract).toHex());
else
{
@@ -145,9 +193,9 @@ void CommandLineInterface::handleBinary(string const& _contract)
cout << m_compiler->object(_contract).toHex() << endl;
}
}
- if (m_args.count(g_argCloneBinaryStr))
+ if (m_args.count(g_argCloneBinary))
{
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(_contract + ".clone_bin", m_compiler->cloneObject(_contract).toHex());
else
{
@@ -155,9 +203,9 @@ void CommandLineInterface::handleBinary(string const& _contract)
cout << m_compiler->cloneObject(_contract).toHex() << endl;
}
}
- if (m_args.count(g_argRuntimeBinaryStr))
+ if (m_args.count(g_argBinaryRuntime))
{
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(_contract + ".bin-runtime", m_compiler->runtimeObject(_contract).toHex());
else
{
@@ -169,7 +217,7 @@ void CommandLineInterface::handleBinary(string const& _contract)
void CommandLineInterface::handleOpcode(string const& _contract)
{
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(_contract + ".opcode", solidity::disassemble(m_compiler->object(_contract).bytecode));
else
{
@@ -181,9 +229,9 @@ void CommandLineInterface::handleOpcode(string const& _contract)
void CommandLineInterface::handleBytecode(string const& _contract)
{
- if (m_args.count(g_argOpcodesStr))
+ if (m_args.count(g_argOpcodes))
handleOpcode(_contract);
- if (m_args.count(g_argBinaryStr) || m_args.count(g_argCloneBinaryStr) || m_args.count(g_argRuntimeBinaryStr))
+ if (m_args.count(g_argBinary) || m_args.count(g_argCloneBinary) || m_args.count(g_argBinaryRuntime))
handleBinary(_contract);
}
@@ -196,12 +244,24 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
for (auto const& it: m_compiler->contractDefinition(_contract).interfaceFunctions())
out += toHex(it.first.ref()) + ": " + it.second->externalSignature() + "\n";
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(_contract + ".signatures", out);
else
cout << "Function signatures: " << endl << out;
}
+void CommandLineInterface::handleOnChainMetadata(string const& _contract)
+{
+ if (!m_args.count(g_argMetadata))
+ return;
+
+ string data = m_compiler->onChainMetadata(_contract);
+ if (m_args.count("output-dir"))
+ createFile(_contract + "_meta.json", data);
+ else
+ cout << "Metadata: " << endl << data << endl;
+}
+
void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract)
{
std::string argName;
@@ -210,17 +270,17 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co
switch(_type)
{
case DocumentationType::ABIInterface:
- argName = g_argAbiStr;
+ argName = g_argAbi;
suffix = ".abi";
title = "Contract JSON ABI";
break;
case DocumentationType::NatspecUser:
- argName = g_argNatspecUserStr;
+ argName = g_argNatspecUser;
suffix = ".docuser";
title = "User Documentation";
break;
case DocumentationType::NatspecDev:
- argName = g_argNatspecDevStr;
+ argName = g_argNatspecDev;
suffix = ".docdev";
title = "Developer Documentation";
break;
@@ -237,7 +297,7 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co
else
output = dev::jsonPrettyPrint(m_compiler->metadata(_contract, _type));
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile(_contract + suffix, output);
else
{
@@ -299,10 +359,10 @@ void CommandLineInterface::handleGasEstimation(string const& _contract)
void CommandLineInterface::handleFormal()
{
- if (!m_args.count("formal"))
+ if (!m_args.count(g_argFormal))
return;
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
createFile("solidity.mlw", m_compiler->formalTranslation());
else
cout << "Formal version:" << endl << m_compiler->formalTranslation() << endl;
@@ -310,12 +370,11 @@ void CommandLineInterface::handleFormal()
void CommandLineInterface::readInputFilesAndConfigureRemappings()
{
- vector<string> inputFiles;
bool addStdin = false;
- if (!m_args.count("input-file"))
+ if (!m_args.count(g_argInputFile))
addStdin = true;
else
- for (string path: m_args["input-file"].as<vector<string>>())
+ for (string path: m_args[g_argInputFile].as<vector<string>>())
{
auto eq = find(path.begin(), path.end(), '=');
if (eq != path.end())
@@ -327,7 +386,7 @@ void CommandLineInterface::readInputFilesAndConfigureRemappings()
auto infile = boost::filesystem::path(path);
if (!boost::filesystem::exists(infile))
{
- cerr << "Skipping non existant input file \"" << infile << "\"" << endl;
+ cerr << "Skipping non-existent input file \"" << infile << "\"" << endl;
continue;
}
@@ -390,7 +449,7 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da
{
namespace fs = boost::filesystem;
// create directory if not existent
- fs::path p(m_args.at("output-dir").as<string>());
+ fs::path p(m_args.at(g_argOutputDir).as<string>());
fs::create_directories(p);
string pathName = (p / _fileName).string();
ofstream outFile(pathName);
@@ -417,65 +476,66 @@ Allowed options)",
po::options_description::m_default_line_length,
po::options_description::m_default_line_length - 23);
desc.add_options()
- ("help", "Show help message and exit.")
- ("version", "Show version and exit.")
- ("optimize", "Enable bytecode optimizer.")
+ (g_argHelp.c_str(), "Show help message and exit.")
+ (g_argVersion.c_str(), "Show version and exit.")
+ (g_argOptimize.c_str(), "Enable bytecode optimizer.")
(
- "optimize-runs",
+ g_argOptimizeRuns.c_str(),
po::value<unsigned>()->value_name("n")->default_value(200),
"Estimated number of contract runs for optimizer tuning."
)
(g_argAddStandard.c_str(), "Add standard contracts.")
(
- "libraries",
+ g_argLibraries.c_str(),
po::value<vector<string>>()->value_name("libs"),
"Direct string or file containing library addresses. Syntax: "
"<libraryName>: <address> [, or whitespace] ...\n"
"Address is interpreted as a hex string optionally prefixed by 0x."
)
(
- "output-dir,o",
+ (g_argOutputDir + ",o").c_str(),
po::value<string>()->value_name("path"),
"If given, creates one file per component and contract/file at the specified directory."
)
(
- "combined-json",
+ g_argCombinedJson.c_str(),
po::value<string>()->value_name(boost::join(g_combinedJsonArgs, ",")),
"Output a single json document containing the specified information."
)
(g_argGas.c_str(), "Print an estimate of the maximal gas usage for each function.")
(
- "assemble",
+ g_argAssemble.c_str(),
"Switch to assembly mode, ignoring all options and assumes input is assembly."
)
(
- "link",
+ g_argLink.c_str(),
"Switch to linker mode, ignoring all options apart from --libraries "
"and modify binaries in place."
);
po::options_description outputComponents("Output Components");
outputComponents.add_options()
- (g_argAstStr.c_str(), "AST of all source files.")
+ (g_argAst.c_str(), "AST of all source files.")
(g_argAstJson.c_str(), "AST of all source files in JSON format.")
- (g_argAsmStr.c_str(), "EVM assembly of the contracts.")
- (g_argAsmJsonStr.c_str(), "EVM assembly of the contracts in JSON format.")
- (g_argOpcodesStr.c_str(), "Opcodes of the contracts.")
- (g_argBinaryStr.c_str(), "Binary of the contracts in hex.")
- (g_argRuntimeBinaryStr.c_str(), "Binary of the runtime part of the contracts in hex.")
- (g_argCloneBinaryStr.c_str(), "Binary of the clone contracts in hex.")
- (g_argAbiStr.c_str(), "ABI specification of the contracts.")
+ (g_argAsm.c_str(), "EVM assembly of the contracts.")
+ (g_argAsmJson.c_str(), "EVM assembly of the contracts in JSON format.")
+ (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_argNatspecUserStr.c_str(), "Natspec user documentation of all contracts.")
- (g_argNatspecDevStr.c_str(), "Natspec developer documentation of all contracts.")
- ("formal", "Translated source suitable for formal analysis.");
+ (g_argNatspecUser.c_str(), "Natspec user documentation of all contracts.")
+ (g_argNatspecDev.c_str(), "Natspec developer documentation of all contracts.")
+ (g_argMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.")
+ (g_argFormal.c_str(), "Translated source suitable for formal analysis.");
desc.add(outputComponents);
po::options_description allOptions = desc;
- allOptions.add_options()("input-file", po::value<vector<string>>(), "input file");
+ allOptions.add_options()(g_argInputFile.c_str(), po::value<vector<string>>(), "input file");
// All positional options should be interpreted as input files
po::positional_options_description filesPositions;
- filesPositions.add("input-file", -1);
+ filesPositions.add(g_argInputFile.c_str(), -1);
// parse the compiler arguments
try
@@ -490,22 +550,22 @@ Allowed options)",
return false;
}
- if (m_args.count("help") || (isatty(fileno(stdin)) && _argc == 1))
+ if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1))
{
cout << desc;
return false;
}
- if (m_args.count("version"))
+ if (m_args.count(g_argVersion))
{
version();
return false;
}
- if (m_args.count("combined-json"))
+ if (m_args.count(g_argCombinedJson))
{
vector<string> requests;
- for (string const& item: boost::split(requests, m_args["combined-json"].as<string>(), boost::is_any_of(",")))
+ for (string const& item: boost::split(requests, m_args[g_argCombinedJson].as<string>(), boost::is_any_of(",")))
if (!g_combinedJsonArgs.count(item))
{
cerr << "Invalid option to --combined-json: " << item << endl;
@@ -521,18 +581,18 @@ bool CommandLineInterface::processInput()
{
readInputFilesAndConfigureRemappings();
- if (m_args.count("libraries"))
- for (string const& library: m_args["libraries"].as<vector<string>>())
+ if (m_args.count(g_argLibraries))
+ for (string const& library: m_args[g_argLibraries].as<vector<string>>())
if (!parseLibraryOption(library))
return false;
- if (m_args.count("assemble"))
+ if (m_args.count(g_argAssemble))
{
// switch to assembly mode
m_onlyAssemble = true;
return assemble();
}
- if (m_args.count("link"))
+ if (m_args.count(g_argLink))
{
// switch to linker mode
m_onlyLink = true;
@@ -574,18 +634,16 @@ bool CommandLineInterface::processInput()
auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); };
try
{
- if (m_args.count("input-file"))
- m_compiler->setRemappings(m_args["input-file"].as<vector<string>>());
+ if (m_args.count(g_argInputFile))
+ m_compiler->setRemappings(m_args[g_argInputFile].as<vector<string>>());
for (auto const& sourceCode: m_sourceCodes)
m_compiler->addSource(sourceCode.first, sourceCode.second);
// TODO: Perhaps we should not compile unless requested
- bool optimize = m_args.count("optimize") > 0;
- unsigned runs = m_args["optimize-runs"].as<unsigned>();
- bool successful = m_compiler->compile(optimize, runs);
- if (successful)
- m_compiler->link(m_libraries);
+ bool optimize = m_args.count(g_argOptimize) > 0;
+ unsigned runs = m_args[g_argOptimizeRuns].as<unsigned>();
+ bool successful = m_compiler->compile(optimize, runs, m_libraries);
- if (successful && m_args.count("formal"))
+ if (successful && m_args.count(g_argFormal))
if (!m_compiler->prepareFormalAnalysis())
successful = false;
@@ -642,71 +700,73 @@ bool CommandLineInterface::processInput()
void CommandLineInterface::handleCombinedJSON()
{
- if (!m_args.count("combined-json"))
+ if (!m_args.count(g_argCombinedJson))
return;
Json::Value output(Json::objectValue);
- output["version"] = ::dev::solidity::VersionString;
+ output[g_strVersion] = ::dev::solidity::VersionString;
set<string> requests;
- boost::split(requests, m_args["combined-json"].as<string>(), boost::is_any_of(","));
+ boost::split(requests, m_args[g_argCombinedJson].as<string>(), boost::is_any_of(","));
vector<string> contracts = m_compiler->contractNames();
if (!contracts.empty())
- output["contracts"] = Json::Value(Json::objectValue);
+ output[g_strContracts] = Json::Value(Json::objectValue);
for (string const& contractName: contracts)
{
Json::Value contractData(Json::objectValue);
- if (requests.count("abi"))
- contractData["abi"] = dev::jsonCompactPrint(m_compiler->interface(contractName));
- if (requests.count("bin"))
- contractData["bin"] = m_compiler->object(contractName).toHex();
- if (requests.count("bin-runtime"))
- contractData["bin-runtime"] = m_compiler->runtimeObject(contractName).toHex();
- if (requests.count("clone-bin"))
- contractData["clone-bin"] = m_compiler->cloneObject(contractName).toHex();
- if (requests.count("opcodes"))
- contractData["opcodes"] = solidity::disassemble(m_compiler->object(contractName).bytecode);
- if (requests.count("asm"))
+ if (requests.count(g_strAbi))
+ contractData[g_strAbi] = dev::jsonCompactPrint(m_compiler->interface(contractName));
+ if (requests.count("metadata"))
+ contractData["metadata"] = m_compiler->onChainMetadata(contractName);
+ if (requests.count(g_strBinary))
+ 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))
{
ostringstream unused;
- contractData["asm"] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true);
+ contractData[g_strAsm] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true);
}
- if (requests.count("srcmap"))
+ if (requests.count(g_strSrcMap))
{
auto map = m_compiler->sourceMapping(contractName);
- contractData["srcmap"] = map ? *map : "";
+ contractData[g_strSrcMap] = map ? *map : "";
}
- if (requests.count("srcmap-runtime"))
+ if (requests.count(g_strSrcMapRuntime))
{
auto map = m_compiler->runtimeSourceMapping(contractName);
- contractData["srcmap-runtime"] = map ? *map : "";
+ contractData[g_strSrcMapRuntime] = map ? *map : "";
}
- if (requests.count("devdoc"))
- contractData["devdoc"] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecDev));
- if (requests.count("userdoc"))
- contractData["userdoc"] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecUser));
- output["contracts"][contractName] = contractData;
+ if (requests.count(g_strNatspecDev))
+ contractData[g_strNatspecDev] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecDev));
+ if (requests.count(g_strNatspecUser))
+ contractData[g_strNatspecUser] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecUser));
+ output[g_strContracts][contractName] = contractData;
}
- bool needsSourceList = requests.count("ast") || requests.count("srcmap") || requests.count("srcmap-runtime");
+ bool needsSourceList = requests.count(g_strAst) || requests.count(g_strSrcMap) || requests.count(g_strSrcMapRuntime);
if (needsSourceList)
{
// Indices into this array are used to abbreviate source names in source locations.
- output["sourceList"] = Json::Value(Json::arrayValue);
+ output[g_strSourceList] = Json::Value(Json::arrayValue);
for (auto const& source: m_compiler->sourceNames())
- output["sourceList"].append(source);
+ output[g_strSourceList].append(source);
}
- if (requests.count("ast"))
+ if (requests.count(g_strAst))
{
- output["sources"] = Json::Value(Json::objectValue);
+ output[g_strSources] = Json::Value(Json::objectValue);
for (auto const& sourceCode: m_sourceCodes)
{
ASTJsonConverter converter(m_compiler->ast(sourceCode.first), m_compiler->sourceIndices());
- output["sources"][sourceCode.first] = Json::Value(Json::objectValue);
- output["sources"][sourceCode.first]["AST"] = converter.json();
+ output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue);
+ output[g_strSources][sourceCode.first]["AST"] = converter.json();
}
}
cout << dev::jsonCompactPrint(output) << endl;
@@ -716,7 +776,7 @@ void CommandLineInterface::handleAst(string const& _argStr)
{
string title;
- if (_argStr == g_argAstStr)
+ if (_argStr == g_argAst)
title = "Syntax trees:";
else if (_argStr == g_argAstJson)
title = "JSON AST:";
@@ -736,13 +796,13 @@ void CommandLineInterface::handleAst(string const& _argStr)
asts
);
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
{
for (auto const& sourceCode: m_sourceCodes)
{
stringstream data;
string postfix = "";
- if (_argStr == g_argAstStr)
+ if (_argStr == g_argAst)
{
ASTPrinter printer(m_compiler->ast(sourceCode.first), sourceCode.second);
printer.print(data);
@@ -763,7 +823,7 @@ void CommandLineInterface::handleAst(string const& _argStr)
for (auto const& sourceCode: m_sourceCodes)
{
cout << endl << "======= " << sourceCode.first << " =======" << endl;
- if (_argStr == g_argAstStr)
+ if (_argStr == g_argAst)
{
ASTPrinter printer(
m_compiler->ast(sourceCode.first),
@@ -888,7 +948,7 @@ void CommandLineInterface::outputCompilationResults()
handleCombinedJSON();
// do we need AST output?
- handleAst(g_argAstStr);
+ handleAst(g_argAst);
handleAst(g_argAstJson);
vector<string> contracts = m_compiler->contractNames();
@@ -898,18 +958,18 @@ void CommandLineInterface::outputCompilationResults()
cout << endl << "======= " << contract << " =======" << endl;
// do we need EVM assembly?
- if (m_args.count(g_argAsmStr) || m_args.count(g_argAsmJsonStr))
+ if (m_args.count(g_argAsm) || m_args.count(g_argAsmJson))
{
- if (m_args.count("output-dir"))
+ if (m_args.count(g_argOutputDir))
{
stringstream data;
- m_compiler->streamAssembly(data, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr));
- createFile(contract + (m_args.count(g_argAsmJsonStr) ? "_evm.json" : ".evm"), data.str());
+ m_compiler->streamAssembly(data, contract, m_sourceCodes, m_args.count(g_argAsmJson));
+ createFile(contract + (m_args.count(g_argAsmJson) ? "_evm.json" : ".evm"), data.str());
}
else
{
cout << "EVM assembly:" << endl;
- m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr));
+ m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJson));
}
}
@@ -918,6 +978,7 @@ void CommandLineInterface::outputCompilationResults()
handleBytecode(contract);
handleSignatureHashes(contract);
+ handleOnChainMetadata(contract);
handleMeta(DocumentationType::ABIInterface, contract);
handleMeta(DocumentationType::NatspecDev, contract);
handleMeta(DocumentationType::NatspecUser, contract);
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index e240fe96..b8fc1823 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris <lefteris@ethdev.com>
@@ -63,6 +63,7 @@ private:
void handleOpcode(std::string const& _contract);
void handleBytecode(std::string const& _contract);
void handleSignatureHashes(std::string const& _contract);
+ void handleOnChainMetadata(std::string const& _contract);
void handleMeta(DocumentationType _type, std::string const& _contract);
void handleGasEstimation(std::string const& _contract);
void handleFormal();
diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp
index 771f0df8..d761b541 100644
--- a/solc/jsonCompiler.cpp
+++ b/solc/jsonCompiler.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -218,6 +218,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
contractData["bytecode"] = compiler.object(contractName).toHex();
contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex();
contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode);
+ contractData["metadata"] = compiler.onChainMetadata(contractName);
contractData["functionHashes"] = functionHashes(compiler.contractDefinition(contractName));
contractData["gasEstimates"] = estimateGas(compiler, contractName);
auto sourceMap = compiler.sourceMapping(contractName);
diff --git a/solc/main.cpp b/solc/main.cpp
index 26010716..28726e26 100644
--- a/solc/main.cpp
+++ b/solc/main.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 33af9981..609aaab3 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -5,6 +5,7 @@ aux_source_directory(libdevcore SRC_LIST)
aux_source_directory(libevmasm SRC_LIST)
aux_source_directory(libsolidity SRC_LIST)
aux_source_directory(contracts SRC_LIST)
+aux_source_directory(liblll SRC_LIST)
get_filename_component(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
@@ -28,7 +29,7 @@ file(GLOB HEADERS "*.h" "*/*.h")
set(EXECUTABLE soltest)
eth_simple_add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
-eth_use(${EXECUTABLE} REQUIRED Solidity::solidity)
+eth_use(${EXECUTABLE} REQUIRED Solidity::solidity Solidity::lll)
include_directories(BEFORE ..)
target_link_libraries(${EXECUTABLE} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES})
diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp
new file mode 100644
index 00000000..ddcd9cb6
--- /dev/null
+++ b/test/ExecutionFramework.cpp
@@ -0,0 +1,153 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2016
+ * Framework for executing contracts and testing them using RPC.
+ */
+
+#include <cstdlib>
+#include <boost/test/framework.hpp>
+#include <libdevcore/CommonIO.h>
+#include <test/ExecutionFramework.h>
+
+using namespace std;
+using namespace dev;
+using namespace dev::test;
+
+namespace // anonymous
+{
+ h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
+}
+
+string getIPCSocketPath()
+{
+ string ipcPath = dev::test::Options::get().ipcPath;
+ if (ipcPath.empty())
+ BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath <path> or the environment variable ETH_TEST_IPC)");
+
+ return ipcPath;
+}
+
+ExecutionFramework::ExecutionFramework() :
+ m_rpc(RPCSession::instance(getIPCSocketPath())),
+ m_optimize(dev::test::Options::get().optimize),
+ m_showMessages(dev::test::Options::get().showMessages),
+ m_sender(m_rpc.account(0))
+{
+ m_rpc.test_rewindToBlock(0);
+}
+
+void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value)
+{
+ if (m_showMessages)
+ {
+ if (_isCreation)
+ cout << "CREATE " << m_sender.hex() << ":" << endl;
+ else
+ cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << endl;
+ if (_value > 0)
+ cout << " value: " << _value << endl;
+ cout << " in: " << toHex(_data) << endl;
+ }
+ RPCSession::TransactionData d;
+ d.data = "0x" + toHex(_data);
+ d.from = "0x" + toString(m_sender);
+ d.gas = toHex(m_gas, HexPrefix::Add);
+ d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
+ d.value = toHex(_value, HexPrefix::Add);
+ if (!_isCreation)
+ {
+ d.to = dev::toString(m_contractAddress);
+ BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "latest").size() > 2);
+ // Use eth_call to get the output
+ m_output = fromHex(m_rpc.eth_call(d, "latest"), WhenError::Throw);
+ }
+
+ string txHash = m_rpc.eth_sendTransaction(d);
+ m_rpc.test_mineBlocks(1);
+ RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash));
+
+ if (_isCreation)
+ {
+ m_contractAddress = Address(receipt.contractAddress);
+ BOOST_REQUIRE(m_contractAddress);
+ string code = m_rpc.eth_getCode(receipt.contractAddress, "latest");
+ m_output = fromHex(code, WhenError::Throw);
+ }
+
+ if (m_showMessages)
+ {
+ cout << " out: " << toHex(m_output) << endl;
+ cout << " tx hash: " << txHash << endl;
+ }
+
+ m_gasUsed = u256(receipt.gasUsed);
+ m_logs.clear();
+ for (auto const& log: receipt.logEntries)
+ {
+ LogEntry entry;
+ entry.address = Address(log.address);
+ for (auto const& topic: log.topics)
+ entry.topics.push_back(h256(topic));
+ entry.data = fromHex(log.data, WhenError::Throw);
+ m_logs.push_back(entry);
+ }
+}
+
+void ExecutionFramework::sendEther(Address const& _to, u256 const& _value)
+{
+ RPCSession::TransactionData d;
+ d.data = "0x";
+ d.from = "0x" + toString(m_sender);
+ d.gas = toHex(m_gas, HexPrefix::Add);
+ d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
+ d.value = toHex(_value, HexPrefix::Add);
+ d.to = dev::toString(_to);
+
+ string txHash = m_rpc.eth_sendTransaction(d);
+ m_rpc.test_mineBlocks(1);
+}
+
+size_t ExecutionFramework::currentTimestamp()
+{
+ auto latestBlock = m_rpc.rpcCall("eth_getBlockByNumber", {"\"latest\"", "false"});
+ return size_t(u256(latestBlock.get("timestamp", "invalid").asString()));
+}
+
+Address ExecutionFramework::account(size_t _i)
+{
+ return Address(m_rpc.accountCreateIfNotExists(_i));
+}
+
+bool ExecutionFramework::addressHasCode(Address const& _addr)
+{
+ string code = m_rpc.eth_getCode(toString(_addr), "latest");
+ return !code.empty() && code != "0x";
+}
+
+u256 ExecutionFramework::balanceAt(Address const& _addr)
+{
+ return u256(m_rpc.eth_getBalance(toString(_addr), "latest"));
+}
+
+bool ExecutionFramework::storageEmpty(Address const& _addr)
+{
+ h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest"));
+ BOOST_CHECK(root);
+ return root == EmptyTrie;
+}
diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h
new file mode 100644
index 00000000..733fd56d
--- /dev/null
+++ b/test/ExecutionFramework.h
@@ -0,0 +1,296 @@
+/*
+ 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 2014
+ * Framework for executing contracts and testing them using RPC.
+ */
+
+#pragma once
+
+#include <functional>
+
+#include "TestHelper.h"
+#include "RPCSession.h"
+
+#include <libdevcore/ABI.h>
+#include <libdevcore/FixedHash.h>
+
+namespace dev
+{
+namespace test
+{
+ using rational = boost::rational<dev::bigint>;
+ /// An Ethereum address: 20 bytes.
+ /// @NOTE This is not endian-specific; it's just a bunch of bytes.
+ using Address = h160;
+
+ // The various denominations; here for ease of use where needed within code.
+ static const u256 ether = exp10<18>();
+ static const u256 finney = exp10<15>();
+ static const u256 szabo = exp10<12>();
+ static const u256 shannon = exp10<9>();
+ static const u256 wei = exp10<0>();
+
+class ExecutionFramework
+{
+
+public:
+ ExecutionFramework();
+
+ virtual bytes const& compileAndRunWithoutCheck(
+ std::string const& _sourceCode,
+ u256 const& _value = 0,
+ std::string const& _contractName = "",
+ bytes const& _arguments = bytes(),
+ std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>()
+ ) = 0;
+
+ bytes const& compileAndRun(
+ std::string const& _sourceCode,
+ u256 const& _value = 0,
+ std::string const& _contractName = "",
+ bytes const& _arguments = bytes(),
+ std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>()
+ )
+ {
+ compileAndRunWithoutCheck(_sourceCode, _value, _contractName, _arguments, _libraryAddresses);
+ BOOST_REQUIRE(!m_output.empty());
+ return m_output;
+ }
+
+ bytes const& callFallbackWithValue(u256 const& _value)
+ {
+ sendMessage(bytes(), false, _value);
+ return m_output;
+ }
+
+ bytes const & callFallback()
+ {
+ return callFallbackWithValue(0);
+ }
+
+ template <class... Args>
+ bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments)
+ {
+ FixedHash<4> hash(dev::keccak256(_sig));
+ sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value);
+ return m_output;
+ }
+
+ template <class... Args>
+ bytes const& callContractFunction(std::string _sig, Args const&... _arguments)
+ {
+ return callContractFunctionWithValue(_sig, 0, _arguments...);
+ }
+
+ template <class CppFunction, class... Args>
+ void testContractAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments)
+ {
+ bytes contractResult = callContractFunction(_sig, _arguments...);
+ bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...);
+ BOOST_CHECK_MESSAGE(
+ contractResult == cppResult,
+ "Computed values do not match.\nContract: " +
+ toHex(contractResult) +
+ "\nC++: " +
+ toHex(cppResult)
+ );
+ }
+
+ template <class CppFunction, class... Args>
+ void testContractAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd)
+ {
+ for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument)
+ {
+ bytes contractResult = callContractFunction(_sig, argument);
+ bytes cppResult = callCppAndEncodeResult(_cppFunction, argument);
+ BOOST_CHECK_MESSAGE(
+ contractResult == cppResult,
+ "Computed values do not match.\nContract: " +
+ toHex(contractResult) +
+ "\nC++: " +
+ toHex(cppResult) +
+ "\nArgument: " +
+ toHex(encode(argument))
+ );
+ }
+ }
+
+ static bytes encode(bool _value) { return encode(byte(_value)); }
+ static bytes encode(int _value) { return encode(u256(_value)); }
+ static bytes encode(size_t _value) { return encode(u256(_value)); }
+ static bytes encode(char const* _value) { return encode(std::string(_value)); }
+ static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; }
+ static bytes encode(u256 const& _value) { return toBigEndian(_value); }
+ /// @returns the fixed-point encoding of a rational number with a given
+ /// number of fractional bits.
+ static bytes encode(std::pair<rational, int> const& _valueAndPrecision)
+ {
+ rational const& value = _valueAndPrecision.first;
+ int fractionalBits = _valueAndPrecision.second;
+ return encode(u256((value.numerator() << fractionalBits) / value.denominator()));
+ }
+ static bytes encode(h256 const& _value) { return _value.asBytes(); }
+ static bytes encode(bytes const& _value, bool _padLeft = true)
+ {
+ bytes padding = bytes((32 - _value.size() % 32) % 32, 0);
+ return _padLeft ? padding + _value : _value + padding;
+ }
+ static bytes encode(std::string const& _value) { return encode(asBytes(_value), false); }
+ template <class _T>
+ static bytes encode(std::vector<_T> const& _value)
+ {
+ bytes ret;
+ for (auto const& v: _value)
+ ret += encode(v);
+ return ret;
+ }
+
+ template <class FirstArg, class... Args>
+ static bytes encodeArgs(FirstArg const& _firstArg, Args const&... _followingArgs)
+ {
+ return encode(_firstArg) + encodeArgs(_followingArgs...);
+ }
+ static bytes encodeArgs()
+ {
+ return bytes();
+ }
+ //@todo might be extended in the future
+ template <class Arg>
+ static bytes encodeDyn(Arg const& _arg)
+ {
+ return encodeArgs(u256(0x20), u256(_arg.size()), _arg);
+ }
+ class ContractInterface
+ {
+ public:
+ ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {}
+
+ void setNextValue(u256 const& _value) { m_nextValue = _value; }
+
+ protected:
+ template <class... Args>
+ bytes const& call(std::string const& _sig, Args const&... _arguments)
+ {
+ auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...);
+ m_nextValue = 0;
+ return ret;
+ }
+
+ void callString(std::string const& _name, std::string const& _arg)
+ {
+ BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty());
+ }
+
+ void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2)
+ {
+ BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty());
+ }
+
+ void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3)
+ {
+ BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty());
+ }
+
+ void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2)
+ {
+ BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty());
+ }
+
+ u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg)
+ {
+ bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg);
+ BOOST_REQUIRE(ret.size() == 0x20);
+ BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12);
+ return eth::abiOut<u160>(ret);
+ }
+
+ std::string callAddressReturnsString(std::string const& _name, u160 const& _arg)
+ {
+ bytesConstRef ret = ref(call(_name + "(address)", _arg));
+ BOOST_REQUIRE(ret.size() >= 0x20);
+ u256 offset = eth::abiOut<u256>(ret);
+ BOOST_REQUIRE_EQUAL(offset, 0x20);
+ u256 len = eth::abiOut<u256>(ret);
+ BOOST_REQUIRE_EQUAL(ret.size(), ((len + 0x1f) / 0x20) * 0x20);
+ return ret.cropped(0, size_t(len)).toString();
+ }
+
+ h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg)
+ {
+ bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg);
+ BOOST_REQUIRE(ret.size() == 0x20);
+ return eth::abiOut<h256>(ret);
+ }
+
+ private:
+ u256 m_nextValue;
+ ExecutionFramework& m_framework;
+ };
+
+private:
+ template <class CppFunction, class... Args>
+ auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
+ -> typename std::enable_if<std::is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type
+ {
+ _cppFunction(_arguments...);
+ return bytes();
+ }
+ template <class CppFunction, class... Args>
+ auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
+ -> typename std::enable_if<!std::is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type
+ {
+ return encode(_cppFunction(_arguments...));
+ }
+
+protected:
+ void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0);
+ void sendEther(Address const& _to, u256 const& _value);
+ size_t currentTimestamp();
+
+ /// @returns the (potentially newly created) _ith address.
+ Address account(size_t _i);
+
+ u256 balanceAt(Address const& _addr);
+ bool storageEmpty(Address const& _addr);
+ bool addressHasCode(Address const& _addr);
+
+ RPCSession& m_rpc;
+
+ struct LogEntry
+ {
+ Address address;
+ std::vector<h256> topics;
+ bytes data;
+ };
+
+ unsigned m_optimizeRuns = 200;
+ bool m_optimize = false;
+ bool m_showMessages = false;
+ Address m_sender;
+ Address m_contractAddress;
+ u256 const m_gasPrice = 100 * szabo;
+ u256 const m_gas = 100000000;
+ bytes m_output;
+ std::vector<LogEntry> m_logs;
+ u256 m_gasUsed;
+};
+
+}
+} // end namespaces
+
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp
index 0a01ddb2..44d21d69 100644
--- a/test/RPCSession.cpp
+++ b/test/RPCSession.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
The Implementation originally from https://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
*/
diff --git a/test/RPCSession.h b/test/RPCSession.h
index 2a9825b0..fc166b99 100644
--- a/test/RPCSession.h
+++ b/test/RPCSession.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RPCSession.h
* @author Dimtiry Khokhlov <dimitry@ethdev.com>
diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp
index df35ff53..0c0857c9 100644
--- a/test/TestHelper.cpp
+++ b/test/TestHelper.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TestHelper.h
* @author Marko Simovic <markobarko@gmail.com>
@@ -39,6 +39,11 @@ Options::Options()
ipcPath = suite.argv[i + 1];
i++;
}
+ else if (string(suite.argv[i]) == "--optimize")
+ optimize = true;
+ else if (string(suite.argv[i]) == "--show-messages")
+ showMessages = true;
+
if (ipcPath.empty())
if (auto path = getenv("ETH_TEST_IPC"))
ipcPath = path;
diff --git a/test/TestHelper.h b/test/TestHelper.h
index 2cb24fd7..8f05eead 100644
--- a/test/TestHelper.h
+++ b/test/TestHelper.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TestHelper.h
* @author Marko Simovic <markobarko@gmail.com>
@@ -106,6 +106,8 @@ namespace test
struct Options: boost::noncopyable
{
std::string ipcPath;
+ bool showMessages = false;
+ bool optimize = false;
static Options const& get();
diff --git a/test/boostTest.cpp b/test/boostTest.cpp
index 4ddae0b7..d1d35be3 100644
--- a/test/boostTest.cpp
+++ b/test/boostTest.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file boostTest.cpp
* @author Marko Simovic <markobarko@gmail.com>
diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp
index 277de4eb..fb8c1c68 100644
--- a/test/contracts/AuctionRegistrar.cpp
+++ b/test/contracts/AuctionRegistrar.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -27,6 +27,7 @@
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
+using namespace dev::test;
namespace dev
{
@@ -213,14 +214,13 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
static unique_ptr<bytes> s_compiledRegistrar;
-class AuctionRegistrarTestFramework: public ExecutionFramework
+class AuctionRegistrarTestFramework: public SolidityExecutionFramework
{
protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
{
- m_optimize = true;
m_compiler.reset(false);
m_compiler.addSource("", registrarCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
@@ -230,11 +230,11 @@ protected:
BOOST_REQUIRE(!m_output.empty());
}
- using ContractInterface = ExecutionFramework::ContractInterface;
+ using ContractInterface = SolidityExecutionFramework::ContractInterface;
class RegistrarInterface: public ContractInterface
{
public:
- RegistrarInterface(ExecutionFramework& _framework): ContractInterface(_framework) {}
+ RegistrarInterface(SolidityExecutionFramework& _framework): ContractInterface(_framework) {}
void reserve(string const& _name)
{
callString("reserve", _name);
diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp
index 736015fa..39c32eb7 100644
--- a/test/contracts/FixedFeeRegistrar.cpp
+++ b/test/contracts/FixedFeeRegistrar.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -35,6 +35,7 @@
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
+using namespace dev::test;
namespace dev
{
@@ -125,14 +126,13 @@ contract FixedFeeRegistrar is Registrar {
static unique_ptr<bytes> s_compiledRegistrar;
-class RegistrarTestFramework: public ExecutionFramework
+class RegistrarTestFramework: public SolidityExecutionFramework
{
protected:
void deployRegistrar()
{
if (!s_compiledRegistrar)
{
- m_optimize = true;
m_compiler.reset(false);
m_compiler.addSource("", registrarCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp
index 4966b26c..80f06613 100644
--- a/test/contracts/Wallet.cpp
+++ b/test/contracts/Wallet.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -35,6 +35,7 @@
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
+using namespace dev::test;
namespace dev
{
@@ -435,7 +436,7 @@ contract Wallet is multisig, multiowned, daylimit {
static unique_ptr<bytes> s_compiledWallet;
-class WalletTestFramework: public ExecutionFramework
+class WalletTestFramework: public SolidityExecutionFramework
{
protected:
void deployWallet(
@@ -447,7 +448,6 @@ protected:
{
if (!s_compiledWallet)
{
- m_optimize = true;
m_compiler.reset(false);
m_compiler.addSource("", walletCode);
ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(m_optimize, m_optimizeRuns), "Compiling contract failed");
diff --git a/test/libdevcore/SwarmHash.cpp b/test/libdevcore/SwarmHash.cpp
index a23c36fd..7f3186ac 100644
--- a/test/libdevcore/SwarmHash.cpp
+++ b/test/libdevcore/SwarmHash.cpp
@@ -31,24 +31,24 @@ namespace test
BOOST_AUTO_TEST_SUITE(SwarmHash)
-string swarmHashHex(bytes const& _input)
+string swarmHashHex(string const& _input)
{
return toHex(swarmHash(_input).asBytes());
}
BOOST_AUTO_TEST_CASE(test_zeros)
{
- BOOST_CHECK_EQUAL(swarmHashHex(bytes()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000 - 1, 0)), string("32f0faabc4265ac238cd945087133ce3d7e9bb2e536053a812b5373c54043adb"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000, 0)), string("411dd45de7246e94589ff5888362c41e85bd3e582a92d0fda8f0e90b76439bec"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000 + 1, 0)), string("69754a0098432bbc2e84fe1205276870748a61a065ab6ef44d6a2e7b13ce044d"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000 - 1, 0)), string("69ad3c581043404f775ffa8d6f1b25ad4a9ee812971190e90209c0966116a321"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000, 0)), string("f00222373ff82d0a178dc6271c78953e9c88f74130a52d401f5ec51475f63c43"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000 + 1, 0)), string("86d6773e79e02fd8145ee1aedba89ace0c15f2566db1249654000039a9a134bf"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x80000, 0)), string("cc0854fe2c6b98e920d5c14b1a88e6d4223e55b8f78883f60939aa2485e361bf"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x80020, 0)), string("ee9ffca246e70d3704740ba4df450fa6988d14a1c2439c7e734c7a77a4eb6fd3"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x800020, 0)), string("78b90b20c90559fb904535181a7c28929ea2f30a2329dbc25232de579709f12f"));
- BOOST_CHECK_EQUAL(swarmHashHex(bytes(2095104, 0)), string("a9958184589fc11b4027a4c233e777ebe2e99c66f96b74aef2a0638a94dd5439"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000 - 1, 0)), string("32f0faabc4265ac238cd945087133ce3d7e9bb2e536053a812b5373c54043adb"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000, 0)), string("411dd45de7246e94589ff5888362c41e85bd3e582a92d0fda8f0e90b76439bec"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000 + 1, 0)), string("69754a0098432bbc2e84fe1205276870748a61a065ab6ef44d6a2e7b13ce044d"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000 - 1, 0)), string("69ad3c581043404f775ffa8d6f1b25ad4a9ee812971190e90209c0966116a321"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000, 0)), string("f00222373ff82d0a178dc6271c78953e9c88f74130a52d401f5ec51475f63c43"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000 + 1, 0)), string("86d6773e79e02fd8145ee1aedba89ace0c15f2566db1249654000039a9a134bf"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x80000, 0)), string("cc0854fe2c6b98e920d5c14b1a88e6d4223e55b8f78883f60939aa2485e361bf"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x80020, 0)), string("ee9ffca246e70d3704740ba4df450fa6988d14a1c2439c7e734c7a77a4eb6fd3"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(0x800020, 0)), string("78b90b20c90559fb904535181a7c28929ea2f30a2329dbc25232de579709f12f"));
+ BOOST_CHECK_EQUAL(swarmHashHex(string(2095104, 0)), string("a9958184589fc11b4027a4c233e777ebe2e99c66f96b74aef2a0638a94dd5439"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libevmasm/SourceLocation.cpp b/test/libevmasm/SourceLocation.cpp
index 64237a4e..6889b3e6 100644
--- a/test/libevmasm/SourceLocation.cpp
+++ b/test/libevmasm/SourceLocation.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Yoichi Hirai <yoichi@ethereum.org>
diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp
new file mode 100644
index 00000000..77c1f740
--- /dev/null
+++ b/test/liblll/EndToEndTest.cpp
@@ -0,0 +1,279 @@
+/*
+ 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 Alex Beregszaszi
+ * @date 2016
+ * End to end tests for LLL.
+ */
+
+#include <string>
+#include <memory>
+#include <boost/test/unit_test.hpp>
+#include <test/liblll/ExecutionFramework.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace lll
+{
+namespace test
+{
+
+BOOST_FIXTURE_TEST_SUITE(LLLEndToEndTest, LLLExecutionFramework)
+
+BOOST_AUTO_TEST_CASE(smoke_test)
+{
+ char const* sourceCode = "(returnlll { (return \"test\") })";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(string("test", 4)));
+}
+
+BOOST_AUTO_TEST_CASE(bare_panic)
+{
+ char const* sourceCode = "(panic)";
+ compileAndRunWithoutCheck(sourceCode);
+ BOOST_REQUIRE(m_output.empty());
+}
+
+BOOST_AUTO_TEST_CASE(exp_operator_const)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (return (exp 2 3)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == toBigEndian(u256(8)));
+}
+
+BOOST_AUTO_TEST_CASE(exp_operator_const_signed)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (return (exp (- 0 2) 3)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == toBigEndian(u256(-8)));
+}
+
+BOOST_AUTO_TEST_CASE(exp_operator_on_range)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (when (= (div (calldataload 0x00) (exp 2 224)) 0xb3de648b)
+ (return (exp 2 (calldataload 0x04))))
+ (jump 0x02)))
+ )";
+ compileAndRun(sourceCode);
+ testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to<int>()); }, 0, 16);
+}
+
+BOOST_AUTO_TEST_CASE(constructor_argument_internal_numeric)
+{
+ char const* sourceCode = R"(
+ (seq
+ (sstore 0x00 65535)
+ (returnlll
+ (return @@0x00)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(u256(65535)));
+}
+
+BOOST_AUTO_TEST_CASE(constructor_argument_internal_string)
+{
+ char const* sourceCode = R"(
+ (seq
+ (sstore 0x00 "test")
+ (returnlll
+ (return @@0x00)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs("test"));
+}
+
+BOOST_AUTO_TEST_CASE(constructor_arguments_external)
+{
+ char const* sourceCode = R"(
+ (seq
+ (codecopy 0x00 (bytecodesize) 64)
+ (sstore 0x00 @0x00)
+ (sstore 0x01 @0x20)
+ (returnlll
+ (seq
+ (when (= (div (calldataload 0x00) (exp 2 224)) 0xf2c9ecd8)
+ (return @@0x00))
+ (when (= (div (calldataload 0x00) (exp 2 224)) 0x89ea642f)
+ (return @@0x01)))))
+ )";
+ compileAndRun(sourceCode, 0, "", encodeArgs(u256(65535), "test"));
+ BOOST_CHECK(callContractFunction("getNumber()") == encodeArgs(u256(65535)));
+ BOOST_CHECK(callContractFunction("getString()") == encodeArgs("test"));
+}
+
+BOOST_AUTO_TEST_CASE(fallback_and_invalid_function)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (when (= (div (calldataload 0x00) (exp 2 224)) 0xab5ed150)
+ (return "one"))
+ (when (= (div (calldataload 0x00) (exp 2 224)) 0xee784123)
+ (return "two"))
+ (return "three")))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("getOne()") == encodeArgs("one"));
+ BOOST_CHECK(callContractFunction("getTwo()") == encodeArgs("two"));
+ BOOST_CHECK(callContractFunction("invalidFunction()") == encodeArgs("three"));
+ BOOST_CHECK(callFallback() == encodeArgs("three"));
+}
+
+BOOST_AUTO_TEST_CASE(lit_string)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (lit 0x00 "abcdef")
+ (return 0x00 0x20)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(string("abcdef")));
+}
+
+BOOST_AUTO_TEST_CASE(arithmetic)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (mstore8 0x00 (+ 160 22))
+ (mstore8 0x01 (- 223 41))
+ (mstore8 0x02 (* 33 2))
+ (mstore8 0x03 (/ 10 2))
+ (mstore8 0x04 (% 67 2))
+ (mstore8 0x05 (& 15 8))
+ (mstore8 0x06 (| 18 8))
+ (mstore8 0x07 (^ 26 6))
+ (return 0x00 0x20)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(
+ fromHex("b6b6420501081a1c000000000000000000000000000000000000000000000000")));
+}
+
+BOOST_AUTO_TEST_CASE(binary)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (mstore8 0x00 (< 53 87))
+ (mstore8 0x01 (< 73 42))
+ (mstore8 0x02 (<= 37 94))
+ (mstore8 0x03 (<= 37 37))
+ (mstore8 0x04 (<= 183 34))
+ (mstore8 0x05 (S< (- 0 53) 87))
+ (mstore8 0x06 (S< 73 (- 0 42)))
+ (mstore8 0x07 (S<= (- 0 37) 94))
+ (mstore8 0x08 (S<= (- 0 37) (- 0 37)))
+ (mstore8 0x09 (S<= 183 (- 0 34)))
+ (mstore8 0x0a (> 73 42))
+ (mstore8 0x0b (> 53 87))
+ (mstore8 0x0c (>= 94 37))
+ (mstore8 0x0d (>= 94 94))
+ (mstore8 0x0e (>= 34 183))
+ (mstore8 0x0f (S> 73 (- 0 42)))
+ (mstore8 0x10 (S> (- 0 53) 87))
+ (mstore8 0x11 (S>= 94 (- 0 37)))
+ (mstore8 0x12 (S>= (- 0 94) (- 0 94)))
+ (mstore8 0x13 (S>= (- 0 34) 183))
+ (mstore8 0x14 (= 53 53))
+ (mstore8 0x15 (= 73 42))
+ (mstore8 0x16 (!= 37 94))
+ (mstore8 0x17 (!= 37 37))
+ (return 0x00 0x20)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(
+ fromHex("0100010100010001010001000101000100010100010001000000000000000000")));
+}
+
+BOOST_AUTO_TEST_CASE(unary)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (mstore8 0x00 (! (< 53 87)))
+ (mstore8 0x01 (! (>= 42 73)))
+ (mstore8 0x02 (~ 0x7f))
+ (mstore8 0x03 (~ 0xaa))
+ (return 0x00 0x20)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(
+ fromHex("0001805500000000000000000000000000000000000000000000000000000000")));
+}
+
+BOOST_AUTO_TEST_CASE(assembly_mload_mstore)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (asm
+ 0x07 0x00 mstore
+ "abcdef" 0x20 mstore
+ 0x00 mload 0x40 mstore
+ 0x20 mload 0x60 mstore
+ 0x40 0x40 return))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(u256(7), string("abcdef")));
+}
+
+BOOST_AUTO_TEST_CASE(assembly_sload_sstore)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (asm
+ 0x07 0x00 sstore
+ "abcdef" 0x01 sstore
+ 0x00 sload 0x00 mstore
+ 0x01 sload 0x20 mstore
+ 0x40 0x00 return))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(u256(7), string("abcdef")));
+}
+
+BOOST_AUTO_TEST_CASE(assembly_codecopy)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (lit 0x00 "abcdef")
+ (asm
+ 0x06 0x16 0x20 codecopy
+ 0x20 0x20 return)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == encodeArgs(string("abcdef")));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/liblll/ExecutionFramework.cpp b/test/liblll/ExecutionFramework.cpp
new file mode 100644
index 00000000..4719c5f5
--- /dev/null
+++ b/test/liblll/ExecutionFramework.cpp
@@ -0,0 +1,33 @@
+/*
+ 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 Alex Beregszaszi
+ * @date 2016
+ * Framework for executing LLL contracts and testing them via RPC.
+ */
+
+#include <cstdlib>
+#include <boost/test/framework.hpp>
+#include <test/liblll/ExecutionFramework.h>
+
+using namespace dev::test;
+using namespace dev::lll::test;
+
+LLLExecutionFramework::LLLExecutionFramework() :
+ ExecutionFramework()
+{
+}
diff --git a/test/liblll/ExecutionFramework.h b/test/liblll/ExecutionFramework.h
new file mode 100644
index 00000000..58e1f0ad
--- /dev/null
+++ b/test/liblll/ExecutionFramework.h
@@ -0,0 +1,73 @@
+/*
+ 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 Alex Beregszaszi
+ * @date 2016
+ * Framework for executing LLL contracts and testing them via RPC.
+ */
+
+#pragma once
+
+#include <functional>
+
+#include "../ExecutionFramework.h"
+
+#include <liblll/Compiler.h>
+
+using namespace dev::test;
+
+namespace dev
+{
+namespace lll
+{
+
+namespace test
+{
+
+class LLLExecutionFramework: public ExecutionFramework
+{
+
+public:
+ LLLExecutionFramework();
+
+ virtual bytes const& compileAndRunWithoutCheck(
+ std::string const& _sourceCode,
+ u256 const& _value = 0,
+ std::string const& _contractName = "",
+ bytes const& _arguments = bytes(),
+ std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>()
+ ) override
+ {
+ BOOST_REQUIRE(_contractName.empty());
+ BOOST_REQUIRE(_libraryAddresses.empty());
+
+ std::vector<std::string> errors;
+ bytes bytecode = eth::compileLLL(_sourceCode, m_optimize, &errors);
+ if (!errors.empty())
+ {
+ for (auto const& error: errors)
+ std::cerr << error << std::endl;
+ BOOST_ERROR("Compiling contract failed");
+ }
+ sendMessage(bytecode + _arguments, true, _value);
+ return m_output;
+ }
+};
+
+}
+}
+} // end namespaces
diff --git a/test/liblll/Parser.cpp b/test/liblll/Parser.cpp
new file mode 100644
index 00000000..0d5d9ea5
--- /dev/null
+++ b/test/liblll/Parser.cpp
@@ -0,0 +1,181 @@
+/*
+ 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 Alex Beregszaszi
+ * @date 2016
+ * Unit tests for the LLL parser.
+ */
+
+#include <string>
+#include <memory>
+#include <boost/test/unit_test.hpp>
+#include <liblll/Compiler.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace lll
+{
+namespace test
+{
+
+namespace
+{
+
+bool successParse(std::string const& _source)
+{
+ std::string ret = eth::parseLLL(_source);
+ return ret.size() != 0;
+}
+
+std::string parse(std::string const& _source)
+{
+ return eth::parseLLL(_source);
+}
+
+}
+
+BOOST_AUTO_TEST_SUITE(LLLParser)
+
+BOOST_AUTO_TEST_CASE(smoke_test)
+{
+ char const* text = "1";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(string)
+{
+ char const* text = "\"string\"";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"("string")");
+}
+
+BOOST_AUTO_TEST_CASE(symbol)
+{
+ char const* text = "symbol";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"(symbol)");
+
+ BOOST_CHECK(successParse("'symbol"));
+ BOOST_CHECK_EQUAL(parse(text), R"(symbol)");
+}
+
+BOOST_AUTO_TEST_CASE(decimals)
+{
+ char const* text = "1234";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"(1234)");
+}
+
+BOOST_AUTO_TEST_CASE(hexadecimals)
+{
+ char const* text = "0x1234";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"(4660)");
+
+ BOOST_CHECK(!successParse("0x"));
+}
+
+BOOST_AUTO_TEST_CASE(sequence)
+{
+ char const* text = "{ 1234 }";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"({ 1234 })");
+}
+
+BOOST_AUTO_TEST_CASE(empty_sequence)
+{
+ char const* text = "{}";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"({ })");
+}
+
+BOOST_AUTO_TEST_CASE(mload)
+{
+ char const* text = "@0";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"(@ 0)");
+
+ BOOST_CHECK(successParse("@0x0"));
+ BOOST_CHECK(successParse("@symbol"));
+ BOOST_CHECK(!successParse("@"));
+}
+
+BOOST_AUTO_TEST_CASE(sload)
+{
+ char const* text = "@@0";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"(@@ 0)");
+
+ BOOST_CHECK(successParse("@@0x0"));
+ BOOST_CHECK(successParse("@@symbol"));
+ BOOST_CHECK(!successParse("@@"));
+}
+
+BOOST_AUTO_TEST_CASE(mstore)
+{
+ char const* text = "[0]:0";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"([ 0 ] 0)");
+
+ BOOST_CHECK(successParse("[0] 0"));
+ BOOST_CHECK(successParse("[0x0]:0x0"));
+ BOOST_CHECK(successParse("[symbol]:symbol"));
+ BOOST_CHECK(!successParse("[]"));
+ BOOST_CHECK(!successParse("[0]"));
+}
+
+BOOST_AUTO_TEST_CASE(sstore)
+{
+ char const* text = "[[0]]:0";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"([[ 0 ]] 0)");
+
+ BOOST_CHECK(successParse("[[0]] 0"));
+ BOOST_CHECK(successParse("[[0x0]]:0x0"));
+ BOOST_CHECK(successParse("[[symbol]]:symbol"));
+ BOOST_CHECK(!successParse("[[]]"));
+ BOOST_CHECK(!successParse("[[0x0]]"));
+}
+
+BOOST_AUTO_TEST_CASE(calldataload)
+{
+ char const* text = "$0";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"($ 0)");
+
+ BOOST_CHECK(successParse("$0x0"));
+ BOOST_CHECK(successParse("$symbol"));
+ BOOST_CHECK(!successParse("$"));
+}
+
+BOOST_AUTO_TEST_CASE(list)
+{
+ char const* text = "( 1234 )";
+ BOOST_CHECK(successParse(text));
+ BOOST_CHECK_EQUAL(parse(text), R"(( 1234 ))");
+
+ BOOST_CHECK(successParse("( 1234 5467 )"));
+ BOOST_CHECK(!successParse("()"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp
index b88218e7..0972ce82 100644
--- a/test/libsolidity/ASTJSON.cpp
+++ b/test/libsolidity/ASTJSON.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp
index e5ce691b..155dd5c9 100644
--- a/test/libsolidity/Assembly.cpp
+++ b/test/libsolidity/Assembly.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris Karapetsas <lefteris@ethdev.com>
@@ -75,7 +75,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode)
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
{
Compiler compiler;
- compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{});
+ compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, bytes());
return compiler.runtimeAssemblyItems();
}
@@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(location_test)
shared_ptr<string const> n = make_shared<string>("");
AssemblyItems items = compileContract(sourceCode);
vector<SourceLocation> locations =
- vector<SourceLocation>(16, SourceLocation(2, 75, n)) +
+ vector<SourceLocation>(18, SourceLocation(2, 75, n)) +
vector<SourceLocation>(27, SourceLocation(20, 72, n)) +
vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} +
vector<SourceLocation>(2, SourceLocation(58, 67, n)) +
diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp
new file mode 100644
index 00000000..75555c9b
--- /dev/null
+++ b/test/libsolidity/ErrorCheck.cpp
@@ -0,0 +1,34 @@
+/*
+ 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/>.
+*/
+/** @file ErrorCheck.cpp
+ * @author Yoichi Hirai <i@yoichihirai.com>
+ * @date 2016
+ */
+
+#include <test/libsolidity/ErrorCheck.h>
+#include <libdevcore/Exceptions.h>
+
+#include <string>
+
+using namespace std;
+
+bool dev::solidity::searchErrorMessage(Error const& _err, std::string const& _substr)
+{
+ if (string const* errorMessage = boost::get_error_info<dev::errinfo_comment>(_err))
+ return errorMessage->find(_substr) != std::string::npos;
+ return _substr.empty();
+}
diff --git a/test/libsolidity/ErrorCheck.h b/test/libsolidity/ErrorCheck.h
new file mode 100644
index 00000000..a309a9d3
--- /dev/null
+++ b/test/libsolidity/ErrorCheck.h
@@ -0,0 +1,32 @@
+/*
+ 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/>.
+*/
+/** @file ErrorCheck.h
+ * @author Yoichi Hirai <i@yoichihirai.com>
+ * @date 2016
+ */
+
+#pragma once
+
+#include <libsolidity/interface/Exceptions.h>
+
+namespace dev
+{
+namespace solidity
+{
+bool searchErrorMessage(Error const& _err, std::string const& _substr);
+}
+}
diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp
index fc103393..0671fb15 100644
--- a/test/libsolidity/GasMeter.cpp
+++ b/test/libsolidity/GasMeter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -32,6 +32,7 @@
using namespace std;
using namespace dev::eth;
using namespace dev::solidity;
+using namespace dev::test;
namespace dev
{
@@ -40,7 +41,7 @@ namespace solidity
namespace test
{
-class GasMeterTestFramework: public ExecutionFramework
+class GasMeterTestFramework: public SolidityExecutionFramework
{
public:
GasMeterTestFramework() { }
diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp
index 1a9e16cc..bc6adc26 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index 185a6215..64073edc 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp
index 80bdf16f..08ef5277 100644
--- a/test/libsolidity/SemVerMatcher.cpp
+++ b/test/libsolidity/SemVerMatcher.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <chris@ethereum.org>
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index a8a39b0b..043d74ed 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Marek Kotewicz <marek@ethdev.com>
@@ -22,8 +22,11 @@
#include "../TestHelper.h"
#include <libsolidity/interface/CompilerStack.h>
-#include <json/json.h>
+
#include <libdevcore/Exceptions.h>
+#include <libdevcore/SwarmHash.h>
+
+#include <json/json.h>
namespace dev
{
@@ -51,7 +54,7 @@ public:
);
}
-private:
+protected:
CompilerStack m_compilerStack;
Json::Reader m_reader;
};
@@ -60,9 +63,11 @@ BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, JSONInterfaceChecker)
BOOST_AUTO_TEST_CASE(basic_test)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a) returns(uint d) { return a * 7; }
+ }
+ )";
char const* interface = R"([
{
@@ -90,8 +95,9 @@ BOOST_AUTO_TEST_CASE(basic_test)
BOOST_AUTO_TEST_CASE(empty_contract)
{
- char const* sourceCode = "contract test {\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test { }
+ )";
char const* interface = "[]";
checkInterface(sourceCode, interface);
@@ -99,10 +105,12 @@ BOOST_AUTO_TEST_CASE(empty_contract)
BOOST_AUTO_TEST_CASE(multiple_methods)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- " function g(uint b) returns(uint e) { return b * 8; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a) returns(uint d) { return a * 7; }
+ function g(uint b) returns(uint e) { return b * 8; }
+ }
+ )";
char const* interface = R"([
{
@@ -148,9 +156,11 @@ BOOST_AUTO_TEST_CASE(multiple_methods)
BOOST_AUTO_TEST_CASE(multiple_params)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a, uint b) returns(uint d) { return a + b; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a, uint b) returns(uint d) { return a + b; }
+ }
+ )";
char const* interface = R"([
{
@@ -183,10 +193,12 @@ BOOST_AUTO_TEST_CASE(multiple_params)
BOOST_AUTO_TEST_CASE(multiple_methods_order)
{
// methods are expected to be in alpabetical order
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- " function c(uint b) returns(uint e) { return b * 8; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a) returns(uint d) { return a * 7; }
+ function c(uint b) returns(uint e) { return b * 8; }
+ }
+ )";
char const* interface = R"([
{
@@ -232,10 +244,12 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
BOOST_AUTO_TEST_CASE(const_function)
{
- char const* sourceCode = "contract test {\n"
- " function foo(uint a, uint b) returns(uint d) { return a + b; }\n"
- " function boo(uint32 a) constant returns(uint b) { return a * 4; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function foo(uint a, uint b) returns(uint d) { return a + b; }
+ function boo(uint32 a) constant returns(uint b) { return a * 4; }
+ }
+ )";
char const* interface = R"([
{
@@ -283,11 +297,13 @@ BOOST_AUTO_TEST_CASE(const_function)
BOOST_AUTO_TEST_CASE(events)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- " event e1(uint b, address indexed c); \n"
- " event e2(); \n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a) returns(uint d) { return a * 7; }
+ event e1(uint b, address indexed c);
+ event e2();
+ }
+ )";
char const* interface = R"([
{
"name": "f",
@@ -338,9 +354,11 @@ BOOST_AUTO_TEST_CASE(events)
BOOST_AUTO_TEST_CASE(events_anonymous)
{
- char const* sourceCode = "contract test {\n"
- " event e() anonymous; \n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ event e() anonymous;
+ }
+ )";
char const* interface = R"([
{
"name": "e",
@@ -356,15 +374,16 @@ BOOST_AUTO_TEST_CASE(events_anonymous)
BOOST_AUTO_TEST_CASE(inherited)
{
- char const* sourceCode =
- " contract Base { \n"
- " function baseFunction(uint p) returns (uint i) { return p; } \n"
- " event baseEvent(bytes32 indexed evtArgBase); \n"
- " } \n"
- " contract Derived is Base { \n"
- " function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } \n"
- " event derivedEvent(uint indexed evtArgDerived); \n"
- " }";
+ char const* sourceCode = R"(
+ contract Base {
+ function baseFunction(uint p) returns (uint i) { return p; }
+ event baseEvent(bytes32 indexed evtArgBase);
+ }
+ contract Derived is Base {
+ function derivedFunction(bytes32 p) returns (bytes32 i) { return p; }
+ event derivedEvent(uint indexed evtArgDerived);
+ }
+ )";
char const* interface = R"([
{
@@ -428,13 +447,14 @@ BOOST_AUTO_TEST_CASE(inherited)
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* sourceCode = R"(
- contract test {
- function f(uint, uint k) returns(uint ret_k, uint ret_g){
- uint g = 8;
- ret_k = k;
- ret_g = g;
+ contract test {
+ function f(uint, uint k) returns(uint ret_k, uint ret_g) {
+ uint g = 8;
+ ret_k = k;
+ ret_g = g;
+ }
}
- })";
+ )";
char const* interface = R"([
{
@@ -472,10 +492,11 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* sourceCode = R"(
contract test {
- function f(uint k) returns(uint){
- return k;
+ function f(uint k) returns(uint) {
+ return k;
+ }
}
- })";
+ )";
char const* interface = R"([
{
@@ -539,7 +560,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi)
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
function test(ActionChoices param) {}
- function ret() returns(ActionChoices){
+ function ret() returns(ActionChoices) {
ActionChoices action = ActionChoices.GoLeft;
return action;
}
@@ -609,7 +630,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) returns (uint[] e, StructType storage f){}
+ function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f) {}
}
)";
@@ -731,6 +752,26 @@ BOOST_AUTO_TEST_CASE(function_type)
checkInterface(sourceCode, interface);
}
+BOOST_AUTO_TEST_CASE(metadata_stamp)
+{
+ // Check that the metadata stamp is at the end of the runtime bytecode.
+ char const* sourceCode = R"(
+ pragma solidity >=0.0;
+ contract test {
+ function g(function(uint) external returns (uint) x) {}
+ }
+ )";
+ BOOST_REQUIRE(m_compilerStack.compile(std::string(sourceCode)));
+ bytes const& bytecode = m_compilerStack.runtimeObject("test").bytecode;
+ bytes hash = dev::swarmHash(m_compilerStack.onChainMetadata("test")).asBytes();
+ BOOST_REQUIRE(hash.size() == 32);
+ BOOST_REQUIRE(bytecode.size() >= 2);
+ size_t metadataCBORSize = (size_t(bytecode.end()[-2]) << 8) + size_t(bytecode.end()[-1]);
+ BOOST_REQUIRE(metadataCBORSize < bytecode.size() - 2);
+ bytes expectation = bytes{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} + hash;
+ BOOST_CHECK(std::equal(expectation.begin(), expectation.end(), bytecode.end() - metadataCBORSize - 2));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 4abe0894..94d4fb7f 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -25,11 +25,13 @@
#include <string>
#include <tuple>
#include <boost/test/unit_test.hpp>
+#include <libevmasm/Assembly.h>
#include <libsolidity/interface/Exceptions.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
using namespace std;
using namespace std::placeholders;
+using namespace dev::test;
namespace dev
{
@@ -38,21 +40,24 @@ namespace solidity
namespace test
{
-BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, ExecutionFramework)
+BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityExecutionFramework)
BOOST_AUTO_TEST_CASE(smoke_test)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) returns(uint d) { return a * 7; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a) returns(uint d) { return a * 7; }
+ }
+ )";
compileAndRun(sourceCode);
- testSolidityAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100);
+ testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100);
}
BOOST_AUTO_TEST_CASE(empty_contract)
{
- char const* sourceCode = "contract test {\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test { }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()).empty());
}
@@ -62,9 +67,10 @@ BOOST_AUTO_TEST_CASE(exp_operator)
char const* sourceCode = R"(
contract test {
function f(uint a) returns(uint d) { return 2 ** a; }
- })";
+ }
+ )";
compileAndRun(sourceCode);
- testSolidityAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to<int>()); }, 0, 16);
+ testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to<int>()); }, 0, 16);
}
BOOST_AUTO_TEST_CASE(exp_operator_const)
@@ -72,7 +78,8 @@ BOOST_AUTO_TEST_CASE(exp_operator_const)
char const* sourceCode = R"(
contract test {
function f() returns(uint d) { return 2 ** 3; }
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(8)));
}
@@ -82,7 +89,8 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed)
char const* sourceCode = R"(
contract test {
function f() returns(int d) { return (-2) ** 3; }
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(-8)));
}
@@ -93,8 +101,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_true_literal)
contract test {
function f() returns(uint d) {
return true ? 5 : 10;
- }
- })";
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(5)));
}
@@ -105,8 +114,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_false_literal)
contract test {
function f() returns(uint d) {
return false ? 5 : 10;
- }
- })";
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(10)));
}
@@ -116,12 +126,13 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple)
char const* sourceCode = R"(
contract test {
function f(uint x) returns(uint d) {
- return x > 100 ?
+ return x > 100 ?
x > 1000 ? 1000 : 100
:
x > 50 ? 50 : 10;
- }
- })";
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256)", u256(1001)) == toBigEndian(u256(1000)));
BOOST_CHECK(callContractFunction("f(uint256)", u256(500)) == toBigEndian(u256(100)));
@@ -135,7 +146,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values)
contract test {
function f(bool cond, uint v) returns (uint a, uint b) {
cond ? a = v : b = v;
- }
+ }
})";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)) == encodeArgs(u256(20), u256(0)));
@@ -167,7 +178,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1)
}
return ret;
- }
+ }
}
)";
compileAndRun(sourceCode);
@@ -201,7 +212,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2)
}
return ret;
- }
+ }
}
)";
compileAndRun(sourceCode);
@@ -217,7 +228,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_different_types)
uint8 x = 0xcd;
uint16 y = 0xabab;
return cond ? x : y;
- }
+ }
}
)";
compileAndRun(sourceCode);
@@ -275,12 +286,14 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions)
BOOST_AUTO_TEST_CASE(recursive_calls)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint n) returns(uint nfac) {\n"
- " if (n <= 1) return 1;\n"
- " else return n * f(n - 1);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint n) returns(uint nfac) {
+ if (n <= 1) return 1;
+ else return n * f(n - 1);
+ }
+ }
+ )";
compileAndRun(sourceCode);
function<u256(u256)> recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256
{
@@ -290,17 +303,19 @@ BOOST_AUTO_TEST_CASE(recursive_calls)
return n * recursive_calls_cpp(n - 1);
};
- testSolidityAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5);
+ testContractAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5);
}
BOOST_AUTO_TEST_CASE(multiple_functions)
{
- char const* sourceCode = "contract test {\n"
- " function a() returns(uint n) { return 0; }\n"
- " function b() returns(uint n) { return 1; }\n"
- " function c() returns(uint n) { return 2; }\n"
- " function f() returns(uint n) { return 3; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a() returns(uint n) { return 0; }
+ function b() returns(uint n) { return 1; }
+ function c() returns(uint n) { return 2; }
+ function f() returns(uint n) { return 3; }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("a()", bytes()) == toBigEndian(u256(0)));
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(1)));
@@ -311,33 +326,39 @@ BOOST_AUTO_TEST_CASE(multiple_functions)
BOOST_AUTO_TEST_CASE(named_args)
{
- char const* sourceCode = "contract test {\n"
- " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
- " function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }
+ function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123)));
}
BOOST_AUTO_TEST_CASE(disorder_named_args)
{
- char const* sourceCode = "contract test {\n"
- " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
- " function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }
+ function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123)));
}
BOOST_AUTO_TEST_CASE(while_loop)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint n) returns(uint nfac) {\n"
- " nfac = 1;\n"
- " var i = 2;\n"
- " while (i <= n) nfac *= i++;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint n) returns(uint nfac) {
+ nfac = 1;
+ var i = 2;
+ while (i <= n) nfac *= i++;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto while_loop_cpp = [](u256 const& n) -> u256
@@ -350,19 +371,21 @@ BOOST_AUTO_TEST_CASE(while_loop)
return nfac;
};
- testSolidityAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5);
+ testContractAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5);
}
BOOST_AUTO_TEST_CASE(do_while_loop)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint n) returns(uint nfac) {\n"
- " nfac = 1;\n"
- " var i = 2;\n"
- " do { nfac *= i++; } while (i <= n);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint n) returns(uint nfac) {
+ nfac = 1;
+ var i = 2;
+ do { nfac *= i++; } while (i <= n);
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto do_while_loop_cpp = [](u256 const& n) -> u256
@@ -378,32 +401,34 @@ BOOST_AUTO_TEST_CASE(do_while_loop)
return nfac;
};
- testSolidityAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5);
+ testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5);
}
BOOST_AUTO_TEST_CASE(nested_loops)
{
// tests that break and continue statements in nested loops jump to the correct place
- char const* sourceCode = "contract test {\n"
- " function f(uint x) returns(uint y) {\n"
- " while (x > 1) {\n"
- " if (x == 10) break;\n"
- " while (x > 5) {\n"
- " if (x == 8) break;\n"
- " x--;\n"
- " if (x == 6) continue;\n"
- " return x;\n"
- " }\n"
- " x--;\n"
- " if (x == 3) continue;\n"
- " break;\n"
- " }\n"
- " return x;\n"
- " }\n"
- "}\n";
- compileAndRun(sourceCode);
-
- auto nested_loops_cpp = [](u256 n) -> u256
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint x) returns(uint y) {
+ while (x > 1) {
+ if (x == 10) break;
+ while (x > 5) {
+ if (x == 8) break;
+ x--;
+ if (x == 6) continue;
+ return x;
+ }
+ x--;
+ if (x == 3) continue;
+ break;
+ }
+ return x;
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+
+ auto nested_loops_cpp = [](u256 n) -> u256
{
while (n > 1)
{
@@ -427,18 +452,20 @@ BOOST_AUTO_TEST_CASE(nested_loops)
return n;
};
- testSolidityAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12);
+ testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12);
}
BOOST_AUTO_TEST_CASE(for_loop)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint n) returns(uint nfac) {\n"
- " nfac = 1;\n"
- " for (var i = 2; i <= n; i++)\n"
- " nfac *= i;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint n) returns(uint nfac) {
+ nfac = 1;
+ for (var i = 2; i <= n; i++)
+ nfac *= i;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto for_loop_cpp = [](u256 const& n) -> u256
@@ -449,21 +476,22 @@ BOOST_AUTO_TEST_CASE(for_loop)
return nfac;
};
- testSolidityAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5);
+ testContractAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5);
}
BOOST_AUTO_TEST_CASE(for_loop_empty)
{
- char const* sourceCode = "contract test {\n"
- " function f() returns(uint ret) {\n"
- " ret = 1;\n"
- " for (;;)\n"
- " {\n"
- " ret += 1;\n"
- " if (ret >= 10) break;\n"
- " }\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() returns(uint ret) {
+ ret = 1;
+ for (;;) {
+ ret += 1;
+ if (ret >= 10) break;
+ }
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto for_loop_empty_cpp = []() -> u256
@@ -477,19 +505,21 @@ BOOST_AUTO_TEST_CASE(for_loop_empty)
return ret;
};
- testSolidityAgainstCpp("f()", for_loop_empty_cpp);
+ testContractAgainstCpp("f()", for_loop_empty_cpp);
}
BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint n) returns(uint nfac) {\n"
- " nfac = 1;\n"
- " uint256 i;\n"
- " for (i = 2; i <= n; i++)\n"
- " nfac *= i;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint n) returns(uint nfac) {
+ nfac = 1;
+ uint256 i;
+ for (i = 2; i <= n; i++)
+ nfac *= i;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto for_loop_simple_init_expr_cpp = [](u256 const& n) -> u256
@@ -501,7 +531,7 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr)
return nfac;
};
- testSolidityAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5);
+ testContractAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5);
}
BOOST_AUTO_TEST_CASE(for_loop_break_continue)
@@ -547,25 +577,27 @@ BOOST_AUTO_TEST_CASE(for_loop_break_continue)
return i;
};
- testSolidityAgainstCppOnRange("f(uint256)", breakContinue, 0, 10);
+ testContractAgainstCppOnRange("f(uint256)", breakContinue, 0, 10);
}
BOOST_AUTO_TEST_CASE(calling_other_functions)
{
- char const* sourceCode = "contract collatz {\n"
- " function run(uint x) returns(uint y) {\n"
- " while ((y = x) > 1) {\n"
- " if (x % 2 == 0) x = evenStep(x);\n"
- " else x = oddStep(x);\n"
- " }\n"
- " }\n"
- " function evenStep(uint x) returns(uint y) {\n"
- " return x / 2;\n"
- " }\n"
- " function oddStep(uint x) returns(uint y) {\n"
- " return 3 * x + 1;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract collatz {
+ function run(uint x) returns(uint y) {
+ while ((y = x) > 1) {
+ if (x % 2 == 0) x = evenStep(x);
+ else x = oddStep(x);
+ }
+ }
+ function evenStep(uint x) returns(uint y) {
+ return x / 2;
+ }
+ function oddStep(uint x) returns(uint y) {
+ return 3 * x + 1;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto evenStep_cpp = [](u256 const& n) -> u256
@@ -591,22 +623,24 @@ BOOST_AUTO_TEST_CASE(calling_other_functions)
return y;
};
- testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(0));
- testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(1));
- testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(2));
- testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(8));
- testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(127));
+ testContractAgainstCpp("run(uint256)", collatz_cpp, u256(0));
+ testContractAgainstCpp("run(uint256)", collatz_cpp, u256(1));
+ testContractAgainstCpp("run(uint256)", collatz_cpp, u256(2));
+ testContractAgainstCpp("run(uint256)", collatz_cpp, u256(8));
+ testContractAgainstCpp("run(uint256)", collatz_cpp, u256(127));
}
BOOST_AUTO_TEST_CASE(many_local_variables)
{
- char const* sourceCode = "contract test {\n"
- " function run(uint x1, uint x2, uint x3) returns(uint y) {\n"
- " var a = 0x1; var b = 0x10; var c = 0x100;\n"
- " y = a + b + c + x1 + x2 + x3;\n"
- " y += b + x2;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run(uint x1, uint x2, uint x3) returns(uint y) {
+ var a = 0x1; var b = 0x10; var c = 0x100;
+ y = a + b + c + x1 + x2 + x3;
+ y += b + x2;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256
{
@@ -616,18 +650,20 @@ BOOST_AUTO_TEST_CASE(many_local_variables)
u256 y = a + b + c + x1 + x2 + x3;
return y + b + x2;
};
- testSolidityAgainstCpp("run(uint256,uint256,uint256)", f, u256(0x1000), u256(0x10000), u256(0x100000));
+ testContractAgainstCpp("run(uint256,uint256,uint256)", f, u256(0x1000), u256(0x10000), u256(0x100000));
}
BOOST_AUTO_TEST_CASE(packing_unpacking_types)
{
- char const* sourceCode = "contract test {\n"
- " function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n"
- " if (a) y = 1;\n"
- " y = y * 0x100000000 | ~b;\n"
- " y = y * 0x10000000000000000 | ~c;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run(bool a, uint32 b, uint64 c) returns(uint256 y) {
+ if (a) y = 1;
+ y = y * 0x100000000 | ~b;
+ y = y * 0x10000000000000000 | ~c;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0"))
== fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f"));
@@ -635,12 +671,14 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types)
BOOST_AUTO_TEST_CASE(packing_signed_types)
{
- char const* sourceCode = "contract test {\n"
- " function run() returns(int8 y) {\n"
- " uint8 x = 0xfa;\n"
- " return int8(x);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run() returns(int8 y) {
+ uint8 x = 0xfa;
+ return int8(x);
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("run()")
== fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa"));
@@ -648,23 +686,27 @@ BOOST_AUTO_TEST_CASE(packing_signed_types)
BOOST_AUTO_TEST_CASE(multiple_return_values)
{
- char const* sourceCode = "contract test {\n"
- " function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) {\n"
- " y1 = x2; y2 = x1;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) {
+ y1 = x2; y2 = x1;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd) == encodeArgs(0xcd, true, 0));
}
BOOST_AUTO_TEST_CASE(short_circuiting)
{
- char const* sourceCode = "contract test {\n"
- " function run(uint x) returns(uint y) {\n"
- " x == 0 || ((x = 8) > 0);\n"
- " return x;"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run(uint x) returns(uint y) {
+ x == 0 || ((x = 8) > 0);
+ return x;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto short_circuiting_cpp = [](u256 n) -> u256
@@ -673,19 +715,21 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
return n;
};
- testSolidityAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2);
+ testContractAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2);
}
BOOST_AUTO_TEST_CASE(high_bits_cleaning)
{
- char const* sourceCode = "contract test {\n"
- " function run() returns(uint256 y) {\n"
- " uint32 t = uint32(0xffffffff);\n"
- " uint32 x = t + 10;\n"
- " if (x >= 0xffffffff) return 0;\n"
- " return x;"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run() returns(uint256 y) {
+ uint32 t = uint32(0xffffffff);
+ uint32 x = t + 10;
+ if (x >= 0xffffffff) return 0;
+ return x;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto high_bits_cleaning_cpp = []() -> u256
{
@@ -695,18 +739,20 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning)
return 0;
return x;
};
- testSolidityAgainstCpp("run()", high_bits_cleaning_cpp);
+ testContractAgainstCpp("run()", high_bits_cleaning_cpp);
}
BOOST_AUTO_TEST_CASE(sign_extension)
{
- char const* sourceCode = "contract test {\n"
- " function run() returns(uint256 y) {\n"
- " int64 x = -int32(0xff);\n"
- " if (x >= 0xff) return 0;\n"
- " return -uint256(x);"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run() returns(uint256 y) {
+ int64 x = -int32(0xff);
+ if (x >= 0xff) return 0;
+ return -uint256(x);
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto sign_extension_cpp = []() -> u256
{
@@ -715,18 +761,20 @@ BOOST_AUTO_TEST_CASE(sign_extension)
return 0;
return u256(x) * -1;
};
- testSolidityAgainstCpp("run()", sign_extension_cpp);
+ testContractAgainstCpp("run()", sign_extension_cpp);
}
BOOST_AUTO_TEST_CASE(small_unsigned_types)
{
- char const* sourceCode = "contract test {\n"
- " function run() returns(uint256 y) {\n"
- " uint32 t = uint32(0xffffff);\n"
- " uint32 x = t * 0xffffff;\n"
- " return x / 0x100;"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run() returns(uint256 y) {
+ uint32 t = uint32(0xffffff);
+ uint32 x = t * 0xffffff;
+ return x / 0x100;
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto small_unsigned_types_cpp = []() -> u256
{
@@ -734,35 +782,39 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types)
uint32_t x = t * 0xffffff;
return x / 0x100;
};
- testSolidityAgainstCpp("run()", small_unsigned_types_cpp);
+ testContractAgainstCpp("run()", small_unsigned_types_cpp);
}
BOOST_AUTO_TEST_CASE(small_signed_types)
{
- char const* sourceCode = "contract test {\n"
- " function run() returns(int256 y) {\n"
- " return -int32(10) * -int64(20);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function run() returns(int256 y) {
+ return -int32(10) * -int64(20);
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto small_signed_types_cpp = []() -> u256
{
return -int32_t(10) * -int64_t(20);
};
- testSolidityAgainstCpp("run()", small_signed_types_cpp);
+ testContractAgainstCpp("run()", small_signed_types_cpp);
}
BOOST_AUTO_TEST_CASE(strings)
{
- char const* sourceCode = "contract test {\n"
- " function fixedBytes() returns(bytes32 ret) {\n"
- " return \"abc\\x00\\xff__\";\n"
- " }\n"
- " function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) {\n"
- " oneRet = one;\n"
- " large = small;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function fixedBytes() returns(bytes32 ret) {
+ return "abc\x00\xff__";
+ }
+ function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) {
+ oneRet = one;
+ large = small;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("fixedBytes()") == encodeArgs(string("abc\0\xff__", 7)));
BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true));
@@ -807,18 +859,20 @@ BOOST_AUTO_TEST_CASE(bytes_comparison)
BOOST_AUTO_TEST_CASE(state_smoke_test)
{
- char const* sourceCode = "contract test {\n"
- " uint256 value1;\n"
- " uint256 value2;\n"
- " function get(uint8 which) returns (uint256 value) {\n"
- " if (which == 0) return value1;\n"
- " else return value2;\n"
- " }\n"
- " function set(uint8 which, uint256 value) {\n"
- " if (which == 0) value1 = value;\n"
- " else value2 = value;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ uint256 value1;
+ uint256 value2;
+ function get(uint8 which) returns (uint256 value) {
+ if (which == 0) return value1;
+ else return value2;
+ }
+ function set(uint8 which, uint256 value) {
+ if (which == 0) value1 = value;
+ else value2 = value;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0));
BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0));
@@ -832,17 +886,19 @@ BOOST_AUTO_TEST_CASE(state_smoke_test)
BOOST_AUTO_TEST_CASE(compound_assign)
{
- char const* sourceCode = "contract test {\n"
- " uint value1;\n"
- " uint value2;\n"
- " function f(uint x, uint y) returns (uint w) {\n"
- " uint value3 = y;"
- " value1 += x;\n"
- " value3 *= x;"
- " value2 *= value3 + value1;\n"
- " return value2 += 7;"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ uint value1;
+ uint value2;
+ function f(uint x, uint y) returns (uint w) {
+ uint value3 = y;
+ value1 += x;
+ value3 *= x;
+ value2 *= value3 + value1;
+ return value2 += 7;
+ }
+ }
+ )";
compileAndRun(sourceCode);
u256 value1;
@@ -855,27 +911,29 @@ BOOST_AUTO_TEST_CASE(compound_assign)
value2 *= value3 + value1;
return value2 += 7;
};
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(0), u256(6));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(1), u256(3));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(2), u256(25));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(3), u256(69));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(4), u256(84));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(5), u256(2));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(6), u256(51));
- testSolidityAgainstCpp("f(uint256,uint256)", f, u256(7), u256(48));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(0), u256(6));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(1), u256(3));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(2), u256(25));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(3), u256(69));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(4), u256(84));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(5), u256(2));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(6), u256(51));
+ testContractAgainstCpp("f(uint256,uint256)", f, u256(7), u256(48));
}
BOOST_AUTO_TEST_CASE(simple_mapping)
{
- char const* sourceCode = "contract test {\n"
- " mapping(uint8 => uint8) table;\n"
- " function get(uint8 k) returns (uint8 v) {\n"
- " return table[k];\n"
- " }\n"
- " function set(uint8 k, uint8 v) {\n"
- " table[k] = v;\n"
- " }\n"
- "}";
+ char const* sourceCode = R"(
+ contract test {
+ mapping(uint8 => uint8) table;
+ function get(uint8 k) returns (uint8 v) {
+ return table[k];
+ }
+ function set(uint8 k, uint8 v) {
+ table[k] = v;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00)));
@@ -897,23 +955,25 @@ BOOST_AUTO_TEST_CASE(simple_mapping)
BOOST_AUTO_TEST_CASE(mapping_state)
{
- char const* sourceCode = "contract Ballot {\n"
- " mapping(address => bool) canVote;\n"
- " mapping(address => uint) voteCount;\n"
- " mapping(address => bool) voted;\n"
- " function getVoteCount(address addr) returns (uint retVoteCount) {\n"
- " return voteCount[addr];\n"
- " }\n"
- " function grantVoteRight(address addr) {\n"
- " canVote[addr] = true;\n"
- " }\n"
- " function vote(address voter, address vote) returns (bool success) {\n"
- " if (!canVote[voter] || voted[voter]) return false;\n"
- " voted[voter] = true;\n"
- " voteCount[vote] = voteCount[vote] + 1;\n"
- " return true;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract Ballot {
+ mapping(address => bool) canVote;
+ mapping(address => uint) voteCount;
+ mapping(address => bool) voted;
+ function getVoteCount(address addr) returns (uint retVoteCount) {
+ return voteCount[addr];
+ }
+ function grantVoteRight(address addr) {
+ canVote[addr] = true;
+ }
+ function vote(address voter, address vote) returns (bool success) {
+ if (!canVote[voter] || voted[voter]) return false;
+ voted[voter] = true;
+ voteCount[vote] = voteCount[vote] + 1;
+ return true;
+ }
+ }
+ )";
compileAndRun(sourceCode);
class Ballot
{
@@ -936,53 +996,55 @@ BOOST_AUTO_TEST_CASE(mapping_state)
auto getVoteCount = bind(&Ballot::getVoteCount, &ballot, _1);
auto grantVoteRight = bind(&Ballot::grantVoteRight, &ballot, _1);
auto vote = bind(&Ballot::vote, &ballot, _1, _2);
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
// voting without vote right should be rejected
- testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(2));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
+ testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(2));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
// grant vote rights
- testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(0));
- testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(1));
+ testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(0));
+ testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(1));
// vote, should increase 2's vote count
- testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(2));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
+ testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(2));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
// vote again, should be rejected
- testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
+ testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
// vote without right to vote
- testSolidityAgainstCpp("vote(address,address)", vote, u160(2), u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
+ testContractAgainstCpp("vote(address,address)", vote, u160(2), u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
// grant vote right and now vote again
- testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(2));
- testSolidityAgainstCpp("vote(address,address)", vote, u160(2), u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
- testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
+ testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(2));
+ testContractAgainstCpp("vote(address,address)", vote, u160(2), u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1));
+ testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2));
}
BOOST_AUTO_TEST_CASE(mapping_state_inc_dec)
{
- char const* sourceCode = "contract test {\n"
- " uint value;\n"
- " mapping(uint => uint) table;\n"
- " function f(uint x) returns (uint y) {\n"
- " value = x;\n"
- " if (x > 0) table[++value] = 8;\n"
- " if (x > 1) value--;\n"
- " if (x > 2) table[value]++;\n"
- " return --table[value++];\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ uint value;
+ mapping(uint => uint) table;
+ function f(uint x) returns (uint y) {
+ value = x;
+ if (x > 0) table[++value] = 8;
+ if (x > 1) value--;
+ if (x > 2) table[value]++;
+ return --table[value++];
+ }
+ }
+ )";
compileAndRun(sourceCode);
u256 value = 0;
@@ -998,18 +1060,20 @@ BOOST_AUTO_TEST_CASE(mapping_state_inc_dec)
table[value]++;
return --table[value++];
};
- testSolidityAgainstCppOnRange("f(uint256)", f, 0, 5);
+ testContractAgainstCppOnRange("f(uint256)", f, 0, 5);
}
BOOST_AUTO_TEST_CASE(multi_level_mapping)
{
- char const* sourceCode = "contract test {\n"
- " mapping(uint => mapping(uint => uint)) table;\n"
- " function f(uint x, uint y, uint z) returns (uint w) {\n"
- " if (z == 0) return table[x][y];\n"
- " else return table[x][y] = z;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ mapping(uint => mapping(uint => uint)) table;
+ function f(uint x, uint y, uint z) returns (uint w) {
+ if (z == 0) return table[x][y];
+ else return table[x][y] = z;
+ }
+ }
+ )";
compileAndRun(sourceCode);
map<u256, map<u256, u256>> table;
@@ -1018,47 +1082,49 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping)
if (_z == 0) return table[_x][_y];
else return table[_x][_y] = _z;
};
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
- testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0));
+ testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0));
}
BOOST_AUTO_TEST_CASE(structs)
{
- char const* sourceCode = "contract test {\n"
- " struct s1 {\n"
- " uint8 x;\n"
- " bool y;\n"
- " }\n"
- " struct s2 {\n"
- " uint32 z;\n"
- " s1 s1data;\n"
- " mapping(uint8 => s2) recursive;\n"
- " }\n"
- " s2 data;\n"
- " function check() returns (bool ok) {\n"
- " return data.z == 1 && data.s1data.x == 2 && \n"
- " data.s1data.y == true && \n"
- " data.recursive[3].recursive[4].z == 5 && \n"
- " data.recursive[4].recursive[3].z == 6 && \n"
- " data.recursive[0].s1data.y == false && \n"
- " data.recursive[4].z == 9;\n"
- " }\n"
- " function set() {\n"
- " data.z = 1;\n"
- " data.s1data.x = 2;\n"
- " data.s1data.y = true;\n"
- " data.recursive[3].recursive[4].z = 5;\n"
- " data.recursive[4].recursive[3].z = 6;\n"
- " data.recursive[0].s1data.y = false;\n"
- " data.recursive[4].z = 9;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ struct s1 {
+ uint8 x;
+ bool y;
+ }
+ struct s2 {
+ uint32 z;
+ s1 s1data;
+ mapping(uint8 => s2) recursive;
+ }
+ s2 data;
+ function check() returns (bool ok) {
+ return data.z == 1 && data.s1data.x == 2 &&
+ data.s1data.y == true &&
+ data.recursive[3].recursive[4].z == 5 &&
+ data.recursive[4].recursive[3].z == 6 &&
+ data.recursive[0].s1data.y == false &&
+ data.recursive[4].z == 9;
+ }
+ function set() {
+ data.z = 1;
+ data.s1data.x = 2;
+ data.s1data.y = true;
+ data.recursive[3].recursive[4].z = 5;
+ data.recursive[4].recursive[3].z = 6;
+ data.recursive[0].s1data.y = false;
+ data.recursive[4].z = 9;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("check()") == encodeArgs(false));
BOOST_CHECK(callContractFunction("set()") == bytes());
@@ -1067,26 +1133,28 @@ BOOST_AUTO_TEST_CASE(structs)
BOOST_AUTO_TEST_CASE(struct_reference)
{
- char const* sourceCode = "contract test {\n"
- " struct s2 {\n"
- " uint32 z;\n"
- " mapping(uint8 => s2) recursive;\n"
- " }\n"
- " s2 data;\n"
- " function check() returns (bool ok) {\n"
- " return data.z == 2 && \n"
- " data.recursive[0].z == 3 && \n"
- " data.recursive[0].recursive[1].z == 0 && \n"
- " data.recursive[0].recursive[0].z == 1;\n"
- " }\n"
- " function set() {\n"
- " data.z = 2;\n"
- " var map = data.recursive;\n"
- " s2 inner = map[0];\n"
- " inner.z = 3;\n"
- " inner.recursive[0].z = inner.recursive[1].z + 1;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ struct s2 {
+ uint32 z;
+ mapping(uint8 => s2) recursive;
+ }
+ s2 data;
+ function check() returns (bool ok) {
+ return data.z == 2 &&
+ data.recursive[0].z == 3 &&
+ data.recursive[0].recursive[1].z == 0 &&
+ data.recursive[0].recursive[0].z == 1;
+ }
+ function set() {
+ data.z = 2;
+ var map = data.recursive;
+ s2 inner = map[0];
+ inner.z = 3;
+ inner.recursive[0].z = inner.recursive[1].z + 1;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("check()") == encodeArgs(false));
BOOST_CHECK(callContractFunction("set()") == bytes());
@@ -1133,12 +1201,13 @@ BOOST_AUTO_TEST_CASE(deleteStruct)
nestedValue = str.nstr.nestedValue;
}
function getTopMapping(uint index) returns(uint ret) {
- ret = str.topMapping[index];
+ ret = str.topMapping[index];
}
function getNestedMapping(uint index) returns(bool ret) {
return str.nstr.nestedMapping[index];
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0));
BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0));
@@ -1159,7 +1228,8 @@ BOOST_AUTO_TEST_CASE(deleteLocal)
delete v;
res = v;
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0));
}
@@ -1176,22 +1246,25 @@ BOOST_AUTO_TEST_CASE(deleteLocals)
res1 = w;
res2 = x;
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7));
}
BOOST_AUTO_TEST_CASE(constructor)
{
- char const* sourceCode = "contract test {\n"
- " mapping(uint => uint) data;\n"
- " function test() {\n"
- " data[7] = 8;\n"
- " }\n"
- " function get(uint key) returns (uint value) {\n"
- " return data[key];"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ mapping(uint => uint) data;
+ function test() {
+ data[7] = 8;
+ }
+ function get(uint key) returns (uint value) {
+ return data[key];
+ }
+ }
+ )";
compileAndRun(sourceCode);
map<u256, byte> data;
data[7] = 8;
@@ -1199,18 +1272,20 @@ BOOST_AUTO_TEST_CASE(constructor)
{
return data[_x];
};
- testSolidityAgainstCpp("get(uint256)", get, u256(6));
- testSolidityAgainstCpp("get(uint256)", get, u256(7));
+ testContractAgainstCpp("get(uint256)", get, u256(6));
+ testContractAgainstCpp("get(uint256)", get, u256(7));
}
BOOST_AUTO_TEST_CASE(simple_accessor)
{
- char const* sourceCode = "contract test {\n"
- " uint256 public data;\n"
- " function test() {\n"
- " data = 8;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ uint256 public data;
+ function test() {
+ data = 8;
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data()") == encodeArgs(8));
}
@@ -1252,7 +1327,7 @@ BOOST_AUTO_TEST_CASE(array_accessor)
BOOST_AUTO_TEST_CASE(accessors_mapping_for_array)
{
char const* sourceCode = R"(
- contract test {
+ contract test {
mapping(uint => uint[8]) public data;
mapping(uint => uint[]) public dynamicData;
function test() {
@@ -1260,7 +1335,7 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array)
dynamicData[2].length = 3;
dynamicData[2][2] = 8;
}
- }
+ }
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data(uint256,uint256)", 2, 2) == encodeArgs(8));
@@ -1271,20 +1346,22 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array)
BOOST_AUTO_TEST_CASE(multiple_elementary_accessors)
{
- char const* sourceCode = "contract test {\n"
- " uint256 public data;\n"
- " bytes6 public name;\n"
- " bytes32 public a_hash;\n"
- " address public an_address;\n"
- " function test() {\n"
- " data = 8;\n"
- " name = \"Celina\";\n"
- " a_hash = sha3(123);\n"
- " an_address = address(0x1337);\n"
- " super_secret_data = 42;\n"
- " }\n"
- " uint256 super_secret_data;"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ uint256 public data;
+ bytes6 public name;
+ bytes32 public a_hash;
+ address public an_address;
+ function test() {
+ data = 8;
+ name = "Celina";
+ a_hash = sha3(123);
+ an_address = address(0x1337);
+ super_secret_data = 42;
+ }
+ uint256 super_secret_data;
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("data()") == encodeArgs(8));
BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina"));
@@ -1336,26 +1413,30 @@ BOOST_AUTO_TEST_CASE(struct_accessor)
BOOST_AUTO_TEST_CASE(balance)
{
- char const* sourceCode = "contract test {\n"
- " function test() payable {}\n"
- " function getBalance() returns (uint256 balance) {\n"
- " return address(this).balance;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function test() payable {}
+ function getBalance() returns (uint256 balance) {
+ return address(this).balance;
+ }
+ }
+ )";
compileAndRun(sourceCode, 23);
BOOST_CHECK(callContractFunction("getBalance()") == encodeArgs(23));
}
BOOST_AUTO_TEST_CASE(blockchain)
{
- char const* sourceCode = "contract test {\n"
- " function test() payable {}\n"
- " function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) {\n"
- " value = msg.value;\n"
- " coinbase = block.coinbase;\n"
- " blockNumber = block.number;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function test() payable {}
+ function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) {
+ value = msg.value;
+ coinbase = block.coinbase;
+ blockNumber = block.number;
+ }
+ }
+ )";
BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true);
m_rpc.test_mineBlocks(5);
compileAndRun(sourceCode, 27);
@@ -1393,12 +1474,14 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same)
BOOST_AUTO_TEST_CASE(now)
{
- char const* sourceCode = "contract test {\n"
- " function someInfo() returns (bool equal, uint val) {\n"
- " equal = block.timestamp == now;\n"
- " val = now;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function someInfo() returns (bool equal, uint val) {
+ equal = block.timestamp == now;
+ val = now;
+ }
+ }
+ )";
m_rpc.test_modifyTimestamp(0x776347e2);
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("someInfo()") == encodeArgs(true, 0x776347e3));
@@ -1411,7 +1494,8 @@ BOOST_AUTO_TEST_CASE(type_conversions_cleanup)
char const* sourceCode = R"(
contract Test {
function test() returns (uint ret) { return uint(address(Test(address(0x11223344556677889900112233445566778899001122)))); }
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_REQUIRE(callContractFunction("test()") == bytes({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22,
@@ -1425,7 +1509,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size)
function bytesToBytes(bytes4 input) returns (bytes2 ret) {
return bytes2(input);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("ab"));
}
@@ -1437,7 +1522,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size)
function bytesToBytes(bytes2 input) returns (bytes4 ret) {
return bytes4(input);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab") == encodeArgs("ab"));
}
@@ -1449,7 +1535,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size)
function bytesToBytes(bytes4 input) returns (bytes4 ret) {
return bytes4(input);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("abcd"));
}
@@ -1462,7 +1549,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size)
function bytesToUint(bytes32 s) returns (uint256 h) {
return uint(s);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToUint(bytes32)", string("abc2")) ==
encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000")));
@@ -1475,7 +1563,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size)
function bytesToUint(bytes1 s) returns (uint8 h) {
return uint8(s);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToUint(bytes1)", string("a")) ==
encodeArgs(u256("0x61")));
@@ -1488,7 +1577,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size)
function bytesToUint(bytes4 s) returns (uint16 h) {
return uint16(s);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) ==
encodeArgs(u256("0x6364")));
@@ -1501,7 +1591,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size)
function bytesToUint(bytes4 s) returns (uint64 h) {
return uint64(s);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) ==
encodeArgs(u256("0x61626364")));
@@ -1515,7 +1606,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size)
function uintToBytes(uint256 h) returns (bytes32 s) {
return bytes32(h);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
u256 a("0x6162630000000000000000000000000000000000000000000000000000000000");
BOOST_CHECK(callContractFunction("uintToBytes(uint256)", a) == encodeArgs(a));
@@ -1528,7 +1620,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size)
function UintToBytes(uint8 h) returns (bytes1 s) {
return bytes1(h);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("UintToBytes(uint8)", u256("0x61")) ==
encodeArgs(string("a")));
@@ -1541,7 +1634,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size)
function uintToBytes(uint32 h) returns (bytes2 s) {
return bytes2(h);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("uintToBytes(uint32)",
u160("0x61626364")) == encodeArgs(string("cd")));
@@ -1554,7 +1648,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size)
function UintToBytes(uint16 h) returns (bytes8 s) {
return bytes8(h);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(
callContractFunction("UintToBytes(uint16)", u256("0x6162")) ==
@@ -1564,13 +1659,15 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size)
BOOST_AUTO_TEST_CASE(send_ether)
{
- char const* sourceCode = "contract test {\n"
- " function test() payable {}\n"
- " function a(address addr, uint amount) returns (uint ret) {\n"
- " addr.send(amount);\n"
- " return address(this).balance;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function test() payable {}
+ function a(address addr, uint amount) returns (uint ret) {
+ addr.send(amount);
+ return address(this).balance;
+ }
+ }
+ )";
u256 amount(130);
compileAndRun(sourceCode, amount + 1);
u160 address(23);
@@ -1580,11 +1677,13 @@ BOOST_AUTO_TEST_CASE(send_ether)
BOOST_AUTO_TEST_CASE(log0)
{
- char const* sourceCode = "contract test {\n"
- " function a() {\n"
- " log0(1);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a() {
+ log0(1);
+ }
+ }
+ )";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
@@ -1595,11 +1694,13 @@ BOOST_AUTO_TEST_CASE(log0)
BOOST_AUTO_TEST_CASE(log1)
{
- char const* sourceCode = "contract test {\n"
- " function a() {\n"
- " log1(1, 2);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a() {
+ log1(1, 2);
+ }
+ }
+ )";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
@@ -1611,11 +1712,13 @@ BOOST_AUTO_TEST_CASE(log1)
BOOST_AUTO_TEST_CASE(log2)
{
- char const* sourceCode = "contract test {\n"
- " function a() {\n"
- " log2(1, 2, 3);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a() {
+ log2(1, 2, 3);
+ }
+ }
+ )";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
@@ -1628,11 +1731,13 @@ BOOST_AUTO_TEST_CASE(log2)
BOOST_AUTO_TEST_CASE(log3)
{
- char const* sourceCode = "contract test {\n"
- " function a() {\n"
- " log3(1, 2, 3, 4);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a() {
+ log3(1, 2, 3, 4);
+ }
+ }
+ )";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
@@ -1645,11 +1750,13 @@ BOOST_AUTO_TEST_CASE(log3)
BOOST_AUTO_TEST_CASE(log4)
{
- char const* sourceCode = "contract test {\n"
- " function a() {\n"
- " log4(1, 2, 3, 4, 5);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a() {
+ log4(1, 2, 3, 4, 5);
+ }
+ }
+ )";
compileAndRun(sourceCode);
callContractFunction("a()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
@@ -1662,11 +1769,13 @@ BOOST_AUTO_TEST_CASE(log4)
BOOST_AUTO_TEST_CASE(log_in_constructor)
{
- char const* sourceCode = "contract test {\n"
- " function test() {\n"
- " log1(1, 2);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function test() {
+ log1(1, 2);
+ }
+ }
+ )";
compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
@@ -1677,13 +1786,15 @@ BOOST_AUTO_TEST_CASE(log_in_constructor)
BOOST_AUTO_TEST_CASE(suicide)
{
- char const* sourceCode = "contract test {\n"
- " function test() payable {}\n"
- " function a(address receiver) returns (uint ret) {\n"
- " suicide(receiver);\n"
- " return 10;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function test() payable {}
+ function a(address receiver) returns (uint ret) {
+ suicide(receiver);
+ return 10;
+ }
+ }
+ )";
u256 amount(130);
compileAndRun(sourceCode, amount);
u160 address(23);
@@ -1694,13 +1805,15 @@ BOOST_AUTO_TEST_CASE(suicide)
BOOST_AUTO_TEST_CASE(selfdestruct)
{
- char const* sourceCode = "contract test {\n"
- " function test() payable {}\n"
- " function a(address receiver) returns (uint ret) {\n"
- " selfdestruct(receiver);\n"
- " return 10;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function test() payable {}
+ function a(address receiver) returns (uint ret) {
+ selfdestruct(receiver);
+ return 10;
+ }
+ }
+ )";
u256 amount(130);
compileAndRun(sourceCode, amount);
u160 address(23);
@@ -1711,28 +1824,32 @@ BOOST_AUTO_TEST_CASE(selfdestruct)
BOOST_AUTO_TEST_CASE(sha3)
{
- char const* sourceCode = "contract test {\n"
- " function a(bytes32 input) returns (bytes32 sha3hash) {\n"
- " return sha3(input);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a(bytes32 input) returns (bytes32 sha3hash) {
+ return sha3(input);
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto f = [&](u256 const& _x) -> u256
{
return dev::keccak256(toBigEndian(_x));
};
- testSolidityAgainstCpp("a(bytes32)", f, u256(4));
- testSolidityAgainstCpp("a(bytes32)", f, u256(5));
- testSolidityAgainstCpp("a(bytes32)", f, u256(-1));
+ testContractAgainstCpp("a(bytes32)", f, u256(4));
+ testContractAgainstCpp("a(bytes32)", f, u256(5));
+ testContractAgainstCpp("a(bytes32)", f, u256(-1));
}
BOOST_AUTO_TEST_CASE(sha256)
{
- char const* sourceCode = "contract test {\n"
- " function a(bytes32 input) returns (bytes32 sha256hash) {\n"
- " return sha256(input);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a(bytes32 input) returns (bytes32 sha256hash) {
+ return sha256(input);
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto f = [&](u256 const& _x) -> bytes
{
@@ -1744,18 +1861,20 @@ BOOST_AUTO_TEST_CASE(sha256)
return fromHex("af9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051");
return fromHex("");
};
- testSolidityAgainstCpp("a(bytes32)", f, u256(4));
- testSolidityAgainstCpp("a(bytes32)", f, u256(5));
- testSolidityAgainstCpp("a(bytes32)", f, u256(-1));
+ testContractAgainstCpp("a(bytes32)", f, u256(4));
+ testContractAgainstCpp("a(bytes32)", f, u256(5));
+ testContractAgainstCpp("a(bytes32)", f, u256(-1));
}
BOOST_AUTO_TEST_CASE(ripemd)
{
- char const* sourceCode = "contract test {\n"
- " function a(bytes32 input) returns (bytes32 sha256hash) {\n"
- " return ripemd160(input);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a(bytes32 input) returns (bytes32 sha256hash) {
+ return ripemd160(input);
+ }
+ }
+ )";
compileAndRun(sourceCode);
auto f = [&](u256 const& _x) -> bytes
{
@@ -1767,18 +1886,20 @@ BOOST_AUTO_TEST_CASE(ripemd)
return fromHex("1cf4e77f5966e13e109703cd8a0df7ceda7f3dc3000000000000000000000000");
return fromHex("");
};
- testSolidityAgainstCpp("a(bytes32)", f, u256(4));
- testSolidityAgainstCpp("a(bytes32)", f, u256(5));
- testSolidityAgainstCpp("a(bytes32)", f, u256(-1));
+ testContractAgainstCpp("a(bytes32)", f, u256(4));
+ testContractAgainstCpp("a(bytes32)", f, u256(5));
+ testContractAgainstCpp("a(bytes32)", f, u256(-1));
}
BOOST_AUTO_TEST_CASE(ecrecover)
{
- char const* sourceCode = "contract test {\n"
- " function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) {\n"
- " return ecrecover(h, v, r, s);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) {
+ return ecrecover(h, v, r, s);
+ }
+ }
+ )";
compileAndRun(sourceCode);
u256 h("0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c");
byte v = 28;
@@ -2796,7 +2917,8 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
ret_k = k;
ret_g = g;
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8));
BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8));
@@ -2809,7 +2931,8 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
function f(uint k) returns(uint){
return k;
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9));
}
@@ -2822,7 +2945,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments)
{
d = sha3(a, b, c);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs(
@@ -2840,7 +2964,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals)
{
d = sha3(a, b, 145);
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs(
@@ -2862,7 +2987,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals)
{
d = sha3(a, b, 145, "foo");
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::keccak256("foo")));
@@ -2888,7 +3014,8 @@ BOOST_AUTO_TEST_CASE(sha3_with_bytes)
data[2] = "o";
return sha3(data) == sha3("foo");
}
- })";
+ }
+ )";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("foo()") == encodeArgs(true));
}
@@ -4464,6 +4591,34 @@ BOOST_AUTO_TEST_CASE(super_overload)
BOOST_CHECK(callContractFunction("h()") == encodeArgs(2));
}
+BOOST_AUTO_TEST_CASE(bool_conversion)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(bool _b) returns(uint) {
+ if (_b)
+ return 1;
+ else
+ return 0;
+ }
+ function g(bool _in) returns (bool _out) {
+ _out = _in;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(bool)", 0) == encodeArgs(0));
+ BOOST_CHECK(callContractFunction("f(bool)", 1) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("f(bool)", 2) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("f(bool)", 3) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("f(bool)", 255) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("g(bool)", 0) == encodeArgs(0));
+ BOOST_CHECK(callContractFunction("g(bool)", 1) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("g(bool)", 2) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("g(bool)", 3) == encodeArgs(1));
+ BOOST_CHECK(callContractFunction("g(bool)", 255) == encodeArgs(1));
+}
+
BOOST_AUTO_TEST_CASE(packed_storage_signed)
{
char const* sourceCode = R"(
@@ -4506,6 +4661,102 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls)
BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9)));
}
+BOOST_AUTO_TEST_CASE(invalid_enum_compared)
+{
+ char const* sourceCode = R"(
+ contract C {
+ enum X { A, B }
+
+ function test_eq() returns (bool) {
+ X garbled;
+ assembly {
+ garbled := 5
+ }
+ return garbled == garbled;
+ }
+ function test_eq_ok() returns (bool) {
+ X garbled = X.A;
+ return garbled == garbled;
+ }
+ function test_neq() returns (bool) {
+ X garbled;
+ assembly {
+ garbled := 5
+ }
+ return garbled != garbled;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test_eq_ok()") == encodeArgs(u256(1)));
+ // both should throw
+ BOOST_CHECK(callContractFunction("test_eq()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("test_neq()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(invalid_enum_logged)
+{
+ char const* sourceCode = R"(
+ contract C {
+ enum X { A, B }
+ event Log(X);
+
+ function test_log() returns (uint) {
+ X garbled = X.A;
+ assembly {
+ garbled := 5
+ }
+ Log(garbled);
+ return 1;
+ }
+ function test_log_ok() returns (uint) {
+ X x = X.A;
+ Log(x);
+ return 1;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test_log_ok()") == encodeArgs(u256(1)));
+ BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
+ BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
+ BOOST_REQUIRE_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Log(uint8)")));
+ BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(0)));
+
+ // should throw
+ BOOST_CHECK(callContractFunction("test_log()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(invalid_enum_stored)
+{
+ char const* sourceCode = R"(
+ contract C {
+ enum X { A, B }
+ X public x;
+
+ function test_store() returns (uint) {
+ X garbled = X.A;
+ assembly {
+ garbled := 5
+ }
+ x = garbled;
+ return 1;
+ }
+ function test_store_ok() returns (uint) {
+ x = X.A;
+ return 1;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test_store_ok()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0)));
+
+ // should throw
+ BOOST_CHECK(callContractFunction("test_store()") == encodeArgs());
+}
+
BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret)
{
char const* sourceCode = R"(
@@ -6324,17 +6575,6 @@ BOOST_AUTO_TEST_CASE(calldata_offset)
BOOST_CHECK(callContractFunction("last()", encodeArgs()) == encodeDyn(string("nd")));
}
-BOOST_AUTO_TEST_CASE(version_stamp_for_libraries)
-{
- char const* sourceCode = "library lib {}";
- m_optimize = true;
- bytes runtimeCode = compileAndRun(sourceCode, 0, "lib");
- BOOST_CHECK(runtimeCode.size() >= 8);
- BOOST_CHECK_EQUAL(runtimeCode[0], int(Instruction::PUSH6)); // might change once we switch to 1.x.x
- BOOST_CHECK_EQUAL(runtimeCode[1], 4); // might change once we switch away from x.4.x
- BOOST_CHECK_EQUAL(runtimeCode[7], int(Instruction::POP));
-}
-
BOOST_AUTO_TEST_CASE(contract_binary_dependencies)
{
char const* sourceCode = R"(
@@ -7608,13 +7848,6 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
u160 cAddr = m_contractAddress;
compileAndRun(sourceCode, 0, "D");
BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7)));
-
- m_optimize = true;
-
- compileAndRun(sourceCode, 0, "C");
- u160 cAddrOpt = m_contractAddress;
- compileAndRun(sourceCode, 0, "D");
- BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7)));
}
BOOST_AUTO_TEST_CASE(calling_uninitialized_function)
@@ -8223,6 +8456,396 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_right)
BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x42)));
}
+BOOST_AUTO_TEST_CASE(shift_left)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint a, uint b) returns (uint) {
+ return a << b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000"));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_left_uint32)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint32 a, uint32 b) returns (uint) {
+ return a << b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_left_uint8)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint8 a, uint8 b) returns (uint) {
+ return a << b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66)));
+ BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_left_larger_type)
+{
+ // This basically tests proper cleanup and conversion. It should not convert x to int8.
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (int8) {
+ uint8 x = 254;
+ int8 y = 1;
+ return y << x;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_left_assignment)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint a, uint b) returns (uint) {
+ a <<= b;
+ return a;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000"));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint a, uint8 b) returns (uint) {
+ a <<= b;
+ return a;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000"));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint a, uint b) returns (uint) {
+ return a >> b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right_garbled)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint8 a, uint8 b) returns (uint) {
+ assembly {
+ a := 0xffffffff
+ }
+ // Higher bits should be cleared before the shift
+ return a >> b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)) == encodeArgs(u256(0xf)));
+ BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right_uint32)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint32 a, uint32 b) returns (uint) {
+ return a >> b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right_uint8)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint8 a, uint8 b) returns (uint) {
+ return a >> b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66)));
+ BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0x0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right_assignment)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint a, uint b) returns (uint) {
+ a >>= b;
+ return a;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(int a, int b) returns (int) {
+ return a >> b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266)));
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16)));
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(int a, int b) returns (int) {
+ a >>= b;
+ return a;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266)));
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16)));
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_negative_rvalue)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(int a, int b) returns (int) {
+ return a << b;
+ }
+ function g(int a, int b) returns (int) {
+ return a >> b;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs());
+ BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(int a, int b) returns (int) {
+ a <<= b;
+ return a;
+ }
+ function g(int a, int b) returns (int) {
+ a >>= b;
+ return a;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs());
+ BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(shift_constant_left_assignment)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint a) {
+ a = 0x42;
+ a <<= 8;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x4200)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_constant_right_assignment)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint a) {
+ a = 0x4200;
+ a >>= 8;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x42)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_cleanup)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint16 x) {
+ x = 0xffff;
+ x += 32;
+ x <<= 8;
+ x >>= 16;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_cleanup_garbled)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() returns (uint8 x) {
+ assembly {
+ x := 0xffff
+ }
+ x >>= 8;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_overflow)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function leftU(uint8 x, uint8 y) returns (uint8) {
+ return x << y;
+ }
+ function leftS(int8 x, int8 y) returns (int8) {
+ return x << y;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8) == encodeArgs(u256(0)));
+ BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1) == encodeArgs(u256(254)));
+ BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0) == encodeArgs(u256(255)));
+
+ // Result is -128 and output is sign-extended, not zero-padded.
+ BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(0) - 128));
+ BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64)));
+}
+
+BOOST_AUTO_TEST_CASE(shift_bytes)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function left(bytes20 x, uint8 y) returns (bytes20) {
+ return x << y;
+ }
+ function right(bytes20 x, uint8 y) returns (bytes20) {
+ return x >> y;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs("901234567890" + string(8, 0)));
+ BOOST_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs(string(8, 0) + "123456789012"));
+}
+
+BOOST_AUTO_TEST_CASE(shift_bytes_cleanup)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function left(uint8 y) returns (bytes20) {
+ bytes20 x;
+ assembly { x := "12345678901234567890abcde" }
+ return x << y;
+ }
+ function right(uint8 y) returns (bytes20) {
+ bytes20 x;
+ assembly { x := "12345678901234567890abcde" }
+ return x >> y;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("left(uint8)", 8 * 8) == encodeArgs("901234567890" + string(8, 0)));
+ BOOST_CHECK(callContractFunction("right(uint8)", 8 * 8) == encodeArgs(string(8, 0) + "123456789012"));
+}
+
+BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function test() returns (uint, uint) {
+ uint32 a = 0xffffffff;
+ uint16 x = uint16(a);
+ uint16 y = x;
+ x /= 0x100;
+ y = y / 0x100;
+ return (x, y);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0xff), u256(0xff)));
+}
+
BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers)
{
char const* sourceCode = R"(
@@ -8280,6 +8903,18 @@ BOOST_AUTO_TEST_CASE(inline_assembly_invalidjumplabel)
BOOST_CHECK(callContractFunction("f()") == encodeArgs());
}
+BOOST_AUTO_TEST_CASE(contracts_separated_with_comment)
+{
+ char const* sourceCode = R"(
+ contract C1 {}
+ /**
+ **/
+ contract C2 {}
+ )";
+ compileAndRun(sourceCode, 0, "C1");
+ compileAndRun(sourceCode, 0, "C2");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp
index 02548121..bb9695d1 100644
--- a/test/libsolidity/SolidityExecutionFramework.cpp
+++ b/test/libsolidity/SolidityExecutionFramework.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -22,115 +22,13 @@
#include <cstdlib>
#include <boost/test/framework.hpp>
-#include <libdevcore/CommonIO.h>
#include <test/libsolidity/SolidityExecutionFramework.h>
-using namespace std;
-using namespace dev;
+using namespace dev::test;
using namespace dev::solidity;
using namespace dev::solidity::test;
-namespace // anonymous
+SolidityExecutionFramework::SolidityExecutionFramework() :
+ ExecutionFramework()
{
- h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
-}
-
-string getIPCSocketPath()
-{
- string ipcPath = dev::test::Options::get().ipcPath;
- if (ipcPath.empty())
- BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath <path> or the environment variable ETH_TEST_IPC)");
-
- return ipcPath;
-}
-
-ExecutionFramework::ExecutionFramework() :
- m_rpc(RPCSession::instance(getIPCSocketPath())),
- m_sender(m_rpc.account(0))
-{
- m_rpc.test_rewindToBlock(0);
-}
-
-void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value)
-{
- RPCSession::TransactionData d;
- d.data = "0x" + toHex(_data);
- d.from = "0x" + toString(m_sender);
- d.gas = toHex(m_gas, HexPrefix::Add);
- d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
- d.value = toHex(_value, HexPrefix::Add);
- if (!_isCreation)
- {
- d.to = dev::toString(m_contractAddress);
- BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "latest").size() > 2);
- // Use eth_call to get the output
- m_output = fromHex(m_rpc.eth_call(d, "latest"), WhenError::Throw);
- }
-
- string txHash = m_rpc.eth_sendTransaction(d);
- m_rpc.test_mineBlocks(1);
- RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash));
-
- if (_isCreation)
- {
- m_contractAddress = Address(receipt.contractAddress);
- BOOST_REQUIRE(m_contractAddress);
- string code = m_rpc.eth_getCode(receipt.contractAddress, "latest");
- m_output = fromHex(code, WhenError::Throw);
- }
-
- m_gasUsed = u256(receipt.gasUsed);
- m_logs.clear();
- for (auto const& log: receipt.logEntries)
- {
- LogEntry entry;
- entry.address = Address(log.address);
- for (auto const& topic: log.topics)
- entry.topics.push_back(h256(topic));
- entry.data = fromHex(log.data, WhenError::Throw);
- m_logs.push_back(entry);
- }
-}
-
-void ExecutionFramework::sendEther(Address const& _to, u256 const& _value)
-{
- RPCSession::TransactionData d;
- d.data = "0x";
- d.from = "0x" + toString(m_sender);
- d.gas = toHex(m_gas, HexPrefix::Add);
- d.gasPrice = toHex(m_gasPrice, HexPrefix::Add);
- d.value = toHex(_value, HexPrefix::Add);
- d.to = dev::toString(_to);
-
- string txHash = m_rpc.eth_sendTransaction(d);
- m_rpc.test_mineBlocks(1);
-}
-
-size_t ExecutionFramework::currentTimestamp()
-{
- auto latestBlock = m_rpc.rpcCall("eth_getBlockByNumber", {"\"latest\"", "false"});
- return size_t(u256(latestBlock.get("timestamp", "invalid").asString()));
-}
-
-Address ExecutionFramework::account(size_t _i)
-{
- return Address(m_rpc.accountCreateIfNotExists(_i));
-}
-
-bool ExecutionFramework::addressHasCode(Address const& _addr)
-{
- string code = m_rpc.eth_getCode(toString(_addr), "latest");
- return !code.empty() && code != "0x";
-}
-
-u256 ExecutionFramework::balanceAt(Address const& _addr)
-{
- return u256(m_rpc.eth_getBalance(toString(_addr), "latest"));
-}
-
-bool ExecutionFramework::storageEmpty(Address const& _addr)
-{
- h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest"));
- BOOST_CHECK(root);
- return root == EmptyTrie;
}
diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h
index 7d44edaf..03e3a881 100644
--- a/test/libsolidity/SolidityExecutionFramework.h
+++ b/test/libsolidity/SolidityExecutionFramework.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -24,12 +24,7 @@
#include <functional>
-#include "../TestHelper.h"
-#include "../RPCSession.h"
-
-#include <libdevcore/ABI.h>
-#include <libdevcore/FixedHash.h>
-#include <libevmasm/Instruction.h>
+#include "../ExecutionFramework.h"
#include <libsolidity/interface/CompilerStack.h>
#include <libsolidity/interface/Exceptions.h>
@@ -39,40 +34,29 @@ namespace dev
{
namespace solidity
{
- using rational = boost::rational<dev::bigint>;
- /// An Ethereum address: 20 bytes.
- /// @NOTE This is not endian-specific; it's just a bunch of bytes.
- using Address = h160;
-
- // The various denominations; here for ease of use where needed within code.
- static const u256 ether = exp10<18>();
- static const u256 finney = exp10<15>();
- static const u256 szabo = exp10<12>();
- static const u256 shannon = exp10<9>();
- static const u256 wei = exp10<0>();
namespace test
{
-class ExecutionFramework
+class SolidityExecutionFramework: public dev::test::ExecutionFramework
{
public:
- ExecutionFramework();
+ SolidityExecutionFramework();
- bytes const& compileAndRunWithoutCheck(
+ virtual bytes const& compileAndRunWithoutCheck(
std::string const& _sourceCode,
u256 const& _value = 0,
std::string const& _contractName = "",
bytes const& _arguments = bytes(),
- std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>()
- )
+ std::map<std::string, dev::test::Address> const& _libraryAddresses = std::map<std::string, dev::test::Address>()
+ ) override
{
// Silence compiler version warning
std::string sourceCode = "pragma solidity >=0.0;\n" + _sourceCode;
m_compiler.reset(false);
m_compiler.addSource("", sourceCode);
- if (!m_compiler.compile(m_optimize, m_optimizeRuns))
+ if (!m_compiler.compile(m_optimize, m_optimizeRuns, _libraryAddresses))
{
for (auto const& error: m_compiler.errors())
SourceReferenceFormatter::printExceptionInformation(
@@ -84,230 +68,13 @@ public:
BOOST_ERROR("Compiling contract failed");
}
eth::LinkerObject obj = m_compiler.object(_contractName);
- obj.link(_libraryAddresses);
BOOST_REQUIRE(obj.linkReferences.empty());
sendMessage(obj.bytecode + _arguments, true, _value);
return m_output;
}
- bytes const& compileAndRun(
- std::string const& _sourceCode,
- u256 const& _value = 0,
- std::string const& _contractName = "",
- bytes const& _arguments = bytes(),
- std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>()
- )
- {
- compileAndRunWithoutCheck(_sourceCode, _value, _contractName, _arguments, _libraryAddresses);
- BOOST_REQUIRE(!m_output.empty());
- return m_output;
- }
-
- template <class... Args>
- bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments)
- {
- FixedHash<4> hash(dev::keccak256(_sig));
- sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value);
- return m_output;
- }
-
- template <class... Args>
- bytes const& callContractFunction(std::string _sig, Args const&... _arguments)
- {
- return callContractFunctionWithValue(_sig, 0, _arguments...);
- }
-
- template <class CppFunction, class... Args>
- void testSolidityAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments)
- {
- bytes solidityResult = callContractFunction(_sig, _arguments...);
- bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...);
- BOOST_CHECK_MESSAGE(
- solidityResult == cppResult,
- "Computed values do not match.\nSolidity: " +
- toHex(solidityResult) +
- "\nC++: " +
- toHex(cppResult)
- );
- }
-
- template <class CppFunction, class... Args>
- void testSolidityAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd)
- {
- for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument)
- {
- bytes solidityResult = callContractFunction(_sig, argument);
- bytes cppResult = callCppAndEncodeResult(_cppFunction, argument);
- BOOST_CHECK_MESSAGE(
- solidityResult == cppResult,
- "Computed values do not match.\nSolidity: " +
- toHex(solidityResult) +
- "\nC++: " +
- toHex(cppResult) +
- "\nArgument: " +
- toHex(encode(argument))
- );
- }
- }
-
- static bytes encode(bool _value) { return encode(byte(_value)); }
- static bytes encode(int _value) { return encode(u256(_value)); }
- static bytes encode(size_t _value) { return encode(u256(_value)); }
- static bytes encode(char const* _value) { return encode(std::string(_value)); }
- static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; }
- static bytes encode(u256 const& _value) { return toBigEndian(_value); }
- /// @returns the fixed-point encoding of a rational number with a given
- /// number of fractional bits.
- static bytes encode(std::pair<rational, int> const& _valueAndPrecision)
- {
- rational const& value = _valueAndPrecision.first;
- int fractionalBits = _valueAndPrecision.second;
- return encode(u256((value.numerator() << fractionalBits) / value.denominator()));
- }
- static bytes encode(h256 const& _value) { return _value.asBytes(); }
- static bytes encode(bytes const& _value, bool _padLeft = true)
- {
- bytes padding = bytes((32 - _value.size() % 32) % 32, 0);
- return _padLeft ? padding + _value : _value + padding;
- }
- static bytes encode(std::string const& _value) { return encode(asBytes(_value), false); }
- template <class _T>
- static bytes encode(std::vector<_T> const& _value)
- {
- bytes ret;
- for (auto const& v: _value)
- ret += encode(v);
- return ret;
- }
-
- template <class FirstArg, class... Args>
- static bytes encodeArgs(FirstArg const& _firstArg, Args const&... _followingArgs)
- {
- return encode(_firstArg) + encodeArgs(_followingArgs...);
- }
- static bytes encodeArgs()
- {
- return bytes();
- }
- //@todo might be extended in the future
- template <class Arg>
- static bytes encodeDyn(Arg const& _arg)
- {
- return encodeArgs(u256(0x20), u256(_arg.size()), _arg);
- }
- class ContractInterface
- {
- public:
- ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {}
-
- void setNextValue(u256 const& _value) { m_nextValue = _value; }
-
- protected:
- template <class... Args>
- bytes const& call(std::string const& _sig, Args const&... _arguments)
- {
- auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...);
- m_nextValue = 0;
- return ret;
- }
-
- void callString(std::string const& _name, std::string const& _arg)
- {
- BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty());
- }
-
- void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2)
- {
- BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty());
- }
-
- void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3)
- {
- BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty());
- }
-
- void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2)
- {
- BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty());
- }
-
- u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg)
- {
- bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg);
- BOOST_REQUIRE(ret.size() == 0x20);
- BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12);
- return eth::abiOut<u160>(ret);
- }
-
- std::string callAddressReturnsString(std::string const& _name, u160 const& _arg)
- {
- bytesConstRef ret = ref(call(_name + "(address)", _arg));
- BOOST_REQUIRE(ret.size() >= 0x20);
- u256 offset = eth::abiOut<u256>(ret);
- BOOST_REQUIRE_EQUAL(offset, 0x20);
- u256 len = eth::abiOut<u256>(ret);
- BOOST_REQUIRE_EQUAL(ret.size(), ((len + 0x1f) / 0x20) * 0x20);
- return ret.cropped(0, size_t(len)).toString();
- }
-
- h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg)
- {
- bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg);
- BOOST_REQUIRE(ret.size() == 0x20);
- return eth::abiOut<h256>(ret);
- }
-
- private:
- u256 m_nextValue;
- ExecutionFramework& m_framework;
- };
-
-private:
- template <class CppFunction, class... Args>
- auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
- -> typename std::enable_if<std::is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type
- {
- _cppFunction(_arguments...);
- return bytes();
- }
- template <class CppFunction, class... Args>
- auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments)
- -> typename std::enable_if<!std::is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type
- {
- return encode(_cppFunction(_arguments...));
- }
-
protected:
- void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0);
- void sendEther(Address const& _to, u256 const& _value);
- size_t currentTimestamp();
-
- /// @returns the (potentially newly created) _ith address.
- Address account(size_t _i);
-
- u256 balanceAt(Address const& _addr);
- bool storageEmpty(Address const& _addr);
- bool addressHasCode(Address const& _addr);
-
- RPCSession& m_rpc;
-
- struct LogEntry
- {
- Address address;
- std::vector<h256> topics;
- bytes data;
- };
-
- size_t m_optimizeRuns = 200;
- bool m_optimize = false;
dev::solidity::CompilerStack m_compiler;
- Address m_sender;
- Address m_contractAddress;
- u256 const m_gasPrice = 100 * szabo;
- u256 const m_gas = 100000000;
- bytes m_output;
- std::vector<LogEntry> m_logs;
- u256 m_gasUsed;
};
}
diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp
index 91edfefd..0c5a09c3 100644
--- a/test/libsolidity/SolidityExpressionCompiler.cpp
+++ b/test/libsolidity/SolidityExpressionCompiler.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -168,9 +168,11 @@ BOOST_AUTO_TEST_SUITE(SolidityExpressionCompiler)
BOOST_AUTO_TEST_CASE(literal_true)
{
- char const* sourceCode = "contract test {\n"
- " function f() { var x = true; }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { var x = true; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH1), 0x1});
@@ -179,9 +181,11 @@ BOOST_AUTO_TEST_CASE(literal_true)
BOOST_AUTO_TEST_CASE(literal_false)
{
- char const* sourceCode = "contract test {\n"
- " function f() { var x = false; }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { var x = false; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH1), 0x0});
@@ -190,9 +194,11 @@ BOOST_AUTO_TEST_CASE(literal_false)
BOOST_AUTO_TEST_CASE(int_literal)
{
- char const* sourceCode = "contract test {\n"
- " function f() { var x = 0x12345678901234567890; }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { var x = 0x12345678901234567890; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90,
@@ -204,11 +210,11 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
- function test ()
- {
+ function test () {
var x = 1 wei;
}
- })";
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH1), 0x1});
@@ -219,11 +225,11 @@ BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
- function test ()
- {
+ function test () {
var x = 1 szabo;
}
- })";
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00});
@@ -249,11 +255,11 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination)
{
char const* sourceCode = R"(
contract test {
- function test ()
- {
+ function test () {
var x = 1 ether;
}
- })";
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00});
@@ -262,9 +268,11 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination)
BOOST_AUTO_TEST_CASE(comparison)
{
- char const* sourceCode = "contract test {\n"
- " function f() { var x = (0x10aa < 0x11aa) != true; }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { var x = (0x10aa < 0x11aa) != true; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH1), 0x1, byte(Instruction::ISZERO), byte(Instruction::ISZERO),
@@ -278,9 +286,11 @@ BOOST_AUTO_TEST_CASE(comparison)
BOOST_AUTO_TEST_CASE(short_circuiting)
{
- char const* sourceCode = "contract test {\n"
- " function f() { var x = true != (4 <= 8 + 10 || 9 != 2); }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { var x = true != (4 <= 8 + 10 || 9 != 2); }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation({byte(Instruction::PUSH1), 0x12, // 8 + 10
@@ -305,9 +315,11 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
BOOST_AUTO_TEST_CASE(arithmetics)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}});
bytes expectation({byte(Instruction::PUSH1), 0x1,
byte(Instruction::PUSH1), 0x2,
@@ -339,9 +351,11 @@ BOOST_AUTO_TEST_CASE(arithmetics)
BOOST_AUTO_TEST_CASE(unary_operators)
{
- char const* sourceCode = "contract test {\n"
- " function f(int y) { var x = !(~+- y == 2); }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(int y) { var x = !(~+- y == 2); }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}});
bytes expectation({byte(Instruction::PUSH1), 0x2,
@@ -356,9 +370,11 @@ BOOST_AUTO_TEST_CASE(unary_operators)
BOOST_AUTO_TEST_CASE(unary_inc_dec)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}});
// Stack: a, x
@@ -406,9 +422,11 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec)
BOOST_AUTO_TEST_CASE(assignment)
{
- char const* sourceCode = "contract test {\n"
- " function f(uint a, uint b) { (a += b) * 2; }"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f(uint a, uint b) { (a += b) * 2; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}});
// Stack: a, b
@@ -427,9 +445,11 @@ BOOST_AUTO_TEST_CASE(assignment)
BOOST_AUTO_TEST_CASE(negative_literals_8bits)
{
- char const* sourceCode = "contract test {\n"
- " function f() { int8 x = -0x80; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { int8 x = -0x80; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80));
@@ -438,9 +458,11 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits)
BOOST_AUTO_TEST_CASE(negative_literals_16bits)
{
- char const* sourceCode = "contract test {\n"
- " function f() { int64 x = ~0xabc; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { int64 x = ~0xabc; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43});
@@ -451,9 +473,11 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals)
{
// first literal itself is too large for 256 bits but it fits after all constant operations
// have been applied
- char const* sourceCode = "contract test {\n"
- " function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode);
bytes expectation(bytes({byte(Instruction::PUSH1), 0xbf}));
@@ -462,11 +486,13 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals)
BOOST_AUTO_TEST_CASE(blockhash)
{
- char const* sourceCode = "contract test {\n"
- " function f() {\n"
- " block.blockhash(3);\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function f() {
+ block.blockhash(3);
+ }
+ }
+ )";
bytes code = compileFirstExpression(sourceCode, {}, {},
{make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block))});
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 865eb7ce..576421fd 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -26,11 +26,13 @@
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/analysis/NameAndTypeResolver.h>
+#include <libsolidity/analysis/StaticAnalyzer.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/analysis/GlobalContext.h>
#include <libsolidity/analysis/TypeChecker.h>
#include "../TestHelper.h"
+#include "ErrorCheck.h"
using namespace std;
@@ -44,8 +46,8 @@ namespace test
namespace
{
-pair<ASTPointer<SourceUnit>, std::shared_ptr<Error::Type const>>
-parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true)
+pair<ASTPointer<SourceUnit>, std::shared_ptr<Error const>>
+parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true, bool _allowMultipleErrors = false)
{
// Silence compiler version warning
string source = _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source;
@@ -61,7 +63,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false,
SyntaxChecker syntaxChecker(errors);
if (!syntaxChecker.checkSyntax(*sourceUnit))
- return make_pair(sourceUnit, std::make_shared<Error::Type const>(errors[0]->type()));
+ return make_pair(sourceUnit, errors.at(0));
std::shared_ptr<GlobalContext> globalContext = make_shared<GlobalContext>();
NameAndTypeResolver resolver(globalContext->declarations(), errors);
@@ -88,15 +90,21 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false,
TypeChecker typeChecker(errors);
bool success = typeChecker.checkTypeRequirements(*contract);
BOOST_CHECK(success || !errors.empty());
-
}
+ if (success)
+ {
+ StaticAnalyzer staticAnalyzer(errors);
+ staticAnalyzer.analyze(*sourceUnit);
+ }
+ if (errors.size() > 1 && !_allowMultipleErrors)
+ BOOST_FAIL("Multiple errors found");
for (auto const& currentError: errors)
{
if (
(_reportWarnings && currentError->type() == Error::Type::Warning) ||
(!_reportWarnings && currentError->type() != Error::Type::Warning)
)
- return make_pair(sourceUnit, std::make_shared<Error::Type const>(currentError->type()));
+ return make_pair(sourceUnit, currentError);
}
}
catch (InternalCompilerError const& _e)
@@ -108,7 +116,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false,
}
catch (Error const& _e)
{
- return make_pair(sourceUnit, std::make_shared<Error::Type const>(_e.type()));
+ return make_pair(sourceUnit, std::make_shared<Error const>(_e));
}
catch (...)
{
@@ -130,9 +138,9 @@ bool success(string const& _source)
return !parseAnalyseAndReturnError(_source).second;
}
-Error::Type expectError(std::string const& _source, bool _warning = false)
+Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false)
{
- auto sourceAndError = parseAnalyseAndReturnError(_source, _warning);
+ auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple);
BOOST_REQUIRE(!!sourceAndError.second);
BOOST_REQUIRE(!!sourceAndError.first);
return *sourceAndError.second;
@@ -150,113 +158,173 @@ static ContractDefinition const* retrieveContract(ASTPointer<SourceUnit> _source
}
static FunctionTypePointer retrieveFunctionBySignature(
- ContractDefinition const* _contract,
+ ContractDefinition const& _contract,
std::string const& _signature
)
{
FixedHash<4> hash(dev::keccak256(_signature));
- return _contract->interfaceFunctions()[hash];
+ return _contract.interfaceFunctions()[hash];
}
}
+#define CHECK_ERROR_OR_WARNING(text, typ, substring, warning, allowMulti) \
+do \
+{ \
+ Error err = expectError((text), (warning), (allowMulti)); \
+ BOOST_CHECK(err.type() == (Error::Type::typ)); \
+ BOOST_CHECK(searchErrorMessage(err, (substring))); \
+} while(0)
+
+// [checkError(text, type, substring)] asserts that the compilation down to typechecking
+// emits an error of type [type] and with a message containing [substring].
+#define CHECK_ERROR(text, type, substring) \
+CHECK_ERROR_OR_WARNING(text, type, substring, false, false)
+
+// [checkError(text, type, substring)] asserts that the compilation down to typechecking
+// emits an error of type [type] and with a message containing [substring].
+#define CHECK_ERROR_ALLOW_MULTI(text, type, substring) \
+CHECK_ERROR_OR_WARNING(text, type, substring, false, true)
+
+// [checkWarning(text, type, substring)] asserts that the compilation down to typechecking
+// emits a warning of type [type] and with a message containing [substring].
+#define CHECK_WARNING(text, substring) \
+CHECK_ERROR_OR_WARNING(text, Warning, substring, true, false)
+
+// [checkSuccess(text)] asserts that the compilation down to typechecking succeeds.
+#define CHECK_SUCCESS(text) do { BOOST_CHECK(success((text))); } while(0)
+
+#define CHECK_SUCCESS_NO_WARNINGS(text) \
+do \
+{ \
+ auto sourceAndError = parseAnalyseAndReturnError((text), true); \
+ BOOST_CHECK(sourceAndError.second == nullptr); \
+} \
+while(0)
+
+
BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution)
BOOST_AUTO_TEST_CASE(smoke_test)
{
- char const* text = "contract test {\n"
- " uint256 stateVariable1;\n"
- " function fun(uint256 arg1) { uint256 y; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ uint256 stateVariable1;
+ function fun(uint256 arg1) { uint256 y; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(double_stateVariable_declaration)
{
- char const* text = "contract test {\n"
- " uint256 variable;\n"
- " uint128 variable;\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ char const* text = R"(
+ contract test {
+ uint256 variable;
+ uint128 variable;
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(double_function_declaration)
{
- char const* text = "contract test {\n"
- " function fun() { uint x; }\n"
- " function fun() { uint x; }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ char const* text = R"(
+ contract test {
+ function fun() { uint x; }
+ function fun() { uint x; }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(double_variable_declaration)
{
- char const* text = "contract test {\n"
- " function f() { uint256 x; if (true) { uint256 x; } }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ char const* text = R"(
+ contract test {
+ function f() {
+ uint256 x;
+ if (true) { uint256 x; }
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(name_shadowing)
{
- char const* text = "contract test {\n"
- " uint256 variable;\n"
- " function f() { uint32 variable ; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ uint256 variable;
+ function f() { uint32 variable; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(name_references)
{
- char const* text = "contract test {\n"
- " uint256 variable;\n"
- " function f(uint256 arg) returns (uint out) { f(variable); test; out; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ uint256 variable;
+ function f(uint256 arg) returns (uint out) { f(variable); test; out; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(undeclared_name)
{
- char const* text = "contract test {\n"
- " uint256 variable;\n"
- " function f(uint256 arg) { f(notfound); }"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ char const* text = R"(
+ contract test {
+ uint256 variable;
+ function f(uint256 arg) {
+ f(notfound);
+ }
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(reference_to_later_declaration)
{
- char const* text = "contract test {\n"
- " function g() { f(); }"
- " function f() { }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function g() { f(); }
+ function f() {}
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive)
{
- char const* text = "contract test {\n"
- " struct MyStructName {\n"
- " address addr;\n"
- " MyStructName x;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ struct MyStructName {
+ address addr;
+ MyStructName x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
{
- char const* text = "contract test {\n"
- " struct MyStructName1 {\n"
- " address addr;\n"
- " uint256 count;\n"
- " MyStructName2 x;\n"
- " }\n"
- " struct MyStructName2 {\n"
- " MyStructName1 x;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ struct MyStructName1 {
+ address addr;
+ uint256 count;
+ MyStructName2 x;
+ }
+ struct MyStructName2 {
+ MyStructName1 x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive)
@@ -267,184 +335,221 @@ BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive)
struct s2 { s1 x; s1 y; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping)
{
- char const* text = "contract test {\n"
- " struct MyStructName1 {\n"
- " address addr;\n"
- " uint256 count;\n"
- " mapping(uint => MyStructName1) x;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ struct MyStructName1 {
+ address addr;
+ uint256 count;
+ mapping(uint => MyStructName1) x;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_inference_smoke_test)
{
- char const* text = "contract test {\n"
- " function f(uint256 arg1, uint32 arg2) returns (bool ret) { var x = arg1 + arg2 == 8; ret = x; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function f(uint256 arg1, uint32 arg2) returns (bool ret) {
+ var x = arg1 + arg2 == 8; ret = x;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_checking_return)
{
- char const* text = "contract test {\n"
- " function f() returns (bool r) { return 1 >= 2; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function f() returns (bool r) { return 1 >= 2; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number)
{
- char const* text = "contract test {\n"
- " function f() returns (bool r1, bool r2) { return 1 >= 2; }"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ function f() returns (bool r1, bool r2) { return 1 >= 2; }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type)
{
- char const* text = "contract test {\n"
- " function f() returns (uint256 r) { return 1 >= 2; }"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ function f() returns (uint256 r) { return 1 >= 2; }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(type_checking_function_call)
{
- char const* text = "contract test {\n"
- " function f() returns (bool r) { return g(12, true) == 3; }\n"
- " function g(uint256 a, bool b) returns (uint256 r) { }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function f() returns (bool r) { return g(12, true) == 3; }
+ function g(uint256 a, bool b) returns (uint256 r) { }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_conversion_for_comparison)
{
- char const* text = "contract test {\n"
- " function f() { uint32(2) == int64(2); }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function f() { uint32(2) == int64(2); }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid)
{
- char const* text = "contract test {\n"
- " function f() { int32(2) == uint64(2); }"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ function f() { int32(2) == uint64(2); }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion)
{
- char const* text = "contract test {\n"
- " function f() returns (int256 r) { var x = int256(uint32(2)); return x; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function f() returns (int256 r) { var x = int256(uint32(2)); return x; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(large_string_literal)
{
- char const* text = "contract test {\n"
- " function f() { var x = \"123456789012345678901234567890123\"; }"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function f() { var x = "123456789012345678901234567890123"; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(balance)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " uint256 x = address(0).balance;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ function fun() {
+ uint256 x = address(0).balance;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(balance_invalid)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " address(0).balance = 7;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ function fun() {
+ address(0).balance = 7;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_to_mapping)
{
- char const* text = "contract test {\n"
- " struct str {\n"
- " mapping(uint=>uint) map;\n"
- " }\n"
- " str data;"
- " function fun() {\n"
- " var a = data.map;\n"
- " data.map = a;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ struct str {
+ mapping(uint=>uint) map;
+ }
+ str data;
+ function fun() {
+ var a = data.map;
+ data.map = a;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_to_struct)
{
- char const* text = "contract test {\n"
- " struct str {\n"
- " mapping(uint=>uint) map;\n"
- " }\n"
- " str data;"
- " function fun() {\n"
- " var a = data;\n"
- " data = a;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract test {
+ struct str {
+ mapping(uint=>uint) map;
+ }
+ str data;
+ function fun() {
+ var a = data;
+ data = a;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(returns_in_constructor)
{
- char const* text = "contract test {\n"
- " function test() returns (uint a) {\n"
- " }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ function test() returns (uint a) { }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(forward_function_reference)
{
- char const* text = "contract First {\n"
- " function fun() returns (bool ret) {\n"
- " return Second(1).fun(1, true, 3) > 0;\n"
- " }\n"
- "}\n"
- "contract Second {\n"
- " function fun(uint a, bool b, uint c) returns (uint ret) {\n"
- " if (First(2).fun() == true) return 1;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract First {
+ function fun() returns (bool ret) {
+ return Second(1).fun(1, true, 3) > 0;
+ }
+ }
+ contract Second {
+ function fun(uint a, bool b, uint c) returns (uint ret) {
+ if (First(2).fun() == true) return 1;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(comparison_bitop_precedence)
{
- char const* text = "contract First {\n"
- " function fun() returns (bool ret) {\n"
- " return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6;\n"
- " }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract First {
+ function fun() returns (bool ret) {
+ return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_no_implementation)
{
ASTPointer<SourceUnit> sourceUnit;
- char const* text = "contract test {\n"
- " function functionName(bytes32 input) returns (bytes32 out);\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function functionName(bytes32 input) returns (bytes32 out);
+ }
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[1].get());
@@ -459,7 +564,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
char const* text = R"(
contract base { function foo(); }
contract derived is base { function foo() {} }
- )";
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
@@ -478,7 +583,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
char const* text = R"(
contract base { function foo(bool); }
contract derived is base { function foo(uint) {} }
- )";
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
@@ -496,10 +601,10 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract)
contract base { function foo(); }
contract derived {
base b;
- function foo() { b = new base();}
- }
- )";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ function foo() { b = new base(); }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional)
@@ -512,7 +617,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional)
function derived(uint i) BaseBase(i){}
function foo() {}
}
- )";
+ )";
ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Parsing and name resolving failed");
}
@@ -526,7 +631,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided)
function derived(uint i) {}
function foo() {}
}
- )";
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed");
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
BOOST_CHECK_EQUAL(nodes.size(), 4);
@@ -542,8 +647,8 @@ BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract)
contract base { function foo(); }
contract derived is base { function foo() {} }
contract wrong is derived { function foo(); }
- )";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor)
@@ -564,11 +669,13 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor)
BOOST_AUTO_TEST_CASE(function_canonical_signature)
{
ASTPointer<SourceUnit> sourceUnit;
- char const* text = "contract Test {\n"
- " function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) {\n"
- " ret = arg1 + arg2;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract Test {
+ function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) {
+ ret = arg1 + arg2;
+ }
+ }
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@@ -581,11 +688,13 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature)
BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases)
{
ASTPointer<SourceUnit> sourceUnit;
- char const* text = "contract Test {\n"
- " function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) {\n"
- " ret = 5;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract Test {
+ function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) {
+ ret = 5;
+ }
+ }
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@@ -606,9 +715,10 @@ BOOST_AUTO_TEST_CASE(function_external_types)
}
contract Test {
function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg, address[] addresses) external returns (uint ret) {
- ret = 5;
+ ret = 5;
}
- })";
+ }
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@@ -630,7 +740,8 @@ BOOST_AUTO_TEST_CASE(enum_external_type)
function boo(ActionChoices enumArg) external returns (uint ret) {
ret = 5;
}
- })";
+ }
+ )";
ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed");
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@@ -647,13 +758,14 @@ BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion)
char const* text = R"(
contract C {}
contract Test {
- function externalCall() {
+ function externalCall() {
C arg;
this.g(arg);
}
function g (C c) external {}
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion)
@@ -661,13 +773,14 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion)
char const* text = R"(
contract C {}
contract Test {
- function externalCall() {
+ function externalCall() {
address arg;
this.g(arg);
}
function g (C c) external {}
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion)
@@ -682,8 +795,9 @@ BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion)
function internalCall() {
g(a);
}
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion)
@@ -698,19 +812,20 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion)
function internalCall() {
g(a);
}
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(hash_collision_in_interface)
{
- char const* text = "contract test {\n"
- " function gsf() {\n"
- " }\n"
- " function tgeo() {\n"
- " }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract test {
+ function gsf() { }
+ function tgeo() { }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(inheritance_basic)
@@ -722,7 +837,7 @@ BOOST_AUTO_TEST_CASE(inheritance_basic)
function f() { baseMember = 7; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inheritance_diamond_basic)
@@ -735,7 +850,7 @@ BOOST_AUTO_TEST_CASE(inheritance_diamond_basic)
function g() { f(); rootFunction(); }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(cyclic_inheritance)
@@ -744,7 +859,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance)
contract A is B { }
contract B is A { }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR_ALLOW_MULTI(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(legal_override_direct)
@@ -753,7 +868,7 @@ BOOST_AUTO_TEST_CASE(legal_override_direct)
contract B { function f() {} }
contract C is B { function f(uint i) {} }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(legal_override_indirect)
@@ -763,7 +878,7 @@ BOOST_AUTO_TEST_CASE(legal_override_indirect)
contract B { function f() {} }
contract C is A, B { }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(illegal_override_visibility)
@@ -772,7 +887,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_visibility)
contract B { function f() internal {} }
contract C is B { function f() public {} }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(illegal_override_constness)
@@ -781,7 +896,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_constness)
contract B { function f() constant {} }
contract C is B { function f() {} }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(complex_inheritance)
@@ -791,7 +906,7 @@ BOOST_AUTO_TEST_CASE(complex_inheritance)
contract B { function f() {} function g() returns (uint8 r) {} }
contract C is A, B { }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(constructor_visibility)
@@ -801,7 +916,7 @@ BOOST_AUTO_TEST_CASE(constructor_visibility)
contract A { function A() { } }
contract B is A { function f() { A x = A(0); } }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(overriding_constructor)
@@ -811,7 +926,7 @@ BOOST_AUTO_TEST_CASE(overriding_constructor)
contract A { function A() { } }
contract B is A { function A() returns (uint8 r) {} }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments)
@@ -820,7 +935,7 @@ BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments)
contract A { function A(uint a) { } }
contract B is A { }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(base_constructor_arguments_override)
@@ -829,7 +944,7 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments_override)
contract A { function A(uint a) { } }
contract B is A { }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion)
@@ -840,7 +955,7 @@ BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion)
function f() { A a = B(1); }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion)
@@ -851,7 +966,7 @@ BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion)
function f() { B b = A(1); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(super_excludes_current_contract)
@@ -868,7 +983,7 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract)
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation)
@@ -880,7 +995,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation)
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_function_modifier_type)
@@ -891,7 +1006,7 @@ BOOST_AUTO_TEST_CASE(invalid_function_modifier_type)
modifier mod1(uint a) { if (a > 0) _; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters)
@@ -903,7 +1018,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters)
modifier mod2(bytes7 a) { while (a == "1234567") _; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
@@ -914,7 +1029,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables)
modifier mod(uint a) { if (a > 0) _; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(legal_modifier_override)
@@ -923,7 +1038,7 @@ BOOST_AUTO_TEST_CASE(legal_modifier_override)
contract A { modifier mod(uint a) { _; } }
contract B is A { modifier mod(uint a) { _; } }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(illegal_modifier_override)
@@ -932,7 +1047,7 @@ BOOST_AUTO_TEST_CASE(illegal_modifier_override)
contract A { modifier mod(uint a) { _; } }
contract B is A { modifier mod(uint8 a) { _; } }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(modifier_overrides_function)
@@ -941,7 +1056,7 @@ BOOST_AUTO_TEST_CASE(modifier_overrides_function)
contract A { modifier mod(uint a) { _; } }
contract B is A { function mod(uint a) { } }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_overrides_modifier)
@@ -950,7 +1065,7 @@ BOOST_AUTO_TEST_CASE(function_overrides_modifier)
contract A { function mod(uint a) { } }
contract B is A { modifier mod(uint a) { _; } }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(modifier_returns_value)
@@ -961,31 +1076,33 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value)
modifier mod(uint a) { _; return 7; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(state_variable_accessors)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "uint256 public foo;\n"
- "mapping(uint=>bytes4) public map;\n"
- "mapping(uint=>mapping(uint=>bytes4)) public multiple_map;\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun() {
+ uint64(2);
+ }
+ uint256 public foo;
+ mapping(uint=>bytes4) public map;
+ mapping(uint=>mapping(uint=>bytes4)) public multiple_map;
+ }
+ )";
ASTPointer<SourceUnit> source;
ContractDefinition const* contract;
ETH_TEST_CHECK_NO_THROW(source = parseAndAnalyse(text), "Parsing and Resolving names failed");
BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr);
- FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()");
+ FunctionTypePointer function = retrieveFunctionBySignature(*contract, "foo()");
BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->returnParameterTypeNames(false);
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
BOOST_CHECK(function->isConstant());
- function = retrieveFunctionBySignature(contract, "map(uint256)");
+ function = retrieveFunctionBySignature(*contract, "map(uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
auto params = function->parameterTypeNames(false);
BOOST_CHECK_EQUAL(params.at(0), "uint256");
@@ -993,7 +1110,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4");
BOOST_CHECK(function->isConstant());
- function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)");
+ function = retrieveFunctionBySignature(*contract, "multiple_map(uint256,uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
params = function->parameterTypeNames(false);
BOOST_CHECK_EQUAL(params.at(0), "uint256");
@@ -1005,34 +1122,38 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "uint256 foo;\n"
- " function foo() {}\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ char const* text = R"(
+ contract test {
+ function fun() {
+ uint64(2);
+ }
+ uint256 foo;
+ function foo() {}
+ }
+ )";
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(private_state_variable)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "uint256 private foo;\n"
- "uint256 internal bar;\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun() {
+ uint64(2);
+ }
+ uint256 private foo;
+ uint256 internal bar;
+ }
+ )";
ASTPointer<SourceUnit> source;
ContractDefinition const* contract;
ETH_TEST_CHECK_NO_THROW(source = parseAndAnalyse(text), "Parsing and Resolving names failed");
BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr);
FunctionTypePointer function;
- function = retrieveFunctionBySignature(contract, "foo()");
+ function = retrieveFunctionBySignature(*contract, "foo()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist");
- function = retrieveFunctionBySignature(contract, "bar()");
+ function = retrieveFunctionBySignature(*contract, "bar()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist");
}
@@ -1045,71 +1166,79 @@ BOOST_AUTO_TEST_CASE(missing_state_variable)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor)
{
// test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126
- char const* text = "contract Parent {\n"
- " uint256 public m_aMember;\n"
- "}\n"
- "contract Child is Parent{\n"
- " function foo() returns (uint256) { return Parent.m_aMember; }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract Parent {
+ uint256 public m_aMember;
+ }
+ contract Child is Parent {
+ function foo() returns (uint256) { return Parent.m_aMember; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only)
{
char const* sourceCode = R"(
contract test {
- struct Data { uint[15] m_array; }
+ struct Data { uint[15] m_array; }
Data public data;
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member)
{
- char const* text = "contract Parent {\n"
- " uint256 internal m_aMember;\n"
- "}\n"
- "contract Child is Parent{\n"
- " function foo() returns (uint256) { return Parent.m_aMember; }\n"
- "}\n";
- BOOST_CHECK(success(text));
+ char const* text = R"(
+ contract Parent {
+ uint256 internal m_aMember;
+ }
+ contract Child is Parent{
+ function foo() returns (uint256) { return Parent.m_aMember; }
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1)
{
- char const* text = "contract Parent1 {\n"
- " uint256 internal m_aMember1;\n"
- "}\n"
- "contract Parent2 is Parent1{\n"
- " uint256 internal m_aMember2;\n"
- "}\n"
- "contract Child is Parent2{\n"
- " function foo() returns (uint256) { return Parent2.m_aMember1; }\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract Parent1 {
+ uint256 internal m_aMember1;
+ }
+ contract Parent2 is Parent1{
+ uint256 internal m_aMember2;
+ }
+ contract Child is Parent2{
+ function foo() returns (uint256) { return Parent2.m_aMember1; }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2)
{
- char const* text = "contract Parent1 {\n"
- " uint256 internal m_aMember1;\n"
- "}\n"
- "contract Parent2 is Parent1{\n"
- " uint256 internal m_aMember2;\n"
- "}\n"
- "contract Child is Parent2{\n"
- " function foo() returns (uint256) { return Child.m_aMember2; }\n"
- " uint256 public m_aMember3;\n"
- "}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ char const* text = R"(
+ contract Parent1 {
+ uint256 internal m_aMember1;
+ }
+ contract Parent2 is Parent1 {
+ uint256 internal m_aMember2;
+ }
+ contract Child is Parent2 {
+ function foo() returns (uint256) { return Child.m_aMember2; }
+ uint256 public m_aMember3;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function)
@@ -1120,7 +1249,7 @@ BOOST_AUTO_TEST_CASE(fallback_function)
function() { x = 2; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(fallback_function_with_arguments)
@@ -1131,7 +1260,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments)
function(uint a) { x = 2; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function_in_library)
@@ -1141,7 +1270,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_in_library)
function() {}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
@@ -1151,7 +1280,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
function() returns (uint) { }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier)
@@ -1162,7 +1291,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier)
function() constant { x = 2; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function_twice)
@@ -1174,7 +1303,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice)
function() { x = 3; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function_inheritance)
@@ -1188,7 +1317,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_inheritance)
function() { x = 2; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(event)
@@ -1197,8 +1326,9 @@ BOOST_AUTO_TEST_CASE(event)
contract c {
event e(uint indexed a, bytes3 indexed s, bool indexed b);
function f() { e(2, "abc", true); }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(event_too_many_indexed)
@@ -1206,8 +1336,9 @@ BOOST_AUTO_TEST_CASE(event_too_many_indexed)
char const* text = R"(
contract c {
event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d);
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed)
@@ -1215,8 +1346,9 @@ BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed)
char const* text = R"(
contract c {
event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d) anonymous;
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed)
@@ -1224,8 +1356,9 @@ BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed)
char const* text = R"(
contract c {
event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous;
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(event_call)
@@ -1234,8 +1367,9 @@ BOOST_AUTO_TEST_CASE(event_call)
contract c {
event e(uint a, bytes3 indexed s, bool indexed b);
function f() { e(2, "abc", true); }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(event_inheritance)
@@ -1246,8 +1380,9 @@ BOOST_AUTO_TEST_CASE(event_inheritance)
}
contract c is base {
function f() { e(2, "abc", true); }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(multiple_events_argument_clash)
@@ -1256,8 +1391,9 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash)
contract c {
event e1(uint a, uint e1, uint e2);
event e2(uint a, uint e1, uint e2);
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(access_to_default_function_visibility)
@@ -1268,8 +1404,9 @@ BOOST_AUTO_TEST_CASE(access_to_default_function_visibility)
}
contract d {
function g() { c(0).f(); }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(access_to_internal_function)
@@ -1280,8 +1417,9 @@ BOOST_AUTO_TEST_CASE(access_to_internal_function)
}
contract d {
function g() { c(0).f(); }
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility)
@@ -1292,8 +1430,9 @@ BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility)
}
contract d {
function g() { c(0).a(); }
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(access_to_internal_state_variable)
@@ -1304,115 +1443,146 @@ BOOST_AUTO_TEST_CASE(access_to_internal_state_variable)
}
contract d {
function g() { c(0).a(); }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(error_count_in_named_args)
{
- char const* sourceCode = "contract test {\n"
- " function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
- " function b() returns (uint r) { r = a({a: 1}); }\n"
- "}\n";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ char const* sourceCode = R"(
+ contract test {
+ function a(uint a, uint b) returns (uint r) {
+ r = a + b;
+ }
+ function b() returns (uint r) {
+ r = a({a: 1});
+ }
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(empty_in_named_args)
{
- char const* sourceCode = "contract test {\n"
- " function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
- " function b() returns (uint r) { r = a({}); }\n"
- "}\n";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ char const* sourceCode = R"(
+ contract test {
+ function a(uint a, uint b) returns (uint r) {
+ r = a + b;
+ }
+ function b() returns (uint r) {
+ r = a({});
+ }
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args)
{
- char const* sourceCode = "contract test {\n"
- " function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
- " function b() returns (uint r) { r = a({a: 1, a: 2}); }\n"
- "}\n";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ char const* sourceCode = R"(
+ contract test {
+ function a(uint a, uint b) returns (uint r) {
+ r = a + b;
+ }
+ function b() returns (uint r) {
+ r = a({a: 1, a: 2});
+ }
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args)
{
- char const* sourceCode = "contract test {\n"
- " function a(uint a, uint b) returns (uint r) { r = a + b; }\n"
- " function b() returns (uint r) { r = a({a: 1, c: 2}); }\n"
- "}\n";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ char const* sourceCode = R"(
+ contract test {
+ function a(uint a, uint b) returns (uint r) {
+ r = a + b;
+ }
+ function b() returns (uint r) {
+ r = a({a: 1, c: 2});
+ }
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter)
{
char const* text = R"(
contract test {
- function f(uint){
+ function f(uint) { }
}
- })";
- BOOST_CHECK(success(text));
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
{
char const* text = R"(
contract test {
- function f() returns(bool){
+ function f() returns(bool) { }
}
- })";
- BOOST_CHECK(success(text));
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
{
char const* text = R"(
contract test {
- function f(uint, uint k) returns(uint ret_k){
+ function f(uint, uint k) returns(uint ret_k) {
return k;
+ }
}
- })";
- BOOST_CHECK(success(text));
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one)
{
char const* text = R"(
contract test {
- function f() returns(uint ret_k, uint){
+ function f() returns(uint ret_k, uint) {
return 5;
+ }
}
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type)
{
- char const* sourceCode = "contract c { function f() { var (x) = f(); } }";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ char const* sourceCode = R"(
+ contract c {
+ function f() { var (x) = f(); }
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units)
{
char const* sourceCodeFine = R"(
contract c {
- function c ()
- {
- a = 115792089237316195423570985008687907853269984665640564039458;
+ function c () {
+ a = 115792089237316195423570985008687907853269984665640564039458;
}
uint256 a;
- })";
+ }
+ )";
ETH_TEST_CHECK_NO_THROW(parseAndAnalyse(sourceCodeFine),
"Parsing and Resolving names failed");
char const* sourceCode = R"(
contract c {
- function c ()
- {
+ function c () {
a = 115792089237316195423570985008687907853269984665640564039458 ether;
}
uint256 a;
- })";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big)
@@ -1420,119 +1590,127 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big)
char const* sourceCode = R"(
contract test {
function f() returns(uint d) { return 2 ** 10000000000; }
- })";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(enum_member_access)
{
char const* text = R"(
- contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
- function test()
- {
- choices = ActionChoices.GoStraight;
- }
- ActionChoices choices;
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test()
+ {
+ choices = ActionChoices.GoStraight;
}
+ ActionChoices choices;
+ }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts)
{
char const* text = R"(
- contract Interface {
- enum MyEnum { One, Two }
- }
- contract Impl {
- function test() returns (Interface.MyEnum) {
- return Interface.MyEnum.One;
- }
+ contract Interface {
+ enum MyEnum { One, Two }
+ }
+ contract Impl {
+ function test() returns (Interface.MyEnum) {
+ return Interface.MyEnum.One;
}
+ }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(enum_invalid_member_access)
{
char const* text = R"(
- contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
- function test()
- {
- choices = ActionChoices.RunAroundWavingYourHands;
- }
- ActionChoices choices;
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test() {
+ choices = ActionChoices.RunAroundWavingYourHands;
}
+ ActionChoices choices;
+ }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access)
{
char const* text = R"(
- contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
- function test()
- {
- choices = Sit;
- }
- ActionChoices choices;
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test() {
+ choices = Sit;
}
+ ActionChoices choices;
+ }
)";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay)
{
char const* text = R"(
- contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
- function test()
- {
- a = uint256(ActionChoices.GoStraight);
- b = uint64(ActionChoices.Sit);
- }
- uint256 a;
- uint64 b;
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test() {
+ a = uint256(ActionChoices.GoStraight);
+ b = uint64(ActionChoices.Sit);
}
+ uint256 a;
+ uint64 b;
+ }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay)
{
char const* text = R"(
- contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
- function test()
- {
- a = 2;
- b = ActionChoices(a);
- }
- uint256 a;
- ActionChoices b;
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test() {
+ a = 2;
+ b = ActionChoices(a);
}
+ uint256 a;
+ ActionChoices b;
+ }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
-BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay)
+BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_256)
{
char const* text = R"(
- contract test {
- enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
- function test()
- {
- a = ActionChoices.GoStraight;
- b = ActionChoices.Sit;
- }
- uint256 a;
- uint64 b;
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test() {
+ a = ActionChoices.GoStraight;
}
+ uint256 a;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_64)
+{
+ char const* text = R"(
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
+ function test() {
+ b = ActionChoices.Sit;
+ }
+ uint64 b;
+ }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay)
@@ -1541,13 +1719,12 @@ BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay)
contract test {
enum Paper { Up, Down, Left, Right }
enum Ground { North, South, West, East }
- function test()
- {
+ function test() {
Ground(Paper.Up);
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(enum_duplicate_values)
@@ -1557,7 +1734,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values)
enum ActionChoices { GoLeft, GoRight, GoLeft, Sit }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name)
@@ -1574,7 +1751,7 @@ BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(private_visibility)
@@ -1586,8 +1763,8 @@ BOOST_AUTO_TEST_CASE(private_visibility)
contract derived is base {
function g() { f(); }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ )";
+ CHECK_ERROR(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access)
@@ -1599,8 +1776,8 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access)
contract derived is base {
function g() { base.f(); }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_visibility)
@@ -1610,8 +1787,8 @@ BOOST_AUTO_TEST_CASE(external_visibility)
function f() external {}
function g() { f(); }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ )";
+ CHECK_ERROR(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(external_base_visibility)
@@ -1623,8 +1800,8 @@ BOOST_AUTO_TEST_CASE(external_base_visibility)
contract derived is base {
function g() { base.f(); }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_argument_assign)
@@ -1633,8 +1810,8 @@ BOOST_AUTO_TEST_CASE(external_argument_assign)
contract c {
function f(uint a) external { a = 1; }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_argument_increment)
@@ -1643,8 +1820,8 @@ BOOST_AUTO_TEST_CASE(external_argument_increment)
contract c {
function f(uint a) external { a++; }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_argument_delete)
@@ -1653,8 +1830,8 @@ BOOST_AUTO_TEST_CASE(external_argument_delete)
contract c {
function f(uint a) external { delete a; }
}
- )";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type)
@@ -1666,7 +1843,7 @@ BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type)
contract Bike is Vehicle {
function f(bytes _a) external returns (uint256 r) {r = 42;}
}
- )";
+ )";
ETH_TEST_CHECK_NO_THROW(parseAndAnalyse(sourceCode), "Parsing and Name Resolving failed");
}
@@ -1675,8 +1852,9 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length)
char const* text = R"(
contract c {
function f(uint a) { uint8[a] x; }
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types1)
@@ -1686,8 +1864,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1)
bytes a;
uint[] b;
function f() { b = a; }
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types2)
@@ -1697,8 +1876,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2)
uint32[] a;
uint8[] b;
function f() { b = a; }
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible)
@@ -1708,8 +1888,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible)
uint32[] a;
uint8[] b;
function f() { a = b; }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic)
@@ -1719,8 +1900,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic)
uint32[] a;
uint8[80] b;
function f() { a = b; }
- })";
- BOOST_CHECK(success(text));
+ }
+ )";
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static)
@@ -1730,8 +1912,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static)
uint[] a;
uint[80] b;
function f() { b = a; }
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int)
@@ -1739,8 +1922,9 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int)
char const* text = R"(
contract c {
uint8 a = 1000;
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string)
@@ -1748,8 +1932,9 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string)
char const* text = R"(
contract c {
uint a = "abc";
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName)
@@ -1864,7 +2049,8 @@ BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1)
contract c {
bytes arr;
function f() { byte a = arr[0];}
- })";
+ }
+ )";
ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Type resolving failed");
}
@@ -1874,8 +2060,9 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable)
contract Foo {
function changeIt() { x = 9; }
uint constant x = 56;
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(complex_const_variable)
@@ -1883,9 +2070,11 @@ BOOST_AUTO_TEST_CASE(complex_const_variable)
//for now constant specifier is valid only for uint bytesXX and enums
char const* text = R"(
contract Foo {
- mapping(uint => bool) constant mapVar;
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ mapping(uint => bool) x;
+ mapping(uint => bool) constant mapVar = x;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(uninitialized_const_variable)
@@ -1893,8 +2082,9 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable)
char const* text = R"(
contract Foo {
uint constant y;
- })";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve)
@@ -1906,7 +2096,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve)
function g() returns(uint) { return f(3, 5); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function)
@@ -1919,7 +2109,7 @@ BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function)
function g() returns(uint) { return f(1); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function)
@@ -1942,7 +2132,7 @@ BOOST_AUTO_TEST_CASE(assignment_of_overloaded_function)
function g() returns(uint) { var x = f; return x(7); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_types_clash)
@@ -1956,7 +2146,7 @@ BOOST_AUTO_TEST_CASE(external_types_clash)
function f(uint8 a) { }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(override_changes_return_types)
@@ -1969,7 +2159,7 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types)
function f(uint a) returns (uint8) { }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multiple_constructors)
@@ -1980,18 +2170,18 @@ BOOST_AUTO_TEST_CASE(multiple_constructors)
function test() {}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ CHECK_ERROR(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(equal_overload)
{
char const* sourceCode = R"(
- contract test {
+ contract C {
function test(uint a) returns (uint b) { }
function test(uint a) external {}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ CHECK_ERROR_ALLOW_MULTI(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(uninitialized_var)
@@ -2001,7 +2191,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_var)
function f() returns (uint) { var x; return 2; }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(string)
@@ -2015,6 +2205,26 @@ BOOST_AUTO_TEST_CASE(string)
BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode));
}
+BOOST_AUTO_TEST_CASE(invalid_utf8_implicit)
+{
+ char const* sourceCode = R"(
+ contract C {
+ string s = "\xa0\x00";
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "invalid UTF-8");
+}
+
+BOOST_AUTO_TEST_CASE(invalid_utf8_explicit)
+{
+ char const* sourceCode = R"(
+ contract C {
+ string s = string("\xa0\x00");
+ }
+ )";
+ CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed");
+}
+
BOOST_AUTO_TEST_CASE(string_index)
{
char const* sourceCode = R"(
@@ -2023,7 +2233,7 @@ BOOST_AUTO_TEST_CASE(string_index)
function f() { var a = s[2]; }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(string_length)
@@ -2034,7 +2244,7 @@ BOOST_AUTO_TEST_CASE(string_length)
function f() { var a = s.length; }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound)
@@ -2044,7 +2254,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound)
int8 public i = -129;
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(negative_integers_to_signed_min)
@@ -2064,7 +2274,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound)
int8 public j = 128;
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound_max)
@@ -2084,7 +2294,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_unsigned)
uint8 public x = -1;
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound)
@@ -2094,7 +2304,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound)
uint8 public x = 700;
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(integer_boolean_operators)
@@ -2102,15 +2312,15 @@ BOOST_AUTO_TEST_CASE(integer_boolean_operators)
char const* sourceCode1 = R"(
contract test { function() { uint x = 1; uint y = 2; x || y; } }
)";
- BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode1, TypeError, "");
char const* sourceCode2 = R"(
contract test { function() { uint x = 1; uint y = 2; x && y; } }
)";
- BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode2, TypeError, "");
char const* sourceCode3 = R"(
contract test { function() { uint x = 1; !x; } }
)";
- BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode3, TypeError, "");
}
BOOST_AUTO_TEST_CASE(exp_signed_variable)
@@ -2118,15 +2328,15 @@ BOOST_AUTO_TEST_CASE(exp_signed_variable)
char const* sourceCode1 = R"(
contract test { function() { uint x = 3; int y = -4; x ** y; } }
)";
- BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode1, TypeError, "");
char const* sourceCode2 = R"(
contract test { function() { uint x = 3; int y = -4; y ** x; } }
)";
- BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode2, TypeError, "");
char const* sourceCode3 = R"(
contract test { function() { int x = -3; int y = -4; x ** y; } }
)";
- BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode3, TypeError, "");
}
BOOST_AUTO_TEST_CASE(reference_compare_operators)
@@ -2134,11 +2344,11 @@ BOOST_AUTO_TEST_CASE(reference_compare_operators)
char const* sourceCode1 = R"(
contract test { bytes a; bytes b; function() { a == b; } }
)";
- BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode1, TypeError, "");
char const* sourceCode2 = R"(
contract test { struct s {uint a;} s x; s y; function() { x == y; } }
)";
- BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode2, TypeError, "");
}
BOOST_AUTO_TEST_CASE(overwrite_memory_location_external)
@@ -2148,7 +2358,7 @@ BOOST_AUTO_TEST_CASE(overwrite_memory_location_external)
function f(uint[] memory a) external {}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(overwrite_storage_location_external)
@@ -2158,7 +2368,7 @@ BOOST_AUTO_TEST_CASE(overwrite_storage_location_external)
function f(uint[] storage a) external {}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(storage_location_local_variables)
@@ -2184,7 +2394,7 @@ BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable)
@@ -2198,7 +2408,7 @@ BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable)
@@ -2215,7 +2425,7 @@ BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers)
@@ -2229,7 +2439,7 @@ BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly)
@@ -2256,7 +2466,7 @@ BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem)
@@ -2285,7 +2495,7 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible)
@@ -2300,7 +2510,7 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable)
@@ -2313,7 +2523,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable)
}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(struct_constructor)
@@ -2367,7 +2577,7 @@ BOOST_AUTO_TEST_CASE(literal_strings)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp)
@@ -2379,7 +2589,7 @@ BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
@@ -2394,7 +2604,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
@@ -2411,7 +2621,7 @@ BOOST_AUTO_TEST_CASE(string_bytes_conversion)
function m() internal { string(b); }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inheriting_from_library)
@@ -2420,7 +2630,7 @@ BOOST_AUTO_TEST_CASE(inheriting_from_library)
library Lib {}
contract Test is Lib {}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(inheriting_library)
@@ -2429,7 +2639,7 @@ BOOST_AUTO_TEST_CASE(inheriting_library)
contract Test {}
library Lib is Test {}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(library_having_variables)
@@ -2437,7 +2647,7 @@ BOOST_AUTO_TEST_CASE(library_having_variables)
char const* text = R"(
library Lib { uint x; }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(valid_library)
@@ -2445,7 +2655,7 @@ BOOST_AUTO_TEST_CASE(valid_library)
char const* text = R"(
library Lib { uint constant x = 9; }
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(call_to_library_function)
@@ -2460,7 +2670,7 @@ BOOST_AUTO_TEST_CASE(call_to_library_function)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract)
@@ -2470,7 +2680,7 @@ BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract)
function f() { var x = new Test(); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(array_out_of_bound_access)
@@ -2484,7 +2694,7 @@ BOOST_AUTO_TEST_CASE(array_out_of_bound_access)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer)
@@ -2494,7 +2704,7 @@ BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer)
function f() { string x = "abc"; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(non_initialized_references)
@@ -2513,7 +2723,7 @@ BOOST_AUTO_TEST_CASE(non_initialized_references)
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Uninitialized storage pointer");
}
BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant)
@@ -2524,7 +2734,7 @@ BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant)
function f() { sha3(2**500); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(cyclic_binary_dependency)
@@ -2534,7 +2744,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency)
contract B { function f() { new C(); } }
contract C { function f() { new A(); } }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance)
@@ -2544,7 +2754,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance)
contract B { function f() { new C(); } }
contract C { function f() { new A(); } }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail)
@@ -2552,7 +2762,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail)
char const* text = R"(
contract C { function f() { var (x,y); } }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine)
@@ -2572,7 +2782,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1)
@@ -2583,7 +2793,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1)
function f() { var (a, b, ) = one(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2)
{
@@ -2593,7 +2803,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2)
function f() { var (a, , ) = one(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3)
@@ -2604,7 +2814,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3)
function f() { var (, , a) = one(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4)
@@ -2615,7 +2825,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4)
function f() { var (, a, b) = one(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(tuples)
@@ -2630,7 +2840,7 @@ BOOST_AUTO_TEST_CASE(tuples)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(tuples_empty_components)
@@ -2642,7 +2852,7 @@ BOOST_AUTO_TEST_CASE(tuples_empty_components)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5)
@@ -2653,7 +2863,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5)
function f() { var (,) = one(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6)
@@ -2664,7 +2874,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6)
function f() { var (a, b, c) = two(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity)
@@ -2685,7 +2895,7 @@ BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_library)
@@ -2696,7 +2906,7 @@ BOOST_AUTO_TEST_CASE(using_for_library)
using D for uint;
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_not_library)
@@ -2707,7 +2917,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_library)
using D for uint;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(using_for_function_exists)
@@ -2721,7 +2931,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_exists)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_function_on_int)
@@ -2735,7 +2945,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_function_on_struct)
@@ -2750,7 +2960,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_overload)
@@ -2769,7 +2979,7 @@ BOOST_AUTO_TEST_CASE(using_for_overload)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_by_name)
@@ -2784,7 +2994,7 @@ BOOST_AUTO_TEST_CASE(using_for_by_name)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_mismatch)
@@ -2798,7 +3008,7 @@ BOOST_AUTO_TEST_CASE(using_for_mismatch)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(using_for_not_used)
@@ -2814,7 +3024,18 @@ BOOST_AUTO_TEST_CASE(using_for_not_used)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(library_memory_struct)
+{
+ char const* text = R"(
+ library c {
+ struct S { uint x; }
+ function f() returns (S ) {}
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch)
@@ -2829,7 +3050,7 @@ BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(bound_function_in_var)
@@ -2845,7 +3066,7 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(create_memory_arrays)
@@ -2863,7 +3084,7 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(mapping_in_memory_array)
@@ -2875,7 +3096,7 @@ BOOST_AUTO_TEST_CASE(mapping_in_memory_array)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(new_for_non_array)
@@ -2887,7 +3108,7 @@ BOOST_AUTO_TEST_CASE(new_for_non_array)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array)
@@ -2899,7 +3120,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_overload_array_type)
@@ -2910,7 +3131,7 @@ BOOST_AUTO_TEST_CASE(function_overload_array_type)
function f(int[] values);
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion)
@@ -2926,7 +3147,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_strings)
@@ -2941,7 +3162,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_st
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_declaration_const_int_conversion)
@@ -2954,7 +3175,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_const_int_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_declaration_const_string_conversion)
@@ -2967,7 +3188,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_const_string_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type)
@@ -2979,7 +3200,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings)
@@ -2991,7 +3212,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_struct_declaration_arrays)
@@ -3007,7 +3228,7 @@ BOOST_AUTO_TEST_CASE(inline_struct_declaration_arrays)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array)
@@ -3019,7 +3240,7 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(dynamic_inline_array)
@@ -3031,7 +3252,7 @@ BOOST_AUTO_TEST_CASE(dynamic_inline_array)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(lvalues_as_inline_array)
@@ -3044,7 +3265,7 @@ BOOST_AUTO_TEST_CASE(lvalues_as_inline_array)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(break_not_in_loop)
@@ -3057,7 +3278,7 @@ BOOST_AUTO_TEST_CASE(break_not_in_loop)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::SyntaxError);
+ CHECK_ERROR(text, SyntaxError, "");
}
BOOST_AUTO_TEST_CASE(continue_not_in_loop)
@@ -3070,7 +3291,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::SyntaxError);
+ CHECK_ERROR(text, SyntaxError, "");
}
BOOST_AUTO_TEST_CASE(continue_not_in_loop_2)
@@ -3085,7 +3306,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop_2)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::SyntaxError);
+ CHECK_ERROR(text, SyntaxError, "");
}
BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression)
@@ -3097,7 +3318,7 @@ BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet)
@@ -3111,7 +3332,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR_ALLOW_MULTI(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct)
@@ -3125,13 +3346,13 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct)
uint x;
}
function f() {
- s1 x;
- s2 y;
+ s1 memory x;
+ s2 memory y;
true ? x : y;
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type)
@@ -3146,7 +3367,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum)
@@ -3164,7 +3385,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping)
@@ -3179,7 +3400,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_with_all_types)
@@ -3261,7 +3482,7 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count)
@@ -3276,7 +3497,7 @@ BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count)
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(index_access_for_bytes)
@@ -3289,7 +3510,7 @@ BOOST_AUTO_TEST_CASE(index_access_for_bytes)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier)
@@ -3305,7 +3526,7 @@ BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(varM_disqualified_as_keyword)
@@ -3343,7 +3564,7 @@ BOOST_AUTO_TEST_CASE(bytes10abc_is_identifier)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(int10abc_is_identifier)
@@ -3356,7 +3577,7 @@ BOOST_AUTO_TEST_CASE(int10abc_is_identifier)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(library_functions_do_not_have_value)
@@ -3440,7 +3661,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_int_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion)
@@ -3453,7 +3674,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion)
@@ -3466,7 +3687,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed)
@@ -3492,7 +3713,7 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert)
@@ -3507,7 +3728,7 @@ BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
@@ -3524,7 +3745,7 @@ BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size)
@@ -3563,7 +3784,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational)
@@ -3607,7 +3828,7 @@ BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
char const* text = R"(
contract test {
function f() {
- fixed a = 3.2;
+ fixed a = 3.25;
bytes32 c = a;
}
}
@@ -3625,7 +3846,7 @@ BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(fixed_points_inside_structs)
@@ -3639,7 +3860,7 @@ BOOST_AUTO_TEST_CASE(fixed_points_inside_structs)
myStruct a = myStruct(3.125, 3);
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_fixed_types)
@@ -3651,7 +3872,7 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_types)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_rationals)
@@ -3663,7 +3884,7 @@ BOOST_AUTO_TEST_CASE(inline_array_rationals)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(rational_index_access)
@@ -3694,17 +3915,50 @@ BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
-BOOST_AUTO_TEST_CASE(rational_as_exponent_value)
+BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_decimal)
{
char const* text = R"(
contract test {
function f() {
fixed g = 2 ** -2.2;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_as_exponent_value_pos_decimal)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
ufixed b = 3 ** 2.5;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_as_exponent_half)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
ufixed24x24 b = 2 ** (1/2);
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_quarter)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
fixed40x40 c = 42 ** (-1/4);
}
}
@@ -3712,15 +3966,48 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value)
BOOST_CHECK(!success(text));
}
-BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents)
+BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_15)
{
char const* text = R"(
contract test {
function f() {
ufixed a = 3 ** ufixed(1.5);
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_half)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
ufixed b = 2 ** ufixed(1/2);
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
fixed c = 42 ** fixed(-1/4);
- fixed d = 16 ** fixed(-0.33);
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg_decimal)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed d = 16 ** fixed(-0.5);
}
}
)";
@@ -3738,7 +4025,7 @@ BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(var_and_rational_with_tuple)
@@ -3750,7 +4037,7 @@ BOOST_AUTO_TEST_CASE(var_and_rational_with_tuple)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(var_handle_divided_integers)
@@ -3762,7 +4049,7 @@ BOOST_AUTO_TEST_CASE(var_handle_divided_integers)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation)
@@ -3770,7 +4057,7 @@ BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = ~3.56;
+ fixed a = ~3.5;
}
}
)";
@@ -3782,7 +4069,7 @@ BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = 1.56 | 3;
+ fixed a = 1.5 | 3;
}
}
)";
@@ -3794,7 +4081,7 @@ BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = 1.56 ^ 3;
+ fixed a = 1.75 ^ 3;
}
}
)";
@@ -3806,7 +4093,7 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = 1.56 & 3;
+ fixed a = 1.75 & 3;
}
}
)";
@@ -3823,7 +4110,7 @@ BOOST_AUTO_TEST_CASE(zero_handling)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(missing_bool_conversion)
@@ -3835,7 +4122,7 @@ BOOST_AUTO_TEST_CASE(missing_bool_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction)
@@ -3847,7 +4134,7 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(signed_rational_modulus)
@@ -3861,7 +4148,7 @@ BOOST_AUTO_TEST_CASE(signed_rational_modulus)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(one_divided_by_three_integer_conversion)
@@ -3886,7 +4173,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(unused_return_value_send)
@@ -3898,7 +4185,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_send)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Return value of low-level calls not used");
}
BOOST_AUTO_TEST_CASE(unused_return_value_call)
@@ -3910,7 +4197,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Return value of low-level calls not used");
}
BOOST_AUTO_TEST_CASE(unused_return_value_call_value)
@@ -3922,7 +4209,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call_value)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Return value of low-level calls not used");
}
BOOST_AUTO_TEST_CASE(unused_return_value_callcode)
@@ -3934,7 +4221,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_callcode)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Return value of low-level calls not used");
}
BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall)
@@ -3946,7 +4233,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Return value of low-level calls not used");
}
BOOST_AUTO_TEST_CASE(modifier_without_underscore)
@@ -3956,7 +4243,7 @@ BOOST_AUTO_TEST_CASE(modifier_without_underscore)
modifier m() {}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::SyntaxError);
+ CHECK_ERROR(text, SyntaxError, "");
}
BOOST_AUTO_TEST_CASE(payable_in_library)
@@ -3966,7 +4253,7 @@ BOOST_AUTO_TEST_CASE(payable_in_library)
function f() payable {}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(payable_external)
@@ -3976,7 +4263,7 @@ BOOST_AUTO_TEST_CASE(payable_external)
function f() payable external {}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(payable_internal)
@@ -3986,7 +4273,7 @@ BOOST_AUTO_TEST_CASE(payable_internal)
function f() payable internal {}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(payable_private)
@@ -3996,7 +4283,7 @@ BOOST_AUTO_TEST_CASE(payable_private)
function f() payable private {}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(illegal_override_payable)
@@ -4005,7 +4292,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable)
contract B { function f() payable {} }
contract C is B { function f() {} }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable)
@@ -4014,7 +4301,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable)
contract B { function f() {} }
contract C is B { function f() payable {} }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(payable_constant_conflict)
@@ -4022,7 +4309,7 @@ BOOST_AUTO_TEST_CASE(payable_constant_conflict)
char const* text = R"(
contract C { function f() payable constant {} }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(calling_payable)
@@ -4035,7 +4322,7 @@ BOOST_AUTO_TEST_CASE(calling_payable)
function g() { r.pay.value(10)(); }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(calling_nonpayable)
@@ -4046,7 +4333,7 @@ BOOST_AUTO_TEST_CASE(calling_nonpayable)
function f() { (new receiver()).nopay.value(10)(); }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(non_payable_constructor)
@@ -4062,7 +4349,7 @@ BOOST_AUTO_TEST_CASE(non_payable_constructor)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma)
@@ -4071,7 +4358,7 @@ BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma)
auto sourceAndError = parseAnalyseAndReturnError(text, true, false);
BOOST_REQUIRE(!!sourceAndError.second);
BOOST_REQUIRE(!!sourceAndError.first);
- BOOST_CHECK(*sourceAndError.second == Error::Type::Warning);
+ BOOST_CHECK(searchErrorMessage(*sourceAndError.second, "Source file does not specify required compiler version!"));
}
BOOST_AUTO_TEST_CASE(unsatisfied_version)
@@ -4079,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(unsatisfied_version)
char const* text = R"(
pragma solidity ^99.99.0;
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::SyntaxError);
+ BOOST_CHECK(expectError(text, true).type() == Error::Type::SyntaxError);
}
BOOST_AUTO_TEST_CASE(constant_constructor)
@@ -4089,7 +4376,7 @@ BOOST_AUTO_TEST_CASE(constant_constructor)
function test() constant {}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_constructor)
@@ -4099,7 +4386,7 @@ BOOST_AUTO_TEST_CASE(external_constructor)
function test() external {}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
@@ -4107,10 +4394,10 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
char const* text = R"(
contract test {
struct S { uint x; }
- function test(uint k) { S[k]; }
+ function test(uint k) { S[k]; }
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype)
@@ -4129,7 +4416,7 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_type)
@@ -4141,7 +4428,7 @@ BOOST_AUTO_TEST_CASE(function_type)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_type_parameter)
@@ -4153,7 +4440,7 @@ BOOST_AUTO_TEST_CASE(function_type_parameter)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_type_returned)
@@ -4165,7 +4452,7 @@ BOOST_AUTO_TEST_CASE(function_type_returned)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(private_function_type)
@@ -4177,7 +4464,7 @@ BOOST_AUTO_TEST_CASE(private_function_type)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(public_function_type)
@@ -4189,7 +4476,7 @@ BOOST_AUTO_TEST_CASE(public_function_type)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(payable_internal_function_type)
@@ -4199,7 +4486,7 @@ BOOST_AUTO_TEST_CASE(payable_internal_function_type)
function (uint) internal payable returns (uint) x;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type)
@@ -4212,7 +4499,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_function_type_returning_internal)
@@ -4222,7 +4509,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_returning_internal)
function() external returns (function () internal) x;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_function_type_taking_internal)
@@ -4232,7 +4519,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_taking_internal)
function(function () internal) external x;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type)
@@ -4245,7 +4532,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter)
@@ -4258,7 +4545,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function)
@@ -4270,7 +4557,7 @@ BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal)
@@ -4281,7 +4568,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external)
@@ -4292,7 +4579,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_type_arrays)
@@ -4309,7 +4596,7 @@ BOOST_AUTO_TEST_CASE(function_type_arrays)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(delete_function_type)
@@ -4330,7 +4617,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(delete_function_type_invalid)
@@ -4342,7 +4629,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type_invalid)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid)
@@ -4354,7 +4641,7 @@ BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal)
@@ -4366,7 +4653,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue)
@@ -4376,7 +4663,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue)
uint public a = 0x42 << -8;
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue)
@@ -4386,7 +4673,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue)
uint public a = 0x42 >> -8;
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue)
@@ -4396,7 +4683,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue)
uint public a = 0x42 << 0x100000000;
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue)
@@ -4406,7 +4693,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue)
uint public a = 0x42 >> 0x100000000;
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack)
@@ -4420,7 +4707,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Inline assembly block is not balanced");
}
BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack)
@@ -4434,7 +4721,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack)
}
}
)";
- BOOST_CHECK(expectError(text, true) == Error::Type::Warning);
+ CHECK_WARNING(text, "Inline assembly block is not balanced");
}
BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
@@ -4452,7 +4739,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_assembly_storage)
@@ -4463,11 +4750,12 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage)
function f() {
assembly {
x := 2
+ pop
}
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "not found, not unique or not lvalue.");
}
BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
@@ -4478,6 +4766,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
modifier m {
assembly {
x := 2
+ pop
}
_;
}
@@ -4485,7 +4774,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(invalid_mobile_type)
@@ -4498,7 +4787,93 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ msg.value;
+ }
+ }
+ )";
+ CHECK_WARNING(text, "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?");
+}
+
+BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_payable_function)
+{
+ char const* text = R"(
+ contract C {
+ function f() payable {
+ msg.value;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_internal_function)
+{
+ char const* text = R"(
+ contract C {
+ function f() internal {
+ msg.value;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_library)
+{
+ char const* text = R"(
+ library C {
+ function f() {
+ msg.value;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(does_not_warn_non_magic_msg_value)
+{
+ char const* text = R"(
+ contract C {
+ struct msg {
+ uint256 value;
+ }
+
+ function f() {
+ msg.value;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_public_function)
+{
+ char const* text = R"(
+ contract c {
+ function f() { }
+ modifier m() { msg.value; _; }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(assignment_to_constant)
+{
+ char const* text = R"(
+ contract c {
+ uint constant a = 1;
+ function f() { a = 2; }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index 49844f15..e32264c4 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Lefteris Karapetsas <lefteris@ethdev.com>
@@ -76,10 +76,12 @@ BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker)
BOOST_AUTO_TEST_CASE(user_basic_test)
{
- char const* sourceCode = "contract test {\n"
- " /// @notice Multiplies `a` by 7\n"
- " function mul(uint a) returns(uint d) { return a * 7; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @notice Multiplies `a` by 7
+ function mul(uint a) returns(uint d) { return a * 7; }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -91,11 +93,13 @@ BOOST_AUTO_TEST_CASE(user_basic_test)
BOOST_AUTO_TEST_CASE(dev_and_user_basic_test)
{
- char const* sourceCode = "contract test {\n"
- " /// @notice Multiplies `a` by 7\n"
- " /// @dev Multiplies a number by 7\n"
- " function mul(uint a) returns(uint d) { return a * 7; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @notice Multiplies `a` by 7
+ /// @dev Multiplies a number by 7
+ function mul(uint a) returns(uint d) { return a * 7; }
+ }
+ )";
char const* devNatspec = "{"
"\"methods\":{"
@@ -116,14 +120,15 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test)
BOOST_AUTO_TEST_CASE(user_multiline_comment)
{
- char const* sourceCode = "contract test {\n"
- " /// @notice Multiplies `a` by 7\n"
- " /// and then adds `b`\n"
- " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n"
- " {\n"
- " return (a * 7) + b;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @notice Multiplies `a` by 7
+ /// and then adds `b`
+ function mul_and_add(uint a, uint256 b) returns(uint256 d) {
+ return (a * 7) + b;
+ }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -135,24 +140,24 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment)
BOOST_AUTO_TEST_CASE(user_multiple_functions)
{
- char const* sourceCode = "contract test {\n"
- " /// @notice Multiplies `a` by 7 and then adds `b`\n"
- " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n"
- " {\n"
- " return (a * 7) + b;\n"
- " }\n"
- "\n"
- " /// @notice Divides `input` by `div`\n"
- " function divide(uint input, uint div) returns(uint d)\n"
- " {\n"
- " return input / div;\n"
- " }\n"
- " /// @notice Subtracts 3 from `input`\n"
- " function sub(int input) returns(int d)\n"
- " {\n"
- " return input - 3;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @notice Multiplies `a` by 7 and then adds `b`
+ function mul_and_add(uint a, uint256 b) returns(uint256 d) {
+ return (a * 7) + b;
+ }
+
+ /// @notice Divides `input` by `div`
+ function divide(uint input, uint div) returns(uint d) {
+ return input / div;
+ }
+
+ /// @notice Subtracts 3 from `input`
+ function sub(int input) returns(int d) {
+ return input - 3;
+ }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -166,8 +171,9 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions)
BOOST_AUTO_TEST_CASE(user_empty_contract)
{
- char const* sourceCode = "contract test {\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test { }
+ )";
char const* natspec = "{\"methods\":{} }";
@@ -176,13 +182,16 @@ BOOST_AUTO_TEST_CASE(user_empty_contract)
BOOST_AUTO_TEST_CASE(dev_and_user_no_doc)
{
- char const* sourceCode = "contract test {\n"
- " function mul(uint a) returns(uint d) { return a * 7; }\n"
- " function sub(int input) returns(int d)\n"
- " {\n"
- " return input - 3;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ function mul(uint a) returns(uint d) {
+ return a * 7;
+ }
+ function sub(int input) returns(int d) {
+ return input - 3;
+ }
+ }
+ )";
char const* devNatspec = "{\"methods\":{}}";
char const* userNatspec = "{\"methods\":{}}";
@@ -193,13 +202,15 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc)
BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev\n"
- " /// Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter\n"
- " /// @param second Documentation for the second parameter\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev
+ /// Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter
+ /// @param second Documentation for the second parameter
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -217,12 +228,14 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl)
BOOST_AUTO_TEST_CASE(dev_multiple_params)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter\n"
- " /// @param second Documentation for the second parameter\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter
+ /// @param second Documentation for the second parameter
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -240,13 +253,15 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params)
BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter starts here.\n"
- " /// Since it's a really complicated parameter we need 2 lines\n"
- " /// @param second Documentation for the second parameter\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter starts here.
+ /// Since it's a really complicated parameter we need 2 lines
+ /// @param second Documentation for the second parameter
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -264,26 +279,27 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description)
BOOST_AUTO_TEST_CASE(dev_multiple_functions)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter\n"
- " /// @param second Documentation for the second parameter\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- " \n"
- " /// @dev Divides 2 numbers\n"
- " /// @param input Documentation for the input parameter\n"
- " /// @param div Documentation for the div parameter\n"
- " function divide(uint input, uint div) returns(uint d)\n"
- " {\n"
- " return input / div;\n"
- " }\n"
- " /// @dev Subtracts 3 from `input`\n"
- " /// @param input Documentation for the input parameter\n"
- " function sub(int input) returns(int d)\n"
- " {\n"
- " return input - 3;\n"
- " }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter
+ /// @param second Documentation for the second parameter
+ function mul(uint a, uint second) returns(uint d) {
+ return a * 7 + second;
+ }
+ /// @dev Divides 2 numbers
+ /// @param input Documentation for the input parameter
+ /// @param div Documentation for the div parameter
+ function divide(uint input, uint div) returns(uint d) {
+ return input / div;
+ }
+ /// @dev Subtracts 3 from `input`
+ /// @param input Documentation for the input parameter
+ function sub(int input) returns(int d) {
+ return input - 3;
+ }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -314,14 +330,16 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions)
BOOST_AUTO_TEST_CASE(dev_return)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter starts here.\n"
- " /// Since it's a really complicated parameter we need 2 lines\n"
- " /// @param second Documentation for the second parameter\n"
- " /// @return The result of the multiplication\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter starts here.
+ /// Since it's a really complicated parameter we need 2 lines
+ /// @param second Documentation for the second parameter
+ /// @return The result of the multiplication
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -339,15 +357,19 @@ BOOST_AUTO_TEST_CASE(dev_return)
}
BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter starts here.\n"
- " /// Since it's a really complicated parameter we need 2 lines\n"
- " /// @param second Documentation for the second parameter\n"
- " /// @return\n"
- " /// The result of the multiplication\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter starts here.
+ /// Since it's a really complicated parameter we need 2 lines
+ /// @param second Documentation for the second parameter
+ /// @return
+ /// The result of the multiplication
+ function mul(uint a, uint second) returns(uint d) {
+ return a * 7 + second;
+ }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -367,15 +389,19 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl)
BOOST_AUTO_TEST_CASE(dev_multiline_return)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter starts here.\n"
- " /// Since it's a really complicated parameter we need 2 lines\n"
- " /// @param second Documentation for the second parameter\n"
- " /// @return The result of the multiplication\n"
- " /// and cookies with nutella\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter starts here.
+ /// Since it's a really complicated parameter we need 2 lines
+ /// @param second Documentation for the second parameter
+ /// @return The result of the multiplication
+ /// and cookies with nutella
+ function mul(uint a, uint second) returns(uint d) {
+ return a * 7 + second;
+ }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -394,17 +420,21 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return)
BOOST_AUTO_TEST_CASE(dev_multiline_comment)
{
- char const* sourceCode = "contract test {\n"
- " /**\n"
- " * @dev Multiplies a number by 7 and adds second parameter\n"
- " * @param a Documentation for the first parameter starts here.\n"
- " * Since it's a really complicated parameter we need 2 lines\n"
- " * @param second Documentation for the second parameter\n"
- " * @return The result of the multiplication\n"
- " * and cookies with nutella\n"
- " */"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /**
+ * @dev Multiplies a number by 7 and adds second parameter
+ * @param a Documentation for the first parameter starts here.
+ * Since it's a really complicated parameter we need 2 lines
+ * @param second Documentation for the second parameter
+ * @return The result of the multiplication
+ * and cookies with nutella
+ */
+ function mul(uint a, uint second) returns(uint d) {
+ return a * 7 + second;
+ }
+ }
+ )";
char const* natspec = "{"
"\"methods\":{"
@@ -423,10 +453,12 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment)
BOOST_AUTO_TEST_CASE(dev_contract_no_doc)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Mul function\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Mul function
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
" \"methods\":{"
@@ -441,12 +473,14 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc)
BOOST_AUTO_TEST_CASE(dev_contract_doc)
{
- char const* sourceCode = " /// @author Lefteris\n"
- " /// @title Just a test contract\n"
- "contract test {\n"
- " /// @dev Mul function\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ /// @author Lefteris
+ /// @title Just a test contract
+ contract test {
+ /// @dev Mul function
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
" \"author\": \"Lefteris\","
@@ -463,13 +497,15 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc)
BOOST_AUTO_TEST_CASE(dev_author_at_function)
{
- char const* sourceCode = " /// @author Lefteris\n"
- " /// @title Just a test contract\n"
- "contract test {\n"
- " /// @dev Mul function\n"
- " /// @author John Doe\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ /// @author Lefteris
+ /// @title Just a test contract
+ contract test {
+ /// @dev Mul function
+ /// @author John Doe
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
char const* natspec = "{"
" \"author\": \"Lefteris\","
@@ -549,25 +585,29 @@ BOOST_AUTO_TEST_CASE(empty_comment)
BOOST_AUTO_TEST_CASE(dev_title_at_function_error)
{
- char const* sourceCode = " /// @author Lefteris\n"
- " /// @title Just a test contract\n"
- "contract test {\n"
- " /// @dev Mul function\n"
- " /// @title I really should not be here\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ /// @author Lefteris
+ /// @title Just a test contract
+ contract test {
+ /// @dev Mul function
+ /// @title I really should not be here
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
expectNatspecError(sourceCode);
}
-BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param)
+BOOST_AUTO_TEST_CASE(dev_documenting_nonexistent_param)
{
- char const* sourceCode = "contract test {\n"
- " /// @dev Multiplies a number by 7 and adds second parameter\n"
- " /// @param a Documentation for the first parameter\n"
- " /// @param not_existing Documentation for the second parameter\n"
- " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n"
- "}\n";
+ char const* sourceCode = R"(
+ contract test {
+ /// @dev Multiplies a number by 7 and adds second parameter
+ /// @param a Documentation for the first parameter
+ /// @param not_existing Documentation for the second parameter
+ function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }
+ }
+ )";
expectNatspecError(sourceCode);
}
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index 017fc0e9..2e2e0c6c 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -20,19 +20,24 @@
* Tests for the Solidity optimizer.
*/
-#include <string>
-#include <tuple>
-#include <memory>
-#include <boost/test/unit_test.hpp>
-#include <boost/lexical_cast.hpp>
#include <test/libsolidity/SolidityExecutionFramework.h>
+
#include <libevmasm/CommonSubexpressionEliminator.h>
+#include <libevmasm/PeepholeOptimiser.h>
#include <libevmasm/ControlFlowGraph.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/BlockDeduplicator.h>
+#include <boost/test/unit_test.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <string>
+#include <tuple>
+#include <memory>
+
using namespace std;
using namespace dev::eth;
+using namespace dev::test;
namespace dev
{
@@ -41,10 +46,29 @@ namespace solidity
namespace test
{
-class OptimizerTestFramework: public ExecutionFramework
+class OptimizerTestFramework: public SolidityExecutionFramework
{
public:
OptimizerTestFramework() { }
+
+ bytes const& compileAndRunWithOptimizer(
+ std::string const& _sourceCode,
+ u256 const& _value = 0,
+ std::string const& _contractName = "",
+ bool const _optimize = true,
+ unsigned const _optimizeRuns = 200
+ )
+ {
+ bool const c_optimize = m_optimize;
+ unsigned const c_optimizeRuns = m_optimizeRuns;
+ m_optimize = _optimize;
+ m_optimizeRuns = _optimizeRuns;
+ bytes const& ret = compileAndRun(_sourceCode, _value, _contractName);
+ m_optimize = c_optimize;
+ m_optimizeRuns = c_optimizeRuns;
+ return ret;
+ }
+
/// Compiles the source code with and without optimizing.
void compileBothVersions(
std::string const& _sourceCode,
@@ -52,22 +76,16 @@ public:
std::string const& _contractName = ""
)
{
- m_optimize = false;
- bytes nonOptimizedBytecode = compileAndRun(_sourceCode, _value, _contractName);
+ bytes nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false);
m_nonOptimizedContract = m_contractAddress;
- m_optimize = true;
- bytes optimizedBytecode = compileAndRun(_sourceCode, _value, _contractName);
- size_t nonOptimizedSize = 0;
- solidity::eachInstruction(nonOptimizedBytecode, [&](Instruction, u256 const&) {
- nonOptimizedSize++;
- });
- size_t optimizedSize = 0;
- solidity::eachInstruction(optimizedBytecode, [&](Instruction, u256 const&) {
- optimizedSize++;
- });
+ bytes optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true);
+ size_t nonOptimizedSize = numInstructions(nonOptimizedBytecode);
+ size_t optimizedSize = numInstructions(optimizedBytecode);
BOOST_CHECK_MESSAGE(
- nonOptimizedSize > optimizedSize,
- "Optimizer did not reduce bytecode size."
+ optimizedSize < nonOptimizedSize,
+ string("Optimizer did not reduce bytecode size. Non-optimized size: ") +
+ std::to_string(nonOptimizedSize) + " - optimized size: " +
+ std::to_string(optimizedSize)
);
m_optimizedContract = m_contractAddress;
}
@@ -151,6 +169,22 @@ public:
}
protected:
+ /// @returns the number of intructions in the given bytecode, not taking the metadata hash
+ /// into account.
+ size_t numInstructions(bytes const& _bytecode)
+ {
+ BOOST_REQUIRE(_bytecode.size() > 5);
+ size_t metadataSize = (_bytecode[_bytecode.size() - 2] << 8) + _bytecode[_bytecode.size() - 1];
+ BOOST_REQUIRE_MESSAGE(metadataSize == 0x29, "Invalid metadata size");
+ BOOST_REQUIRE(_bytecode.size() >= metadataSize + 2);
+ bytes realCode = bytes(_bytecode.begin(), _bytecode.end() - metadataSize - 2);
+ size_t instructions = 0;
+ solidity::eachInstruction(realCode, [&](Instruction, u256 const&) {
+ instructions++;
+ });
+ return instructions;
+ }
+
Address m_optimizedContract;
Address m_nonOptimizedContract;
};
@@ -310,8 +344,7 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches)
compareVersions("f(uint256,bytes32)", 8, "def");
compareVersions("f(uint256,bytes32)", 10, "ghi");
- m_optimize = true;
- bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c");
+ bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true);
size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
if (_instr == Instruction::SHA3)
@@ -354,8 +387,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions)
compileBothVersions(sourceCode);
compareVersions("f(uint256,bytes32)", 7, "abc");
- m_optimize = true;
- bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test");
+ bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true);
size_t numSHA3s = 0;
eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) {
if (_instr == Instruction::SHA3)
@@ -1121,6 +1153,40 @@ BOOST_AUTO_TEST_CASE(block_deduplicator_loops)
BOOST_CHECK_EQUAL(pushTags.size(), 1);
}
+BOOST_AUTO_TEST_CASE(clear_unreachable_code)
+{
+ AssemblyItems items{
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMP,
+ u256(0),
+ Instruction::SLOAD,
+ AssemblyItem(Tag, 2),
+ u256(5),
+ u256(6),
+ Instruction::SSTORE,
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMP,
+ u256(5),
+ u256(6)
+ };
+ AssemblyItems expectation{
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMP,
+ AssemblyItem(Tag, 2),
+ u256(5),
+ u256(6),
+ Instruction::SSTORE,
+ AssemblyItem(PushTag, 1),
+ Instruction::JUMP
+ };
+ PeepholeOptimiser peepOpt(items);
+ BOOST_REQUIRE(peepOpt.optimise());
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ items.begin(), items.end(),
+ expectation.begin(), expectation.end()
+ );
+}
+
BOOST_AUTO_TEST_CASE(computing_constants)
{
char const* sourceCode = R"(
@@ -1148,9 +1214,7 @@ BOOST_AUTO_TEST_CASE(computing_constants)
compareVersions("set()");
compareVersions("get()");
- m_optimize = true;
- m_optimizeRuns = 1;
- bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c");
+ bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true, 1);
bytes complicatedConstant = toBigEndian(u256("0x817416927846239487123469187231298734162934871263941234127518276"));
unsigned occurrences = 0;
for (auto iter = optimizedBytecode.cbegin(); iter < optimizedBytecode.cend(); ++occurrences)
@@ -1266,6 +1330,29 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join)
compareVersions("test()");
}
+BOOST_AUTO_TEST_CASE(cse_sub_zero)
+{
+ checkCSE({
+ u256(0),
+ Instruction::DUP2,
+ Instruction::SUB
+ }, {
+ Instruction::DUP1
+ });
+
+ checkCSE({
+ Instruction::DUP1,
+ u256(0),
+ Instruction::SUB
+ }, {
+ u256(0),
+ Instruction::DUP2,
+ Instruction::SWAP1,
+ Instruction::SUB
+ });
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index 914dbc30..a3bfab75 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
@@ -26,6 +26,7 @@
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/interface/Exceptions.h>
#include "../TestHelper.h"
+#include "ErrorCheck.h"
using namespace std;
@@ -71,6 +72,22 @@ bool successParse(std::string const& _source)
return true;
}
+Error getError(std::string const& _source)
+{
+ ErrorList errors;
+ try
+ {
+ parseText(_source, errors);
+ }
+ catch (FatalError const& /*_exception*/)
+ {
+ // no-op
+ }
+ Error const* error = Error::containsErrorOfType(errors, Error::Type::ParserError);
+ BOOST_REQUIRE(error);
+ return *error;
+}
+
void checkFunctionNatspec(
FunctionDefinition const* _function,
std::string const& _expectedDoc
@@ -83,78 +100,102 @@ void checkFunctionNatspec(
}
+#define CHECK_PARSE_ERROR(source, substring) \
+do \
+{\
+ Error err = getError((source)); \
+ BOOST_CHECK(searchErrorMessage(err, (substring))); \
+}\
+while(0)
+
BOOST_AUTO_TEST_SUITE(SolidityParser)
BOOST_AUTO_TEST_CASE(smoke_test)
{
- char const* text = "contract test {\n"
- " uint256 stateVariable1;\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVariable1;
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration)
{
- char const* text = "contract test {\n"
- " uint256 ;\n"
- "}\n";
- BOOST_CHECK(!successParse(text));
+ char const* text = R"(
+ contract test {
+ uint256 ;
+ }
+ )";
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(empty_function)
{
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " function functionName(bytes20 arg1, address addr) constant\n"
- " returns (int id)\n"
- " { }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ function functionName(bytes20 arg1, address addr) constant
+ returns (int id)
+ { }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(no_function_params)
{
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " function functionName() {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ function functionName() {}
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(single_function_param)
{
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " function functionName(bytes32 input) returns (bytes32 out) {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ function functionName(bytes32 input) returns (bytes32 out) {}
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(function_no_body)
{
- char const* text = "contract test {\n"
- " function functionName(bytes32 input) returns (bytes32 out);\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function functionName(bytes32 input) returns (bytes32 out);
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args)
{
- char const* text = "contract test {\n"
- " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
- " function b() returns (uint r) { r = a({: 1, : 2, : 3}); }\n"
- "}\n";
- BOOST_CHECK(!successParse(text));
+ char const* text = R"(
+ contract test {
+ function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }
+ function b() returns (uint r) { r = a({: 1, : 2, : 3}); }
+ }
+ )";
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(missing_argument_in_named_args)
{
- char const* text = "contract test {\n"
- " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n"
- " function b() returns (uint r) { r = a({a: , b: , c: }); }\n"
- "}\n";
- BOOST_CHECK(!successParse(text));
+ char const* text = R"(
+ contract test {
+ function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }
+ function b() returns (uint r) { r = a({a: , b: , c: }); }
+ }
+ )";
+ CHECK_PARSE_ERROR(text, "Expected primary expression");
}
BOOST_AUTO_TEST_CASE(two_exact_functions)
@@ -184,11 +225,13 @@ BOOST_AUTO_TEST_CASE(overloaded_functions)
BOOST_AUTO_TEST_CASE(function_natspec_documentation)
{
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " /// This is a test function\n"
- " function functionName(bytes32 input) returns (bytes32 out) {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ /// This is a test function
+ function functionName(bytes32 input) returns (bytes32 out) {}
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -202,11 +245,13 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation)
BOOST_AUTO_TEST_CASE(function_normal_comments)
{
FunctionDefinition const* function = nullptr;
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " // We won't see this comment\n"
- " function functionName(bytes32 input) returns (bytes32 out) {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ // We won't see this comment
+ function functionName(bytes32 input) returns (bytes32 out) {}
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -219,17 +264,19 @@ BOOST_AUTO_TEST_CASE(function_normal_comments)
BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
{
FunctionDefinition const* function = nullptr;
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " /// This is test function 1\n"
- " function functionName1(bytes32 input) returns (bytes32 out) {}\n"
- " /// This is test function 2\n"
- " function functionName2(bytes32 input) returns (bytes32 out) {}\n"
- " // nothing to see here\n"
- " function functionName3(bytes32 input) returns (bytes32 out) {}\n"
- " /// This is test function 4\n"
- " function functionName4(bytes32 input) returns (bytes32 out) {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ /// This is test function 1
+ function functionName1(bytes32 input) returns (bytes32 out) {}
+ /// This is test function 2
+ function functionName2(bytes32 input) returns (bytes32 out) {}
+ // nothing to see here
+ function functionName3(bytes32 input) returns (bytes32 out) {}
+ /// This is test function 4
+ function functionName4(bytes32 input) returns (bytes32 out) {}
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -252,12 +299,14 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation)
BOOST_AUTO_TEST_CASE(multiline_function_documentation)
{
FunctionDefinition const* function = nullptr;
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " /// This is a test function\n"
- " /// and it has 2 lines\n"
- " function functionName1(bytes32 input) returns (bytes32 out) {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ /// This is a test function
+ /// and it has 2 lines
+ function functionName1(bytes32 input) returns (bytes32 out) {}
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -270,19 +319,21 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation)
BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body)
{
FunctionDefinition const* function = nullptr;
- char const* text = "contract test {\n"
- " /// fun1 description\n"
- " function fun1(uint256 a) {\n"
- " var b;\n"
- " /// I should not interfere with actual natspec comments\n"
- " uint256 c;\n"
- " mapping(address=>bytes32) d;\n"
- " bytes7 name = \"Solidity\";"
- " }\n"
- " /// This is a test function\n"
- " /// and it has 2 lines\n"
- " function fun(bytes32 input) returns (bytes32 out) {}\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ /// fun1 description
+ function fun1(uint256 a) {
+ var b;
+ /// I should not interfere with actual natspec comments
+ uint256 c;
+ mapping(address=>bytes32) d;
+ bytes7 name = "Solidity";
+ }
+ /// This is a test function
+ /// and it has 2 lines
+ function fun(bytes32 input) returns (bytes32 out) {}
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -299,17 +350,19 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body)
BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature)
{
FunctionDefinition const* function = nullptr;
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " function ///I am in the wrong place \n"
- " fun1(uint256 a) {\n"
- " var b;\n"
- " /// I should not interfere with actual natspec comments\n"
- " uint256 c;\n"
- " mapping(address=>bytes32) d;\n"
- " bytes7 name = \"Solidity\";"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ function ///I am in the wrong place
+ fun1(uint256 a) {
+ var b;
+ /// I should not interfere with actual natspec comments
+ uint256 c;
+ mapping(address=>bytes32) d;
+ bytes7 name = "Solidity";
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -323,17 +376,19 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature)
BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature)
{
FunctionDefinition const* function = nullptr;
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " function fun1(uint256 a) {\n"
- " /// I should have been above the function signature\n"
- " var b;\n"
- " /// I should not interfere with actual natspec comments\n"
- " uint256 c;\n"
- " mapping(address=>bytes32) d;\n"
- " bytes7 name = \"Solidity\";"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ function fun1(uint256 a) {
+ /// I should have been above the function signature
+ var b;
+ /// I should not interfere with actual natspec comments
+ uint256 c;
+ mapping(address=>bytes32) d;
+ bytes7 name = "Solidity";
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
ErrorList errors;
ASTPointer<ContractDefinition> contract = parseText(text, errors);
@@ -346,71 +401,83 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature)
BOOST_AUTO_TEST_CASE(struct_definition)
{
- char const* text = "contract test {\n"
- " uint256 stateVar;\n"
- " struct MyStructName {\n"
- " address addr;\n"
- " uint256 count;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ uint256 stateVar;
+ struct MyStructName {
+ address addr;
+ uint256 count;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(mapping)
{
- char const* text = "contract test {\n"
- " mapping(address => bytes32) names;\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ mapping(address => bytes32) names;
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(mapping_in_struct)
{
- char const* text = "contract test {\n"
- " struct test_struct {\n"
- " address addr;\n"
- " uint256 count;\n"
- " mapping(bytes32 => test_struct) self_reference;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ struct test_struct {
+ address addr;
+ uint256 count;
+ mapping(bytes32 => test_struct) self_reference;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct)
{
- char const* text = "contract test {\n"
- " struct test_struct {\n"
- " address addr;\n"
- " mapping (uint64 => mapping (bytes32 => uint)) complex_mapping;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ struct test_struct {
+ address addr;
+ mapping (uint64 => mapping (bytes32 => uint)) complex_mapping;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(variable_definition)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " var b;\n"
- " uint256 c;\n"
- " mapping(address=>bytes32) d;\n"
- " customtype varname;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ var b;
+ uint256 c;
+ mapping(address=>bytes32) d;
+ customtype varname;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(variable_definition_with_initialization)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " var b = 2;\n"
- " uint256 c = 0x87;\n"
- " mapping(address=>bytes32) d;\n"
- " bytes7 name = \"Solidity\";"
- " customtype varname;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ var b = 2;
+ uint256 c = 0x87;
+ mapping(address=>bytes32) d;
+ bytes7 name = "Solidity";
+ customtype varname;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
@@ -421,7 +488,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_parameter)
function fun(var a) {}
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected explicit type name");
}
BOOST_AUTO_TEST_CASE(variable_definition_in_mapping)
@@ -433,7 +500,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_mapping)
}
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected elementary type name for mapping key type");
}
BOOST_AUTO_TEST_CASE(variable_definition_in_function_return)
@@ -445,26 +512,30 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_return)
}
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected explicit type name");
}
BOOST_AUTO_TEST_CASE(operator_expression)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " uint256 x = (1 + 4) || false && (1 - 12) + -9;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ uint256 x = (1 + 4) || false && (1 - 12) + -9;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(complex_expression)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " uint256 x = (1 + 4).member(++67)[a/=9] || true;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ uint256 x = (1 + 4).member(++67)[a/=9] || true;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
@@ -475,248 +546,294 @@ BOOST_AUTO_TEST_CASE(exp_expression)
function fun(uint256 a) {
uint256 x = 3 ** a;
}
- })";
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(while_loop)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " while (true) { uint256 x = 1; break; continue; } x = 9;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ while (true) { uint256 x = 1; break; continue; } x = 9;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(for_loop_vardef_initexpr)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " for (uint256 i = 0; i < 10; i++)\n"
- " { uint256 x = i; break; continue; }\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ for (uint256 i = 0; i < 10; i++) {
+ uint256 x = i; break; continue;
+ }
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " uint256 i =0;\n"
- " for (i = 0; i < 10; i++)\n"
- " { uint256 x = i; break; continue; }\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ uint256 i =0;
+ for (i = 0; i < 10; i++) {
+ uint256 x = i; break; continue;
+ }
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " uint256 i =0;\n"
- " for (;;)\n"
- " { uint256 x = i; break; continue; }\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ uint256 i =0;
+ for (;;) {
+ uint256 x = i; break; continue;
+ }
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(for_loop_single_stmt_body)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " uint256 i =0;\n"
- " for (i = 0; i < 10; i++)\n"
- " continue;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ uint256 i = 0;
+ for (i = 0; i < 10; i++)
+ continue;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(if_statement)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) {\n"
- " if (a >= 8) { return 2; } else { var b = 7; }\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) {
+ if (a >= 8) { return 2; } else { var b = 7; }
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(else_if_statement)
{
- char const* text = "contract test {\n"
- " function fun(uint256 a) returns (address b) {\n"
- " if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun(uint256 a) returns (address b) {
+ if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " uint64[7](3);\n"
- " uint64[](3);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun() {
+ uint64(2);
+ uint64[7](3);
+ uint64[](3);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(type_conversion_to_dynamic_array)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " var x = uint64[](3);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun() {
+ var x = uint64[](3);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(import_directive)
{
- char const* text = "import \"abc\";\n"
- "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ import "abc";
+ contract test {
+ function fun() {
+ uint64(2);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(multiple_contracts)
{
- char const* text = "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n"
- "contract test2 {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract test {
+ function fun() {
+ uint64(2);
+ }
+ }
+ contract test2 {
+ function fun() {
+ uint64(2);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(multiple_contracts_and_imports)
{
- char const* text = "import \"abc\";\n"
- "contract test {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n"
- "import \"def\";\n"
- "contract test2 {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n"
- "import \"ghi\";\n";
+ char const* text = R"(
+ import "abc";
+ contract test {
+ function fun() {
+ uint64(2);
+ }
+ }
+ import "def";
+ contract test2 {
+ function fun() {
+ uint64(2);
+ }
+ }
+ import "ghi";
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(contract_inheritance)
{
- char const* text = "contract base {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n"
- "contract derived is base {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract base {
+ function fun() {
+ uint64(2);
+ }
+ }
+ contract derived is base {
+ function fun() {
+ uint64(2);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(contract_multiple_inheritance)
{
- char const* text = "contract base {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n"
- "contract derived is base, nonExisting {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract base {
+ function fun() {
+ uint64(2);
+ }
+ }
+ contract derived is base, nonExisting {
+ function fun() {
+ uint64(2);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(contract_multiple_inheritance_with_arguments)
{
- char const* text = "contract base {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n"
- "contract derived is base(2), nonExisting(\"abc\", \"def\", base.fun()) {\n"
- " function fun() {\n"
- " uint64(2);\n"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract base {
+ function fun() {
+ uint64(2);
+ }
+ }
+ contract derived is base(2), nonExisting("abc", "def", base.fun()) {
+ function fun() {
+ uint64(2);
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(placeholder_in_function_context)
{
- char const* text = "contract c {\n"
- " function fun() returns (uint r) {\n"
- " var _ = 8;\n"
- " return _ + 1;"
- " }\n"
- "}\n";
+ char const* text = R"(
+ contract c {
+ function fun() returns (uint r) {
+ var _ = 8;
+ return _ + 1;
+ }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(modifier)
{
- char const* text = "contract c {\n"
- " modifier mod { if (msg.sender == 0) _; }\n"
- "}\n";
+ char const* text = R"(
+ contract c {
+ modifier mod { if (msg.sender == 0) _; }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(modifier_without_semicolon)
{
- char const* text = "contract c {\n"
- " modifier mod { if (msg.sender == 0) _ }\n"
- "}\n";
- BOOST_CHECK(!successParse(text));
+ char const* text = R"(
+ contract c {
+ modifier mod { if (msg.sender == 0) _ }
+ }
+ )";
+ CHECK_PARSE_ERROR(text, "Expected token Semicolon got");
}
BOOST_AUTO_TEST_CASE(modifier_arguments)
{
- char const* text = "contract c {\n"
- " modifier mod(uint a) { if (msg.sender == a) _; }\n"
- "}\n";
+ char const* text = R"(
+ contract c {
+ modifier mod(address a) { if (msg.sender == a) _; }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(modifier_invocation)
{
- char const* text = "contract c {\n"
- " modifier mod1(uint a) { if (msg.sender == a) _; }\n"
- " modifier mod2 { if (msg.sender == 2) _; }\n"
- " function f() mod1(7) mod2 { }\n"
- "}\n";
+ char const* text = R"(
+ contract c {
+ modifier mod1(uint a) { if (msg.sender == a) _; }
+ modifier mod2 { if (msg.sender == 2) _; }
+ function f() mod1(7) mod2 { }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
BOOST_AUTO_TEST_CASE(fallback_function)
{
- char const* text = "contract c {\n"
- " function() { }\n"
- "}\n";
+ char const* text = R"(
+ contract c {
+ function() { }
+ }
+ )";
BOOST_CHECK(successParse(text));
}
@@ -769,7 +886,7 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
contract c {
uint private internal a;
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Visibility already specified");
}
BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations)
@@ -824,7 +941,7 @@ BOOST_AUTO_TEST_CASE(empty_enum_declaration)
contract c {
enum foo { }
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "enum with no members is not allowed");
}
BOOST_AUTO_TEST_CASE(malformed_enum_declaration)
@@ -833,7 +950,7 @@ BOOST_AUTO_TEST_CASE(malformed_enum_declaration)
contract c {
enum foo { WARNING,}
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected Identifier after");
}
BOOST_AUTO_TEST_CASE(external_function)
@@ -851,7 +968,7 @@ BOOST_AUTO_TEST_CASE(external_variable)
contract c {
uint external x;
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(arrays_in_storage)
@@ -899,7 +1016,7 @@ BOOST_AUTO_TEST_CASE(constant_is_keyword)
contract Foo {
uint constant = 4;
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(var_array)
@@ -908,7 +1025,7 @@ BOOST_AUTO_TEST_CASE(var_array)
contract Foo {
function f() { var[] a; }
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(location_specifiers_for_params)
@@ -940,7 +1057,7 @@ BOOST_AUTO_TEST_CASE(location_specifiers_for_state)
contract Foo {
uint[] memory x;
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(location_specifiers_with_var)
@@ -949,7 +1066,7 @@ BOOST_AUTO_TEST_CASE(location_specifiers_with_var)
contract Foo {
function f() { var memory x; }
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Location specifier needs explicit type name");
}
BOOST_AUTO_TEST_CASE(empty_comment)
@@ -962,6 +1079,19 @@ BOOST_AUTO_TEST_CASE(empty_comment)
BOOST_CHECK(successParse(text));
}
+BOOST_AUTO_TEST_CASE(comment_end_with_double_star)
+{
+ char const* text = R"(
+ contract C1 {
+ /**
+ **/
+ }
+ contract C2 {}
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+
BOOST_AUTO_TEST_CASE(library_simple)
{
char const* text = R"(
@@ -983,7 +1113,7 @@ BOOST_AUTO_TEST_CASE(local_const_variable)
return local;
}
})";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected token Semicolon");
}
BOOST_AUTO_TEST_CASE(multi_variable_declaration)
@@ -1102,7 +1232,7 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_lvalue)
}
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected expression");
}
BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue)
@@ -1115,7 +1245,7 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue)
}
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected expression");
}
BOOST_AUTO_TEST_CASE(conditional_true_false_literal)
@@ -1216,7 +1346,7 @@ BOOST_AUTO_TEST_CASE(no_double_radix_in_fixed_literal)
fixed40x40 pi = 3.14.15;
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected token Semicolon");
}
BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check)
@@ -1228,7 +1358,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check)
}
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected primary expression");
}
BOOST_AUTO_TEST_CASE(payable_accessor)
@@ -1238,7 +1368,7 @@ BOOST_AUTO_TEST_CASE(payable_accessor)
uint payable x;
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected identifier");
}
BOOST_AUTO_TEST_CASE(function_type_in_expression)
@@ -1271,7 +1401,7 @@ BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_modifiers)
function (uint, uint) modifier1() returns (uint) f1;
}
)";
- BOOST_CHECK(!successParse(text));
+ CHECK_PARSE_ERROR(text, "Expected token LBrace");
}
BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_assignment)
diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp
index 31b75f25..eb2f042c 100644
--- a/test/libsolidity/SolidityScanner.cpp
+++ b/test/libsolidity/SolidityScanner.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp
index 87dda9c2..dc3143c8 100644
--- a/test/libsolidity/SolidityTypes.cpp
+++ b/test/libsolidity/SolidityTypes.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ This file is part of solidity.
- cpp-ethereum is free software: you can redistribute it and/or modify
+ 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.
- cpp-ethereum is distributed in the hope that it will be useful,
+ 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>