aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml10
-rw-r--r--CMakeLists.txt2
-rw-r--r--Changelog.md30
-rw-r--r--appveyor.yml10
-rw-r--r--cmake/EthCompilerSettings.cmake2
-rw-r--r--docs/conf.py4
-rw-r--r--docs/contracts.rst6
-rw-r--r--docs/control-structures.rst81
-rw-r--r--docs/installing-solidity.rst15
-rw-r--r--docs/introduction-to-smart-contracts.rst6
-rw-r--r--docs/miscellaneous.rst11
-rw-r--r--docs/types.rst164
-rw-r--r--libdevcore/Common.h11
-rw-r--r--libdevcore/CommonData.cpp3
-rw-r--r--libdevcore/JSON.h44
-rw-r--r--libdevcore/SwarmHash.cpp63
-rw-r--r--libdevcore/SwarmHash.h31
-rw-r--r--libdevcore/UTF8.h2
-rw-r--r--libevmasm/Assembly.cpp209
-rw-r--r--libevmasm/Assembly.h48
-rw-r--r--libevmasm/AssemblyItem.cpp43
-rw-r--r--libevmasm/AssemblyItem.h18
-rw-r--r--libevmasm/BlockDeduplicator.cpp45
-rw-r--r--libevmasm/BlockDeduplicator.h24
-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.h13
-rw-r--r--libevmasm/EVMSchedule.h8
-rw-r--r--libevmasm/Exceptions.h8
-rw-r--r--libevmasm/ExpressionClasses.cpp8
-rw-r--r--libevmasm/ExpressionClasses.h8
-rw-r--r--libevmasm/GasMeter.cpp48
-rw-r--r--libevmasm/GasMeter.h11
-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.cpp245
-rw-r--r--libevmasm/PeepholeOptimiser.h54
-rw-r--r--libevmasm/SemanticInformation.cpp8
-rw-r--r--libevmasm/SemanticInformation.h8
-rw-r--r--libevmasm/SourceLocation.h23
-rw-r--r--liblll/CodeFragment.cpp7
-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.cpp33
-rw-r--r--libsolidity/analysis/ReferencesResolver.h9
-rw-r--r--libsolidity/analysis/SemVerHandler.cpp8
-rw-r--r--libsolidity/analysis/SemVerHandler.h8
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp8
-rw-r--r--libsolidity/analysis/SyntaxChecker.h8
-rw-r--r--libsolidity/analysis/TypeChecker.cpp20
-rw-r--r--libsolidity/analysis/TypeChecker.h9
-rw-r--r--libsolidity/ast/AST.cpp16
-rw-r--r--libsolidity/ast/AST.h64
-rw-r--r--libsolidity/ast/ASTAnnotations.cpp8
-rw-r--r--libsolidity/ast/ASTAnnotations.h8
-rw-r--r--libsolidity/ast/ASTForward.h9
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp33
-rw-r--r--libsolidity/ast/ASTJsonConverter.h10
-rw-r--r--libsolidity/ast/ASTPrinter.cpp22
-rw-r--r--libsolidity/ast/ASTPrinter.h10
-rw-r--r--libsolidity/ast/ASTUtils.cpp8
-rw-r--r--libsolidity/ast/ASTUtils.h8
-rw-r--r--libsolidity/ast/ASTVisitor.h12
-rw-r--r--libsolidity/ast/AST_accept.h28
-rw-r--r--libsolidity/ast/Types.cpp166
-rw-r--r--libsolidity/ast/Types.h28
-rw-r--r--libsolidity/codegen/ArrayUtils.cpp10
-rw-r--r--libsolidity/codegen/ArrayUtils.h8
-rw-r--r--libsolidity/codegen/Compiler.cpp25
-rw-r--r--libsolidity/codegen/Compiler.h16
-rw-r--r--libsolidity/codegen/CompilerContext.cpp38
-rw-r--r--libsolidity/codegen/CompilerContext.h92
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp153
-rw-r--r--libsolidity/codegen/CompilerUtils.h22
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp109
-rw-r--r--libsolidity/codegen/ContractCompiler.h21
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp58
-rw-r--r--libsolidity/codegen/ExpressionCompiler.h8
-rw-r--r--libsolidity/codegen/LValue.cpp79
-rw-r--r--libsolidity/codegen/LValue.h8
-rw-r--r--libsolidity/formal/Why3Translator.cpp18
-rw-r--r--libsolidity/formal/Why3Translator.h8
-rw-r--r--libsolidity/grammar.txt14
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp30
-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.cpp33
-rw-r--r--libsolidity/interface/CompilerStack.h22
-rw-r--r--libsolidity/interface/Exceptions.cpp8
-rw-r--r--libsolidity/interface/Exceptions.h9
-rw-r--r--libsolidity/interface/GasEstimator.cpp8
-rw-r--r--libsolidity/interface/GasEstimator.h8
-rw-r--r--libsolidity/interface/InterfaceHandler.cpp21
-rw-r--r--libsolidity/interface/InterfaceHandler.h24
-rw-r--r--libsolidity/interface/SourceReferenceFormatter.cpp8
-rw-r--r--libsolidity/interface/SourceReferenceFormatter.h8
-rw-r--r--libsolidity/interface/Utils.h14
-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.cpp202
-rw-r--r--libsolidity/parsing/Parser.h25
-rw-r--r--libsolidity/parsing/ParserBase.cpp8
-rw-r--r--libsolidity/parsing/ParserBase.h8
-rw-r--r--libsolidity/parsing/Scanner.cpp8
-rw-r--r--libsolidity/parsing/Scanner.h8
-rw-r--r--libsolidity/parsing/Token.cpp8
-rw-r--r--libsolidity/parsing/Token.h8
-rw-r--r--scripts/Dockerfile12
-rwxr-xr-xscripts/tests.sh27
-rw-r--r--solc/CommandLineInterface.cpp33
-rw-r--r--solc/CommandLineInterface.h8
-rw-r--r--solc/jsonCompiler.cpp19
-rw-r--r--solc/main.cpp8
-rw-r--r--std/StandardToken.sol2
-rw-r--r--std/Token.sol2
-rw-r--r--std/mortal.sol2
-rw-r--r--std/owned.sol2
-rw-r--r--std/std.sol2
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/RPCSession.cpp8
-rw-r--r--test/RPCSession.h8
-rw-r--r--test/TestHelper.cpp11
-rw-r--r--test/TestHelper.h9
-rw-r--r--test/boostTest.cpp8
-rw-r--r--test/contracts/AuctionRegistrar.cpp9
-rw-r--r--test/contracts/FixedFeeRegistrar.cpp9
-rw-r--r--test/contracts/Wallet.cpp11
-rw-r--r--test/libdevcore/SwarmHash.cpp57
-rw-r--r--test/libevmasm/SourceLocation.cpp50
-rw-r--r--test/libsolidity/ASTJSON.cpp53
-rw-r--r--test/libsolidity/Assembly.cpp18
-rw-r--r--test/libsolidity/ErrorCheck.cpp34
-rw-r--r--test/libsolidity/ErrorCheck.h32
-rw-r--r--test/libsolidity/GasMeter.cpp8
-rw-r--r--test/libsolidity/Imports.cpp8
-rw-r--r--test/libsolidity/InlineAssembly.cpp31
-rw-r--r--test/libsolidity/SemVerMatcher.cpp8
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp46
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp853
-rw-r--r--test/libsolidity/SolidityExecutionFramework.cpp9
-rw-r--r--test/libsolidity/SolidityExecutionFramework.h8
-rw-r--r--test/libsolidity/SolidityExpressionCompiler.cpp45
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp868
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp20
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp104
-rw-r--r--test/libsolidity/SolidityParser.cpp119
-rw-r--r--test/libsolidity/SolidityScanner.cpp8
-rw-r--r--test/libsolidity/SolidityTypes.cpp8
170 files changed, 4457 insertions, 1399 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 20c96869..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.5")
+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 ee106047..b5e48173 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,4 +1,32 @@
-### 0.4.5 (unreleased)
+### 0.4.7 (unreleased)
+
+Features:
+ * Optimizer: Some dead code elimination.
+
+Bugfixes:
+ * Type checker: string literals that are not valid UTF-8 cannot be converted to string type
+
+### 0.4.6 (2016-11-22)
+
+Bugfixes:
+ * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs (introduced in 0.4.5)
+
+### 0.4.5 (2016-11-21)
+
+Features:
+ * Function types
+ * Do-while loops: support for a ``do <block> while (<expr>);`` control structure
+ * Inline assembly: support ``invalidJumpLabel`` as a jump label.
+ * Type checker: now more eagerly searches for a common type of an inline array with mixed types
+ * Code generator: generates a runtime error when an out-of-range value is converted into an enum type.
+
+Bugfixes:
+
+ * Inline assembly: calculate stack height warning correctly even when local variables are used.
+ * Code generator: check for value transfer in non-payable constructors.
+ * Parser: disallow empty enum definitions.
+ * Type checker: disallow conversion between different enum types.
+ * Interface JSON: do not include trailing new line.
### 0.4.4 (2016-10-31)
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 97db9168..c734423b 100644
--- a/cmake/EthCompilerSettings.cmake
+++ b/cmake/EthCompilerSettings.cmake
@@ -71,7 +71,7 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
add_compile_options(-fPIC)
# Configuration-specific compiler settings.
- set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
+ set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DETH_DEBUG")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
diff --git a/docs/conf.py b/docs/conf.py
index e17d5fd8..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.5'
+version = '0.4.7'
# The full version, including alpha/beta/rc tags.
-release = '0.4.5-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/control-structures.rst b/docs/control-structures.rst
index 597829d3..974a093f 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -2,21 +2,81 @@
Expressions and Control Structures
##################################
-.. index:: if, else, while, for, break, continue, return, switch, goto
+.. 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``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with
+there is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with
the usual semantics known from C or JavaScript.
Parentheses can *not* be omitted for conditionals, but curly brances can be omitted
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
@@ -329,9 +389,10 @@ Currently, there are situations, where exceptions happen automatically in Solidi
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 perform an external function call targeting a contract that contains no code.
-7. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function).
-8. If your contract receives Ether via a public accessor function.
+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.
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.
@@ -426,7 +487,7 @@ these curly braces, the following can be used (see the later sections for more d
- literals, e.g. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters)
- opcodes (in "instruction style"), e.g. ``mload sload dup1 sstore``, for a list see below
- - opcodes in functional style, e.g. ``add(1, mlod(0))``
+ - opcodes in functional style, e.g. ``add(1, mload(0))``
- labels, e.g. ``name:``
- variable declarations, e.g. ``let x := 7`` or ``let x := add(y, 3)``
- identifiers (externals, labels or assembly-local variables), e.g. ``jump(name)``, ``3 x add``
@@ -715,6 +776,10 @@ will have a wrong impression about the stack height at label ``two``:
three:
}
+.. note::
+
+ ``invalidJumpLabel`` is a pre-defined label. Jumping to this location will always
+ result in an invalid jump, effectively aborting execution of the code.
Declaring Assembly-Local Variables
----------------------------------
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 eeea85a7..aee1e03b 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -25,7 +25,7 @@ Storage
storedData = x;
}
- function get() constant returns (uint retVal) {
+ function get() constant returns (uint) {
return storedData;
}
}
@@ -136,7 +136,7 @@ like this one. The accessor function created by the ``public`` keyword
is a bit more complex in this case. It roughly looks like the
following::
- function balances(address _account) returns (uint balance) {
+ function balances(address _account) returns (uint) {
return balances[_account];
}
@@ -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..15ff374d 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -74,6 +74,17 @@ Solidity always places new objects at the free memory pointer and memory is neve
.. index: memory 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.
+
*****************
Esoteric Features
*****************
diff --git a/docs/types.rst b/docs/types.rst
index 9e7d9b4a..0436fc70 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -169,9 +169,10 @@ 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.
+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 +186,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 +209,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 +225,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.
@@ -234,10 +243,11 @@ Hexademical Literals behave like String Literals and have the same convertibilit
.. _enums:
Enums
-=====
+-----
Enums are one way to create a user-defined type in Solidity. They are explicitly convertible
-to and from all integer types but implicit conversion is not allowed.
+to and from all integer types but implicit conversion is not allowed. The explicit conversions
+check the value ranges at runtime and a failure causes an exception. Enums needs at least one member.
::
@@ -266,6 +276,138 @@ to and from all integer types but implicit conversion is not allowed.
}
}
+.. index:: ! function type, ! type; function
+
+.. _function_types:
+
+Function Types
+--------------
+
+Function types are the types of functions. Variables of function type
+can be assigned from functions and function parameters of function type
+can be used to pass functions to and return functions from function calls.
+Function types come in two flavours - *internal* and *external* functions:
+
+Internal functions can only be used inside the current contract (more specifically,
+inside the current code unit, which also includes internal library functions
+and inherited functions) because they cannot be executed outside of the
+context of the current contract. Calling an internal function is realized
+by jumping to its entry label, just like when calling a function of the current
+contract internally.
+
+External functions consist of an address and a function signature and they can
+be passed via and returned from external function calls.
+
+Function types are notated as follows::
+
+ function (<parameter types>) {internal|external} [constant] [payable] [returns (<return types>)]
+
+In contrast to the parameter types, the return types cannot be empty - if the
+function type should not return anything, the whole ``returns (<return types>)``
+part has to be omitted.
+
+By default, function types are internal, so the ``internal`` keyword can be
+omitted.
+
+There are two ways to access a function in the current contract: Either directly
+by its name, ``f``, or using ``this.f``. The former will result in an internal
+function, the latter in an external function.
+
+If a function type variable is not initialized, calling it will result
+in an exception. The same happens if you call a function after using ``delete``
+on it.
+
+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);
+ for (uint i = 0; i < self.length; i++) {
+ r[i] = f(self[i]);
+ }
+ }
+ function reduce(
+ uint[] memory self,
+ function (uint x, uint y) returns (uint) f
+ )
+ internal
+ returns (uint r)
+ {
+ r = self[0];
+ for (uint i = 1; i < self.length; i++) {
+ r = f(r, self[i]);
+ }
+ }
+ function range(uint length) internal returns (uint[] memory r) {
+ r = new uint[](length);
+ for (uint i = 0; i < r.length; i++) {
+ r[i] = i;
+ }
+ }
+ }
+
+ contract Pyramid {
+ using ArrayUtils for *;
+ function pyramid(uint l) returns (uint) {
+ return ArrayUtils.range(l).map(square).reduce(sum);
+ }
+ function square(uint x) internal returns (uint) {
+ return x * x;
+ }
+ function sum(uint x, uint y) internal returns (uint) {
+ return x + y;
+ }
+ }
+
+Another example that uses external function types::
+
+ pragma solidity ^0.4.5;
+
+ contract Oracle {
+ struct Request {
+ bytes data;
+ function(bytes memory) external callback;
+ }
+ Request[] requests;
+ event NewRequest(uint);
+ function query(bytes data, function(bytes memory) external callback) {
+ requests.push(Request(data, callback));
+ NewRequest(requests.length - 1);
+ }
+ function reply(uint requestID, bytes response) {
+ // Here goes the check that the reply comes from a trusted source
+ requests[requestID].callback(response);
+ }
+ }
+
+ contract OracleUser {
+ Oracle constant oracle = Oracle(0x1234567); // known contract
+ function buySomething() {
+ oracle.query("USD", this.oracleResponse);
+ }
+ function oracleResponse(bytes response) {
+ if (msg.sender != address(oracle)) throw;
+ // Use the data
+ }
+ }
+
+Note that lambda or inline functions are planned but not yet supported.
+
.. index:: ! type;reference, ! reference type, storage, memory, location, array, struct
Reference Types
@@ -606,9 +748,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/CommonData.cpp b/libdevcore/CommonData.cpp
index b27271cf..062d1b29 100644
--- a/libdevcore/CommonData.cpp
+++ b/libdevcore/CommonData.cpp
@@ -20,9 +20,6 @@
*/
#include "CommonData.h"
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
#include "Exceptions.h"
using namespace std;
using namespace dev;
diff --git a/libdevcore/JSON.h b/libdevcore/JSON.h
new file mode 100644
index 00000000..7876dfb2
--- /dev/null
+++ b/libdevcore/JSON.h
@@ -0,0 +1,44 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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,
+ 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/>.
+*/
+/** @file JSON.h
+ * @date 2016
+ *
+ * JSON related helpers
+ */
+
+#pragma once
+
+#include <json/json.h>
+
+namespace dev
+{
+
+/// Serialise the JSON object (@a _input) with identation
+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)
+{
+ Json::FastWriter writer;
+ writer.omitEndingLineFeed();
+ return writer.write(_input);
+}
+
+}
diff --git a/libdevcore/SwarmHash.cpp b/libdevcore/SwarmHash.cpp
new file mode 100644
index 00000000..e7b844eb
--- /dev/null
+++ b/libdevcore/SwarmHash.cpp
@@ -0,0 +1,63 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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,
+ 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/>.
+*/
+/** @file SwarmHash.cpp
+ */
+
+#include <libdevcore/SwarmHash.h>
+
+#include <libdevcore/SHA3.h>
+
+using namespace std;
+using namespace dev;
+
+
+bytes toLittleEndian(size_t _size)
+{
+ bytes encoded(8);
+ for (size_t i = 0; i < 8; ++i)
+ encoded[i] = (_size >> (8 * i)) & 0xff;
+ return encoded;
+}
+
+h256 swarmHashSimple(bytesConstRef _data, size_t _size)
+{
+ return keccak256(toLittleEndian(_size) + _data.toBytes());
+}
+
+h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length)
+{
+ if (_length <= 0x1000)
+ return swarmHashSimple(bytesConstRef(_input.data() + _offset, _length), _length);
+ else
+ {
+ bytes innerNodes;
+ size_t maxRepresentedSize = 0x1000;
+ while (maxRepresentedSize * (0x1000 / 32) < _length)
+ maxRepresentedSize *= (0x1000 / 32);
+ for (size_t i = 0; i < _length; i += maxRepresentedSize)
+ {
+ size_t size = std::min(maxRepresentedSize, _length - i);
+ innerNodes += swarmHashIntermediate(_input, _offset + i, size).asBytes();
+ }
+ return swarmHashSimple(bytesConstRef(&innerNodes), _length);
+ }
+}
+
+h256 dev::swarmHash(bytes const& _input)
+{
+ return swarmHashIntermediate(_input, 0, _input.size());
+}
diff --git a/libdevcore/SwarmHash.h b/libdevcore/SwarmHash.h
new file mode 100644
index 00000000..925509ab
--- /dev/null
+++ b/libdevcore/SwarmHash.h
@@ -0,0 +1,31 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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,
+ 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/>.
+*/
+/** @file SwarmHash.h
+ */
+
+#pragma once
+
+#include <libdevcore/FixedHash.h>
+#include <libdevcore/Common.h>
+
+namespace dev
+{
+
+/// Compute the "swarm hash" of @a _data
+h256 swarmHash(bytes const& _data);
+
+}
diff --git a/libdevcore/UTF8.h b/libdevcore/UTF8.h
index 3e39273c..9bdc2b4f 100644
--- a/libdevcore/UTF8.h
+++ b/libdevcore/UTF8.h
@@ -29,7 +29,7 @@ namespace dev
{
/// Validate an input for UTF8 encoding
-/// @returns true if it is invalid and the first invalid position in invalidPosition
+/// @returns false if it is invalid and the first invalid position in invalidPosition
bool validate(std::string const& _input, size_t& _invalidPosition);
}
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index e881c1e2..edbb9828 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>
@@ -20,13 +20,17 @@
*/
#include "Assembly.h"
-#include <fstream>
+
#include <libevmasm/CommonSubexpressionEliminator.h>
#include <libevmasm/ControlFlowGraph.h>
+#include <libevmasm/PeepholeOptimiser.h>
#include <libevmasm/BlockDeduplicator.h>
#include <libevmasm/ConstantOptimiser.h>
#include <libevmasm/GasMeter.h>
+
+#include <fstream>
#include <json/json.h>
+
using namespace std;
using namespace dev;
using namespace dev::eth;
@@ -75,17 +79,17 @@ string Assembly::out() const
return ret.str();
}
-unsigned Assembly::bytesRequired() const
+unsigned Assembly::bytesRequired(unsigned subTagSize) const
{
- for (unsigned br = 1;; ++br)
+ for (unsigned tagSize = subTagSize; true; ++tagSize)
{
unsigned ret = 1;
for (auto const& i: m_data)
ret += i.second.size();
for (AssemblyItem const& i: m_items)
- ret += i.bytesRequired(br);
- if (dev::bytesRequired(ret) <= br)
+ ret += i.bytesRequired(tagSize);
+ if (dev::bytesRequired(ret) <= tagSize)
return ret;
}
}
@@ -132,13 +136,19 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
if (i.data() == 0)
_out << " PUSH [ErrorTag]";
else
- _out << " PUSH [tag" << dec << i.data() << "]";
+ {
+ size_t subId = i.splitForeignPushTag().first;
+ if (subId == size_t(-1))
+ _out << " PUSH [tag" << dec << i.splitForeignPushTag().second << "]";
+ else
+ _out << " PUSH [tag" << dec << subId << ":" << i.splitForeignPushTag().second << "]";
+ }
break;
case PushSub:
- _out << " PUSH [$" << h256(i.data()).abridgedMiddle() << "]";
+ _out << " PUSH [$" << size_t(i.data()) << "]";
break;
case PushSubSize:
- _out << " PUSH #[$" << h256(i.data()).abridgedMiddle() << "]";
+ _out << " PUSH #[$" << size_t(i.data()) << "]";
break;
case PushProgramSize:
_out << " PUSHSIZE";
@@ -167,7 +177,7 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
for (size_t i = 0; i < m_subs.size(); ++i)
{
_out << _prefix << " " << hex << i << ": " << endl;
- m_subs[i].stream(_out, _prefix + " ", _sourceCodes);
+ m_subs[i]->stream(_out, _prefix + " ", _sourceCodes);
}
}
return _out;
@@ -266,7 +276,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
{
std::stringstream hexStr;
hexStr << hex << i;
- data[hexStr.str()] = m_subs[i].stream(_out, "", _sourceCodes, true);
+ data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true);
}
root[".data"] = data;
_out << root;
@@ -308,63 +318,78 @@ void Assembly::injectStart(AssemblyItem const& _i)
Assembly& Assembly::optimise(bool _enable, bool _isCreation, size_t _runs)
{
- if (!_enable)
- return *this;
+ optimiseInternal(_enable, _isCreation, _runs);
+ return *this;
+}
+map<u256, u256> Assembly::optimiseInternal(bool _enable, bool _isCreation, size_t _runs)
+{
+ for (size_t subId = 0; subId < m_subs.size(); ++subId)
+ {
+ map<u256, u256> subTagReplacements = m_subs[subId]->optimiseInternal(_enable, false, _runs);
+ BlockDeduplicator::applyTagReplacement(m_items, subTagReplacements, subId);
+ }
+
+ map<u256, u256> tagReplacements;
unsigned total = 0;
for (unsigned count = 1; count > 0; total += count)
{
count = 0;
+ PeepholeOptimiser peepOpt(m_items);
+ while (peepOpt.optimise())
+ count++;
+
+ if (!_enable)
+ continue;
+
// This only modifies PushTags, we have to run again to actually remove code.
BlockDeduplicator dedup(m_items);
if (dedup.deduplicate())
+ {
+ tagReplacements.insert(dedup.replacedTags().begin(), dedup.replacedTags().end());
count++;
+ }
{
- // Control flow graph that resets knowledge at path joins.
- ControlFlowGraph cfg(m_items, false);
+ // Control flow graph optimization has been here before but is disabled because it
+ // assumes we only jump to tags that are pushed. This is not the case anymore with
+ // function types that can be stored in storage.
AssemblyItems optimisedItems;
- for (BasicBlock const& block: cfg.optimisedBlocks())
+
+ auto iter = m_items.begin();
+ while (iter != m_items.end())
{
- // We used to start with the block's initial state but it caused
- // too many inconsistencies.
KnownState emptyState;
CommonSubexpressionEliminator eliminator(emptyState);
- auto iter = m_items.begin() + block.begin;
- auto const end = m_items.begin() + block.end;
- while (iter < end)
+ auto orig = iter;
+ iter = eliminator.feedItems(iter, m_items.end());
+ bool shouldReplace = false;
+ AssemblyItems optimisedChunk;
+ try
{
- auto orig = iter;
- iter = eliminator.feedItems(iter, end);
- bool shouldReplace = false;
- AssemblyItems optimisedChunk;
- try
- {
- optimisedChunk = eliminator.getOptimizedItems();
- shouldReplace = (optimisedChunk.size() < size_t(iter - orig));
- }
- catch (StackTooDeepException const&)
- {
- // This might happen if the opcode reconstruction is not as efficient
- // as the hand-crafted code.
- }
- catch (ItemNotAvailableException const&)
- {
- // This might happen if e.g. associativity and commutativity rules
- // reorganise the expression tree, but not all leaves are available.
- }
-
- if (shouldReplace)
- {
- count++;
- optimisedItems += optimisedChunk;
- }
- else
- copy(orig, iter, back_inserter(optimisedItems));
+ optimisedChunk = eliminator.getOptimizedItems();
+ shouldReplace = (optimisedChunk.size() < size_t(iter - orig));
+ }
+ catch (StackTooDeepException const&)
+ {
+ // This might happen if the opcode reconstruction is not as efficient
+ // as the hand-crafted code.
+ }
+ catch (ItemNotAvailableException const&)
+ {
+ // This might happen if e.g. associativity and commutativity rules
+ // reorganise the expression tree, but not all leaves are available.
}
- }
+ if (shouldReplace)
+ {
+ count++;
+ optimisedItems += optimisedChunk;
+ }
+ else
+ copy(orig, iter, back_inserter(optimisedItems));
+ }
if (optimisedItems.size() < m_items.size())
{
m_items = move(optimisedItems);
@@ -373,17 +398,15 @@ Assembly& Assembly::optimise(bool _enable, bool _isCreation, size_t _runs)
}
}
- total += ConstantOptimisationMethod::optimiseConstants(
- _isCreation,
- _isCreation ? 1 : _runs,
- *this,
- m_items
- );
-
- for (auto& sub: m_subs)
- sub.optimise(true, false, _runs);
+ if (_enable)
+ total += ConstantOptimisationMethod::optimiseConstants(
+ _isCreation,
+ _isCreation ? 1 : _runs,
+ *this,
+ m_items
+ );
- return *this;
+ return tagReplacements;
}
LinkerObject const& Assembly::assemble() const
@@ -391,20 +414,28 @@ LinkerObject const& Assembly::assemble() const
if (!m_assembledObject.bytecode.empty())
return m_assembledObject;
+ size_t subTagSize = 1;
+ for (auto const& sub: m_subs)
+ {
+ sub->assemble();
+ if (!sub->m_tagPositionsInBytecode.empty())
+ subTagSize = max(subTagSize, *max_element(sub->m_tagPositionsInBytecode.begin(), sub->m_tagPositionsInBytecode.end()));
+ }
+
LinkerObject& ret = m_assembledObject;
- unsigned totalBytes = bytesRequired();
- vector<unsigned> tagPos(m_usedTags);
- map<unsigned, unsigned> tagRef;
+ size_t bytesRequiredForCode = bytesRequired(subTagSize);
+ m_tagPositionsInBytecode = vector<size_t>(m_usedTags, -1);
+ map<size_t, pair<size_t, size_t>> tagRef;
multimap<h256, unsigned> dataRef;
multimap<size_t, size_t> subRef;
vector<unsigned> sizeRef; ///< Pointers to code locations where the size of the program is inserted
- unsigned bytesPerTag = dev::bytesRequired(totalBytes);
+ unsigned bytesPerTag = dev::bytesRequired(bytesRequiredForCode);
byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag;
- unsigned bytesRequiredIncludingData = bytesRequired();
+ unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1;
for (auto const& sub: m_subs)
- bytesRequiredIncludingData += sub.assemble().bytecode.size();
+ bytesRequiredIncludingData += sub->assemble().bytecode.size();
unsigned bytesPerDataRef = dev::bytesRequired(bytesRequiredIncludingData);
byte dataRefPush = (byte)Instruction::PUSH1 - 1 + bytesPerDataRef;
@@ -413,8 +444,8 @@ LinkerObject const& Assembly::assemble() const
for (AssemblyItem const& i: m_items)
{
// store position of the invalid jump destination
- if (i.type() != Tag && tagPos[0] == 0)
- tagPos[0] = ret.bytecode.size();
+ if (i.type() != Tag && m_tagPositionsInBytecode[0] == size_t(-1))
+ m_tagPositionsInBytecode[0] = ret.bytecode.size();
switch (i.type())
{
@@ -446,7 +477,7 @@ LinkerObject const& Assembly::assemble() const
case PushTag:
{
ret.bytecode.push_back(tagPush);
- tagRef[ret.bytecode.size()] = (unsigned)i.data();
+ tagRef[ret.bytecode.size()] = i.splitForeignPushTag();
ret.bytecode.resize(ret.bytecode.size() + bytesPerTag);
break;
}
@@ -462,7 +493,7 @@ LinkerObject const& Assembly::assemble() const
break;
case PushSubSize:
{
- auto s = m_subs.at(size_t(i.data())).assemble().bytecode.size();
+ auto s = m_subs.at(size_t(i.data()))->assemble().bytecode.size();
i.setPushedValue(u256(s));
byte b = max<unsigned>(1, dev::bytesRequired(s));
ret.bytecode.push_back((byte)Instruction::PUSH1 - 1 + b);
@@ -484,25 +515,16 @@ LinkerObject const& Assembly::assemble() const
ret.bytecode.resize(ret.bytecode.size() + 20);
break;
case Tag:
- tagPos[(unsigned)i.data()] = ret.bytecode.size();
assertThrow(i.data() != 0, AssemblyException, "");
+ assertThrow(i.splitForeignPushTag().first == size_t(-1), AssemblyException, "Foreign tag.");
+ assertThrow(ret.bytecode.size() < 0xffffffffL, AssemblyException, "Tag too large.");
+ m_tagPositionsInBytecode[size_t(i.data())] = ret.bytecode.size();
ret.bytecode.push_back((byte)Instruction::JUMPDEST);
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}
}
- for (auto const& i: tagRef)
- {
- bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
- auto tag = i.second;
- if (tag >= tagPos.size())
- tag = 0;
- if (tag == 0)
- assertThrow(tagPos[tag] != 0, AssemblyException, "");
-
- toBigEndian(tagPos[tag], r);
- }
if (!dataRef.empty() && !subRef.empty())
ret.bytecode.push_back(0);
@@ -516,7 +538,24 @@ LinkerObject const& Assembly::assemble() const
bytesRef r(ret.bytecode.data() + ref->second, bytesPerDataRef);
toBigEndian(ret.bytecode.size(), r);
}
- ret.append(m_subs[i].assemble());
+ ret.append(m_subs[i]->assemble());
+ }
+ for (auto const& i: tagRef)
+ {
+ size_t subId;
+ size_t tagId;
+ tie(subId, tagId) = i.second;
+ assertThrow(subId == size_t(-1) || subId < m_subs.size(), AssemblyException, "Invalid sub id");
+ std::vector<size_t> const& tagPositions =
+ subId == size_t(-1) ?
+ m_tagPositionsInBytecode :
+ m_subs[subId]->m_tagPositionsInBytecode;
+ assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag.");
+ size_t pos = tagPositions[tagId];
+ assertThrow(pos != size_t(-1), AssemblyException, "Reference to tag without position.");
+ assertThrow(dev::bytesRequired(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space.");
+ bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
+ toBigEndian(pos, r);
}
for (auto const& dataItem: m_data)
{
diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h
index dae1e1da..a5fd4d51 100644
--- a/libevmasm/Assembly.h
+++ b/libevmasm/Assembly.h
@@ -1,43 +1,45 @@
/*
- 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>
- * @date 2014
- */
#pragma once
-#include <iostream>
-#include <sstream>
-#include <libdevcore/Common.h>
-#include <libdevcore/Assertions.h>
-#include <libdevcore/SHA3.h>
#include <libevmasm/Instruction.h>
#include <libevmasm/SourceLocation.h>
#include <libevmasm/AssemblyItem.h>
#include <libevmasm/LinkerObject.h>
-#include "Exceptions.h"
+#include <libevmasm/Exceptions.h>
+
+#include <libdevcore/Common.h>
+#include <libdevcore/Assertions.h>
+#include <libdevcore/SHA3.h>
+
#include <json/json.h>
+#include <iostream>
+#include <sstream>
+#include <memory>
+
namespace dev
{
namespace eth
{
+using AssemblyPointer = std::shared_ptr<Assembly>;
+
class Assembly
{
public:
@@ -46,20 +48,18 @@ public:
AssemblyItem newTag() { return AssemblyItem(Tag, m_usedTags++); }
AssemblyItem newPushTag() { return AssemblyItem(PushTag, m_usedTags++); }
AssemblyItem newData(bytes const& _data) { h256 h(dev::keccak256(asString(_data))); m_data[h] = _data; return AssemblyItem(PushData, h); }
- AssemblyItem newSub(Assembly const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
- Assembly const& sub(size_t _sub) const { return m_subs.at(_sub); }
- Assembly& sub(size_t _sub) { return m_subs.at(_sub); }
+ AssemblyItem newSub(AssemblyPointer const& _sub) { m_subs.push_back(_sub); return AssemblyItem(PushSub, m_subs.size() - 1); }
+ Assembly const& sub(size_t _sub) const { return *m_subs.at(_sub); }
+ Assembly& sub(size_t _sub) { return *m_subs.at(_sub); }
AssemblyItem newPushString(std::string const& _data) { h256 h(dev::keccak256(_data)); m_strings[h] = _data; return AssemblyItem(PushString, h); }
AssemblyItem newPushSubSize(u256 const& _subId) { return AssemblyItem(PushSubSize, _subId); }
AssemblyItem newPushLibraryAddress(std::string const& _identifier);
- AssemblyItem append() { return append(newTag()); }
void append(Assembly const& _a);
void append(Assembly const& _a, int _deposit);
AssemblyItem const& append(AssemblyItem const& _i);
AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); }
AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); }
- AssemblyItem appendSubSize(Assembly const& _a) { auto ret = newSub(_a); append(newPushSubSize(ret.data())); return ret; }
/// Pushes the final size of the current assembly itself. Use this when the code is modified
/// after compilation and CODESIZE is not an option.
void appendProgramSize() { append(AssemblyItem(PushProgramSize)); }
@@ -101,6 +101,7 @@ public:
/// execution gas usage is optimised. @a _isCreation should be true for the top-level assembly.
/// @a _runs specifes an estimate on how often each opcode in this assembly will be executed,
/// i.e. use a small value to optimise for size and a large value to optimise for runtime.
+ /// If @a _enable is not set, will perform some simple peephole optimizations.
Assembly& optimise(bool _enable, bool _isCreation = true, size_t _runs = 200);
Json::Value stream(
std::ostream& _out,
@@ -110,9 +111,13 @@ public:
) const;
protected:
+ /// Does the same operations as @a optimise, but should only be applied to a sub and
+ /// returns the replaced tags.
+ std::map<u256, u256> optimiseInternal(bool _enable, bool _isCreation, size_t _runs);
+
std::string locationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const;
void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
- unsigned bytesRequired() const;
+ unsigned bytesRequired(unsigned subTagSize) const;
private:
Json::Value streamAsmJson(std::ostream& _out, StringMap const& _sourceCodes) const;
@@ -124,11 +129,12 @@ protected:
unsigned m_usedTags = 1;
AssemblyItems m_items;
std::map<h256, bytes> m_data;
- std::vector<Assembly> m_subs;
+ 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.
mutable LinkerObject m_assembledObject;
+ mutable std::vector<size_t> m_tagPositionsInBytecode;
int m_deposit = 0;
int m_baseDeposit = 0;
diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp
index 599ded85..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>
@@ -26,6 +26,29 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
+AssemblyItem AssemblyItem::toSubAssemblyTag(size_t _subId) const
+{
+ assertThrow(m_data < (u256(1) << 64), Exception, "Tag already has subassembly set.");
+
+ assertThrow(m_type == PushTag || m_type == Tag, Exception, "");
+ AssemblyItem r = *this;
+ r.m_type = PushTag;
+ r.setPushTagSubIdAndTag(_subId, size_t(m_data));
+ return r;
+}
+
+pair<size_t, size_t> AssemblyItem::splitForeignPushTag() const
+{
+ assertThrow(m_type == PushTag || m_type == Tag, Exception, "");
+ return make_pair(size_t(m_data / (u256(1) << 64)) - 1, size_t(m_data));
+}
+
+void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag)
+{
+ assertThrow(m_type == PushTag || m_type == Tag, Exception, "");
+ setData(_tag + (u256(_subId + 1) << 64));
+}
+
unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const
{
switch (m_type)
@@ -104,8 +127,14 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " PushString" << hex << (unsigned)_item.data();
break;
case PushTag:
- _out << " PushTag " << _item.data();
+ {
+ size_t subId = _item.splitForeignPushTag().first;
+ if (subId == size_t(-1))
+ _out << " PushTag " << _item.splitForeignPushTag().second;
+ else
+ _out << " PushTag " << subId << ":" << _item.splitForeignPushTag().second;
break;
+ }
case Tag:
_out << " Tag " << _item.data();
break;
@@ -113,10 +142,10 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " PushData " << hex << (unsigned)_item.data();
break;
case PushSub:
- _out << " PushSub " << hex << h256(_item.data()).abridgedMiddle();
+ _out << " PushSub " << hex << size_t(_item.data());
break;
case PushSubSize:
- _out << " PushSubSize " << hex << h256(_item.data()).abridgedMiddle();
+ _out << " PushSubSize " << hex << size_t(_item.data());
break;
case PushProgramSize:
_out << " PushProgramSize";
diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h
index 1c3d9789..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
*/
@@ -69,6 +69,14 @@ public:
AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); }
AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); }
+ /// Converts the tag to a subassembly tag. This has to be called in order to move a tag across assemblies.
+ /// @param _subId the identifier of the subassembly the tag is taken from.
+ AssemblyItem toSubAssemblyTag(size_t _subId) const;
+ /// @returns splits the data of the push tag into sub assembly id and actual tag id.
+ /// The sub assembly id of non-foreign push tags is -1.
+ std::pair<size_t, size_t> splitForeignPushTag() const;
+ /// Sets sub-assembly part and tag for a push tag.
+ void setPushTagSubIdAndTag(size_t _subId, size_t _tag);
AssemblyItemType type() const { return m_type; }
u256 const& data() const { return m_data; }
diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp
index 3bb7a797..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
@@ -77,7 +77,6 @@ bool BlockDeduplicator::deduplicate()
{
//@todo this should probably be optimized.
set<size_t, function<bool(size_t, size_t)>> blocksSeen(comparator);
- map<u256, u256> tagReplacement;
for (size_t i = 0; i < m_items.size(); ++i)
{
if (m_items.at(i).type() != Tag)
@@ -86,22 +85,40 @@ bool BlockDeduplicator::deduplicate()
if (it == blocksSeen.end())
blocksSeen.insert(i);
else
- tagReplacement[m_items.at(i).data()] = m_items.at(*it).data();
+ m_replacedTags[m_items.at(i).data()] = m_items.at(*it).data();
}
- bool changed = false;
- for (AssemblyItem& item: m_items)
- if (item.type() == PushTag && tagReplacement.count(item.data()))
- {
- changed = true;
- item.setData(tagReplacement.at(item.data()));
- }
- if (!changed)
+ if (!applyTagReplacement(m_items, m_replacedTags))
break;
}
return iterations > 0;
}
+bool BlockDeduplicator::applyTagReplacement(
+ AssemblyItems& _items,
+ map<u256, u256> const& _replacements,
+ size_t _subId
+)
+{
+ bool changed = false;
+ for (AssemblyItem& item: _items)
+ if (item.type() == PushTag)
+ {
+ size_t subId;
+ size_t tagId;
+ tie(subId, tagId) = item.splitForeignPushTag();
+ if (subId != _subId)
+ continue;
+ auto it = _replacements.find(tagId);
+ if (it != _replacements.end())
+ {
+ changed = true;
+ item.setPushTagSubIdAndTag(subId, size_t(it->second));
+ }
+ }
+ return changed;
+}
+
BlockDeduplicator::BlockIterator& BlockDeduplicator::BlockIterator::operator++()
{
if (it == end)
diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h
index c48835fd..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
@@ -23,9 +23,12 @@
#pragma once
+#include <libdevcore/Common.h>
+
#include <cstddef>
#include <vector>
#include <functional>
+#include <map>
namespace dev
{
@@ -45,6 +48,18 @@ public:
BlockDeduplicator(AssemblyItems& _items): m_items(_items) {}
/// @returns true if something was changed
bool deduplicate();
+ /// @returns the tags that were replaced.
+ std::map<u256, u256> const& replacedTags() const { return m_replacedTags; }
+
+ /// Replaces all PushTag operations insied @a _items that match a key in
+ /// @a _replacements by the respective value. If @a _subID is not -1, only
+ /// apply the replacement for foreign tags from this sub id.
+ /// @returns true iff a replacement was performed.
+ static bool applyTagReplacement(
+ AssemblyItems& _items,
+ std::map<u256, u256> const& _replacements,
+ size_t _subID = size_t(-1)
+ );
private:
/// Iterator that skips tags and skips to the end if (all branches of) the control
@@ -70,6 +85,7 @@ private:
AssemblyItem const* replaceWith;
};
+ std::map<u256, u256> m_replacedTags;
AssemblyItems& m_items;
};
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 03a1f717..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
@@ -89,6 +89,11 @@ struct BasicBlock
using BasicBlocks = std::vector<BasicBlock>;
+/**
+ * Control flow graph optimizer.
+ * ASSUMES THAT WE ONLY JUMP TO TAGS THAT WERE PREVIOUSLY PUSHED. THIS IS NOT TRUE ANYMORE
+ * NOW THAT FUNCTION TAGS CAN BE STORED IN STORAGE.
+ */
class ControlFlowGraph
{
public:
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..e32b2da2 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
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 51f3cf1d..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>
@@ -39,7 +39,7 @@ GasMeter::GasConsumption& GasMeter::GasConsumption::operator+=(GasConsumption co
return *this;
}
-GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item)
+GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _includeExternalCosts)
{
GasConsumption gas;
switch (_item.type())
@@ -128,23 +128,35 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item)
case Instruction::CALLCODE:
case Instruction::DELEGATECALL:
{
- gas = GasCosts::callGas;
- if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0)))
- gas += (*value);
- else
+ if (_includeExternalCosts)
+ // We assume that we do not know the target contract and thus, the consumption is infinite.
gas = GasConsumption::infinite();
- if (_item.instruction() == Instruction::CALL)
- gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists.
- int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1;
- if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize)))
- gas += GasCosts::callValueTransferGas;
- gas += memoryGas(-2 - valueSize, -3 - valueSize);
- gas += memoryGas(-4 - valueSize, -5 - valueSize);
+ else
+ {
+ gas = GasCosts::callGas;
+ if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0)))
+ gas += (*value);
+ else
+ gas = GasConsumption::infinite();
+ if (_item.instruction() == Instruction::CALL)
+ gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists.
+ int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1;
+ if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize)))
+ gas += GasCosts::callValueTransferGas;
+ gas += memoryGas(-2 - valueSize, -3 - valueSize);
+ gas += memoryGas(-4 - valueSize, -5 - valueSize);
+ }
break;
}
case Instruction::CREATE:
- gas = GasCosts::createGas;
- gas += memoryGas(-1, -2);
+ if (_includeExternalCosts)
+ // We assume that we do not know the target contract and thus, the consumption is infinite.
+ gas = GasConsumption::infinite();
+ else
+ {
+ gas = GasCosts::createGas;
+ gas += memoryGas(-1, -2);
+ }
break;
case Instruction::EXP:
gas = GasCosts::expGas;
diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h
index 1a607a9f..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>
@@ -102,7 +102,8 @@ public:
/// @returns an upper bound on the gas consumed by the given instruction and updates
/// the state.
- GasConsumption estimateMax(AssemblyItem const& _item);
+ /// @param _inculdeExternalCosts if true, include costs caused by other contracts in calls.
+ GasConsumption estimateMax(AssemblyItem const& _item, bool _includeExternalCosts = true);
u256 const& largestMemoryAccess() const { return m_largestMemoryAccess; }
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
new file mode 100644
index 00000000..b96b0295
--- /dev/null
+++ b/libevmasm/PeepholeOptimiser.cpp
@@ -0,0 +1,245 @@
+/*
+ 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 PeepholeOptimiser.cpp
+ * Performs local optimising code changes to assembly.
+ */
+
+#include "PeepholeOptimiser.h"
+
+#include <libevmasm/AssemblyItem.h>
+#include <libevmasm/SemanticInformation.h>
+
+using namespace std;
+using namespace dev::eth;
+using namespace dev;
+
+// TODO: Extend this to use the tools from ExpressionClasses.cpp
+
+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 bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out)
+ {
+ 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);
+ }
+};
+
+template <class Method, size_t WindowSize>
+struct SimplePeepholeOptimizerMethod
+{
+ static bool apply(OptimiserState& _state)
+ {
+ 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 Identity: SimplePeepholeOptimizerMethod<Identity, 1>
+{
+ static bool applySimple(AssemblyItem const& _item, std::back_insert_iterator<AssemblyItems> _out)
+ {
+ *_out = _item;
+ return true;
+ }
+};
+
+struct PushPop: SimplePeepholeOptimizerMethod<PushPop, 2>
+{
+ 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 (
+ _pushTag.type() == PushTag &&
+ (_jump == Instruction::JUMP || _jump == Instruction::JUMPI) &&
+ _tag.type() == Tag &&
+ _pushTag.data() == _tag.data()
+ )
+ {
+ if (_jump == Instruction::JUMPI)
+ *_out = AssemblyItem(Instruction::POP, _jump.location());
+ *_out = _tag;
+ return true;
+ }
+ else
+ return false;
+ }
+};
+
+struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions, 3>
+{
+ static bool applySimple(
+ AssemblyItem const& _pushTag,
+ AssemblyItem const& _pushConstant,
+ AssemblyItem const& _and,
+ std::back_insert_iterator<AssemblyItems> _out
+ )
+ {
+ if (
+ _pushTag.type() == PushTag &&
+ _and == Instruction::AND &&
+ _pushConstant.type() == Push &&
+ (_pushConstant.data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF)
+ )
+ {
+ *_out = _pushTag;
+ return true;
+ }
+ else
+ return false;
+ }
+};
+
+/// Removes everything after a JUMP (or similar) until the next JUMPDEST.
+struct UnreachableCode
+{
+ 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&)
+{
+ assertThrow(false, OptimizerException, "Peephole optimizer failed to apply identity.");
+}
+
+template <typename Method, typename... OtherMethods>
+void applyMethods(OptimiserState& _state, Method, OtherMethods... _other)
+{
+ if (!Method::apply(_state))
+ applyMethods(_state, _other...);
+}
+
+bool PeepholeOptimiser::optimise()
+{
+ OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)};
+ while (state.i < m_items.size())
+ applyMethods(state, PushPop(), OpPop(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity());
+ if (m_optimisedItems.size() < m_items.size())
+ {
+ m_items = std::move(m_optimisedItems);
+ return true;
+ }
+ else
+ return false;
+
+}
diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h
new file mode 100644
index 00000000..a74cc8b3
--- /dev/null
+++ b/libevmasm/PeepholeOptimiser.h
@@ -0,0 +1,54 @@
+/*
+ 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 PeepholeOptimiser.h
+ * Performs local optimising code changes to assembly.
+ */
+#pragma once
+
+#include <vector>
+#include <cstddef>
+#include <iterator>
+
+namespace dev
+{
+namespace eth
+{
+class AssemblyItem;
+using AssemblyItems = std::vector<AssemblyItem>;
+
+class PeepholeOptimisationMethod
+{
+public:
+ virtual size_t windowSize() const;
+ virtual bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator<AssemblyItems> _out);
+};
+
+class PeepholeOptimiser
+{
+public:
+ explicit PeepholeOptimiser(AssemblyItems& _items): m_items(_items) {}
+
+ bool optimise();
+
+private:
+ AssemblyItems& m_items;
+ AssemblyItems m_optimisedItems;
+};
+
+}
+}
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 05304d14..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>
@@ -55,7 +55,11 @@ struct SourceLocation
return *this;
}
- bool operator==(SourceLocation const& _other) const { return start == _other.start && end == _other.end;}
+ bool operator==(SourceLocation const& _other) const
+ {
+ return start == _other.start && end == _other.end &&
+ ((!sourceName && !_other.sourceName) || (sourceName && _other.sourceName && *sourceName == *_other.sourceName));
+ }
bool operator!=(SourceLocation const& _other) const { return !operator==(_other); }
inline bool operator<(SourceLocation const& _other) const;
inline bool contains(SourceLocation const& _other) const;
@@ -79,20 +83,21 @@ inline std::ostream& operator<<(std::ostream& _out, SourceLocation const& _locat
bool SourceLocation::operator<(SourceLocation const& _other) const
{
if (!sourceName || !_other.sourceName)
- return int(!!sourceName) < int(!!_other.sourceName);
- return make_tuple(*sourceName, start, end) < make_tuple(*_other.sourceName, _other.start, _other.end);
+ return std::make_tuple(int(!!sourceName), start, end) < std::make_tuple(int(!!_other.sourceName), _other.start, _other.end);
+ else
+ return std::make_tuple(*sourceName, start, end) < std::make_tuple(*_other.sourceName, _other.start, _other.end);
}
bool SourceLocation::contains(SourceLocation const& _other) const
{
- if (isEmpty() || _other.isEmpty() || !sourceName || !_other.sourceName || *sourceName != *_other.sourceName)
+ if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName)))
return false;
return start <= _other.start && _other.end <= end;
}
bool SourceLocation::intersects(SourceLocation const& _other) const
{
- if (isEmpty() || _other.isEmpty() || !sourceName || !_other.sourceName || *sourceName != *_other.sourceName)
+ if (isEmpty() || _other.isEmpty() || ((!sourceName || !_other.sourceName || *sourceName != *_other.sourceName) && (sourceName || _other.sourceName)))
return false;
return _other.start < end && start < _other.end;
}
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp
index 39b6376c..d757dcf1 100644
--- a/liblll/CodeFragment.cpp
+++ b/liblll/CodeFragment.cpp
@@ -474,7 +474,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireSize(2);
requireDeposit(0, 1);
- auto begin = m_asm.append();
+ auto begin = m_asm.append(m_asm.newTag());
m_asm.append(code[0].m_asm);
if (us == "WHILE")
m_asm.append(Instruction::ISZERO);
@@ -489,7 +489,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireDeposit(1, 1);
m_asm.append(code[0].m_asm, 0);
- auto begin = m_asm.append();
+ auto begin = m_asm.append(m_asm.newTag());
m_asm.append(code[1].m_asm);
m_asm.append(Instruction::ISZERO);
auto end = m_asm.appendJumpI();
@@ -520,7 +520,8 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
requireMaxSize(3);
requireDeposit(1, 1);
- auto subPush = m_asm.appendSubSize(code[0].assembly(ns));
+ auto subPush = m_asm.newSub(make_shared<Assembly>(code[0].assembly(ns)));
+ m_asm.append(m_asm.newPushSubSize(subPush.data()));
m_asm.append(Instruction::DUP1);
if (code.size() == 3)
{
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 a7b9e8b8..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>
@@ -83,6 +83,31 @@ void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName)
fatalTypeError(_typeName.location(), "Name has to refer to a struct, enum or contract.");
}
+void ReferencesResolver::endVisit(FunctionTypeName const& _typeName)
+{
+ switch (_typeName.visibility())
+ {
+ case VariableDeclaration::Visibility::Default:
+ case VariableDeclaration::Visibility::Internal:
+ case VariableDeclaration::Visibility::External:
+ break;
+ default:
+ typeError(_typeName.location(), "Invalid visibility, can only be \"external\" or \"internal\".");
+ }
+
+ if (_typeName.isPayable() && _typeName.visibility() != VariableDeclaration::Visibility::External)
+ fatalTypeError(_typeName.location(), "Only external function types can be payable.");
+ if (_typeName.visibility() == VariableDeclaration::Visibility::External)
+ for (auto const& t: _typeName.parameterTypes() + _typeName.returnParameterTypes())
+ {
+ solAssert(t->annotation().type, "Type not set for parameter.");
+ if (!t->annotation().type->canBeUsedExternally(false))
+ fatalTypeError(t->location(), "Internal type cannot be used for external function type.");
+ }
+
+ _typeName.annotation().type = make_shared<FunctionType>(_typeName);
+}
+
void ReferencesResolver::endVisit(Mapping const& _typeName)
{
TypePointer keyType = _typeName.keyType().annotation().type;
diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h
index 1986b2bb..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>
@@ -62,6 +62,7 @@ private:
virtual bool visit(Identifier const& _identifier) override;
virtual bool visit(ElementaryTypeName const& _typeName) override;
virtual void endVisit(UserDefinedTypeName const& _typeName) override;
+ virtual void endVisit(FunctionTypeName const& _typeName) override;
virtual void endVisit(Mapping const& _typeName) override;
virtual void endVisit(ArrayTypeName const& _typeName) override;
virtual bool visit(InlineAssembly const& _inlineAssembly) override;
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/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 46f4f7f6..7235b57a 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>
@@ -574,6 +574,14 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
return false;
}
+void TypeChecker::endVisit(FunctionTypeName const& _funType)
+{
+ FunctionType const& fun = dynamic_cast<FunctionType const&>(*_funType.annotation().type);
+ if (fun.location() == FunctionType::Location::External)
+ if (!fun.canBeUsedExternally(false))
+ typeError(_funType.location(), "External function type uses internal types.");
+}
+
bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
// Inline assembly does not have its own type-checking phase, so we just run the
@@ -996,9 +1004,9 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
fatalTypeError(components[i]->location(), "Invalid mobile type.");
if (i == 0)
- inlineArrayType = types[i]->mobileType();
+ inlineArrayType = types[i];
else if (inlineArrayType)
- inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType());
+ inlineArrayType = Type::commonType(inlineArrayType, types[i]);
}
}
else
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index be1e02be..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>
@@ -87,6 +87,7 @@ private:
/// case this is a base constructor call.
void visitManually(ModifierInvocation const& _modifier, std::vector<ContractDefinition const*> const& _bases);
virtual bool visit(EventDefinition const& _eventDef) override;
+ virtual void endVisit(FunctionTypeName const& _funType) override;
virtual bool visit(InlineAssembly const& _inlineAssembly) override;
virtual bool visit(IfStatement const& _ifStatement) override;
virtual bool visit(WhileStatement const& _whileStatement) override;
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 695d9881..9b478393 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>
@@ -160,22 +160,22 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::inter
return *m_interfaceFunctionList;
}
-string const& ContractDefinition::devDocumentation() const
+Json::Value const& ContractDefinition::devDocumentation() const
{
return m_devDocumentation;
}
-string const& ContractDefinition::userDocumentation() const
+Json::Value const& ContractDefinition::userDocumentation() const
{
return m_userDocumentation;
}
-void ContractDefinition::setDevDocumentation(string const& _devDocumentation)
+void ContractDefinition::setDevDocumentation(Json::Value const& _devDocumentation)
{
m_devDocumentation = _devDocumentation;
}
-void ContractDefinition::setUserDocumentation(string const& _userDocumentation)
+void ContractDefinition::setUserDocumentation(Json::Value const& _userDocumentation)
{
m_userDocumentation = _userDocumentation;
}
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 7ed4ddce..89b96f09 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>
@@ -35,6 +35,7 @@
#include <libsolidity/ast/Types.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/ASTAnnotations.h>
+#include <json/json.h>
namespace dev
{
@@ -343,11 +344,11 @@ public:
/// Returns the fallback function or nullptr if no fallback function was specified.
FunctionDefinition const* fallbackFunction() const;
- std::string const& userDocumentation() const;
- void setUserDocumentation(std::string const& _userDocumentation);
+ Json::Value const& userDocumentation() const;
+ void setUserDocumentation(Json::Value const& _userDocumentation);
- std::string const& devDocumentation() const;
- void setDevDocumentation(std::string const& _devDocumentation);
+ Json::Value const& devDocumentation() const;
+ void setDevDocumentation(Json::Value const& _devDocumentation);
virtual TypePointer type() const override;
@@ -359,8 +360,8 @@ private:
bool m_isLibrary;
// parsed Natspec documentation of the contract.
- std::string m_userDocumentation;
- std::string m_devDocumentation;
+ Json::Value m_userDocumentation;
+ Json::Value m_devDocumentation;
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList;
@@ -822,6 +823,41 @@ private:
};
/**
+ * A literal function type. Its source form is "function (paramType1, paramType2) internal / external returns (retType1, retType2)"
+ */
+class FunctionTypeName: public TypeName
+{
+public:
+ FunctionTypeName(
+ SourceLocation const& _location,
+ ASTPointer<ParameterList> const& _parameterTypes,
+ ASTPointer<ParameterList> const& _returnTypes,
+ Declaration::Visibility _visibility,
+ bool _isDeclaredConst,
+ bool _isPayable
+ ):
+ TypeName(_location), m_parameterTypes(_parameterTypes), m_returnTypes(_returnTypes),
+ m_visibility(_visibility), m_isDeclaredConst(_isDeclaredConst), m_isPayable(_isPayable)
+ {}
+ virtual void accept(ASTVisitor& _visitor) override;
+ virtual void accept(ASTConstVisitor& _visitor) const override;
+
+ std::vector<ASTPointer<VariableDeclaration>> const& parameterTypes() const { return m_parameterTypes->parameters(); }
+ std::vector<ASTPointer<VariableDeclaration>> const& returnParameterTypes() const { return m_returnTypes->parameters(); }
+
+ Declaration::Visibility visibility() const { return m_visibility; }
+ bool isDeclaredConst() const { return m_isDeclaredConst; }
+ bool isPayable() const { return m_isPayable; }
+
+private:
+ ASTPointer<ParameterList> m_parameterTypes;
+ ASTPointer<ParameterList> m_returnTypes;
+ Declaration::Visibility m_visibility;
+ bool m_isDeclaredConst;
+ bool m_isPayable;
+};
+
+/**
* A mapping type. Its source form is "mapping('keyType' => 'valueType')"
*/
class Mapping: public TypeName
@@ -1005,18 +1041,22 @@ public:
SourceLocation const& _location,
ASTPointer<ASTString> const& _docString,
ASTPointer<Expression> const& _condition,
- ASTPointer<Statement> const& _body
+ ASTPointer<Statement> const& _body,
+ bool _isDoWhile
):
- BreakableStatement(_location, _docString), m_condition(_condition), m_body(_body) {}
+ BreakableStatement(_location, _docString), m_condition(_condition), m_body(_body),
+ m_isDoWhile(_isDoWhile) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
Expression const& condition() const { return *m_condition; }
Statement const& body() const { return *m_body; }
+ bool isDoWhile() const { return m_isDoWhile; }
private:
ASTPointer<Expression> m_condition;
ASTPointer<Statement> m_body;
+ bool m_isDoWhile;
};
/**
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..768e56db 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>
diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h
index 59fc1b57..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>
@@ -54,6 +54,7 @@ class MagicVariableDeclaration;
class TypeName;
class ElementaryTypeName;
class UserDefinedTypeName;
+class FunctionTypeName;
class Mapping;
class ArrayTypeName;
class Statement;
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index b573feda..030b32ba 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>
@@ -226,6 +226,20 @@ bool ASTJsonConverter::visit(UserDefinedTypeName const& _node)
return true;
}
+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("constant", _node.isDeclaredConst())
+ }, true);
+ return true;
+}
+
bool ASTJsonConverter::visit(Mapping const& _node)
{
addJsonNode(_node, "Mapping", {}, true);
@@ -264,7 +278,11 @@ bool ASTJsonConverter::visit(IfStatement const& _node)
bool ASTJsonConverter::visit(WhileStatement const& _node)
{
- addJsonNode(_node, "WhileStatement", {}, true);
+ addJsonNode(
+ _node,
+ _node.isDoWhile() ? "DoWhileStatement" : "WhileStatement",
+ {},
+ true);
return true;
}
@@ -503,6 +521,11 @@ void ASTJsonConverter::endVisit(UserDefinedTypeName const&)
{
}
+void ASTJsonConverter::endVisit(FunctionTypeName const&)
+{
+ goUp();
+}
+
void ASTJsonConverter::endVisit(Mapping const&)
{
goUp();
diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h
index 7c7b37f8..277476d5 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>
@@ -69,6 +69,7 @@ public:
bool visit(TypeName const& _node) override;
bool visit(ElementaryTypeName const& _node) override;
bool visit(UserDefinedTypeName const& _node) override;
+ bool visit(FunctionTypeName const& _node) override;
bool visit(Mapping const& _node) override;
bool visit(ArrayTypeName const& _node) override;
bool visit(InlineAssembly const& _node) override;
@@ -114,6 +115,7 @@ public:
void endVisit(TypeName const&) override;
void endVisit(ElementaryTypeName const&) override;
void endVisit(UserDefinedTypeName const&) override;
+ void endVisit(FunctionTypeName const&) override;
void endVisit(Mapping const&) override;
void endVisit(ArrayTypeName const&) override;
void endVisit(InlineAssembly const&) override;
diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp
index a9de457a..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>
@@ -164,6 +164,13 @@ bool ASTPrinter::visit(UserDefinedTypeName const& _node)
return goDeeper();
}
+bool ASTPrinter::visit(FunctionTypeName const& _node)
+{
+ writeLine("FunctionTypeName");
+ printSourcePart(_node);
+ return goDeeper();
+}
+
bool ASTPrinter::visit(Mapping const& _node)
{
writeLine("Mapping");
@@ -208,7 +215,7 @@ bool ASTPrinter::visit(IfStatement const& _node)
bool ASTPrinter::visit(WhileStatement const& _node)
{
- writeLine("WhileStatement");
+ writeLine(_node.isDoWhile() ? "DoWhileStatement" : "WhileStatement");
printSourcePart(_node);
return goDeeper();
}
@@ -442,6 +449,11 @@ void ASTPrinter::endVisit(UserDefinedTypeName const&)
m_indentation--;
}
+void ASTPrinter::endVisit(FunctionTypeName const&)
+{
+ m_indentation--;
+}
+
void ASTPrinter::endVisit(Mapping const&)
{
m_indentation--;
diff --git a/libsolidity/ast/ASTPrinter.h b/libsolidity/ast/ASTPrinter.h
index f0ab1098..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>
@@ -63,6 +63,7 @@ public:
bool visit(TypeName const& _node) override;
bool visit(ElementaryTypeName const& _node) override;
bool visit(UserDefinedTypeName const& _node) override;
+ bool visit(FunctionTypeName const& _node) override;
bool visit(Mapping const& _node) override;
bool visit(ArrayTypeName const& _node) override;
bool visit(InlineAssembly const& _node) override;
@@ -106,6 +107,7 @@ public:
void endVisit(TypeName const&) override;
void endVisit(ElementaryTypeName const&) override;
void endVisit(UserDefinedTypeName const&) override;
+ void endVisit(FunctionTypeName const&) override;
void endVisit(Mapping const&) override;
void endVisit(ArrayTypeName const&) override;
void endVisit(InlineAssembly const&) override;
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 3a1b55d3..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>
@@ -61,6 +61,7 @@ public:
virtual bool visit(TypeName& _node) { return visitNode(_node); }
virtual bool visit(ElementaryTypeName& _node) { return visitNode(_node); }
virtual bool visit(UserDefinedTypeName& _node) { return visitNode(_node); }
+ virtual bool visit(FunctionTypeName& _node) { return visitNode(_node); }
virtual bool visit(Mapping& _node) { return visitNode(_node); }
virtual bool visit(ArrayTypeName& _node) { return visitNode(_node); }
virtual bool visit(InlineAssembly& _node) { return visitNode(_node); }
@@ -106,6 +107,7 @@ public:
virtual void endVisit(TypeName& _node) { endVisitNode(_node); }
virtual void endVisit(ElementaryTypeName& _node) { endVisitNode(_node); }
virtual void endVisit(UserDefinedTypeName& _node) { endVisitNode(_node); }
+ virtual void endVisit(FunctionTypeName& _node) { endVisitNode(_node); }
virtual void endVisit(Mapping& _node) { endVisitNode(_node); }
virtual void endVisit(ArrayTypeName& _node) { endVisitNode(_node); }
virtual void endVisit(InlineAssembly& _node) { endVisitNode(_node); }
@@ -163,6 +165,7 @@ public:
virtual bool visit(TypeName const& _node) { return visitNode(_node); }
virtual bool visit(ElementaryTypeName const& _node) { return visitNode(_node); }
virtual bool visit(UserDefinedTypeName const& _node) { return visitNode(_node); }
+ virtual bool visit(FunctionTypeName const& _node) { return visitNode(_node); }
virtual bool visit(Mapping const& _node) { return visitNode(_node); }
virtual bool visit(ArrayTypeName const& _node) { return visitNode(_node); }
virtual bool visit(Block const& _node) { return visitNode(_node); }
@@ -208,6 +211,7 @@ public:
virtual void endVisit(TypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(ElementaryTypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(UserDefinedTypeName const& _node) { endVisitNode(_node); }
+ virtual void endVisit(FunctionTypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(Mapping const& _node) { endVisitNode(_node); }
virtual void endVisit(ArrayTypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(Block const& _node) { endVisitNode(_node); }
diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h
index b5a3806b..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>
@@ -327,6 +327,26 @@ void UserDefinedTypeName::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
+void FunctionTypeName::accept(ASTVisitor& _visitor)
+{
+ if (_visitor.visit(*this))
+ {
+ m_parameterTypes->accept(_visitor);
+ m_returnTypes->accept(_visitor);
+ }
+ _visitor.endVisit(*this);
+}
+
+void FunctionTypeName::accept(ASTConstVisitor& _visitor) const
+{
+ if (_visitor.visit(*this))
+ {
+ m_parameterTypes->accept(_visitor);
+ m_returnTypes->accept(_visitor);
+ }
+ _visitor.endVisit(*this);
+}
+
void Mapping::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 7fe97fa7..b22f3c08 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>
@@ -200,10 +200,10 @@ TypePointer Type::commonType(TypePointer const& _a, TypePointer const& _b)
{
if (!_a || !_b)
return TypePointer();
- else if (_b->isImplicitlyConvertibleTo(*_a))
- return _a;
- else if (_a->isImplicitlyConvertibleTo(*_b))
- return _b;
+ else if (_b->isImplicitlyConvertibleTo(*_a->mobileType()))
+ return _a->mobileType();
+ else if (_a->isImplicitlyConvertibleTo(*_b->mobileType()))
+ return _b->mobileType();
else
return TypePointer();
}
@@ -879,7 +879,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;
}
@@ -906,6 +907,12 @@ TypePointer StringLiteralType::mobileType() const
return make_shared<ArrayType>(DataLocation::Memory, true);
}
+bool StringLiteralType::isValidUTF8() const
+{
+ size_t dontCare {};
+ return dev::validate(m_value, dontCare);
+}
+
shared_ptr<FixedBytesType> FixedBytesType::smallestTypeForLiteral(string const& _literal)
{
if (_literal.length() <= 32)
@@ -1265,6 +1272,7 @@ TypePointer ArrayType::decodingType() const
TypePointer ArrayType::interfaceType(bool _inLibrary) const
{
+ // Note: This has to fulfill canBeUsedExternally(_inLibrary) == !!interfaceType(_inLibrary)
if (_inLibrary && location() == DataLocation::Storage)
return shared_from_this();
@@ -1282,6 +1290,21 @@ TypePointer ArrayType::interfaceType(bool _inLibrary) const
return make_shared<ArrayType>(DataLocation::Memory, baseExt, m_length);
}
+bool ArrayType::canBeUsedExternally(bool _inLibrary) const
+{
+ // Note: This has to fulfill canBeUsedExternally(_inLibrary) == !!interfaceType(_inLibrary)
+ if (_inLibrary && location() == DataLocation::Storage)
+ return true;
+ else if (m_arrayKind != ArrayKind::Ordinary)
+ return true;
+ else if (!m_baseType->canBeUsedExternally(_inLibrary))
+ return false;
+ else if (m_baseType->category() == Category::Array && m_baseType->isDynamicallySized())
+ return false;
+ else
+ return true;
+}
+
u256 ArrayType::memorySize() const
{
solAssert(!isDynamicallySized(), "");
@@ -1451,7 +1474,7 @@ u256 StructType::storageSize() const
string StructType::toString(bool _short) const
{
- string ret = "struct " + m_struct.name();
+ string ret = "struct " + m_struct.annotation().canonicalName;
if (!_short)
ret += " " + stringForReferencePart();
return ret;
@@ -1561,7 +1584,7 @@ bool EnumType::operator==(Type const& _other) const
unsigned EnumType::storageBytes() const
{
- size_t elements = m_enum.members().size();
+ size_t elements = numberOfMembers();
if (elements <= 1)
return 1;
else
@@ -1570,7 +1593,7 @@ unsigned EnumType::storageBytes() const
string EnumType::toString(bool) const
{
- return string("enum ") + m_enum.name();
+ return string("enum ") + m_enum.annotation().canonicalName;
}
string EnumType::canonicalName(bool) const
@@ -1578,9 +1601,14 @@ string EnumType::canonicalName(bool) const
return m_enum.annotation().canonicalName;
}
+size_t EnumType::numberOfMembers() const
+{
+ return m_enum.members().size();
+};
+
bool EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
- return _convertTo.category() == category() || _convertTo.category() == Category::Integer;
+ return _convertTo == *this || _convertTo.category() == Category::Integer;
}
unsigned EnumType::memberValue(ASTString const& _member) const
@@ -1699,7 +1727,7 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons
FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal):
m_location(_isInternal ? Location::Internal : Location::External),
m_isConstant(_function.isDeclaredConst()),
- m_isPayable(_function.isPayable()),
+ m_isPayable(_isInternal ? false : _function.isPayable()),
m_declaration(&_function)
{
TypePointers params;
@@ -1800,6 +1828,38 @@ FunctionType::FunctionType(EventDefinition const& _event):
swap(paramNames, m_parameterNames);
}
+FunctionType::FunctionType(FunctionTypeName const& _typeName):
+ m_location(_typeName.visibility() == VariableDeclaration::Visibility::External ? Location::External : Location::Internal),
+ m_isConstant(_typeName.isDeclaredConst()),
+ m_isPayable(_typeName.isPayable())
+{
+ if (_typeName.isPayable())
+ {
+ solAssert(m_location == Location::External, "Internal payable function type used.");
+ solAssert(!m_isConstant, "Payable constant function");
+ }
+ for (auto const& t: _typeName.parameterTypes())
+ {
+ solAssert(t->annotation().type, "Type not set for parameter.");
+ if (m_location == Location::External)
+ solAssert(
+ t->annotation().type->canBeUsedExternally(false),
+ "Internal type used as parameter for external function."
+ );
+ m_parameterTypes.push_back(t->annotation().type);
+ }
+ for (auto const& t: _typeName.returnParameterTypes())
+ {
+ solAssert(t->annotation().type, "Type not set for return parameter.");
+ if (m_location == Location::External)
+ solAssert(
+ t->annotation().type->canBeUsedExternally(false),
+ "Internal type used as return parameter for external function."
+ );
+ m_returnParameterTypes.push_back(t->annotation().type);
+ }
+}
+
FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _contract)
{
FunctionDefinition const* constructor = _contract.constructor();
@@ -1875,22 +1935,69 @@ bool FunctionType::operator==(Type const& _other) const
return true;
}
+TypePointer FunctionType::unaryOperatorResult(Token::Value _operator) const
+{
+ if (_operator == Token::Value::Delete)
+ return make_shared<TupleType>();
+ return TypePointer();
+}
+
+string FunctionType::canonicalName(bool) const
+{
+ solAssert(m_location == Location::External, "");
+ return "function";
+}
+
string FunctionType::toString(bool _short) const
{
string name = "function (";
for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
name += (*it)->toString(_short) + (it + 1 == m_parameterTypes.end() ? "" : ",");
- name += ") returns (";
- for (auto it = m_returnParameterTypes.begin(); it != m_returnParameterTypes.end(); ++it)
- name += (*it)->toString(_short) + (it + 1 == m_returnParameterTypes.end() ? "" : ",");
- return name + ")";
+ name += ")";
+ if (m_isConstant)
+ name += " constant";
+ if (m_isPayable)
+ name += " payable";
+ if (m_location == Location::External)
+ name += " external";
+ if (!m_returnParameterTypes.empty())
+ {
+ name += " returns (";
+ for (auto it = m_returnParameterTypes.begin(); it != m_returnParameterTypes.end(); ++it)
+ name += (*it)->toString(_short) + (it + 1 == m_returnParameterTypes.end() ? "" : ",");
+ name += ")";
+ }
+ return name;
+}
+
+unsigned FunctionType::calldataEncodedSize(bool _padded) const
+{
+ unsigned size = storageBytes();
+ if (_padded)
+ size = ((size + 31) / 32) * 32;
+ return size;
}
u256 FunctionType::storageSize() const
{
- BOOST_THROW_EXCEPTION(
- InternalCompilerError()
- << errinfo_comment("Storage size of non-storable function type requested."));
+ if (m_location == Location::External || m_location == Location::Internal)
+ return 1;
+ else
+ BOOST_THROW_EXCEPTION(
+ InternalCompilerError()
+ << errinfo_comment("Storage size of non-storable function type requested."));
+}
+
+unsigned FunctionType::storageBytes() const
+{
+ if (m_location == Location::External)
+ return 20 + 4;
+ else if (m_location == Location::Internal)
+ return 8; // it should really not be possible to create larger programs
+ else
+ BOOST_THROW_EXCEPTION(
+ InternalCompilerError()
+ << errinfo_comment("Storage size of non-storable function type requested."));
}
unsigned FunctionType::sizeOnStack() const
@@ -2013,6 +2120,23 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
}
}
+TypePointer FunctionType::encodingType() const
+{
+ // Only external functions can be encoded, internal functions cannot leave code boundaries.
+ if (m_location == Location::External)
+ return shared_from_this();
+ else
+ return TypePointer();
+}
+
+TypePointer FunctionType::interfaceType(bool /*_inLibrary*/) const
+{
+ if (m_location == Location::External)
+ return shared_from_this();
+ else
+ return TypePointer();
+}
+
bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes, TypePointer const& _selfType) const
{
solAssert(!bound() || _selfType, "");
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 3f94d11a..72640a1c 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>
@@ -254,6 +254,9 @@ public:
/// @param _inLibrary if set, returns types as used in a library, e.g. struct and contract types
/// are returned without modification.
virtual TypePointer interfaceType(bool /*_inLibrary*/) const { return TypePointer(); }
+ /// @returns true iff this type can be passed on via calls (to libraries if _inLibrary is true),
+ /// should be have identical to !!interfaceType(_inLibrary) but might do optimizations.
+ virtual bool canBeUsedExternally(bool _inLibrary) const { return !!interfaceType(_inLibrary); }
private:
/// @returns a member list containing all members added to this type by `using for` directives.
@@ -422,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:
@@ -580,6 +585,7 @@ public:
virtual TypePointer encodingType() const override;
virtual TypePointer decodingType() const override;
virtual TypePointer interfaceType(bool _inLibrary) const override;
+ virtual bool canBeUsedExternally(bool _inLibrary) const override;
/// @returns true if this is a byte array or a string
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
@@ -738,6 +744,7 @@ public:
EnumDefinition const& enumDefinition() const { return m_enum; }
/// @returns the value that the string has in the Enum
unsigned int memberValue(ASTString const& _member) const;
+ size_t numberOfMembers() const;
private:
EnumDefinition const& m_enum;
@@ -820,6 +827,8 @@ public:
explicit FunctionType(VariableDeclaration const& _varDecl);
/// Creates the function type of an event.
explicit FunctionType(EventDefinition const& _event);
+ /// Creates the type of a function type name.
+ explicit FunctionType(FunctionTypeName const& _typeName);
/// Function type constructor to be used for a plain type (not derived from a declaration).
FunctionType(
strings const& _parameterTypes,
@@ -889,12 +898,19 @@ public:
TypePointer selfType() const;
virtual bool operator==(Type const& _other) const override;
+ virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
+ virtual std::string canonicalName(bool /*_addDataLocation*/) const override;
virtual std::string toString(bool _short) const override;
- virtual bool canBeStored() const override { return false; }
+ virtual unsigned calldataEncodedSize(bool _padded) const override;
+ virtual bool canBeStored() const override { return m_location == Location::Internal || m_location == Location::External; }
virtual u256 storageSize() const override;
- virtual bool canLiveOutsideStorage() const override { return false; }
+ virtual unsigned storageBytes() const override;
+ virtual bool isValueType() const override { return true; }
+ virtual bool canLiveOutsideStorage() const override { return m_location == Location::Internal || m_location == Location::External; }
virtual unsigned sizeOnStack() const override;
virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
+ virtual TypePointer encodingType() const override;
+ virtual TypePointer interfaceType(bool _inLibrary) const override;
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an
/// appropriate external types (i.e. the interfaceType()s) of input/return parameters of
diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp
index e7e8a98e..c0eb736a 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>
@@ -270,7 +270,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const
{
- solAssert(
+ solUnimplementedAssert(
!_sourceType.baseType()->isDynamicallySized(),
"Nested dynamic arrays not implemented here."
);
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 1ae5dda9..22d25698 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>
@@ -33,14 +33,15 @@ void Compiler::compileContract(
std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts
)
{
- ContractCompiler runtimeCompiler(m_runtimeContext, m_optimize);
+ ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
runtimeCompiler.compileContract(_contract, _contracts);
- ContractCompiler creationCompiler(m_context, m_optimize);
- m_runtimeSub = creationCompiler.compileConstructor(m_runtimeContext, _contract, _contracts);
+ // This might modify m_runtimeContext because it can access runtime functions at
+ // creation time.
+ ContractCompiler creationCompiler(&runtimeCompiler, m_context, m_optimize);
+ m_runtimeSub = creationCompiler.compileConstructor(_contract, _contracts);
- if (m_optimize)
- m_context.optimise(m_optimizeRuns);
+ m_context.optimise(m_optimize, m_optimizeRuns);
if (_contract.isLibrary())
{
@@ -54,11 +55,11 @@ void Compiler::compileClone(
map<ContractDefinition const*, eth::Assembly const*> const& _contracts
)
{
- ContractCompiler cloneCompiler(m_context, m_optimize);
+ ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
+ ContractCompiler cloneCompiler(&runtimeCompiler, m_context, m_optimize);
m_runtimeSub = cloneCompiler.compileClone(_contract, _contracts);
- if (m_optimize)
- m_context.optimise(m_optimizeRuns);
+ m_context.optimise(m_optimize, m_optimizeRuns);
}
eth::AssemblyItem Compiler::functionEntryLabel(FunctionDefinition const& _function) const
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index fccb68a9..c8bf7861 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>
@@ -35,7 +35,9 @@ class Compiler
public:
explicit Compiler(bool _optimize = false, unsigned _runs = 200):
m_optimize(_optimize),
- m_optimizeRuns(_runs)
+ m_optimizeRuns(_runs),
+ m_runtimeContext(),
+ m_context(&m_runtimeContext)
{ }
void compileContract(
@@ -69,9 +71,9 @@ public:
private:
bool const m_optimize;
unsigned const m_optimizeRuns;
- CompilerContext m_context;
- size_t m_runtimeSub = size_t(-1); ///< Identifier of the runtime sub-assembly, if present.
CompilerContext m_runtimeContext;
+ size_t m_runtimeSub = size_t(-1); ///< Identifier of the runtime sub-assembly, if present.
+ CompilerContext m_context;
};
}
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 3ac5bd3c..b99b0548 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>
@@ -60,8 +60,8 @@ void CompilerContext::startFunction(Declaration const& _function)
void CompilerContext::addVariable(VariableDeclaration const& _declaration,
unsigned _offsetToCurrent)
{
- solAssert(m_asm.deposit() >= 0 && unsigned(m_asm.deposit()) >= _offsetToCurrent, "");
- m_localVariables[&_declaration] = unsigned(m_asm.deposit()) - _offsetToCurrent;
+ solAssert(m_asm->deposit() >= 0 && unsigned(m_asm->deposit()) >= _offsetToCurrent, "");
+ m_localVariables[&_declaration] = unsigned(m_asm->deposit()) - _offsetToCurrent;
}
void CompilerContext::removeVariable(VariableDeclaration const& _declaration)
@@ -92,22 +92,22 @@ eth::AssemblyItem CompilerContext::functionEntryLabelIfExists(Declaration const&
return m_functionCompilationQueue.entryLabelIfExists(_declaration);
}
-eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel(FunctionDefinition const& _function)
+FunctionDefinition const& CompilerContext::resolveVirtualFunction(FunctionDefinition const& _function)
{
// Libraries do not allow inheritance and their functions can be inlined, so we should not
// search the inheritance hierarchy (which will be the wrong one in case the function
// is inlined).
if (auto scope = dynamic_cast<ContractDefinition const*>(_function.scope()))
if (scope->isLibrary())
- return functionEntryLabel(_function);
+ return _function;
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
- return virtualFunctionEntryLabel(_function, m_inheritanceHierarchy.begin());
+ return resolveVirtualFunction(_function, m_inheritanceHierarchy.begin());
}
-eth::AssemblyItem CompilerContext::superFunctionEntryLabel(FunctionDefinition const& _function, ContractDefinition const& _base)
+FunctionDefinition const& CompilerContext::superFunction(FunctionDefinition const& _function, ContractDefinition const& _base)
{
solAssert(!m_inheritanceHierarchy.empty(), "No inheritance hierarchy set.");
- return virtualFunctionEntryLabel(_function, superContract(_base));
+ return resolveVirtualFunction(_function, superContract(_base));
}
FunctionDefinition const* CompilerContext::nextConstructor(ContractDefinition const& _contract) const
@@ -145,12 +145,12 @@ unsigned CompilerContext::baseStackOffsetOfVariable(Declaration const& _declarat
unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const
{
- return m_asm.deposit() - _baseOffset - 1;
+ return m_asm->deposit() - _baseOffset - 1;
}
unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
{
- return m_asm.deposit() - _offset - 1;
+ return m_asm->deposit() - _offset - 1;
}
pair<u256, unsigned> CompilerContext::storageLocationOfVariable(const Declaration& _declaration) const
@@ -217,17 +217,17 @@ void CompilerContext::appendInlineAssembly(
return true;
};
- solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, m_asm, identifierAccess), "");
+ solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), "");
}
void CompilerContext::injectVersionStampIntoSub(size_t _subIndex)
{
- eth::Assembly& sub = m_asm.sub(_subIndex);
+ eth::Assembly& sub = m_asm->sub(_subIndex);
sub.injectStart(Instruction::POP);
sub.injectStart(fromBigEndian<u256>(binaryVersion()));
}
-eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel(
+FunctionDefinition const& CompilerContext::resolveVirtualFunction(
FunctionDefinition const& _function,
vector<ContractDefinition const*>::const_iterator _searchStart
)
@@ -242,9 +242,9 @@ eth::AssemblyItem CompilerContext::virtualFunctionEntryLabel(
!function->isConstructor() &&
FunctionType(*function).hasEqualArgumentTypes(functionType)
)
- return functionEntryLabel(*function);
+ return *function;
solAssert(false, "Super function " + name + " not found.");
- return m_asm.newTag(); // not reached
+ return _function; // not reached
}
vector<ContractDefinition const*>::const_iterator CompilerContext::superContract(ContractDefinition const& _contract) const
@@ -257,7 +257,7 @@ vector<ContractDefinition const*>::const_iterator CompilerContext::superContract
void CompilerContext::updateSourceLocation()
{
- m_asm.setSourceLocation(m_visitedNodes.empty() ? SourceLocation() : m_visitedNodes.top()->location());
+ m_asm->setSourceLocation(m_visitedNodes.empty() ? SourceLocation() : m_visitedNodes.top()->location());
}
eth::AssemblyItem CompilerContext::FunctionCompilationQueue::entryLabel(
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 0c1500b0..3c6d9d73 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>
@@ -44,6 +44,14 @@ namespace solidity {
class CompilerContext
{
public:
+ CompilerContext(CompilerContext* _runtimeContext = nullptr):
+ m_asm(std::make_shared<eth::Assembly>()),
+ m_runtimeContext(_runtimeContext)
+ {
+ if (m_runtimeContext)
+ m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data());
+ }
+
void addMagicGlobal(MagicVariableDeclaration const& _declaration);
void addStateVariable(VariableDeclaration const& _declaration, u256 const& _storageOffset, unsigned _byteOffset);
void addVariable(VariableDeclaration const& _declaration, unsigned _offsetToCurrent = 0);
@@ -52,9 +60,9 @@ public:
void setCompiledContracts(std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts) { m_compiledContracts = _contracts; }
eth::Assembly const& compiledContract(ContractDefinition const& _contract) const;
- void setStackOffset(int _offset) { m_asm.setDeposit(_offset); }
- void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); }
- unsigned stackHeight() const { solAssert(m_asm.deposit() >= 0, ""); return unsigned(m_asm.deposit()); }
+ void setStackOffset(int _offset) { m_asm->setDeposit(_offset); }
+ void adjustStackOffset(int _adjustment) { m_asm->adjustDeposit(_adjustment); }
+ unsigned stackHeight() const { solAssert(m_asm->deposit() >= 0, ""); return unsigned(m_asm->deposit()); }
bool isMagicGlobal(Declaration const* _declaration) const { return m_magicGlobals.count(_declaration) != 0; }
bool isLocalVariable(Declaration const* _declaration) const;
@@ -67,10 +75,10 @@ public:
eth::AssemblyItem functionEntryLabelIfExists(Declaration const& _declaration) const;
void setInheritanceHierarchy(std::vector<ContractDefinition const*> const& _hierarchy) { m_inheritanceHierarchy = _hierarchy; }
/// @returns the entry label of the given function and takes overrides into account.
- eth::AssemblyItem virtualFunctionEntryLabel(FunctionDefinition const& _function);
- /// @returns the entry label of a function that overrides the given declaration from the most derived class just
+ FunctionDefinition const& resolveVirtualFunction(FunctionDefinition const& _function);
+ /// @returns the function that overrides the given declaration from the most derived class just
/// above _base in the current inheritance hierarchy.
- eth::AssemblyItem superFunctionEntryLabel(FunctionDefinition const& _function, ContractDefinition const& _base);
+ FunctionDefinition const& superFunction(FunctionDefinition const& _function, ContractDefinition const& _base);
FunctionDefinition const* nextConstructor(ContractDefinition const& _contract) const;
/// @returns the next function in the queue of functions that are still to be compiled
@@ -95,30 +103,33 @@ public:
std::pair<u256, unsigned> storageLocationOfVariable(Declaration const& _declaration) const;
/// Appends a JUMPI instruction to a new tag and @returns the tag
- eth::AssemblyItem appendConditionalJump() { return m_asm.appendJumpI().tag(); }
+ eth::AssemblyItem appendConditionalJump() { return m_asm->appendJumpI().tag(); }
/// Appends a JUMPI instruction to @a _tag
- CompilerContext& appendConditionalJumpTo(eth::AssemblyItem const& _tag) { m_asm.appendJumpI(_tag); return *this; }
+ CompilerContext& appendConditionalJumpTo(eth::AssemblyItem const& _tag) { m_asm->appendJumpI(_tag); return *this; }
/// Appends a JUMP to a new tag and @returns the tag
- eth::AssemblyItem appendJumpToNew() { return m_asm.appendJump().tag(); }
+ eth::AssemblyItem appendJumpToNew() { return m_asm->appendJump().tag(); }
/// Appends a JUMP to a tag already on the stack
CompilerContext& appendJump(eth::AssemblyItem::JumpType _jumpType = eth::AssemblyItem::JumpType::Ordinary);
/// Returns an "ErrorTag"
- eth::AssemblyItem errorTag() { return m_asm.errorTag(); }
+ eth::AssemblyItem errorTag() { return m_asm->errorTag(); }
/// Appends a JUMP to a specific tag
- CompilerContext& appendJumpTo(eth::AssemblyItem const& _tag) { m_asm.appendJump(_tag); return *this; }
+ CompilerContext& appendJumpTo(eth::AssemblyItem const& _tag) { m_asm->appendJump(_tag); return *this; }
/// Appends pushing of a new tag and @returns the new tag.
- eth::AssemblyItem pushNewTag() { return m_asm.append(m_asm.newPushTag()).tag(); }
+ eth::AssemblyItem pushNewTag() { return m_asm->append(m_asm->newPushTag()).tag(); }
/// @returns a new tag without pushing any opcodes or data
- eth::AssemblyItem newTag() { return m_asm.newTag(); }
+ eth::AssemblyItem newTag() { return m_asm->newTag(); }
/// Adds a subroutine to the code (in the data section) and pushes its size (via a tag)
- /// on the stack. @returns the assembly item corresponding to the pushed subroutine, i.e. its offset.
- eth::AssemblyItem addSubroutine(eth::Assembly const& _assembly) { return m_asm.appendSubSize(_assembly); }
+ /// on the stack. @returns the pushsub assembly item.
+ eth::AssemblyItem addSubroutine(eth::AssemblyPointer const& _assembly) { auto sub = m_asm->newSub(_assembly); m_asm->append(m_asm->newPushSubSize(size_t(sub.data()))); return sub; }
+ void pushSubroutineSize(size_t _subRoutine) { m_asm->append(m_asm->newPushSubSize(_subRoutine)); }
+ /// Pushes the offset of the subroutine.
+ void pushSubroutineOffset(size_t _subRoutine) { m_asm->append(eth::AssemblyItem(eth::PushSub, _subRoutine)); }
/// Pushes the size of the final program
- void appendProgramSize() { return m_asm.appendProgramSize(); }
+ void appendProgramSize() { m_asm->appendProgramSize(); }
/// Adds data to the data section, pushes a reference to the stack
- eth::AssemblyItem appendData(bytes const& _data) { return m_asm.append(_data); }
+ eth::AssemblyItem appendData(bytes const& _data) { return m_asm->append(_data); }
/// Appends the address (virtual, will be filled in by linker) of a library.
- void appendLibraryAddress(std::string const& _identifier) { m_asm.appendLibraryAddress(_identifier); }
+ void appendLibraryAddress(std::string const& _identifier) { m_asm->appendLibraryAddress(_identifier); }
/// Resets the stack of visited nodes with a new stack having only @c _node
void resetVisitedNodes(ASTNode const* _node);
/// Pops the stack of visited nodes
@@ -127,10 +138,10 @@ public:
void pushVisitedNodes(ASTNode const* _node) { m_visitedNodes.push(_node); updateSourceLocation(); }
/// Append elements to the current instruction list and adjust @a m_stackOffset.
- CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm.append(_item); return *this; }
- CompilerContext& operator<<(Instruction _instruction) { m_asm.append(_instruction); return *this; }
- CompilerContext& operator<<(u256 const& _value) { m_asm.append(_value); return *this; }
- CompilerContext& operator<<(bytes const& _data) { m_asm.append(_data); return *this; }
+ CompilerContext& operator<<(eth::AssemblyItem const& _item) { m_asm->append(_item); return *this; }
+ CompilerContext& operator<<(Instruction _instruction) { m_asm->append(_instruction); return *this; }
+ CompilerContext& operator<<(u256 const& _value) { m_asm->append(_value); return *this; }
+ CompilerContext& operator<<(bytes const& _data) { m_asm->append(_data); return *this; }
/// Appends inline assembly. @a _replacements are string-matching replacements that are performed
/// prior to parsing the inline assembly.
@@ -144,22 +155,27 @@ public:
/// Prepends "PUSH <compiler version number> POP"
void injectVersionStampIntoSub(size_t _subIndex);
- void optimise(unsigned _runs = 200) { m_asm.optimise(true, true, _runs); }
+ void optimise(bool _fullOptimsation, unsigned _runs = 200) { m_asm->optimise(_fullOptimsation, true, _runs); }
+
+ /// @returns the runtime context if in creation mode and runtime context is set, nullptr otherwise.
+ CompilerContext* runtimeContext() { return m_runtimeContext; }
+ /// @returns the identifier of the runtime subroutine.
+ size_t runtimeSub() const { return m_runtimeSub; }
- eth::Assembly const& assembly() const { return m_asm; }
+ eth::Assembly const& assembly() const { return *m_asm; }
/// @returns non-const reference to the underlying assembly. Should be avoided in favour of
/// wrappers in this class.
- eth::Assembly& nonConstAssembly() { return m_asm; }
+ eth::Assembly& nonConstAssembly() { return *m_asm; }
/// @arg _sourceCodes is the map of input files to source code strings
/// @arg _inJsonFormat shows whether the out should be in Json format
Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
{
- return m_asm.stream(_stream, "", _sourceCodes, _inJsonFormat);
+ return m_asm->stream(_stream, "", _sourceCodes, _inJsonFormat);
}
- eth::LinkerObject const& assembledObject() { return m_asm.assemble(); }
- eth::LinkerObject const& assembledRuntimeObject(size_t _subIndex) { return m_asm.sub(_subIndex).assemble(); }
+ eth::LinkerObject const& assembledObject() { return m_asm->assemble(); }
+ eth::LinkerObject const& assembledRuntimeObject(size_t _subIndex) { return m_asm->sub(_subIndex).assemble(); }
/**
* Helper class to pop the visited nodes stack when a scope closes
@@ -172,9 +188,9 @@ public:
};
private:
- /// @returns the entry label of the given function - searches the inheritance hierarchy
- /// startig from the given point towards the base.
- eth::AssemblyItem virtualFunctionEntryLabel(
+ /// Searches the inheritance hierarchy towards the base starting from @a _searchStart and returns
+ /// the first function definition that is overwritten by _function.
+ FunctionDefinition const& resolveVirtualFunction(
FunctionDefinition const& _function,
std::vector<ContractDefinition const*>::const_iterator _searchStart
);
@@ -215,7 +231,7 @@ private:
mutable std::queue<Declaration const*> m_functionsToCompile;
} m_functionCompilationQueue;
- eth::Assembly m_asm;
+ eth::AssemblyPointer m_asm;
/// Magic global variables like msg, tx or this, distinguished by type.
std::set<Declaration const*> m_magicGlobals;
/// Other already compiled contracts to be used in contract creation calls.
@@ -228,6 +244,10 @@ private:
std::vector<ContractDefinition const*> m_inheritanceHierarchy;
/// Stack of current visited AST nodes, used for location attachment
std::stack<ASTNode const*> m_visitedNodes;
+ /// The runtime context if in Creation mode, this is used for generating tags that would be stored into the storage and then used at runtime.
+ CompilerContext *m_runtimeContext;
+ /// The index of the runtime subroutine.
+ size_t m_runtimeSub = -1;
};
}
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index e064c1a6..d5361ac6 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>
@@ -133,12 +133,22 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
m_context << u256(str->value().size());
m_context << Instruction::ADD;
}
+ else if (
+ _type.category() == Type::Category::Function &&
+ dynamic_cast<FunctionType const&>(_type).location() == FunctionType::Location::External
+ )
+ {
+ solUnimplementedAssert(_padToWordBoundaries, "Non-padded store for function not implemented.");
+ combineExternalFunctionType(true);
+ m_context << Instruction::DUP2 << Instruction::MSTORE;
+ m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
+ }
else
{
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries);
if (numBytes > 0)
{
- solAssert(
+ solUnimplementedAssert(
_type.sizeOnStack() == 1,
"Memory store of types with stack size != 1 not implemented."
);
@@ -161,7 +171,7 @@ void CompilerUtils::encodeToMemory(
solAssert(targetTypes.size() == _givenTypes.size(), "");
for (TypePointer& t: targetTypes)
{
- solAssert(
+ solUnimplementedAssert(
t->mobileType() &&
t->mobileType()->interfaceType(_encodeAsLibraryTypes) &&
t->mobileType()->interfaceType(_encodeAsLibraryTypes)->encodingType(),
@@ -206,7 +216,8 @@ void CompilerUtils::encodeToMemory(
else if (
_givenTypes[i]->dataStoredIn(DataLocation::Storage) ||
_givenTypes[i]->dataStoredIn(DataLocation::CallData) ||
- _givenTypes[i]->category() == Type::Category::StringLiteral
+ _givenTypes[i]->category() == Type::Category::StringLiteral ||
+ _givenTypes[i]->category() == Type::Category::Function
)
type = _givenTypes[i]; // delay conversion
else
@@ -304,7 +315,50 @@ void CompilerUtils::memoryCopy()
m_context << Instruction::POP; // ignore return value
}
-void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded)
+void CompilerUtils::splitExternalFunctionType(bool _leftAligned)
+{
+ // We have to split the left-aligned <address><function identifier> into two stack slots:
+ // address (right aligned), function identifier (right aligned)
+ if (_leftAligned)
+ {
+ m_context << Instruction::DUP1 << (u256(1) << (64 + 32)) << Instruction::SWAP1 << Instruction::DIV;
+ // <input> <address>
+ m_context << Instruction::SWAP1 << (u256(1) << 64) << Instruction::SWAP1 << Instruction::DIV;
+ }
+ else
+ {
+ m_context << Instruction::DUP1 << (u256(1) << 32) << Instruction::SWAP1 << Instruction::DIV;
+ m_context << ((u256(1) << 160) - 1) << Instruction::AND << Instruction::SWAP1;
+ }
+ m_context << u256(0xffffffffUL) << Instruction::AND;
+}
+
+void CompilerUtils::combineExternalFunctionType(bool _leftAligned)
+{
+ // <address> <function_id>
+ m_context << u256(0xffffffffUL) << Instruction::AND << Instruction::SWAP1;
+ if (!_leftAligned)
+ m_context << ((u256(1) << 160) - 1) << Instruction::AND;
+ m_context << (u256(1) << 32) << Instruction::MUL;
+ m_context << Instruction::OR;
+ if (_leftAligned)
+ m_context << (u256(1) << 64) << Instruction::MUL;
+}
+
+void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function)
+{
+ m_context << m_context.functionEntryLabel(_function).pushTag();
+ // If there is a runtime context, we have to merge both labels into the same
+ // stack slot in case we store it in storage.
+ if (CompilerContext* rtc = m_context.runtimeContext())
+ m_context <<
+ (u256(1) << 32) <<
+ Instruction::MUL <<
+ rtc->functionEntryLabel(_function).toSubAssemblyTag(m_context.runtimeSub()) <<
+ Instruction::OR;
+}
+
+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.
@@ -315,6 +369,14 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
Type::Category stackTypeCategory = _typeOnStack.category();
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)
{
case Type::Category::FixedBytes:
@@ -348,10 +410,18 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
}
break;
case Type::Category::Enum:
- solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Enum, "");
+ solAssert(_targetType == _typeOnStack || targetTypeCategory == Type::Category::Integer, "");
+ if (enumOverflowCheckPending)
+ {
+ EnumType const& enumType = dynamic_cast<decltype(enumType)>(_typeOnStack);
+ solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error.");
+ m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT;
+ m_context.appendConditionalJumpTo(m_context.errorTag());
+ enumOverflowCheckPending = false;
+ }
break;
case Type::Category::FixedPoint:
- solAssert(false, "Not yet implemented - FixedPointType.");
+ solUnimplemented("Not yet implemented - FixedPointType.");
case Type::Category::Integer:
case Type::Category::Contract:
case Type::Category::RationalNumber:
@@ -372,6 +442,11 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
solAssert(_typeOnStack.mobileType(), "");
// just clean
convertType(_typeOnStack, *_typeOnStack.mobileType(), true);
+ EnumType const& enumType = dynamic_cast<decltype(enumType)>(_targetType);
+ solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error.");
+ m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT;
+ m_context.appendConditionalJumpTo(m_context.errorTag());
+ enumOverflowCheckPending = false;
}
else if (targetTypeCategory == Type::Category::FixedPoint)
{
@@ -386,7 +461,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack))
if (targetFixedPointType.integerBits() > typeOnStack->numBits())
cleanHigherOrderBits(*typeOnStack);
- solAssert(false, "Not yet implemented - FixedPointType.");
+ solUnimplemented("Not yet implemented - FixedPointType.");
}
else
{
@@ -399,7 +474,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
RationalNumberType const& constType = dynamic_cast<RationalNumberType const&>(_typeOnStack);
// We know that the stack is clean, we only have to clean for a narrowing conversion
// where cleanup is forced.
- solAssert(!constType.isFractional(), "Not yet implemented - FixedPointType.");
+ solUnimplementedAssert(!constType.isFractional(), "Not yet implemented - FixedPointType.");
if (targetType.numBits() < constType.integerType()->numBits() && _cleanupNeeded)
cleanHigherOrderBits(targetType);
}
@@ -413,6 +488,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;
@@ -651,15 +734,31 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
solAssert(_targetType == _typeOnStack, "Invalid conversion for bool.");
if (_cleanupNeeded)
m_context << Instruction::ISZERO << Instruction::ISZERO;
+ break;
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)
{
+ if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
+ {
+ if (funType->location() == FunctionType::Location::Internal)
+ {
+ m_context << m_context.errorTag();
+ return;
+ }
+ }
auto const* referenceType = dynamic_cast<ReferenceType const*>(&_type);
if (!referenceType || referenceType->location() == DataLocation::Storage)
{
@@ -804,21 +903,27 @@ void CompilerUtils::storeStringData(bytesConstRef _data)
unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries)
{
unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries);
- bool leftAligned = _type.category() == Type::Category::FixedBytes;
+ bool isExternalFunctionType = false;
+ if (auto const* funType = dynamic_cast<FunctionType const*>(&_type))
+ if (funType->location() == FunctionType::Location::External)
+ isExternalFunctionType = true;
if (numBytes == 0)
+ {
m_context << Instruction::POP << u256(0);
- else
+ return numBytes;
+ }
+ solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
+ m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD);
+ if (isExternalFunctionType)
+ splitExternalFunctionType(true);
+ else if (numBytes != 32)
{
- solAssert(numBytes <= 32, "Static memory load of more than 32 bytes requested.");
- m_context << (_fromCalldata ? Instruction::CALLDATALOAD : Instruction::MLOAD);
- if (numBytes != 32)
- {
- // add leading or trailing zeros by dividing/multiplying depending on alignment
- u256 shiftFactor = u256(1) << ((32 - numBytes) * 8);
- m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV;
- if (leftAligned)
- m_context << shiftFactor << Instruction::MUL;
- }
+ bool leftAligned = _type.category() == Type::Category::FixedBytes;
+ // add leading or trailing zeros by dividing/multiplying depending on alignment
+ u256 shiftFactor = u256(1) << ((32 - numBytes) * 8);
+ m_context << shiftFactor << Instruction::SWAP1 << Instruction::DIV;
+ if (leftAligned)
+ m_context << shiftFactor << Instruction::MUL;
}
return numBytes;
diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h
index da74dc90..4baf48ff 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>
@@ -114,12 +114,24 @@ public:
/// Stack post:
void memoryCopy();
+ /// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true)
+ /// external function type <address><function identifier> into two stack slots:
+ /// address (right aligned), function identifier (right aligned)
+ void splitExternalFunctionType(bool _rightAligned);
+ /// Performs the opposite operation of splitExternalFunctionType(_rightAligned)
+ void combineExternalFunctionType(bool _rightAligned);
+ /// Appends code that combines the construction-time (if available) and runtime function
+ /// entry label of the given function into a single stack slot.
+ /// Note: This might cause the compilation queue of the runtime context to be extended.
+ void pushCombinedFunctionEntryLabel(Declaration const& _function);
+
/// Appends code for an implicit or explicit type conversion. This includes erasing higher
/// order bits (@see appendHighBitCleanup) when widening integer but also copy to memory
/// 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.
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index ebb84784..437c484a 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>
@@ -60,14 +60,13 @@ void ContractCompiler::compileContract(
}
size_t ContractCompiler::compileConstructor(
- CompilerContext const& _runtimeContext,
ContractDefinition const& _contract,
std::map<const ContractDefinition*, eth::Assembly const*> const& _contracts
)
{
CompilerContext::LocationSetter locationSetter(m_context, _contract);
initializeContext(_contract, _contracts);
- return packIntoContractCreator(_contract, _runtimeContext);
+ return packIntoContractCreator(_contract);
}
size_t ContractCompiler::compileClone(
@@ -80,7 +79,7 @@ size_t ContractCompiler::compileClone(
appendInitAndConstructorCode(_contract);
//@todo determine largest return size of all runtime functions
- eth::AssemblyItem runtimeSub = m_context.addSubroutine(cloneRuntime());
+ auto runtimeSub = m_context.addSubroutine(cloneRuntime());
// stack contains sub size
m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY;
@@ -88,7 +87,6 @@ size_t ContractCompiler::compileClone(
appendMissingFunctions();
- solAssert(runtimeSub.data() < numeric_limits<size_t>::max(), "");
return size_t(runtimeSub.data());
}
@@ -104,6 +102,13 @@ void ContractCompiler::initializeContext(
m_context.resetVisitedNodes(&_contract);
}
+void ContractCompiler::appendCallValueCheck()
+{
+ // Throw if function is not payable but call contained ether.
+ m_context << Instruction::CALLVALUE;
+ m_context.appendConditionalJumpTo(m_context.errorTag());
+}
+
void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _contract)
{
// Determine the arguments that are used for the base constructors.
@@ -139,23 +144,35 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c
appendConstructor(*constructor);
else if (auto c = m_context.nextConstructor(_contract))
appendBaseConstructor(*c);
+ else
+ appendCallValueCheck();
}
-size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext)
+size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract)
{
- appendInitAndConstructorCode(_contract);
+ solAssert(!!m_runtimeCompiler, "");
- eth::AssemblyItem runtimeSub = m_context.addSubroutine(_runtimeContext.assembly());
+ appendInitAndConstructorCode(_contract);
- // stack contains sub size
- m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY;
- m_context << u256(0) << Instruction::RETURN;
+ // We jump to the deploy routine because we first have to append all missing functions,
+ // which can cause further functions to be added to the runtime context.
+ eth::AssemblyItem deployRoutine = m_context.appendJumpToNew();
- // note that we have to include the functions again because of absolute jump labels
+ // We have to include copies of functions in the construction time and runtime context
+ // because of absolute jumps.
appendMissingFunctions();
+ m_runtimeCompiler->appendMissingFunctions();
- solAssert(runtimeSub.data() < numeric_limits<size_t>::max(), "");
- return size_t(runtimeSub.data());
+ m_context << deployRoutine;
+
+ solAssert(m_context.runtimeSub() != size_t(-1), "Runtime sub not registered");
+ m_context.pushSubroutineSize(m_context.runtimeSub());
+ m_context << Instruction::DUP1;
+ m_context.pushSubroutineOffset(m_context.runtimeSub());
+ m_context << u256(0) << Instruction::CODECOPY;
+ m_context << u256(0) << Instruction::RETURN;
+
+ return m_context.runtimeSub();
}
void ContractCompiler::appendBaseConstructor(FunctionDefinition const& _constructor)
@@ -176,6 +193,9 @@ void ContractCompiler::appendBaseConstructor(FunctionDefinition const& _construc
void ContractCompiler::appendConstructor(FunctionDefinition const& _constructor)
{
CompilerContext::LocationSetter locationSetter(m_context, _constructor);
+ if (!_constructor.isPayable())
+ appendCallValueCheck();
+
// copy constructor arguments from code to memory and then to stack, they are supplied after the actual program
if (!_constructor.parameters().empty())
{
@@ -243,11 +263,8 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
if (fallback)
{
if (!fallback->isPayable())
- {
- // Throw if function is not payable but call contained ether.
- m_context << Instruction::CALLVALUE;
- m_context.appendConditionalJumpTo(m_context.errorTag());
- }
+ appendCallValueCheck();
+
eth::AssemblyItem returnTag = m_context.pushNewTag();
fallback->accept(*this);
m_context << returnTag;
@@ -266,11 +283,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
// We have to allow this for libraries, because value of the previous
// call is still visible in the delegatecall.
if (!functionType->isPayable() && !_contract.isLibrary())
- {
- // Throw if function is not payable but call contained ether.
- m_context << Instruction::CALLVALUE;
- m_context.appendConditionalJumpTo(m_context.errorTag());
- }
+ appendCallValueCheck();
eth::AssemblyItem returnTag = m_context.pushNewTag();
m_context << CompilerUtils::dataStartOffset;
@@ -293,13 +306,14 @@ void ContractCompiler::appendCalldataUnpacker(TypePointers const& _typeParameter
{
// stack: v1 v2 ... v(k-1) base_offset current_offset
TypePointer type = parameterType->decodingType();
+ solAssert(type, "No decoding type found.");
if (type->category() == Type::Category::Array)
{
auto const& arrayType = dynamic_cast<ArrayType const&>(*type);
- solAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
+ solUnimplementedAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
if (_fromMemory)
{
- solAssert(
+ solUnimplementedAssert(
arrayType.baseType()->isValueType(),
"Nested memory arrays not yet implemented here."
);
@@ -515,7 +529,19 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{
solAssert(!!decl->type(), "Type of declaration required but not yet determined.");
if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(decl))
- _assembly.append(m_context.virtualFunctionEntryLabel(*functionDef).pushTag());
+ {
+ functionDef = &m_context.resolveVirtualFunction(*functionDef);
+ _assembly.append(m_context.functionEntryLabel(*functionDef).pushTag());
+ // If there is a runtime context, we have to merge both labels into the same
+ // stack slot in case we store it in storage.
+ if (CompilerContext* rtc = m_context.runtimeContext())
+ {
+ _assembly.append(u256(1) << 32);
+ _assembly.append(Instruction::MUL);
+ _assembly.append(rtc->functionEntryLabel(*functionDef).toSubAssemblyTag(m_context.runtimeSub()));
+ _assembly.append(Instruction::OR);
+ }
+ }
else if (auto variable = dynamic_cast<VariableDeclaration const*>(decl))
{
solAssert(!variable->isConstant(), "");
@@ -611,12 +637,25 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
m_breakTags.push_back(loopEnd);
m_context << loopStart;
- compileExpression(_whileStatement.condition());
- m_context << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(loopEnd);
+
+ // While loops have the condition prepended
+ if (!_whileStatement.isDoWhile())
+ {
+ compileExpression(_whileStatement.condition());
+ m_context << Instruction::ISZERO;
+ m_context.appendConditionalJumpTo(loopEnd);
+ }
_whileStatement.body().accept(*this);
+ // Do-while loops have the condition appended
+ if (_whileStatement.isDoWhile())
+ {
+ compileExpression(_whileStatement.condition());
+ m_context << Instruction::ISZERO;
+ m_context.appendConditionalJumpTo(loopEnd);
+ }
+
m_context.appendJumpTo(loopStart);
m_context << loopEnd;
@@ -858,7 +897,7 @@ void ContractCompiler::compileExpression(Expression const& _expression, TypePoin
CompilerUtils(m_context).convertType(*_expression.annotation().type, *_targetType);
}
-eth::Assembly ContractCompiler::cloneRuntime()
+eth::AssemblyPointer ContractCompiler::cloneRuntime()
{
eth::Assembly a;
a << Instruction::CALLDATASIZE;
@@ -876,5 +915,5 @@ eth::Assembly ContractCompiler::cloneRuntime()
a.appendJumpI(a.errorTag());
//@todo adjust for larger return values, make this dynamic.
a << u256(0x20) << u256(0) << Instruction::RETURN;
- return a;
+ return make_shared<eth::Assembly>(a);
}
diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h
index 0799a543..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>
@@ -38,11 +38,12 @@ namespace solidity {
class ContractCompiler: private ASTConstVisitor
{
public:
- explicit ContractCompiler(CompilerContext& _context, bool _optimise):
+ explicit ContractCompiler(ContractCompiler* _runtimeCompiler, CompilerContext& _context, bool _optimise):
m_optimise(_optimise),
+ m_runtimeCompiler(_runtimeCompiler),
m_context(_context)
{
- m_context = CompilerContext();
+ m_context = CompilerContext(_runtimeCompiler ? &_runtimeCompiler->m_context : nullptr);
}
void compileContract(
@@ -52,7 +53,6 @@ public:
/// Compiles the constructor part of the contract.
/// @returns the identifier of the runtime sub-assembly.
size_t compileConstructor(
- CompilerContext const& _runtimeContext,
ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
);
@@ -74,12 +74,13 @@ private:
/// Adds the code that is run at creation time. Should be run after exchanging the run-time context
/// with a new and initialized context. Adds the constructor code.
/// @returns the identifier of the runtime sub assembly
- size_t packIntoContractCreator(ContractDefinition const& _contract, CompilerContext const& _runtimeContext);
+ size_t packIntoContractCreator(ContractDefinition const& _contract);
/// Appends state variable initialisation and constructor code.
void appendInitAndConstructorCode(ContractDefinition const& _contract);
void appendBaseConstructor(FunctionDefinition const& _constructor);
void appendConstructor(FunctionDefinition const& _constructor);
void appendFunctionSelector(ContractDefinition const& _contract);
+ void appendCallValueCheck();
/// Creates code that unpacks the arguments for the given function represented by a vector of TypePointers.
/// From memory if @a _fromMemory is true, otherwise from call data.
/// Expects source offset on the stack, which is removed.
@@ -114,9 +115,11 @@ private:
void compileExpression(Expression const& _expression, TypePointer const& _targetType = TypePointer());
/// @returns the runtime assembly for clone contracts.
- static eth::Assembly cloneRuntime();
+ static eth::AssemblyPointer cloneRuntime();
bool const m_optimise;
+ /// Pointer to the runtime compiler in case this is a creation compiler.
+ ContractCompiler* m_runtimeCompiler = nullptr;
CompilerContext& m_context;
std::vector<eth::AssemblyItem> m_breakTags; ///< tag to jump to for a "break" statement
std::vector<eth::AssemblyItem> m_continueTags; ///< tag to jump to for a "continue" statement
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 9a096e2d..58330764 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>
@@ -99,7 +99,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
{
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
- solAssert(
+ solUnimplementedAssert(
!paramTypes[i]->isDynamicallySized(),
"Accessors for mapping with dynamically-sized keys not yet implemented."
);
@@ -211,7 +211,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
Token::Value op = _assignment.assignmentOperator();
if (op != Token::Assign) // compound assignment
{
- solAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types.");
+ solUnimplementedAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types.");
unsigned lvalueSize = m_currentLValue->sizeOnStack();
unsigned itemSize = _assignment.annotation().type->sizeOnStack();
if (lvalueSize > 0)
@@ -312,7 +312,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
if (!_unaryOperation.isPrefixOperation())
{
// store value for later
- solAssert(_unaryOperation.annotation().type->sizeOnStack() == 1, "Stack size != 1 not implemented.");
+ solUnimplementedAssert(_unaryOperation.annotation().type->sizeOnStack() == 1, "Stack size != 1 not implemented.");
m_context << Instruction::DUP1;
if (m_currentLValue->sizeOnStack() > 0)
for (unsigned i = 1 + m_currentLValue->sizeOnStack(); i > 0; --i)
@@ -488,6 +488,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
parameterSize += function.selfType()->sizeOnStack();
}
+ if (m_context.runtimeContext())
+ // We have a runtime context, so we need the creation part.
+ m_context << (u256(1) << 32) << Instruction::SWAP1 << Instruction::DIV;
+ else
+ // Extract the runtime part.
+ m_context << ((u256(1) << 32) - 1) << Instruction::AND;
+
m_context.appendJump(eth::AssemblyItem::JumpType::IntoFunction);
m_context << returnLabel;
@@ -521,8 +528,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// copy the contract's code into memory
eth::Assembly const& assembly = m_context.compiledContract(contract);
utils().fetchFreeMemoryPointer();
+ // TODO we create a copy here, which is actually what we want.
+ // This should be revisited at the point where we fix
+ // https://github.com/ethereum/solidity/issues/1092
// pushes size
- eth::AssemblyItem subroutine = m_context.addSubroutine(assembly);
+ auto subroutine = m_context.addSubroutine(make_shared<eth::Assembly>(assembly));
m_context << Instruction::DUP1 << subroutine;
m_context << Instruction::DUP4 << Instruction::CODECOPY;
@@ -845,9 +855,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
);
if (funType->location() == FunctionType::Location::Internal)
{
- m_context << m_context.functionEntryLabel(
- dynamic_cast<FunctionDefinition const&>(funType->declaration())
- ).pushTag();
+ FunctionDefinition const& funDef = dynamic_cast<decltype(funDef)>(funType->declaration());
+ utils().pushCombinedFunctionEntryLabel(funDef);
utils().moveIntoStack(funType->selfType()->sizeOnStack(), 1);
}
else
@@ -883,7 +892,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
// us to link against it although we actually do not need it.
auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration);
solAssert(!!function, "Function not found in member access");
- m_context << m_context.functionEntryLabel(*function).pushTag();
+ utils().pushCombinedFunctionEntryLabel(*function);
}
}
else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type.get()))
@@ -915,10 +924,10 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
if (type.isSuper())
{
solAssert(!!_memberAccess.annotation().referencedDeclaration, "Referenced declaration not resolved.");
- m_context << m_context.superFunctionEntryLabel(
+ utils().pushCombinedFunctionEntryLabel(m_context.superFunction(
dynamic_cast<FunctionDefinition const&>(*_memberAccess.annotation().referencedDeclaration),
type.contractDefinition()
- ).pushTag();
+ ));
}
else
{
@@ -1141,7 +1150,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
break;
case DataLocation::CallData:
//@todo if we implement this, the value in calldata has to be added to the base offset
- solAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
+ solUnimplementedAssert(!arrayType.baseType()->isDynamicallySized(), "Nested arrays not yet implemented.");
if (arrayType.baseType()->isValueType())
CompilerUtils(m_context).loadFromMemoryDynamic(
*arrayType.baseType(),
@@ -1203,7 +1212,7 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
}
}
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
- m_context << m_context.virtualFunctionEntryLabel(*functionDef).pushTag();
+ utils().pushCombinedFunctionEntryLabel(m_context.resolveVirtualFunction(*functionDef));
else if (auto variable = dynamic_cast<VariableDeclaration const*>(declaration))
appendVariable(*variable, static_cast<Expression const&>(_identifier));
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
@@ -1266,6 +1275,17 @@ void ExpressionCompiler::appendCompareOperatorCode(Token::Value _operator, Type
{
if (_operator == Token::Equal || _operator == Token::NotEqual)
{
+ if (FunctionType const* funType = dynamic_cast<decltype(funType)>(&_type))
+ {
+ if (funType->location() == FunctionType::Location::Internal)
+ {
+ // We have to remove the upper bits (construction time value) because they might
+ // be "unknown" in one of the operands and not in the other.
+ m_context << ((u256(1) << 32) - 1) << Instruction::AND;
+ m_context << Instruction::SWAP1;
+ m_context << ((u256(1) << 32) - 1) << Instruction::AND;
+ }
+ }
m_context << Instruction::EQ;
if (_operator == Token::NotEqual)
m_context << Instruction::ISZERO;
@@ -1318,7 +1338,7 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty
bool const c_isSigned = type.isSigned();
if (_type.category() == Type::Category::FixedPoint)
- solAssert(false, "Not yet implemented - FixedPointType.");
+ solUnimplemented("Not yet implemented - FixedPointType.");
switch (_operator)
{
@@ -1372,7 +1392,7 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator)
void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator)
{
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Shift operators not yet implemented."));
+ BOOST_THROW_EXCEPTION(UnimplementedFeatureError() << errinfo_comment("Shift operators not yet implemented."));
switch (_operator)
{
case Token::SHL:
@@ -1634,7 +1654,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression)
{
- solAssert(_expectedType.isValueType(), "Not implemented for non-value types.");
+ solUnimplementedAssert(_expectedType.isValueType(), "Not implemented for non-value types.");
_expression.accept(*this);
utils().convertType(*_expression.annotation().type, _expectedType, true);
utils().storeInMemoryDynamic(_expectedType);
diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h
index f4ce1fec..f08bded9 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>
diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp
index c1e05792..23fe2d4e 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>
@@ -120,7 +120,7 @@ void MemoryItem::storeValue(Type const& _sourceType, SourceLocation const&, bool
}
else
{
- solAssert(_sourceType == *m_dataType, "Conversion not implemented for assignment to memory.");
+ solUnimplementedAssert(_sourceType == *m_dataType, "Conversion not implemented for assignment to memory.");
solAssert(m_dataType->sizeOnStack() == 1, "");
if (!_move)
@@ -153,7 +153,8 @@ StorageItem::StorageItem(CompilerContext& _compilerContext, Type const& _type):
{
if (m_dataType->isValueType())
{
- solAssert(m_dataType->storageSize() == m_dataType->sizeOnStack(), "");
+ if (m_dataType->category() != Type::Category::Function)
+ solAssert(m_dataType->storageSize() == m_dataType->sizeOnStack(), "");
solAssert(m_dataType->storageSize() == 1, "Invalid storage size.");
}
}
@@ -176,38 +177,65 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const
m_context << Instruction::POP << Instruction::SLOAD;
else
{
+ bool cleaned = false;
m_context
<< Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1
<< u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV;
if (m_dataType->category() == Type::Category::FixedPoint)
// implementation should be very similar to the integer case.
- solAssert(false, "Not yet implemented - FixedPointType.");
+ solUnimplemented("Not yet implemented - FixedPointType.");
if (m_dataType->category() == Type::Category::FixedBytes)
+ {
m_context << (u256(0x1) << (256 - 8 * m_dataType->storageBytes())) << Instruction::MUL;
+ cleaned = true;
+ }
else if (
m_dataType->category() == Type::Category::Integer &&
dynamic_cast<IntegerType const&>(*m_dataType).isSigned()
)
+ {
m_context << u256(m_dataType->storageBytes() - 1) << Instruction::SIGNEXTEND;
- else
+ cleaned = true;
+ }
+ else if (FunctionType const* fun = dynamic_cast<decltype(fun)>(m_dataType))
+ {
+ if (fun->location() == FunctionType::Location::External)
+ {
+ CompilerUtils(m_context).splitExternalFunctionType(false);
+ cleaned = true;
+ }
+ }
+ if (!cleaned)
+ {
+ solAssert(m_dataType->sizeOnStack() == 1, "");
m_context << ((u256(0x1) << (8 * m_dataType->storageBytes())) - 1) << Instruction::AND;
+ }
}
}
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())
{
solAssert(m_dataType->storageBytes() <= 32, "Invalid storage bytes size.");
solAssert(m_dataType->storageBytes() > 0, "Invalid storage bytes size.");
+
if (m_dataType->storageBytes() == 32)
{
+ solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size.");
// offset should be zero
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
@@ -222,28 +250,39 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc
m_context
<< Instruction::DUP2 << ((u256(1) << (8 * m_dataType->storageBytes())) - 1)
<< Instruction::MUL;
- m_context << Instruction::NOT << Instruction::AND;
- // stack: value storage_ref multiplier cleared_value
- m_context
- << Instruction::SWAP1 << Instruction::DUP4;
+ m_context << Instruction::NOT << Instruction::AND << Instruction::SWAP1;
+ // stack: value storage_ref cleared_value multiplier
+ utils.copyToStackTop(3 + m_dataType->sizeOnStack(), m_dataType->sizeOnStack());
// stack: value storage_ref cleared_value multiplier value
- if (m_dataType->category() == Type::Category::FixedBytes)
+ 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);
+ else
+ m_context <<
+ ((u256(1) << (8 * m_dataType->storageBytes())) - 1) <<
+ 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
m_context << Instruction::SWAP1 << Instruction::SSTORE;
if (_move)
- m_context << Instruction::POP;
+ utils.popStackElement(*m_dataType);
}
}
else
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 813fa3ab..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>
@@ -410,6 +410,16 @@ bool Why3Translator::visit(WhileStatement const& _node)
{
addSourceFromDocStrings(_node.annotation());
+ // Why3 does not appear to support do-while loops,
+ // so we will simulate them by performing a while
+ // loop with the body prepended once.
+
+ if (_node.isDoWhile())
+ {
+ visitIndentedUnlessBlock(_node.body());
+ newLine();
+ }
+
add("while ");
_node.condition().accept(*this);
newLine();
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/grammar.txt b/libsolidity/grammar.txt
index d84ee10c..0aa6690b 100644
--- a/libsolidity/grammar.txt
+++ b/libsolidity/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' | 'external' | 'public' | 'internal' | 'private' )*
+ ( FunctionCall | Identifier | 'constant' |' payable' | 'external' | 'public' | 'internal' | 'private' )*
( 'returns' ParameterList )? Block
EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';'
@@ -31,18 +31,21 @@ EnumDefinition = 'enum' Identifier '{' EnumValue? (',' EnumValue)* '}'
IndexedParameterList = '(' ( TypeName 'indexed'? Identifier? (',' TypeName 'indexed'? Identifier?)* )? ')'
ParameterList = '(' ( TypeName Identifier? (',' TypeName Identifier?)* )? ')'
+TypeNameList = '(' ( TypeName (',' TypeName )* )? ')'
// semantic restriction: mappings and structs (recursively) containing mappings
// are not allowed in argument lists
VariableDeclaration = TypeName Identifier
-TypeName = ElementaryTypeName | Identifier StorageLocation? | Mapping | ArrayTypeName
+TypeName = ElementaryTypeName | Identifier StorageLocation? | Mapping | ArrayTypeName | FunctionTypeName
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
ArrayTypeName = TypeName StorageLocation? '[' Expression? ']'
+FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant' | 'payable' )*
+ ( 'returns' TypeNameList )?
StorageLocation = 'memory' | 'storage'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | ForStatement | Block |
- ( PlaceholderStatement | Continue | Break | Return |
+ ( DoWhileStatement | PlaceholderStatement | Continue | Break | Return |
Throw | SimpleStatement ) ';'
ExpressionStatement = Expression
@@ -51,6 +54,7 @@ WhileStatement = 'while' '(' Expression ')' Statement
PlaceholderStatement = '_'
SimpleStatement = VariableDefinition | ExpressionStatement
ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement
+DoWhileStatement = 'do' Statement 'while' '(' Expression ')'
Continue = 'continue'
Break = 'break'
Return = 'return' Expression?
@@ -64,7 +68,7 @@ Expression =
| Expression '**' Expression
| Expression ('*' | '/' | '%') Expression
| Expression ('+' | '-') Expression
- | Expression ('<<' | '>>' | '>>>')
+ | Expression ('<<' | '>>')
| Expression '&' Expression
| Expression '^' Expression
| Expression '|' Expression
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index 5d920cb7..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>
@@ -81,7 +81,11 @@ struct GeneratorState
class LabelOrganizer: public boost::static_visitor<>
{
public:
- LabelOrganizer(GeneratorState& _state): m_state(_state) {}
+ LabelOrganizer(GeneratorState& _state): m_state(_state)
+ {
+ // Make the Solidity ErrorTag available to inline assembly
+ m_state.labels.insert(make_pair("invalidJumpLabel", m_state.assembly.errorTag()));
+ }
template <class T>
void operator()(T const& /*_item*/) { }
@@ -216,10 +220,18 @@ public:
size_t numVariables = m_state.variables.size();
int deposit = m_state.assembly.deposit();
std::for_each(_block.statements.begin(), _block.statements.end(), boost::apply_visitor(*this));
- deposit = m_state.assembly.deposit() - deposit;
+
+ // pop variables
+ while (m_state.variables.size() > numVariables)
+ {
+ m_state.assembly.append(solidity::Instruction::POP);
+ m_state.variables.pop_back();
+ }
m_state.assembly.setSourceLocation(_block.location);
+ deposit = m_state.assembly.deposit() - deposit;
+
// issue warnings for stack height discrepancies
if (deposit < 0)
{
@@ -238,12 +250,6 @@ public:
);
}
- // pop variables
- while (m_state.variables.size() > numVariables)
- {
- m_state.assembly.append(solidity::Instruction::POP);
- m_state.variables.pop_back();
- }
}
private:
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 efbbd237..9305c5e3 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>
@@ -37,6 +37,7 @@
#include <libsolidity/interface/InterfaceHandler.h>
#include <libsolidity/formal/Why3Translator.h>
+#include <libevmasm/Exceptions.h>
#include <libdevcore/SHA3.h>
#include <boost/algorithm/string.hpp>
@@ -345,17 +346,17 @@ map<string, unsigned> CompilerStack::sourceIndices() const
return indices;
}
-string const& CompilerStack::interface(string const& _contractName) const
+Json::Value const& CompilerStack::interface(string const& _contractName) const
{
return metadata(_contractName, DocumentationType::ABIInterface);
}
-string const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const
+Json::Value const& CompilerStack::metadata(string const& _contractName, DocumentationType _type) const
{
if (!m_parseSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
- std::unique_ptr<string const>* doc;
+ std::unique_ptr<Json::Value const>* doc;
Contract const& currentContract = contract(_contractName);
// checks wheather we already have the documentation
@@ -376,7 +377,7 @@ string const& CompilerStack::metadata(string const& _contractName, Documentation
// caches the result
if (!*doc)
- doc->reset(new string(InterfaceHandler::documentation(*currentContract.contract, _type)));
+ doc->reset(new Json::Value(InterfaceHandler::documentation(*currentContract.contract, _type)));
return *(*doc);
}
@@ -590,9 +591,19 @@ void CompilerStack::compileContract(
compiledContract.runtimeObject = compiler->runtimeObject();
_compiledContracts[compiledContract.contract] = &compiler->assembly();
- Compiler cloneCompiler(_optimize, _runs);
- cloneCompiler.compileClone(_contract, _compiledContracts);
- compiledContract.cloneObject = cloneCompiler.assembledObject();
+ try
+ {
+ Compiler cloneCompiler(_optimize, _runs);
+ cloneCompiler.compileClone(_contract, _compiledContracts);
+ compiledContract.cloneObject = cloneCompiler.assembledObject();
+ }
+ catch (eth::AssemblyException const&)
+ {
+ // In some cases (if the constructor requests a runtime function), it is not
+ // possible to compile the clone.
+
+ // TODO: Report error / warning
+ }
}
std::string CompilerStack::defaultContractName() const
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index da479638..ea706122 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>
@@ -162,14 +162,14 @@ public:
/// @returns a mapping assigning each source name its index inside the vector returned
/// by sourceNames().
std::map<std::string, unsigned> sourceIndices() const;
- /// @returns a string representing the contract interface in JSON.
+ /// @returns a JSON representing the contract interface.
/// Prerequisite: Successful call to parse or compile.
- std::string const& interface(std::string const& _contractName = "") const;
- /// @returns a string representing the contract's documentation in JSON.
+ Json::Value const& interface(std::string const& _contractName = "") const;
+ /// @returns a JSON representing the contract's documentation.
/// Prerequisite: Successful call to parse or compile.
/// @param type The type of the documentation to get.
/// Can be one of 4 types defined at @c DocumentationType
- std::string const& metadata(std::string const& _contractName, DocumentationType _type) const;
+ Json::Value const& metadata(std::string const& _contractName, DocumentationType _type) const;
/// @returns the previously used scanner, useful for counting lines during error reporting.
Scanner const& scanner(std::string const& _sourceName = "") const;
@@ -213,9 +213,9 @@ private:
eth::LinkerObject object;
eth::LinkerObject runtimeObject;
eth::LinkerObject cloneObject;
- mutable std::unique_ptr<std::string const> interface;
- mutable std::unique_ptr<std::string const> userDocumentation;
- mutable std::unique_ptr<std::string const> devDocumentation;
+ mutable std::unique_ptr<Json::Value const> interface;
+ mutable std::unique_ptr<Json::Value const> userDocumentation;
+ mutable std::unique_ptr<Json::Value const> devDocumentation;
mutable std::unique_ptr<std::string const> sourceMapping;
mutable std::unique_ptr<std::string const> runtimeSourceMapping;
};
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 07835320..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>
@@ -37,6 +37,7 @@ using ErrorList = std::vector<std::shared_ptr<Error const>>;
struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
struct FatalError: virtual Exception {};
+struct UnimplementedFeatureError: virtual Exception{};
class Error: virtual public Exception
{
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.cpp b/libsolidity/interface/InterfaceHandler.cpp
index de16a372..9944bb22 100644
--- a/libsolidity/interface/InterfaceHandler.cpp
+++ b/libsolidity/interface/InterfaceHandler.cpp
@@ -8,7 +8,7 @@ using namespace std;
using namespace dev;
using namespace dev::solidity;
-string InterfaceHandler::documentation(
+Json::Value InterfaceHandler::documentation(
ContractDefinition const& _contractDef,
DocumentationType _type
)
@@ -24,10 +24,9 @@ string InterfaceHandler::documentation(
}
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type"));
- return "";
}
-string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
+Json::Value InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
{
Json::Value abi(Json::arrayValue);
@@ -67,8 +66,9 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
{
Json::Value method;
method["type"] = "constructor";
- auto externalFunction = FunctionType(*_contractDef.constructor()).interfaceFunctionType();
+ auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType();
solAssert(!!externalFunction, "");
+ method["payable"] = externalFunction->isPayable();
method["inputs"] = populateParameters(
externalFunction->parameterNames(),
externalFunction->parameterTypeNames(_contractDef.isLibrary())
@@ -77,7 +77,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
}
if (_contractDef.fallbackFunction())
{
- auto externalFunctionType = FunctionType(*_contractDef.fallbackFunction()).interfaceFunctionType();
+ auto externalFunctionType = FunctionType(*_contractDef.fallbackFunction(), false).interfaceFunctionType();
solAssert(!!externalFunctionType, "");
Json::Value method;
method["type"] = "fallback";
@@ -103,10 +103,11 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef)
event["inputs"] = params;
abi.append(event);
}
- return Json::FastWriter().write(abi);
+
+ return abi;
}
-string InterfaceHandler::userDocumentation(ContractDefinition const& _contractDef)
+Json::Value InterfaceHandler::userDocumentation(ContractDefinition const& _contractDef)
{
Json::Value doc;
Json::Value methods(Json::objectValue);
@@ -126,10 +127,10 @@ string InterfaceHandler::userDocumentation(ContractDefinition const& _contractDe
}
doc["methods"] = methods;
- return Json::StyledWriter().write(doc);
+ return doc;
}
-string InterfaceHandler::devDocumentation(ContractDefinition const& _contractDef)
+Json::Value InterfaceHandler::devDocumentation(ContractDefinition const& _contractDef)
{
Json::Value doc;
Json::Value methods(Json::objectValue);
@@ -175,7 +176,7 @@ string InterfaceHandler::devDocumentation(ContractDefinition const& _contractDef
}
doc["methods"] = methods;
- return Json::StyledWriter().write(doc);
+ return doc;
}
string InterfaceHandler::extractDoc(multimap<string, DocTag> const& _tags, string const& _name)
diff --git a/libsolidity/interface/InterfaceHandler.h b/libsolidity/interface/InterfaceHandler.h
index 54199e4e..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>
@@ -64,24 +64,24 @@ public:
/// @param _contractDef The contract definition
/// @param _type The type of the documentation. Can be one of the
/// types provided by @c DocumentationType
- /// @return A string with the json representation of provided type
- static std::string documentation(
+ /// @return A JSON representation of provided type
+ static Json::Value documentation(
ContractDefinition const& _contractDef,
DocumentationType _type
);
/// Get the ABI Interface of the contract
/// @param _contractDef The contract definition
- /// @return A string with the json representation of the contract's ABI Interface
- static std::string abiInterface(ContractDefinition const& _contractDef);
+ /// @return A JSONrepresentation of the contract's ABI Interface
+ static Json::Value abiInterface(ContractDefinition const& _contractDef);
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
- /// @return A string with the json representation of the contract's user documentation
- static std::string userDocumentation(ContractDefinition const& _contractDef);
+ /// @return A JSON representation of the contract's user documentation
+ static Json::Value userDocumentation(ContractDefinition const& _contractDef);
/// Genereates the Developer's documentation of the contract
/// @param _contractDef The contract definition
- /// @return A string with the json representation
+ /// @return A JSON representation
/// of the contract's developer documentation
- static std::string devDocumentation(ContractDefinition const& _contractDef);
+ static Json::Value devDocumentation(ContractDefinition const& _contractDef);
private:
/// @returns concatenation of all content under the given tag name.
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 738669ac..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>
@@ -30,6 +30,7 @@ namespace dev
namespace solidity
{
struct InternalCompilerError;
+struct UnimplementedFeatureError;
}
}
@@ -37,3 +38,8 @@ struct InternalCompilerError;
#define solAssert(CONDITION, DESCRIPTION) \
assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION)
+#define solUnimplementedAssert(CONDITION, DESCRIPTION) \
+ assertThrow(CONDITION, ::dev::solidity::UnimplementedFeatureError, DESCRIPTION)
+
+#define solUnimplemented(DESCRIPTION) \
+ solUnimplementedAssert(false, DESCRIPTION)
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 0e99d1e7..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>
@@ -217,7 +217,9 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
if (currentTokenValue == Token::RBrace)
break;
else if (currentTokenValue == Token::Function)
- subNodes.push_back(parseFunctionDefinition(name.get()));
+ // This can be a function or a state variable of function type (especially
+ // complicated to distinguish fallback function from function type state variable)
+ subNodes.push_back(parseFunctionDefinitionOrFunctionTypeStateVariable(name.get()));
else if (currentTokenValue == Token::Struct)
subNodes.push_back(parseStructDefinition());
else if (currentTokenValue == Token::Enum)
@@ -288,81 +290,121 @@ Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
return visibility;
}
-ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* _contractName)
+Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers)
{
- ASTNodeFactory nodeFactory(*this);
- ASTPointer<ASTString> docstring;
- if (m_scanner->currentCommentLiteral() != "")
- docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
-
+ FunctionHeaderParserResult result;
expectToken(Token::Function);
- ASTPointer<ASTString> name;
- if (m_scanner->currentToken() == Token::LParen)
- name = make_shared<ASTString>(); // anonymous function
+ if (_forceEmptyName || m_scanner->currentToken() == Token::LParen)
+ result.name = make_shared<ASTString>(); // anonymous function
else
- name = expectIdentifierToken();
+ result.name = expectIdentifierToken();
VarDeclParserOptions options;
options.allowLocationSpecifier = true;
- ASTPointer<ParameterList> parameters(parseParameterList(options));
- bool isDeclaredConst = false;
- bool isPayable = false;
- Declaration::Visibility visibility(Declaration::Visibility::Default);
- vector<ASTPointer<ModifierInvocation>> modifiers;
+ result.parameters = parseParameterList(options);
while (true)
{
Token::Value token = m_scanner->currentToken();
if (token == Token::Const)
{
- isDeclaredConst = true;
+ result.isDeclaredConst = true;
m_scanner->next();
}
else if (m_scanner->currentToken() == Token::Payable)
{
- isPayable = true;
+ result.isPayable = true;
m_scanner->next();
}
- else if (token == Token::Identifier)
- modifiers.push_back(parseModifierInvocation());
+ else if (_allowModifiers && token == Token::Identifier)
+ {
+ // This can either be a modifier (function declaration) or the name of the
+ // variable (function type name plus variable).
+ if (
+ m_scanner->peekNextToken() == Token::Semicolon ||
+ m_scanner->peekNextToken() == Token::Assign
+ )
+ // Variable declaration, break here.
+ break;
+ else
+ result.modifiers.push_back(parseModifierInvocation());
+ }
else if (Token::isVisibilitySpecifier(token))
{
- if (visibility != Declaration::Visibility::Default)
+ if (result.visibility != Declaration::Visibility::Default)
fatalParserError(string("Multiple visibility specifiers."));
- visibility = parseVisibilitySpecifier(token);
+ result.visibility = parseVisibilitySpecifier(token);
}
else
break;
}
- ASTPointer<ParameterList> returnParameters;
if (m_scanner->currentToken() == Token::Returns)
{
bool const permitEmptyParameterList = false;
m_scanner->next();
- returnParameters = parseParameterList(options, permitEmptyParameterList);
+ result.returnParameters = parseParameterList(options, permitEmptyParameterList);
}
else
- returnParameters = createEmptyParameterList();
- ASTPointer<Block> block = ASTPointer<Block>();
- nodeFactory.markEndPosition();
- if (m_scanner->currentToken() != Token::Semicolon)
+ result.returnParameters = createEmptyParameterList();
+ return result;
+}
+
+ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(ASTString const* _contractName)
+{
+ ASTNodeFactory nodeFactory(*this);
+ ASTPointer<ASTString> docstring;
+ if (m_scanner->currentCommentLiteral() != "")
+ docstring = make_shared<ASTString>(m_scanner->currentCommentLiteral());
+
+ FunctionHeaderParserResult header = parseFunctionHeader(false, true);
+
+ if (
+ !header.modifiers.empty() ||
+ !header.name->empty() ||
+ m_scanner->currentToken() == Token::Semicolon ||
+ m_scanner->currentToken() == Token::LBrace
+ )
{
- block = parseBlock();
- nodeFactory.setEndPositionFromNode(block);
+ // this has to be a function
+ ASTPointer<Block> block = ASTPointer<Block>();
+ nodeFactory.markEndPosition();
+ if (m_scanner->currentToken() != Token::Semicolon)
+ {
+ block = parseBlock();
+ nodeFactory.setEndPositionFromNode(block);
+ }
+ else
+ m_scanner->next(); // just consume the ';'
+ bool const c_isConstructor = (_contractName && *header.name == *_contractName);
+ return nodeFactory.createNode<FunctionDefinition>(
+ header.name,
+ header.visibility,
+ c_isConstructor,
+ docstring,
+ header.parameters,
+ header.isDeclaredConst,
+ header.modifiers,
+ header.returnParameters,
+ header.isPayable,
+ block
+ );
}
else
- m_scanner->next(); // just consume the ';'
- bool const c_isConstructor = (_contractName && *name == *_contractName);
- return nodeFactory.createNode<FunctionDefinition>(
- name,
- visibility,
- c_isConstructor,
- docstring,
- parameters,
- isDeclaredConst,
- modifiers,
- returnParameters,
- isPayable,
- block
- );
+ {
+ // this has to be a state variable
+ ASTPointer<TypeName> type = nodeFactory.createNode<FunctionTypeName>(
+ header.parameters,
+ header.returnParameters,
+ header.visibility,
+ header.isDeclaredConst,
+ header.isPayable
+ );
+ type = parseTypeNameSuffix(type, nodeFactory);
+ VarDeclParserOptions options;
+ options.isStateVariable = true;
+ options.allowInitialValue = true;
+ auto node = parseVariableDeclaration(options, type);
+ expectToken(Token::Semicolon);
+ return node;
+ }
}
ASTPointer<StructDefinition> Parser::parseStructDefinition()
@@ -406,6 +448,8 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
if (m_scanner->currentToken() != Token::Identifier)
fatalParserError(string("Expected Identifier after ','"));
}
+ if (members.size() == 0)
+ parserError({"enum with no members is not allowed."});
nodeFactory.markEndPosition();
expectToken(Token::RBrace);
@@ -609,6 +653,21 @@ ASTPointer<UserDefinedTypeName> Parser::parseUserDefinedTypeName()
return nodeFactory.createNode<UserDefinedTypeName>(identifierPath);
}
+ASTPointer<TypeName> Parser::parseTypeNameSuffix(ASTPointer<TypeName> type, ASTNodeFactory& nodeFactory)
+{
+ while (m_scanner->currentToken() == Token::LBrack)
+ {
+ m_scanner->next();
+ ASTPointer<Expression> length;
+ if (m_scanner->currentToken() != Token::RBrack)
+ length = parseExpression();
+ nodeFactory.markEndPosition();
+ expectToken(Token::RBrack);
+ type = nodeFactory.createNode<ArrayTypeName>(type, length);
+ }
+ return type;
+}
+
ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
{
ASTNodeFactory nodeFactory(*this);
@@ -629,6 +688,8 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
fatalParserError(string("Expected explicit type name."));
m_scanner->next();
}
+ else if (token == Token::Function)
+ type = parseFunctionType();
else if (token == Token::Mapping)
type = parseMapping();
else if (token == Token::Identifier)
@@ -638,19 +699,23 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
if (type)
// Parse "[...]" postfixes for arrays.
- while (m_scanner->currentToken() == Token::LBrack)
- {
- m_scanner->next();
- ASTPointer<Expression> length;
- if (m_scanner->currentToken() != Token::RBrack)
- length = parseExpression();
- nodeFactory.markEndPosition();
- expectToken(Token::RBrack);
- type = nodeFactory.createNode<ArrayTypeName>(type, length);
- }
+ type = parseTypeNameSuffix(type, nodeFactory);
return type;
}
+ASTPointer<FunctionTypeName> Parser::parseFunctionType()
+{
+ ASTNodeFactory nodeFactory(*this);
+ FunctionHeaderParserResult header = parseFunctionHeader(true, false);
+ return nodeFactory.createNode<FunctionTypeName>(
+ header.parameters,
+ header.returnParameters,
+ header.visibility,
+ header.isDeclaredConst,
+ header.isPayable
+ );
+}
+
ASTPointer<Mapping> Parser::parseMapping()
{
ASTNodeFactory nodeFactory(*this);
@@ -722,6 +787,8 @@ ASTPointer<Statement> Parser::parseStatement()
return parseIfStatement(docString);
case Token::While:
return parseWhileStatement(docString);
+ case Token::Do:
+ return parseDoWhileStatement(docString);
case Token::For:
return parseForStatement(docString);
case Token::LBrace:
@@ -816,9 +883,24 @@ ASTPointer<WhileStatement> Parser::parseWhileStatement(ASTPointer<ASTString> con
expectToken(Token::RParen);
ASTPointer<Statement> body = parseStatement();
nodeFactory.setEndPositionFromNode(body);
- return nodeFactory.createNode<WhileStatement>(_docString, condition, body);
+ return nodeFactory.createNode<WhileStatement>(_docString, condition, body, false);
+}
+
+ASTPointer<WhileStatement> Parser::parseDoWhileStatement(ASTPointer<ASTString> const& _docString)
+{
+ ASTNodeFactory nodeFactory(*this);
+ expectToken(Token::Do);
+ ASTPointer<Statement> body = parseStatement();
+ expectToken(Token::While);
+ expectToken(Token::LParen);
+ ASTPointer<Expression> condition = parseExpression();
+ expectToken(Token::RParen);
+ nodeFactory.markEndPosition();
+ expectToken(Token::Semicolon);
+ return nodeFactory.createNode<WhileStatement>(_docString, condition, body, true);
}
+
ASTPointer<ForStatement> Parser::parseForStatement(ASTPointer<ASTString> const& _docString)
{
ASTNodeFactory nodeFactory(*this);
@@ -1259,7 +1341,7 @@ Parser::LookAheadInfo Parser::peekStatementType() const
Token::Value token(m_scanner->currentToken());
bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
- if (token == Token::Mapping || token == Token::Var)
+ if (token == Token::Mapping || token == Token::Function || token == Token::Var)
return LookAheadInfo::VariableDeclarationStatement;
if (mightBeTypeName)
{
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 9c30cf60..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>
@@ -53,6 +53,18 @@ private:
bool allowLocationSpecifier = false;
};
+ /// This struct is shared for parsing a function header and a function type.
+ struct FunctionHeaderParserResult
+ {
+ ASTPointer<ASTString> name;
+ ASTPointer<ParameterList> parameters;
+ ASTPointer<ParameterList> returnParameters;
+ Declaration::Visibility visibility = Declaration::Visibility::Default;
+ bool isDeclaredConst = false;
+ bool isPayable = false;
+ std::vector<ASTPointer<ModifierInvocation>> modifiers;
+ };
+
///@{
///@name Parsing functions for the AST nodes
ASTPointer<PragmaDirective> parsePragmaDirective();
@@ -60,6 +72,8 @@ private:
ASTPointer<ContractDefinition> parseContractDefinition(bool _isLibrary);
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
Declaration::Visibility parseVisibilitySpecifier(Token::Value _token);
+ FunctionHeaderParserResult parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers);
+ ASTPointer<ASTNode> parseFunctionDefinitionOrFunctionTypeStateVariable(ASTString const* _contractName);
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
ASTPointer<StructDefinition> parseStructDefinition();
ASTPointer<EnumDefinition> parseEnumDefinition();
@@ -74,7 +88,9 @@ private:
ASTPointer<ModifierInvocation> parseModifierInvocation();
ASTPointer<Identifier> parseIdentifier();
ASTPointer<UserDefinedTypeName> parseUserDefinedTypeName();
+ ASTPointer<TypeName> parseTypeNameSuffix(ASTPointer<TypeName> type, ASTNodeFactory& nodeFactory);
ASTPointer<TypeName> parseTypeName(bool _allowVar);
+ ASTPointer<FunctionTypeName> parseFunctionType();
ASTPointer<Mapping> parseMapping();
ASTPointer<ParameterList> parseParameterList(
VarDeclParserOptions const& _options,
@@ -85,6 +101,7 @@ private:
ASTPointer<InlineAssembly> parseInlineAssembly(ASTPointer<ASTString> const& _docString = {});
ASTPointer<IfStatement> parseIfStatement(ASTPointer<ASTString> const& _docString);
ASTPointer<WhileStatement> parseWhileStatement(ASTPointer<ASTString> const& _docString);
+ ASTPointer<WhileStatement> parseDoWhileStatement(ASTPointer<ASTString> const& _docString);
ASTPointer<ForStatement> parseForStatement(ASTPointer<ASTString> const& _docString);
/// A "simple statement" can be a variable declaration statement or an expression statement.
ASTPointer<Statement> parseSimpleStatement(ASTPointer<ASTString> const& _docString);
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..6115101e 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:
diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h
index 36cba112..65de8bd4 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:
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..3ce0f424 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
diff --git a/scripts/Dockerfile b/scripts/Dockerfile
new file mode 100644
index 00000000..e34436ed
--- /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 develop 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/tests.sh b/scripts/tests.sh
index 93afd2d2..dfbda734 100755
--- a/scripts/tests.sh
+++ b/scripts/tests.sh
@@ -28,8 +28,22 @@
set -e
-# There is an implicit assumption here that we HAVE to run from root directory.
-REPO_ROOT=$(pwd)
+REPO_ROOT="$(dirname "$0")"/..
+
+ # Compile all files in std and examples.
+
+for f in "$REPO_ROOT"/std/*.sol
+do
+ echo "Compiling $f..."
+ set +e
+ output=$("$REPO_ROOT"/build/solc/solc "$f" 2>&1)
+ failed=$?
+ # Remove the pre-release warning from the compiler output
+ output=$(echo "$output" | grep -v 'pre-release')
+ echo "$output"
+ set -e
+ test -z "$output" -a "$failed" -eq 0
+done
# This conditional is only needed because we don't have a working Homebrew
# install for `eth` at the time of writing, so we unzip the ZIP file locally
@@ -51,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/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 84cc2534..c677cf1f 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>
@@ -41,6 +41,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
+#include <libdevcore/JSON.h>
#include <libevmasm/Instruction.h>
#include <libevmasm/GasMeter.h>
#include <libsolidity/interface/Version.h>
@@ -230,12 +231,18 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co
if (m_args.count(argName))
{
+ std::string output;
+ if (_type == DocumentationType::ABIInterface)
+ output = dev::jsonCompactPrint(m_compiler->metadata(_contract, _type));
+ else
+ output = dev::jsonPrettyPrint(m_compiler->metadata(_contract, _type));
+
if (m_args.count("output-dir"))
- createFile(_contract + suffix, m_compiler->metadata(_contract, _type));
+ createFile(_contract + suffix, output);
else
{
cout << title << endl;
- cout << m_compiler->metadata(_contract, _type) << endl;
+ cout << output << endl;
}
}
@@ -604,6 +611,12 @@ bool CommandLineInterface::processInput()
<< boost::diagnostic_information(_exception);
return false;
}
+ catch (UnimplementedFeatureError const& _exception)
+ {
+ cerr << "Unimplemented feature:" << endl
+ << boost::diagnostic_information(_exception);
+ return false;
+ }
catch (Error const& _error)
{
if (_error.type() == Error::Type::DocstringParsingError)
@@ -645,7 +658,7 @@ void CommandLineInterface::handleCombinedJSON()
{
Json::Value contractData(Json::objectValue);
if (requests.count("abi"))
- contractData["abi"] = m_compiler->interface(contractName);
+ contractData["abi"] = dev::jsonCompactPrint(m_compiler->interface(contractName));
if (requests.count("bin"))
contractData["bin"] = m_compiler->object(contractName).toHex();
if (requests.count("bin-runtime"))
@@ -670,9 +683,9 @@ void CommandLineInterface::handleCombinedJSON()
contractData["srcmap-runtime"] = map ? *map : "";
}
if (requests.count("devdoc"))
- contractData["devdoc"] = m_compiler->metadata(contractName, DocumentationType::NatspecDev);
+ contractData["devdoc"] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecDev));
if (requests.count("userdoc"))
- contractData["userdoc"] = m_compiler->metadata(contractName, DocumentationType::NatspecUser);
+ contractData["userdoc"] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecUser));
output["contracts"][contractName] = contractData;
}
@@ -696,7 +709,7 @@ void CommandLineInterface::handleCombinedJSON()
output["sources"][sourceCode.first]["AST"] = converter.json();
}
}
- cout << Json::FastWriter().write(output) << endl;
+ cout << dev::jsonCompactPrint(output) << endl;
}
void CommandLineInterface::handleAst(string const& _argStr)
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index e240fe96..33ae6ee6 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>
diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp
index ef69105e..0f95ebe5 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>
@@ -27,6 +27,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonIO.h>
+#include <libdevcore/JSON.h>
#include <libevmasm/Instruction.h>
#include <libevmasm/GasMeter.h>
#include <libsolidity/parsing/Scanner.h>
@@ -189,6 +190,10 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
{
errors.append(formatError(exception, "Internal compiler error", scannerFromSourceName));
}
+ catch (UnimplementedFeatureError const& exception)
+ {
+ errors.append(formatError(exception, "Unimplemented feature", scannerFromSourceName));
+ }
catch (Exception const& exception)
{
errors.append("Exception during compilation: " + boost::diagnostic_information(exception));
@@ -209,7 +214,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
for (string const& contractName: compiler.contractNames())
{
Json::Value contractData(Json::objectValue);
- contractData["interface"] = compiler.interface(contractName);
+ contractData["interface"] = dev::jsonCompactPrint(compiler.interface(contractName));
contractData["bytecode"] = compiler.object(contractName).toHex();
contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex();
contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode);
@@ -270,7 +275,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback
try
{
- return Json::FastWriter().write(output);
+ return dev::jsonCompactPrint(output);
}
catch (...)
{
@@ -288,7 +293,7 @@ string compileMulti(string const& _input, bool _optimize, CStyleReadFileCallback
errors.append("Error parsing input JSON: " + reader.getFormattedErrorMessages());
Json::Value output(Json::objectValue);
output["errors"] = errors;
- return Json::FastWriter().write(output);
+ return dev::jsonCompactPrint(output);
}
else
{
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/std/StandardToken.sol b/std/StandardToken.sol
index 41f2d709..4ff1b8f9 100644
--- a/std/StandardToken.sol
+++ b/std/StandardToken.sol
@@ -1,3 +1,5 @@
+pragma solidity ^0.4.0;
+
import "./Token.sol";
contract StandardToken is Token {
diff --git a/std/Token.sol b/std/Token.sol
index 396dbf9e..59566f26 100644
--- a/std/Token.sol
+++ b/std/Token.sol
@@ -1,3 +1,5 @@
+pragma solidity ^0.4.0;
+
contract Token {
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
diff --git a/std/mortal.sol b/std/mortal.sol
index 8de019ab..f0a6f4ce 100644
--- a/std/mortal.sol
+++ b/std/mortal.sol
@@ -1,3 +1,5 @@
+pragma solidity ^0.4.0;
+
import "./owned.sol";
contract mortal is owned {
diff --git a/std/owned.sol b/std/owned.sol
index 3d7674f5..bbb8d957 100644
--- a/std/owned.sol
+++ b/std/owned.sol
@@ -1,3 +1,5 @@
+pragma solidity ^0.4.0;
+
contract owned {
address owner;
diff --git a/std/std.sol b/std/std.sol
index c3f66b1b..4d65bef2 100644
--- a/std/std.sol
+++ b/std/std.sol
@@ -1,3 +1,5 @@
+pragma solidity ^0.4.0;
+
import "./owned.sol";
import "./mortal.sol";
import "./Token.sol";
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2f001b21..33af9981 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,8 +1,10 @@
cmake_policy(SET CMP0015 NEW)
aux_source_directory(. SRC_LIST)
-aux_source_directory(contracts SRC_LIST)
+aux_source_directory(libdevcore SRC_LIST)
+aux_source_directory(libevmasm SRC_LIST)
aux_source_directory(libsolidity SRC_LIST)
+aux_source_directory(contracts SRC_LIST)
get_filename_component(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
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..d670ebff 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,9 @@ Options::Options()
ipcPath = suite.argv[i + 1];
i++;
}
+ else if (string(suite.argv[i]) == "--optimize")
+ optimize = 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..afe4a68f 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,7 @@ namespace test
struct Options: boost::noncopyable
{
std::string ipcPath;
+ 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..0b573bca 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>
@@ -220,7 +220,6 @@ protected:
{
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/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp
index 736015fa..8aabdac2 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>
@@ -132,7 +132,6 @@ protected:
{
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 ec968058..935baf5b 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>
@@ -368,7 +368,7 @@ contract Wallet is multisig, multiowned, daylimit {
// constructor - just pass on the owner array to the multiowned and
// the limit to daylimit
- function Wallet(address[] _owners, uint _required, uint _daylimit)
+ function Wallet(address[] _owners, uint _required, uint _daylimit) payable
multiowned(_owners, _required) daylimit(_daylimit) {
}
@@ -447,7 +447,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
new file mode 100644
index 00000000..a23c36fd
--- /dev/null
+++ b/test/libdevcore/SwarmHash.cpp
@@ -0,0 +1,57 @@
+/*
+ This file is part of cpp-ethereum.
+
+ cpp-ethereum 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,
+ 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/>.
+*/
+/**
+ * Unit tests for the swarm hash computation routine.
+ */
+
+#include <libdevcore/SwarmHash.h>
+
+#include "../TestHelper.h"
+
+using namespace std;
+
+namespace dev
+{
+namespace test
+{
+
+BOOST_AUTO_TEST_SUITE(SwarmHash)
+
+string swarmHashHex(bytes 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_AUTO_TEST_SUITE_END()
+
+}
+}
diff --git a/test/libevmasm/SourceLocation.cpp b/test/libevmasm/SourceLocation.cpp
new file mode 100644
index 00000000..6889b3e6
--- /dev/null
+++ b/test/libevmasm/SourceLocation.cpp
@@ -0,0 +1,50 @@
+/*
+ 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 Yoichi Hirai <yoichi@ethereum.org>
+ * @date 2016
+ * Unit tests for the SourceLocation class.
+ */
+
+#include <libevmasm/SourceLocation.h>
+
+#include "../TestHelper.h"
+
+namespace dev
+{
+namespace solidity
+{
+namespace test
+{
+
+BOOST_AUTO_TEST_SUITE(SourceLocationTest)
+
+BOOST_AUTO_TEST_CASE(test_fail)
+{
+ BOOST_CHECK(SourceLocation() == SourceLocation());
+ BOOST_CHECK(SourceLocation(0, 3, std::make_shared<std::string>("sourceA")) != SourceLocation(0, 3, std::make_shared<std::string>("sourceB")));
+ BOOST_CHECK(SourceLocation(0, 3, std::make_shared<std::string>("source")) == SourceLocation(0, 3, std::make_shared<std::string>("source")));
+ BOOST_CHECK(SourceLocation(3, 7, std::make_shared<std::string>("source")).contains(SourceLocation(4, 6, std::make_shared<std::string>("source"))));
+ BOOST_CHECK(!SourceLocation(3, 7, std::make_shared<std::string>("sourceA")).contains(SourceLocation(4, 6, std::make_shared<std::string>("sourceB"))));
+ BOOST_CHECK(SourceLocation(3, 7, std::make_shared<std::string>("sourceA")) < SourceLocation(4, 6, std::make_shared<std::string>("sourceB")));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
+} // end namespaces
diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp
index a0fc5dd7..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>
@@ -94,20 +94,6 @@ BOOST_AUTO_TEST_CASE(using_for_directive)
BOOST_CHECK_EQUAL(usingFor["children"][1]["attributes"]["name"], "uint");
}
-BOOST_AUTO_TEST_CASE(enum_definition)
-{
- CompilerStack c;
- c.addSource("a", "contract C { enum E {} }");
- c.parse();
- map<string, unsigned> sourceIndices;
- sourceIndices["a"] = 1;
- Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
- Json::Value enumDefinition = astJson["children"][0]["children"][0];
- BOOST_CHECK_EQUAL(enumDefinition["name"], "EnumDefinition");
- BOOST_CHECK_EQUAL(enumDefinition["attributes"]["name"], "E");
- BOOST_CHECK_EQUAL(enumDefinition["src"], "13:9:1");
-}
-
BOOST_AUTO_TEST_CASE(enum_value)
{
CompilerStack c;
@@ -211,6 +197,37 @@ BOOST_AUTO_TEST_CASE(non_utf8)
BOOST_CHECK(literal["attributes"]["type"].asString().find("invalid") != string::npos);
}
+BOOST_AUTO_TEST_CASE(function_type)
+{
+ CompilerStack c;
+ c.addSource("a",
+ "contract C { function f(function() external payable returns (uint) x) "
+ "returns (function() external constant returns (uint)) {} }"
+ );
+ c.parse();
+ map<string, unsigned> sourceIndices;
+ sourceIndices["a"] = 1;
+ Json::Value astJson = ASTJsonConverter(c.ast("a"), sourceIndices).json();
+ Json::Value fun = astJson["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(fun["name"], "FunctionDefinition");
+ Json::Value argument = fun["children"][0]["children"][0];
+ BOOST_CHECK_EQUAL(argument["name"], "VariableDeclaration");
+ BOOST_CHECK_EQUAL(argument["attributes"]["name"], "x");
+ BOOST_CHECK_EQUAL(argument["attributes"]["type"], "function () payable external returns (uint256)");
+ Json::Value funType = argument["children"][0];
+ BOOST_CHECK_EQUAL(funType["attributes"]["constant"], false);
+ BOOST_CHECK_EQUAL(funType["attributes"]["payable"], true);
+ BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external");
+ Json::Value retval = fun["children"][1]["children"][0];
+ BOOST_CHECK_EQUAL(retval["name"], "VariableDeclaration");
+ BOOST_CHECK_EQUAL(retval["attributes"]["name"], "");
+ BOOST_CHECK_EQUAL(retval["attributes"]["type"], "function () constant external returns (uint256)");
+ funType = retval["children"][0];
+ BOOST_CHECK_EQUAL(funType["attributes"]["constant"], true);
+ BOOST_CHECK_EQUAL(funType["attributes"]["payable"], false);
+ BOOST_CHECK_EQUAL(funType["attributes"]["visibility"], "external");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp
index 8d7a3540..cc77bd4c 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>
@@ -91,8 +91,10 @@ void checkAssemblyLocations(AssemblyItems const& _items, vector<SourceLocation>
BOOST_CHECK_MESSAGE(
_items[i].location() == _locations[i],
"Location mismatch for assembly item " + to_string(i) + ". Found: " +
+ (_items[i].location().sourceName ? *_items[i].location().sourceName + ":" : "(null source name)") +
to_string(_items[i].location().start) + "-" +
to_string(_items[i].location().end) + ", expected: " +
+ (_locations[i].sourceName ? *_locations[i].sourceName + ":" : "(null source name)") +
to_string(_locations[i].start) + "-" +
to_string(_locations[i].end));
}
@@ -111,13 +113,13 @@ BOOST_AUTO_TEST_CASE(location_test)
}
}
)";
- shared_ptr<string const> n = make_shared<string>("source");
+ shared_ptr<string const> n = make_shared<string>("");
AssemblyItems items = compileContract(sourceCode);
vector<SourceLocation> locations =
- vector<SourceLocation>(18, SourceLocation(2, 75, n)) +
- vector<SourceLocation>(31, SourceLocation(20, 72, n)) +
+ vector<SourceLocation>(16, SourceLocation(2, 75, n)) +
+ vector<SourceLocation>(27, SourceLocation(20, 72, n)) +
vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} +
- vector<SourceLocation>(4, SourceLocation(58, 67, n)) +
+ vector<SourceLocation>(2, SourceLocation(58, 67, n)) +
vector<SourceLocation>(3, SourceLocation(20, 72, n));
checkAssemblyLocations(items, locations);
}
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..bc224284 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>
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 6c04367f..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>
@@ -41,7 +41,7 @@ namespace test
namespace
{
-bool successParse(std::string const& _source, bool _assemble = false)
+bool successParse(std::string const& _source, bool _assemble = false, bool _allowWarnings = true)
{
assembly::InlineAssemblyStack stack;
try
@@ -51,8 +51,9 @@ bool successParse(std::string const& _source, bool _assemble = false)
if (_assemble)
{
stack.assemble();
- if (!stack.errors().empty() && !Error::containsOnlyWarnings(stack.errors()))
- return false;
+ if (!stack.errors().empty())
+ if (!_allowWarnings || !Error::containsOnlyWarnings(stack.errors()))
+ return false;
}
}
catch (FatalError const&)
@@ -67,9 +68,9 @@ bool successParse(std::string const& _source, bool _assemble = false)
return true;
}
-bool successAssemble(string const& _source)
+bool successAssemble(string const& _source, bool _allowWarnings = true)
{
- return successParse(_source, true);
+ return successParse(_source, true, _allowWarnings);
}
}
@@ -169,6 +170,18 @@ BOOST_AUTO_TEST_CASE(magic_variables)
BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover }"));
}
+BOOST_AUTO_TEST_CASE(imbalanced_stack)
+{
+ BOOST_CHECK(successAssemble("{ 1 2 mul pop }", false));
+ BOOST_CHECK(!successAssemble("{ 1 }", false));
+ BOOST_CHECK(successAssemble("{ let x := 4 7 add }", false));
+}
+
+BOOST_AUTO_TEST_CASE(error_tag)
+{
+ BOOST_CHECK(successAssemble("{ invalidJumpLabel }"));
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
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 073d7d97..6fc2bcee 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>
@@ -40,14 +40,14 @@ public:
void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
{
ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse("pragma solidity >=0.0;\n" + _code), "Parsing contract failed");
- std::string generatedInterfaceString = m_compilerStack.metadata("", DocumentationType::ABIInterface);
- Json::Value generatedInterface;
- m_reader.parse(generatedInterfaceString, generatedInterface);
+
+ Json::Value generatedInterface = m_compilerStack.metadata("", DocumentationType::ABIInterface);
Json::Value expectedInterface;
m_reader.parse(_expectedInterfaceString, expectedInterface);
BOOST_CHECK_MESSAGE(
expectedInterface == generatedInterface,
- "Expected:\n" << expectedInterface.toStyledString() << "\n but got:\n" << generatedInterface.toStyledString()
+ "Expected:\n" << expectedInterface.toStyledString() <<
+ "\n but got:\n" << generatedInterface.toStyledString()
);
}
@@ -524,6 +524,7 @@ BOOST_AUTO_TEST_CASE(constructor_abi)
"type": "bool"
}
],
+ "payable": false,
"type": "constructor"
}
])";
@@ -567,6 +568,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi)
"type": "uint8"
}
],
+ "payable": false,
"type": "constructor"
}
]
@@ -684,7 +686,7 @@ BOOST_AUTO_TEST_CASE(payable_function)
checkInterface(sourceCode, interface);
}
-BOOST_AUTO_TEST_CASE(payable_fallback_unction)
+BOOST_AUTO_TEST_CASE(payable_fallback_function)
{
char const* sourceCode = R"(
contract test {
@@ -703,6 +705,32 @@ BOOST_AUTO_TEST_CASE(payable_fallback_unction)
checkInterface(sourceCode, interface);
}
+BOOST_AUTO_TEST_CASE(function_type)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function g(function(uint) external returns (uint) x) {}
+ }
+ )";
+
+ char const* interface = R"(
+ [
+ {
+ "constant" : false,
+ "payable": false,
+ "inputs": [{
+ "name": "x",
+ "type": "function"
+ }],
+ "name": "g",
+ "outputs": [],
+ "type" : "function"
+ }
+ ]
+ )";
+ checkInterface(sourceCode, interface);
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 8600443d..6478ea86 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>
@@ -353,6 +353,34 @@ BOOST_AUTO_TEST_CASE(while_loop)
testSolidityAgainstCppOnRange("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";
+ compileAndRun(sourceCode);
+
+ auto do_while_loop_cpp = [](u256 const& n) -> u256
+ {
+ u256 nfac = 1;
+ u256 i = 2;
+ do
+ {
+ nfac *= i++;
+ }
+ while (i <= n);
+
+ return nfac;
+ };
+
+ testSolidityAgainstCppOnRange("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
@@ -1309,6 +1337,7 @@ 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"
@@ -1320,6 +1349,7 @@ BOOST_AUTO_TEST_CASE(balance)
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"
@@ -1535,6 +1565,7 @@ 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"
@@ -1647,6 +1678,7 @@ 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"
@@ -1663,6 +1695,7 @@ 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"
@@ -2928,24 +2961,24 @@ BOOST_AUTO_TEST_CASE(generic_call)
BOOST_AUTO_TEST_CASE(generic_callcode)
{
char const* sourceCode = R"**(
- contract receiver {
+ contract Receiver {
uint public received;
function receive(uint256 x) payable { received = x; }
}
- contract sender {
+ contract Sender {
uint public received;
- function sender() payable { }
+ function Sender() payable { }
function doSend(address rec) returns (uint d)
{
bytes4 signature = bytes4(bytes32(sha3("receive(uint256)")));
rec.callcode.value(2)(signature, 23);
- return receiver(rec).received();
+ return Receiver(rec).received();
}
}
)**";
- compileAndRun(sourceCode, 0, "receiver");
+ compileAndRun(sourceCode, 0, "Receiver");
u160 const c_receiverAddress = m_contractAddress;
- compileAndRun(sourceCode, 50, "sender");
+ compileAndRun(sourceCode, 50, "Sender");
u160 const c_senderAddress = m_contractAddress;
BOOST_CHECK(callContractFunction("doSend(address)", c_receiverAddress) == encodeArgs(0));
BOOST_CHECK(callContractFunction("received()") == encodeArgs(23));
@@ -2960,16 +2993,18 @@ BOOST_AUTO_TEST_CASE(generic_callcode)
BOOST_AUTO_TEST_CASE(generic_delegatecall)
{
char const* sourceCode = R"**(
- contract receiver {
+ contract Receiver {
uint public received;
address public sender;
uint public value;
+ function Receiver() payable {}
function receive(uint256 x) payable { received = x; sender = msg.sender; value = msg.value; }
}
- contract sender {
+ contract Sender {
uint public received;
address public sender;
uint public value;
+ function Sender() payable {}
function doSend(address rec) payable
{
bytes4 signature = bytes4(bytes32(sha3("receive(uint256)")));
@@ -2977,9 +3012,9 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall)
}
}
)**";
- compileAndRun(sourceCode, 0, "receiver");
+ compileAndRun(sourceCode, 0, "Receiver");
u160 const c_receiverAddress = m_contractAddress;
- compileAndRun(sourceCode, 50, "sender");
+ compileAndRun(sourceCode, 50, "Sender");
u160 const c_senderAddress = m_contractAddress;
BOOST_CHECK(m_sender != c_senderAddress); // just for sanity
BOOST_CHECK(callContractFunctionWithValue("doSend(address)", 11, c_receiverAddress) == encodeArgs());
@@ -3314,6 +3349,42 @@ BOOST_AUTO_TEST_CASE(using_enums)
BOOST_CHECK(callContractFunction("getChoice()") == encodeArgs(2));
}
+BOOST_AUTO_TEST_CASE(enum_explicit_overflow)
+{
+ char const* sourceCode = R"(
+ contract test {
+ enum ActionChoices { GoLeft, GoRight, GoStraight }
+ function test()
+ {
+ }
+ function getChoiceExp(uint x) returns (uint d)
+ {
+ choice = ActionChoices(x);
+ d = uint256(choice);
+ }
+ function getChoiceFromSigned(int x) returns (uint d)
+ {
+ choice = ActionChoices(x);
+ d = uint256(choice);
+ }
+ function getChoiceFromNegativeLiteral() returns (uint d)
+ {
+ choice = ActionChoices(-1);
+ d = uint256(choice);
+ }
+ ActionChoices choice;
+ }
+ )";
+ compileAndRun(sourceCode);
+ // These should throw
+ BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 3) == encodeArgs());
+ BOOST_CHECK(callContractFunction("getChoiceFromSigned(int256)", -1) == encodeArgs());
+ BOOST_CHECK(callContractFunction("getChoiceFromNegativeLiteral()") == encodeArgs());
+ // These should work
+ BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 2) == encodeArgs(2));
+ BOOST_CHECK(callContractFunction("getChoiceExp(uint256)", 0) == encodeArgs(0));
+}
+
BOOST_AUTO_TEST_CASE(using_contract_enums_with_explicit_contract_name)
{
char const* sourceCode = R"(
@@ -4435,6 +4506,163 @@ 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"(
+ contract C {
+ enum X { A, B }
+
+ function test_return() returns (X) {
+ X garbled;
+ assembly {
+ garbled := 5
+ }
+ return garbled;
+ }
+ function test_inline_assignment() returns (X _ret) {
+ assembly {
+ _ret := 5
+ }
+ }
+ function test_assignment() returns (X _ret) {
+ X tmp;
+ assembly {
+ tmp := 5
+ }
+ _ret = tmp;
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ // both should throw
+ BOOST_CHECK(callContractFunction("test_return()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("test_inline_assignment()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("test_assignment()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(invalid_enum_as_external_arg)
+{
+ char const* sourceCode = R"(
+ contract C {
+ enum X { A, B }
+
+ function tested (X x) returns (uint) {
+ return 1;
+ }
+
+ function test() returns (uint) {
+ X garbled;
+
+ assembly {
+ garbled := 5
+ }
+
+ return this.tested(garbled);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ // should throw
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs());
+}
+
+
BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)
{
// bug #1798
@@ -4693,6 +4921,7 @@ BOOST_AUTO_TEST_CASE(failing_send)
}
}
contract Main {
+ function Main() payable {}
function callHelper(address _a) returns (bool r, uint bal) {
r = !_a.send(5);
bal = this.balance;
@@ -4715,6 +4944,7 @@ BOOST_AUTO_TEST_CASE(send_zero_ether)
}
}
contract Main {
+ function Main() payable {}
function s() returns (bool) {
var r = new Receiver();
return r.send(0);
@@ -6216,6 +6446,7 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library)
char const* sourceCode = R"(
library lib {}
contract c {
+ function c() payable {}
function f(address x) returns (bool) {
return x.send(1);
}
@@ -6325,6 +6556,20 @@ BOOST_AUTO_TEST_CASE(decayed_tuple)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2)));
}
+BOOST_AUTO_TEST_CASE(inline_tuple_with_rational_numbers)
+{
+ char const* sourceCode = R"(
+ contract c {
+ function f() returns (int8) {
+ int8[5] memory foo3 = [int8(1), -1, 0, 0, 0];
+ return foo3[0];
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1)));
+}
+
BOOST_AUTO_TEST_CASE(destructuring_assignment)
{
char const* sourceCode = R"(
@@ -7140,6 +7385,7 @@ BOOST_AUTO_TEST_CASE(failed_create)
contract D { function D() payable {} }
contract C {
uint public x;
+ function C() payable {}
function f(uint amount) returns (address) {
x++;
return (new D).value(amount)();
@@ -7253,7 +7499,7 @@ BOOST_AUTO_TEST_CASE(mutex)
}
contract Fund is mutexed {
uint shares;
- function Fund() { shares = msg.value; }
+ function Fund() payable { shares = msg.value; }
function withdraw(uint amount) protected returns (uint) {
// NOTE: It is very bad practice to write this function this way.
// Please refer to the documentation of how to do this properly.
@@ -7467,6 +7713,568 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call)
BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7)));
}
+BOOST_AUTO_TEST_CASE(calling_uninitialized_function)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function intern() returns (uint) {
+ function (uint) internal returns (uint) x;
+ x(2);
+ return 7;
+ }
+ function extern() returns (uint) {
+ function (uint) external returns (uint) x;
+ x(2);
+ return 7;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ // This should throw exceptions
+ BOOST_CHECK(callContractFunction("intern()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("extern()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(calling_uninitialized_function_in_detail)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function() internal returns (uint) x;
+ int mutex;
+ function t() returns (uint) {
+ if (mutex > 0)
+ return 7;
+ mutex = 1;
+ // Avoid re-executing this function if we jump somewhere.
+ x();
+ return 2;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(pass_function_types_internally)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint x) returns (uint) {
+ return eval(g, x);
+ }
+ function eval(function(uint) returns (uint) x, uint a) internal returns (uint) {
+ return x(a);
+ }
+ function g(uint x) returns (uint) { return x + 1; }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8)));
+}
+
+BOOST_AUTO_TEST_CASE(pass_function_types_externally)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f(uint x) returns (uint) {
+ return this.eval(this.g, x);
+ }
+ function f2(uint x) returns (uint) {
+ return eval(this.g, x);
+ }
+ function eval(function(uint) external returns (uint) x, uint a) returns (uint) {
+ return x(a);
+ }
+ function g(uint x) returns (uint) { return x + 1; }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256)", 7) == encodeArgs(u256(8)));
+ BOOST_CHECK(callContractFunction("f2(uint256)", 7) == encodeArgs(u256(8)));
+}
+
+BOOST_AUTO_TEST_CASE(receive_external_function_type)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function g() returns (uint) { return 7; }
+ function f(function() external returns (uint) g) returns (uint) {
+ return g();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction(
+ "f(function)",
+ m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0)
+ ) == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(return_external_function_type)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function g() {}
+ function f() returns (function() external) {
+ return this.g;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(
+ callContractFunction("f()") ==
+ m_contractAddress.asBytes() + FixedHash<4>(dev::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0)
+ );
+}
+
+BOOST_AUTO_TEST_CASE(store_function)
+{
+ char const* sourceCode = R"(
+ contract Other {
+ function addTwo(uint x) returns (uint) { return x + 2; }
+ }
+ contract C {
+ function (function (uint) external returns (uint)) returns (uint) ev;
+ function (uint) external returns (uint) x;
+ function store(function(uint) external returns (uint) y) {
+ x = y;
+ }
+ function eval(function(uint) external returns (uint) y) returns (uint) {
+ return y(7);
+ }
+ function t() returns (uint) {
+ ev = eval;
+ this.store((new Other()).addTwo);
+ return ev(x);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(9)));
+}
+
+BOOST_AUTO_TEST_CASE(store_function_in_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public result_in_constructor;
+ function (uint) internal returns (uint) x;
+ function C () {
+ x = double;
+ result_in_constructor = use(2);
+ }
+ function double(uint _arg) returns (uint _ret) {
+ _ret = _arg * 2;
+ }
+ function use(uint _arg) returns (uint) {
+ return x(_arg);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("use(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6)));
+ BOOST_CHECK(callContractFunction("result_in_constructor()") == encodeArgs(u256(4)));
+}
+
+// TODO: store bound internal library functions
+
+BOOST_AUTO_TEST_CASE(store_internal_unused_function_in_constructor)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function () internal returns (uint) x;
+ function C () {
+ x = unused;
+ }
+ function unused() internal returns (uint) {
+ return 7;
+ }
+ function t() returns (uint) {
+ return x();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(store_internal_unused_library_function_in_constructor)
+{
+ char const* sourceCode = R"(
+ library L { function x() internal returns (uint) { return 7; } }
+ contract C {
+ function () internal returns (uint) x;
+ function C () {
+ x = L.x;
+ }
+ function t() returns (uint) {
+ return x();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("t()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime)
+{
+ char const* sourceCode = R"(
+ contract C {
+ uint public initial;
+ function C() {
+ initial = double(2);
+ }
+ function double(uint _arg) returns (uint _ret) {
+ _ret = _arg * 2;
+ }
+ function runtime(uint _arg) returns (uint) {
+ return double(_arg);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("runtime(uint256)", encodeArgs(u256(3))) == encodeArgs(u256(6)));
+ BOOST_CHECK(callContractFunction("initial()") == encodeArgs(u256(4)));
+}
+
+BOOST_AUTO_TEST_CASE(same_function_in_construction_and_runtime_equality_check)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function (uint) internal returns (uint) x;
+ function C() {
+ x = double;
+ }
+ function test() returns (bool) {
+ return x == double;
+ }
+ function double(uint _arg) returns (uint _ret) {
+ _ret = _arg * 2;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(true));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_library_internal)
+{
+ char const* sourceCode = R"(
+ library Utils {
+ function reduce(uint[] memory array, function(uint, uint) returns (uint) f, uint init) internal returns (uint) {
+ for (uint i = 0; i < array.length; i++) {
+ init = f(array[i], init);
+ }
+ return init;
+ }
+ function sum(uint a, uint b) internal returns (uint) {
+ return a + b;
+ }
+ }
+ contract C {
+ function f(uint[] x) returns (uint) {
+ return Utils.reduce(x, Utils.sum, 0);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f(uint256[])", 0x20, 3, u256(1), u256(7), u256(3)) == encodeArgs(u256(11)));
+}
+
+
+BOOST_AUTO_TEST_CASE(call_function_returning_function)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function f0() returns (uint) {
+ return 2;
+ }
+ function f1() internal returns (function() returns (uint)) {
+ return f0;
+ }
+ function f2() internal returns (function() returns (function () returns (uint))) {
+ return f1;
+ }
+ function f3() internal returns (function() returns (function () returns (function () returns (uint))))
+ {
+ return f2;
+ }
+ function f() returns (uint) {
+ function() returns(function() returns(function() returns(function() returns(uint)))) x;
+ x = f3;
+ return x()()()();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "test");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2)));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_of_functions)
+{
+ char const* sourceCode = R"(
+ contract Flow {
+ bool public success;
+
+ mapping (address => function () internal) stages;
+
+ function stage0() internal {
+ stages[msg.sender] = stage1;
+ }
+
+ function stage1() internal {
+ stages[msg.sender] = stage2;
+ }
+
+ function stage2() internal {
+ success = true;
+ }
+
+ function Flow() {
+ stages[msg.sender] = stage0;
+ }
+
+ function f() returns (uint) {
+ stages[msg.sender]();
+ return 7;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "Flow");
+ BOOST_CHECK(callContractFunction("success()") == encodeArgs(false));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("success()") == encodeArgs(false));
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("success()") == encodeArgs(true));
+}
+
+BOOST_AUTO_TEST_CASE(packed_functions)
+{
+ char const* sourceCode = R"(
+ contract C {
+ // these should take the same slot
+ function() returns (uint) a;
+ function() external returns (uint) b;
+ function() external returns (uint) c;
+ function() returns (uint) d;
+ uint8 public x;
+
+ function set() {
+ x = 2;
+ d = g;
+ c = this.h;
+ b = this.h;
+ a = g;
+ }
+ function t1() returns (uint) {
+ return a();
+ }
+ function t2() returns (uint) {
+ return b();
+ }
+ function t3() returns (uint) {
+ return a();
+ }
+ function t4() returns (uint) {
+ return b();
+ }
+ function g() returns (uint) {
+ return 7;
+ }
+ function h() returns (uint) {
+ return 8;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("set()") == encodeArgs());
+ BOOST_CHECK(callContractFunction("t1()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(8)));
+ BOOST_CHECK(callContractFunction("t3()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("t4()") == encodeArgs(u256(8)));
+ BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(2)));
+}
+
+BOOST_AUTO_TEST_CASE(function_memory_array)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function a(uint x) returns (uint) { return x + 1; }
+ function b(uint x) returns (uint) { return x + 2; }
+ function c(uint x) returns (uint) { return x + 3; }
+ function d(uint x) returns (uint) { return x + 5; }
+ function e(uint x) returns (uint) { return x + 8; }
+ function test(uint x, uint i) returns (uint) {
+ function(uint) internal returns (uint)[] memory arr =
+ new function(uint) internal returns (uint)[](10);
+ arr[0] = a;
+ arr[1] = b;
+ arr[2] = c;
+ arr[3] = d;
+ arr[4] = e;
+ return arr[i](x);
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)) == encodeArgs(u256(11)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)) == encodeArgs(u256(12)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)) == encodeArgs(u256(13)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)) == encodeArgs(u256(15)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)) == encodeArgs(u256(18)));
+ BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)) == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(function_delete_storage)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function a() returns (uint) { return 7; }
+ function() internal returns (uint) y;
+ function set() returns (uint) {
+ y = a;
+ return y();
+ }
+ function d() returns (uint) {
+ delete y;
+ return 1;
+ }
+ function ca() returns (uint) {
+ return y();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("set()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("ca()") == encodeArgs(u256(7)));
+ BOOST_CHECK(callContractFunction("d()") == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("ca()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(function_delete_stack)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function a() returns (uint) { return 7; }
+ function test() returns (uint) {
+ var y = a;
+ delete y;
+ y();
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs());
+}
+
+BOOST_AUTO_TEST_CASE(copy_function_storage_array)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function() internal returns (uint)[] x;
+ function() internal returns (uint)[] y;
+ function test() returns (uint) {
+ x.length = 10;
+ x[9] = a;
+ y = x;
+ return y[9]();
+ }
+ function a() returns (uint) {
+ return 7;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(function_array_cross_calls)
+{
+ char const* sourceCode = R"(
+ contract D {
+ function f(function() external returns (function() external returns (uint))[] x)
+ returns (function() external returns (uint)[3] r)
+ {
+ r[0] = x[0]();
+ r[1] = x[1]();
+ r[2] = x[2]();
+ }
+ }
+ contract C {
+ function test() returns (uint, uint, uint) {
+ function() external returns (function() external returns (uint))[] memory x =
+ new function() external returns (function() external returns (uint))[](10);
+ for (uint i = 0; i < x.length; i ++)
+ x[i] = this.h;
+ x[0] = this.htwo;
+ var y = (new D()).f(x);
+ return (y[0](), y[1](), y[2]());
+ }
+ function e() returns (uint) { return 5; }
+ function f() returns (uint) { return 6; }
+ function g() returns (uint) { return 7; }
+ uint counter;
+ function h() returns (function() external returns (uint)) {
+ return counter++ == 0 ? this.f : this.g;
+ }
+ function htwo() returns (function() external returns (uint)) {
+ return this.e;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(5), u256(6), u256(7)));
+}
+
+BOOST_AUTO_TEST_CASE(copy_internal_function_array_to_storage)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function() internal returns (uint)[20] x;
+ int mutex;
+ function one() returns (uint) {
+ function() internal returns (uint)[20] xmem;
+ x = xmem;
+ return 3;
+ }
+ function two() returns (uint) {
+ if (mutex > 0)
+ return 7;
+ mutex = 1;
+ // If this test fails, it might re-execute this function.
+ x[0]();
+ return 2;
+ }
+ }
+ )";
+
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("one()") == encodeArgs(u256(3)));
+ BOOST_CHECK(callContractFunction("two()") == encodeArgs());
+}
+
BOOST_AUTO_TEST_CASE(shift_constant_left)
{
char const* sourceCode = R"(
@@ -7553,6 +8361,21 @@ BOOST_AUTO_TEST_CASE(packed_storage_overflow)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x1234), u256(0), u256(0), u256(0xfffe)));
}
+BOOST_AUTO_TEST_CASE(inline_assembly_invalidjumplabel)
+{
+ char const* sourceCode = R"(
+ contract C {
+ function f() {
+ assembly {
+ jump(invalidJumpLabel)
+ }
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "C");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs());
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp
index 02548121..00943367 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>
@@ -46,6 +46,7 @@ string getIPCSocketPath()
ExecutionFramework::ExecutionFramework() :
m_rpc(RPCSession::instance(getIPCSocketPath())),
+ m_optimize(dev::test::Options::get().optimize),
m_sender(m_rpc.account(0))
{
m_rpc.test_rewindToBlock(0);
diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h
index 7d44edaf..b2ea9c08 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>
diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp
index e9a05745..cab9f09f 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>
@@ -325,12 +325,12 @@ BOOST_AUTO_TEST_CASE(arithmetics)
byte(Instruction::ADD),
byte(Instruction::DUP2),
byte(Instruction::ISZERO),
- byte(Instruction::PUSH1), 0x2,
+ byte(Instruction::PUSH1), 0x0,
byte(Instruction::JUMPI),
byte(Instruction::MOD),
byte(Instruction::DUP2),
byte(Instruction::ISZERO),
- byte(Instruction::PUSH1), 0x2,
+ byte(Instruction::PUSH1), 0x0,
byte(Instruction::JUMPI),
byte(Instruction::DIV),
byte(Instruction::MUL)});
@@ -425,39 +425,6 @@ BOOST_AUTO_TEST_CASE(assignment)
BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
}
-BOOST_AUTO_TEST_CASE(function_call)
-{
- char const* sourceCode = "contract test {\n"
- " function f(uint a, uint b) { a += g(a + 1, b) * 2; }\n"
- " function g(uint a, uint b) returns (uint c) {}\n"
- "}\n";
- bytes code = compileFirstExpression(sourceCode, {{"test", "g"}},
- {{"test", "f", "a"}, {"test", "f", "b"}});
-
- // Stack: a, b
- bytes expectation({byte(Instruction::PUSH1), 0x02,
- byte(Instruction::PUSH1), 0x0c,
- byte(Instruction::PUSH1), 0x01,
- byte(Instruction::DUP5),
- byte(Instruction::ADD),
- // Stack here: a b 2 <ret label> (a+1)
- byte(Instruction::DUP4),
- byte(Instruction::PUSH1), 0x13,
- byte(Instruction::JUMP),
- byte(Instruction::JUMPDEST),
- // Stack here: a b 2 g(a+1, b)
- byte(Instruction::MUL),
- // Stack here: a b g(a+1, b)*2
- byte(Instruction::DUP3),
- byte(Instruction::ADD),
- // Stack here: a b a+g(a+1, b)*2
- byte(Instruction::SWAP2),
- byte(Instruction::POP),
- byte(Instruction::DUP2),
- byte(Instruction::JUMPDEST)});
- BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end());
-}
-
BOOST_AUTO_TEST_CASE(negative_literals_8bits)
{
char const* sourceCode = "contract test {\n"
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 640cc108..7a132068 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>
@@ -31,6 +31,7 @@
#include <libsolidity/analysis/GlobalContext.h>
#include <libsolidity/analysis/TypeChecker.h>
#include "../TestHelper.h"
+#include "ErrorCheck.h"
using namespace std;
@@ -44,7 +45,7 @@ namespace test
namespace
{
-pair<ASTPointer<SourceUnit>, std::shared_ptr<Error::Type const>>
+pair<ASTPointer<SourceUnit>, std::shared_ptr<Error const>>
parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true)
{
// Silence compiler version warning
@@ -57,11 +58,11 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false,
{
sourceUnit = parser.parse(std::make_shared<Scanner>(CharStream(source)));
if(!sourceUnit)
- return make_pair(sourceUnit, nullptr);
+ BOOST_FAIL("Parsing failed in type checker test.");
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);
@@ -96,7 +97,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false,
(_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 +109,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,7 +131,7 @@ 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)
{
auto sourceAndError = parseAnalyseAndReturnError(_source, _warning);
BOOST_REQUIRE(!!sourceAndError.second);
@@ -160,6 +161,28 @@ static FunctionTypePointer retrieveFunctionBySignature(
}
+#define CHECK_ERROR_OR_WARNING(text, typ, substring, warning) \
+do \
+{ \
+ Error err = expectError((text), (warning)); \
+ 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)
+
+// [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)
+
+// [checkSuccess(text)] asserts that the compilation down to typechecking succeeds.
+#define CHECK_SUCCESS(text) do { BOOST_CHECK(success((text))); } while(0)
+
+
BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution)
BOOST_AUTO_TEST_CASE(smoke_test)
@@ -168,7 +191,7 @@ BOOST_AUTO_TEST_CASE(smoke_test)
" uint256 stateVariable1;\n"
" function fun(uint256 arg1) { uint256 y; }"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(double_stateVariable_declaration)
@@ -177,7 +200,7 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration)
" uint256 variable;\n"
" uint128 variable;\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(double_function_declaration)
@@ -186,7 +209,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration)
" function fun() { uint x; }\n"
" function fun() { uint x; }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(double_variable_declaration)
@@ -194,7 +217,7 @@ 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);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(name_shadowing)
@@ -203,7 +226,7 @@ BOOST_AUTO_TEST_CASE(name_shadowing)
" uint256 variable;\n"
" function f() { uint32 variable ; }"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(name_references)
@@ -212,7 +235,7 @@ BOOST_AUTO_TEST_CASE(name_references)
" uint256 variable;\n"
" function f(uint256 arg) returns (uint out) { f(variable); test; out; }"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(undeclared_name)
@@ -221,7 +244,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name)
" uint256 variable;\n"
" function f(uint256 arg) { f(notfound); }"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(reference_to_later_declaration)
@@ -230,7 +253,7 @@ BOOST_AUTO_TEST_CASE(reference_to_later_declaration)
" function g() { f(); }"
" function f() { }"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive)
@@ -241,7 +264,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive)
" MyStructName x;\n"
" }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
@@ -256,7 +279,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
" MyStructName1 x;\n"
" }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive)
@@ -267,7 +290,7 @@ 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)
@@ -279,7 +302,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping)
" mapping(uint => MyStructName1) x;\n"
" }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_inference_smoke_test)
@@ -287,7 +310,7 @@ 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));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_checking_return)
@@ -295,7 +318,7 @@ 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));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number)
@@ -303,7 +326,7 @@ 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);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type)
@@ -311,7 +334,7 @@ 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);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(type_checking_function_call)
@@ -320,7 +343,7 @@ BOOST_AUTO_TEST_CASE(type_checking_function_call)
" 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));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_conversion_for_comparison)
@@ -328,7 +351,7 @@ 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));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid)
@@ -336,7 +359,7 @@ 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);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion)
@@ -344,7 +367,7 @@ 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));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(large_string_literal)
@@ -352,7 +375,7 @@ BOOST_AUTO_TEST_CASE(large_string_literal)
char const* text = "contract test {\n"
" function f() { var x = \"123456789012345678901234567890123\"; }"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(balance)
@@ -362,7 +385,7 @@ BOOST_AUTO_TEST_CASE(balance)
" uint256 x = address(0).balance;\n"
" }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(balance_invalid)
@@ -372,7 +395,7 @@ BOOST_AUTO_TEST_CASE(balance_invalid)
" address(0).balance = 7;\n"
" }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_to_mapping)
@@ -387,7 +410,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_mapping)
" data.map = a;\n"
" }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(assignment_to_struct)
@@ -402,7 +425,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_struct)
" data = a;\n"
" }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(returns_in_constructor)
@@ -411,7 +434,7 @@ BOOST_AUTO_TEST_CASE(returns_in_constructor)
" function test() returns (uint a) {\n"
" }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(forward_function_reference)
@@ -426,7 +449,7 @@ BOOST_AUTO_TEST_CASE(forward_function_reference)
" if (First(2).fun() == true) return 1;\n"
" }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(comparison_bitop_precedence)
@@ -436,7 +459,7 @@ BOOST_AUTO_TEST_CASE(comparison_bitop_precedence)
" return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6;\n"
" }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_no_implementation)
@@ -499,7 +522,7 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract)
function foo() { b = new base();}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional)
@@ -543,7 +566,7 @@ BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract)
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)
@@ -653,7 +676,7 @@ BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion)
}
function g (C c) external {}
})";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion)
@@ -667,7 +690,7 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion)
}
function g (C c) external {}
})";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion)
@@ -683,7 +706,7 @@ BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion)
g(a);
}
})";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion)
@@ -699,7 +722,7 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion)
g(a);
}
})";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(hash_collision_in_interface)
@@ -710,7 +733,7 @@ BOOST_AUTO_TEST_CASE(hash_collision_in_interface)
" function tgeo() {\n"
" }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(inheritance_basic)
@@ -722,7 +745,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 +758,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 +767,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance)
contract A is B { }
contract B is A { }
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(legal_override_direct)
@@ -753,7 +776,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 +786,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 +795,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 +804,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 +814,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 +824,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 +834,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 +843,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 +852,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 +863,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 +874,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 +891,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 +903,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 +914,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 +926,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 +937,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 +946,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 +955,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 +964,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 +973,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,7 +984,7 @@ 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)
@@ -1012,7 +1035,7 @@ BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor)
"uint256 foo;\n"
" function foo() {}\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(private_state_variable)
@@ -1045,7 +1068,7 @@ BOOST_AUTO_TEST_CASE(missing_state_variable)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
@@ -1058,7 +1081,7 @@ BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor)
"contract Child is Parent{\n"
" function foo() returns (uint256) { return Parent.m_aMember; }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only)
@@ -1069,7 +1092,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only)
Data public data;
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member)
@@ -1080,7 +1103,7 @@ BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member)
"contract Child is Parent{\n"
" function foo() returns (uint256) { return Parent.m_aMember; }\n"
"}\n";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1)
@@ -1094,7 +1117,7 @@ BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1)
"contract Child is Parent2{\n"
" function foo() returns (uint256) { return Parent2.m_aMember1; }\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2)
@@ -1109,7 +1132,7 @@ BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2)
" function foo() returns (uint256) { return Child.m_aMember2; }\n"
" uint256 public m_aMember3;\n"
"}\n";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function)
@@ -1120,7 +1143,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 +1154,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 +1164,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 +1174,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 +1185,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 +1197,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice)
function() { x = 3; }
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(fallback_function_inheritance)
@@ -1188,7 +1211,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_inheritance)
function() { x = 2; }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(event)
@@ -1198,7 +1221,7 @@ BOOST_AUTO_TEST_CASE(event)
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)
@@ -1207,7 +1230,7 @@ BOOST_AUTO_TEST_CASE(event_too_many_indexed)
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)
@@ -1216,7 +1239,7 @@ BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed)
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)
@@ -1225,7 +1248,7 @@ BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed)
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)
@@ -1235,7 +1258,7 @@ BOOST_AUTO_TEST_CASE(event_call)
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)
@@ -1247,7 +1270,7 @@ 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)
@@ -1257,7 +1280,7 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash)
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)
@@ -1269,7 +1292,7 @@ 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)
@@ -1281,7 +1304,7 @@ 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)
@@ -1293,7 +1316,7 @@ 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)
@@ -1305,7 +1328,7 @@ 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)
@@ -1314,7 +1337,7 @@ BOOST_AUTO_TEST_CASE(error_count_in_named_args)
" 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);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(empty_in_named_args)
@@ -1323,7 +1346,7 @@ BOOST_AUTO_TEST_CASE(empty_in_named_args)
" 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);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args)
@@ -1332,7 +1355,7 @@ BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args)
" 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);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args)
@@ -1341,7 +1364,7 @@ BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args)
" 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);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter)
@@ -1351,7 +1374,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter)
function f(uint){
}
})";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
@@ -1361,7 +1384,7 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter)
function f() returns(bool){
}
})";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
@@ -1372,7 +1395,7 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one)
return k;
}
})";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one)
@@ -1383,13 +1406,13 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one)
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);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units)
@@ -1412,7 +1435,7 @@ BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units)
}
uint256 a;
})";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big)
@@ -1421,7 +1444,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big)
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)
@@ -1436,7 +1459,7 @@ BOOST_AUTO_TEST_CASE(enum_member_access)
ActionChoices choices;
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts)
@@ -1451,7 +1474,7 @@ BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(enum_invalid_member_access)
@@ -1466,7 +1489,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_member_access)
ActionChoices choices;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access)
@@ -1481,7 +1504,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access)
ActionChoices choices;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay)
@@ -1498,7 +1521,7 @@ BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay)
uint64 b;
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay)
@@ -1515,7 +1538,7 @@ BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay)
ActionChoices b;
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay)
@@ -1532,7 +1555,22 @@ BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay)
uint64 b;
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay)
+{
+ char const* text = R"(
+ contract test {
+ enum Paper { Up, Down, Left, Right }
+ enum Ground { North, South, West, East }
+ function test()
+ {
+ Ground(Paper.Up);
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(enum_duplicate_values)
@@ -1542,7 +1580,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)
@@ -1559,7 +1597,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)
@@ -1572,7 +1610,7 @@ BOOST_AUTO_TEST_CASE(private_visibility)
function g() { f(); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ CHECK_ERROR(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access)
@@ -1585,7 +1623,7 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access)
function g() { base.f(); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_visibility)
@@ -1596,7 +1634,7 @@ BOOST_AUTO_TEST_CASE(external_visibility)
function g() { f(); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ CHECK_ERROR(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(external_base_visibility)
@@ -1609,7 +1647,7 @@ BOOST_AUTO_TEST_CASE(external_base_visibility)
function g() { base.f(); }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_argument_assign)
@@ -1619,7 +1657,7 @@ BOOST_AUTO_TEST_CASE(external_argument_assign)
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)
@@ -1629,7 +1667,7 @@ BOOST_AUTO_TEST_CASE(external_argument_increment)
function f(uint a) external { a++; }
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError);
+ CHECK_ERROR(sourceCode, TypeError, "");
}
BOOST_AUTO_TEST_CASE(external_argument_delete)
@@ -1639,7 +1677,7 @@ BOOST_AUTO_TEST_CASE(external_argument_delete)
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)
@@ -1661,7 +1699,7 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length)
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)
@@ -1672,7 +1710,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1)
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)
@@ -1683,7 +1721,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2)
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)
@@ -1694,7 +1732,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible)
uint8[] b;
function f() { a = b; }
})";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic)
@@ -1705,7 +1743,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic)
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)
@@ -1716,7 +1754,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static)
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)
@@ -1725,7 +1763,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int)
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)
@@ -1734,7 +1772,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string)
contract c {
uint a = "abc";
})";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName)
@@ -1860,7 +1898,7 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable)
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)
@@ -1870,7 +1908,7 @@ BOOST_AUTO_TEST_CASE(complex_const_variable)
contract Foo {
mapping(uint => bool) constant mapVar;
})";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(uninitialized_const_variable)
@@ -1879,7 +1917,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable)
contract Foo {
uint constant y;
})";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve)
@@ -1891,7 +1929,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)
@@ -1904,7 +1942,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)
@@ -1927,7 +1965,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)
@@ -1941,7 +1979,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)
@@ -1954,7 +1992,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)
@@ -1965,7 +2003,7 @@ 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)
@@ -1976,7 +2014,7 @@ BOOST_AUTO_TEST_CASE(equal_overload)
function test(uint a) external {}
}
)";
- BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError);
+ CHECK_ERROR(sourceCode, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(uninitialized_var)
@@ -1986,7 +2024,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)
@@ -2000,6 +2038,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"(
@@ -2008,7 +2066,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)
@@ -2019,7 +2077,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)
@@ -2029,7 +2087,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)
@@ -2049,7 +2107,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)
@@ -2069,7 +2127,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)
@@ -2079,7 +2137,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)
@@ -2087,15 +2145,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)
@@ -2103,15 +2161,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)
@@ -2119,11 +2177,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)
@@ -2133,7 +2191,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)
@@ -2143,7 +2201,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)
@@ -2169,7 +2227,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)
@@ -2183,7 +2241,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)
@@ -2200,7 +2258,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)
@@ -2214,7 +2272,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)
@@ -2241,7 +2299,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)
@@ -2270,7 +2328,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)
@@ -2285,7 +2343,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)
@@ -2298,7 +2356,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)
@@ -2352,7 +2410,7 @@ BOOST_AUTO_TEST_CASE(literal_strings)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp)
@@ -2364,7 +2422,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)
@@ -2379,7 +2437,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)
@@ -2396,7 +2454,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)
@@ -2405,7 +2463,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)
@@ -2414,7 +2472,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)
@@ -2422,7 +2480,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)
@@ -2430,7 +2488,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)
@@ -2445,7 +2503,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)
@@ -2455,7 +2513,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)
@@ -2469,7 +2527,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)
@@ -2479,7 +2537,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)
@@ -2498,7 +2556,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)
@@ -2509,7 +2567,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)
@@ -2519,7 +2577,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)
@@ -2529,7 +2587,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)
@@ -2537,7 +2595,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)
@@ -2557,7 +2615,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)
@@ -2568,7 +2626,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)
{
@@ -2578,7 +2636,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)
@@ -2589,7 +2647,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)
@@ -2600,7 +2658,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)
@@ -2615,7 +2673,7 @@ BOOST_AUTO_TEST_CASE(tuples)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(tuples_empty_components)
@@ -2627,7 +2685,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)
@@ -2638,7 +2696,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)
@@ -2649,7 +2707,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)
@@ -2670,7 +2728,7 @@ BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_library)
@@ -2681,7 +2739,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)
@@ -2692,7 +2750,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)
@@ -2706,7 +2764,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)
@@ -2720,7 +2778,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)
@@ -2735,7 +2793,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_overload)
@@ -2754,7 +2812,7 @@ BOOST_AUTO_TEST_CASE(using_for_overload)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_by_name)
@@ -2769,7 +2827,7 @@ BOOST_AUTO_TEST_CASE(using_for_by_name)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(using_for_mismatch)
@@ -2783,7 +2841,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)
@@ -2799,7 +2857,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)
@@ -2814,7 +2883,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)
@@ -2830,7 +2899,7 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(create_memory_arrays)
@@ -2848,7 +2917,7 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(mapping_in_memory_array)
@@ -2860,7 +2929,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)
@@ -2872,7 +2941,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)
@@ -2884,7 +2953,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)
@@ -2895,7 +2964,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)
@@ -2911,7 +2980,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)
@@ -2926,7 +2995,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)
@@ -2939,7 +3008,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)
@@ -2952,7 +3021,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)
@@ -2964,7 +3033,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)
@@ -2976,7 +3045,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)
@@ -2992,7 +3061,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)
@@ -3004,7 +3073,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)
@@ -3016,7 +3085,7 @@ BOOST_AUTO_TEST_CASE(dynamic_inline_array)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(lvalues_as_inline_array)
@@ -3029,7 +3098,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)
@@ -3042,7 +3111,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)
@@ -3055,7 +3124,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)
@@ -3070,7 +3139,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)
@@ -3082,7 +3151,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)
@@ -3096,7 +3165,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct)
@@ -3116,7 +3185,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct)
}
}
)";
- BOOST_CHECK(expectError(text) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type)
@@ -3131,7 +3200,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)
@@ -3149,7 +3218,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)
@@ -3164,7 +3233,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)
@@ -3246,7 +3315,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)
@@ -3261,7 +3330,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)
@@ -3274,7 +3343,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)
@@ -3290,7 +3359,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)
@@ -3328,7 +3397,7 @@ BOOST_AUTO_TEST_CASE(bytes10abc_is_identifier)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(int10abc_is_identifier)
@@ -3341,7 +3410,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)
@@ -3425,7 +3494,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)
@@ -3438,7 +3507,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)
@@ -3451,7 +3520,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)
@@ -3477,7 +3546,7 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert)
@@ -3492,7 +3561,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)
@@ -3509,7 +3578,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)
@@ -3548,7 +3617,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)
@@ -3610,7 +3679,7 @@ BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(fixed_points_inside_structs)
@@ -3624,7 +3693,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)
@@ -3636,7 +3705,7 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_types)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_array_rationals)
@@ -3648,7 +3717,7 @@ BOOST_AUTO_TEST_CASE(inline_array_rationals)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(rational_index_access)
@@ -3679,7 +3748,7 @@ BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(rational_as_exponent_value)
@@ -3723,7 +3792,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)
@@ -3735,7 +3804,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)
@@ -3747,7 +3816,7 @@ BOOST_AUTO_TEST_CASE(var_handle_divided_integers)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation)
@@ -3808,7 +3877,7 @@ BOOST_AUTO_TEST_CASE(zero_handling)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(missing_bool_conversion)
@@ -3820,7 +3889,7 @@ BOOST_AUTO_TEST_CASE(missing_bool_conversion)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction)
@@ -3832,7 +3901,7 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(signed_rational_modulus)
@@ -3846,7 +3915,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)
@@ -3871,7 +3940,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(unused_return_value_send)
@@ -3883,7 +3952,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)
@@ -3895,7 +3964,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)
@@ -3907,7 +3976,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)
@@ -3919,7 +3988,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)
@@ -3931,7 +4000,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)
@@ -3941,7 +4010,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)
@@ -3951,7 +4020,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)
@@ -3961,7 +4030,7 @@ BOOST_AUTO_TEST_CASE(payable_external)
function f() payable external {}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(payable_internal)
@@ -3971,7 +4040,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)
@@ -3981,7 +4050,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)
@@ -3990,7 +4059,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)
@@ -3999,7 +4068,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)
@@ -4007,7 +4076,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)
@@ -4015,12 +4084,12 @@ BOOST_AUTO_TEST_CASE(calling_payable)
char const* text = R"(
contract receiver { function pay() payable {} }
contract test {
- funciton f() { (new receiver()).pay.value(10)(); }
- recevier r = new receiver();
+ function f() { (new receiver()).pay.value(10)(); }
+ receiver r = new receiver();
function g() { r.pay.value(10)(); }
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(calling_nonpayable)
@@ -4031,7 +4100,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)
@@ -4047,7 +4116,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)
@@ -4056,7 +4125,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)
@@ -4064,7 +4133,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)
@@ -4074,7 +4143,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)
@@ -4084,7 +4153,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)
@@ -4095,7 +4164,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
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)
@@ -4114,7 +4183,232 @@ 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)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ function(uint) returns (uint) x;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(function_type_parameter)
+{
+ char const* text = R"(
+ contract C {
+ function f(function(uint) external returns (uint) g) returns (function(uint) external returns (uint)) {
+ return g;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(function_type_returned)
+{
+ char const* text = R"(
+ contract C {
+ function f() returns (function(uint) external returns (uint) g) {
+ return g;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(private_function_type)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ function(uint) private returns (uint) x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(public_function_type)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ function(uint) public returns (uint) x;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(payable_internal_function_type)
+{
+ char const* text = R"(
+ contract C {
+ function (uint) internal payable returns (uint) x;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type)
+{
+ char const* text = R"(
+ contract C {
+ function (uint) external returns (uint) x;
+ function f() {
+ x.value(2)();
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(external_function_type_returning_internal)
+{
+ char const* text = R"(
+ contract C {
+ function() external returns (function () internal) x;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(external_function_type_taking_internal)
+{
+ char const* text = R"(
+ contract C {
+ function(function () internal) external x;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type)
+{
+ char const* text = R"(
+ contract C {
+ function (uint) external payable returns (uint) x;
+ function f() {
+ x.value(2)(1);
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter)
+{
+ // It should not be possible to give internal functions
+ // as parameters to external functions.
+ char const* text = R"(
+ contract C {
+ function f(function(uint) internal returns (uint) x) {
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function)
+{
+ // It should not be possible to return internal functions from external functions.
+ char const* text = R"(
+ contract C {
+ function f() returns (function(uint) internal returns (uint) x) {
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal)
+{
+ char const* text = R"(
+ library L {
+ function f(function(uint) internal returns (uint) x) internal {
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external)
+{
+ char const* text = R"(
+ library L {
+ function f(function(uint) internal returns (uint) x) {
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(function_type_arrays)
+{
+ char const* text = R"(
+ contract C {
+ function(uint) external returns (uint)[] public x;
+ function(uint) internal returns (uint)[10] y;
+ function f() {
+ function(uint) returns (uint)[10] memory a;
+ function(uint) returns (uint)[10] storage b = y;
+ function(uint) external returns (uint)[] memory c;
+ c = new function(uint) external returns (uint)[](200);
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(delete_function_type)
+{
+ char const* text = R"(
+ contract C {
+ function(uint) external returns (uint) x;
+ function(uint) internal returns (uint) y;
+ function f() {
+ delete x;
+ var a = y;
+ delete a;
+ delete y;
+ var c = f;
+ delete c;
+ function(uint) internal returns (uint) g;
+ delete g;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(delete_function_type_invalid)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ delete f;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
+}
+
+BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid)
+{
+ char const* text = R"(
+ contract C {
+ function f() {
+ delete this.f;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal)
@@ -4126,7 +4420,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)
@@ -4136,7 +4430,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)
@@ -4146,7 +4440,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)
@@ -4156,7 +4450,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)
@@ -4166,7 +4460,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)
@@ -4180,7 +4474,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)
@@ -4194,7 +4488,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)
@@ -4212,7 +4506,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
}
}
)";
- BOOST_CHECK(success(text));
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(inline_assembly_storage)
@@ -4227,7 +4521,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError);
+ CHECK_ERROR(text, DeclarationError, "");
}
BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
@@ -4245,7 +4539,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)
@@ -4258,7 +4552,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type)
}
}
)";
- BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
+ CHECK_ERROR(text, TypeError, "");
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index 1f74e928..ef69e85c 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>
@@ -45,21 +45,19 @@ public:
bool _userDocumentation
)
{
- std::string generatedDocumentationString;
ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parse("pragma solidity >=0.0;\n" + _code), "Parsing failed");
+ Json::Value generatedDocumentation;
if (_userDocumentation)
- generatedDocumentationString = m_compilerStack.metadata("", DocumentationType::NatspecUser);
+ generatedDocumentation = m_compilerStack.metadata("", DocumentationType::NatspecUser);
else
- generatedDocumentationString = m_compilerStack.metadata("", DocumentationType::NatspecDev);
- Json::Value generatedDocumentation;
- m_reader.parse(generatedDocumentationString, generatedDocumentation);
+ generatedDocumentation = m_compilerStack.metadata("", DocumentationType::NatspecDev);
Json::Value expectedDocumentation;
m_reader.parse(_expectedDocumentationString, expectedDocumentation);
BOOST_CHECK_MESSAGE(
expectedDocumentation == generatedDocumentation,
- "Expected " << _expectedDocumentationString <<
- "\n but got:\n" << generatedDocumentationString
+ "Expected " << expectedDocumentation.toStyledString() <<
+ "\n but got:\n" << generatedDocumentation.toStyledString()
);
}
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index 562b7859..a53a2638 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,17 +20,21 @@
* 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;
@@ -365,16 +369,6 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions)
// BOOST_CHECK_EQUAL(2, numSHA3s);
}
-BOOST_AUTO_TEST_CASE(successor_not_found_bug)
-{
- // This bug was caused because MSVC chose to use the u256->bool conversion
- // instead of u256->unsigned
- char const* sourceCode = R"(
- contract greeter { function greeter() {} }
- )";
- compileBothVersions(sourceCode);
-}
-
BOOST_AUTO_TEST_CASE(incorrect_storage_access_bug)
{
// This bug appeared because a sha3 operation with too low sequence number was used,
@@ -1131,6 +1125,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"(
@@ -1238,6 +1266,44 @@ BOOST_AUTO_TEST_CASE(inconsistency)
compareVersions("trigger()");
}
+BOOST_AUTO_TEST_CASE(dead_code_elimination_across_assemblies)
+{
+ // This tests that a runtime-function that is stored in storage in the constructor
+ // is not removed as part of dead code elimination.
+ char const* sourceCode = R"(
+ contract DCE {
+ function () internal returns (uint) stored;
+ function DCE() {
+ stored = f;
+ }
+ function f() internal returns (uint) { return 7; }
+ function test() returns (uint) { return stored(); }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("test()");
+}
+
+BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ uint256 public totalSupply = 100;
+ function f() returns (uint r) {
+ if (false)
+ r = totalSupply;
+ totalSupply -= 10;
+ }
+ function test() returns (uint) {
+ f();
+ return this.totalSupply();
+ }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("test()");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index a81a9828..a3217f08 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>
@@ -824,7 +824,7 @@ BOOST_AUTO_TEST_CASE(empty_enum_declaration)
contract c {
enum foo { }
})";
- BOOST_CHECK(successParse(text));
+ BOOST_CHECK(!successParse(text));
}
BOOST_AUTO_TEST_CASE(malformed_enum_declaration)
@@ -1241,6 +1241,115 @@ BOOST_AUTO_TEST_CASE(payable_accessor)
BOOST_CHECK(!successParse(text));
}
+BOOST_AUTO_TEST_CASE(function_type_in_expression)
+{
+ char const* text = R"(
+ contract test {
+ function f(uint x, uint y) returns (uint a) {}
+ function g() {
+ function (uint, uint) internal returns (uint) f1 = f;
+ }
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_as_storage_variable)
+{
+ char const* text = R"(
+ contract test {
+ function (uint, uint) internal returns (uint) f1;
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_modifiers)
+{
+ char const* text = R"(
+ contract test {
+ function (uint, uint) modifier1() returns (uint) f1;
+ }
+ )";
+ BOOST_CHECK(!successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_assignment)
+{
+ char const* text = R"(
+ contract test {
+ function f(uint x, uint y) returns (uint a) {}
+ function (uint, uint) internal returns (uint) f1 = f;
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_in_struct)
+{
+ char const* text = R"(
+ contract test {
+ struct S {
+ function (uint x, uint y) internal returns (uint a) f;
+ function (uint, uint) external returns (uint) g;
+ uint d;
+ }
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_as_parameter)
+{
+ char const* text = R"(
+ contract test {
+ function f(function(uint) external returns (uint) g) internal returns (uint a) {
+ return g(1);
+ }
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(calling_function)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ function() returns(function() returns(function() returns(function() returns(uint)))) x;
+ uint y;
+ y = x()()()();
+ }
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(mapping_and_array_of_functions)
+{
+ char const* text = R"(
+ contract test {
+ mapping (address => function() internal returns (uint)) a;
+ mapping (address => function() external) b;
+ mapping (address => function() external[]) c;
+ function() external[] d;
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+BOOST_AUTO_TEST_CASE(function_type_state_variable)
+{
+ char const* text = R"(
+ contract test {
+ function() x;
+ function() y = x;
+ }
+ )";
+ BOOST_CHECK(successParse(text));
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
}
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>