From 6d97a56af17d65425d72c5df973b2fa4fac74a7a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 31 Oct 2016 23:15:57 +0000 Subject: [PATCH 001/185] LLL: support multiple strings in LIT --- liblll/CodeFragment.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 0f8f26061..f143ca43c 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -287,10 +287,10 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (pos.m_asm.deposit() != 1) error(); } - else if (ii == 2 && !i.tag() && i.which() == sp::utree_type::string_type) + else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::string_type) { auto sr = i.get, sp::utree_type::string_type>>(); - data = bytes((byte const*)sr.begin(), (byte const*)sr.end()); + data.insert(data.end(), (byte const *)sr.begin(), (byte const*)sr.end()); } else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::any_type) { From 75b1ae89102d1f917b59b3fa67046181cd74aa7e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 31 Oct 2016 23:17:09 +0000 Subject: [PATCH 002/185] LLL: only support variable length bigendian numbers in LIT --- liblll/CodeFragment.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index f143ca43c..1bf587cec 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -297,21 +297,10 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) bigint bi = *i.get(); if (bi < 0) error(); - else if (bi > bigint(u256(0) - 1)) - { - if (ii == 2 && _t.size() == 3) - { - // One big int - allow it as hex. - data.resize(bytesRequired(bi)); - toBigEndian(bi, data); - } - else - error(); - } else { - data.resize(data.size() + 32); - *(h256*)(&data.back() - 31) = (u256)bi; + bytes tmp = toCompactBigEndian(bi); + data.insert(data.end(), tmp.begin(), tmp.end()); } } else if (ii) From 6e0934664b7da3b09fc6294fa39c756670f46f52 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 8 Nov 2016 23:09:40 +0000 Subject: [PATCH 003/185] Display emscripten output size --- scripts/travis-emscripten/build_emscripten.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh index f5374a330..9ca53b893 100755 --- a/scripts/travis-emscripten/build_emscripten.sh +++ b/scripts/travis-emscripten/build_emscripten.sh @@ -95,4 +95,8 @@ emmake make -j 4 cd .. cp build/solc/soljson.js ./ +OUTPUT_SIZE=`stat -f "%z" build/solc/soljson.js` + +echo "Emscripten output size: $OUTPUT_SIZE" + echo -en 'travis_fold:end:compiling_solidity\\r' From 7bbaeedc317096ef89a10c87313f15b020d5adee Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 8 Nov 2016 23:11:51 +0000 Subject: [PATCH 004/185] Add optimisation flags for Emscripten --- cmake/EthCompilerSettings.cmake | 3 +++ scripts/travis-emscripten/build_emscripten.sh | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake index af6ae9281..97db9168c 100644 --- a/cmake/EthCompilerSettings.cmake +++ b/cmake/EthCompilerSettings.cmake @@ -155,6 +155,9 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA if (EMSCRIPTEN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --memory-init-file 0 -O3 -s LINKABLE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s NO_EXIT_RUNTIME=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_DYNAMIC_EXECUTION=1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_FILESYSTEM=1 -s AGGRESSIVE_VARIABLE_ELIMINATION=1") add_definitions(-DETH_EMSCRIPTEN=1) endif() endif() diff --git a/scripts/travis-emscripten/build_emscripten.sh b/scripts/travis-emscripten/build_emscripten.sh index 9ca53b893..a6eb01a09 100755 --- a/scripts/travis-emscripten/build_emscripten.sh +++ b/scripts/travis-emscripten/build_emscripten.sh @@ -95,8 +95,8 @@ emmake make -j 4 cd .. cp build/solc/soljson.js ./ -OUTPUT_SIZE=`stat -f "%z" build/solc/soljson.js` +OUTPUT_SIZE=`ls -la build/solc/soljson.js` -echo "Emscripten output size: $OUTPUT_SIZE" +echo "Emscripten output size: ${OUTPUT_SIZE}" echo -en 'travis_fold:end:compiling_solidity\\r' From a97befb9119ef3ff354ff626d6cf449fa7efa486 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Fri, 11 Nov 2016 09:28:23 -0300 Subject: [PATCH 005/185] Remove macOS Sierra note from install_deps.sh --- scripts/install_deps.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/install_deps.sh b/scripts/install_deps.sh index c9f827699..255176ab5 100755 --- a/scripts/install_deps.sh +++ b/scripts/install_deps.sh @@ -83,12 +83,6 @@ case $(uname -s) in ;; 10.12) echo "Installing solidity dependencies on macOS 10.12 Sierra." - echo "" - echo "NOTE - You are in unknown territory with this preview OS." - echo "Even Homebrew doesn't have official support yet, and there are" - echo "known issues (see https://github.com/ethereum/webthree-umbrella/issues/614)." - echo "If you would like to partner with us to work through these issues, that" - echo "would be fantastic. Please just comment on that issue. Thanks!" ;; *) echo "Unsupported macOS version." From 39559c1bb6ffc42f8573cada15afd2398e3d99e9 Mon Sep 17 00:00:00 2001 From: ethers Date: Thu, 17 Nov 2016 18:06:28 -0800 Subject: [PATCH 006/185] styleguide: Ordering of functions Ordering would help readers identify which functions they can call, and to find the "specials" (constructor and fallback function). Mixing the "specials" in the middle of the code, as well as internal functions between external and public functions, don't help readers Based on https://github.com/ConsenSys/MultiSigWallet/issues/19 --- docs/style-guide.rst | 68 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 272a1b310..80ffd493b 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -150,6 +150,74 @@ No:: ... } +Order of Functions +================== + +Ordering helps readers identify which functions they can call, and to find the "specials" (constructor and fallback function). + +Functions should be grouped according to their visibility and ordered: + +- constructor +- fallback function (if exists) +- external +- public +- internal +- private + +Within a grouping, place the `constant` functions last. + +Yes:: + + contract A { + function A() { + ... + } + + function () payable { + ... + } + + // External functions + // ... + + // External functions that are constant + // ... + + // Public functions + // ... + + // Internal functions + // ... + + // Private functions + // ... + } + +No:: + + contract A { + + // External functions + // ... + + // Private functions + // ... + + // Public functions + // ... + + function A() { + ... + } + + function () payable { + ... + } + + // Internal functions + // ... + } + Whitespace in Expressions ========================= From 549bca149408262341375f39a75e878e68d2df6b Mon Sep 17 00:00:00 2001 From: ethers Date: Thu, 17 Nov 2016 18:09:22 -0800 Subject: [PATCH 007/185] Don't include a whitespace in fallback function --- docs/style-guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 80ffd493b..b0560917b 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -173,7 +173,7 @@ Yes:: ... } - function () payable { + function() payable { ... } @@ -210,7 +210,7 @@ No:: ... } - function () payable { + function() payable { ... } From 1d9aee97c2532d57bd27e65f8b22079ebbe71e3a Mon Sep 17 00:00:00 2001 From: ethers Date: Thu, 17 Nov 2016 18:13:33 -0800 Subject: [PATCH 008/185] styleguide: Don't include a whitespace in the fallback function --- docs/style-guide.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index b0560917b..46b915e1b 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -262,6 +262,19 @@ No:: y = 2; long_variable = 3; +Don't include a whitespace in the fallback function: + +Yes:: + + function() { + ... + } + +No:: + + function () { + ... + } Control Structures ================== From feebe3e7555a6977acd787d255cb8a2f085a4efe Mon Sep 17 00:00:00 2001 From: ethers Date: Thu, 17 Nov 2016 18:14:26 -0800 Subject: [PATCH 009/185] Fallback functions don't always have to be payable --- docs/style-guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 46b915e1b..eef04099b 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -173,7 +173,7 @@ Yes:: ... } - function() payable { + function() { ... } @@ -210,7 +210,7 @@ No:: ... } - function() payable { + function() { ... } From 92f1c9d4929538b72b97981f67e8999717a35e01 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 18 Nov 2016 03:15:24 +0000 Subject: [PATCH 010/185] Properly define the pragma directive in the grammar --- libsolidity/grammar.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/grammar.txt b/libsolidity/grammar.txt index c8bc3aed0..0aa6690ba 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 ';' From 9dda8f7d84d50a974b6de759a543f001803d9028 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Thu, 17 Nov 2016 18:01:28 -0600 Subject: [PATCH 011/185] add ostream to bytes for ease of development Signed-off-by: VoR0220 fix up Signed-off-by: VoR0220 --- libdevcore/Common.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index d65cfeacd..dababe79f 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -135,6 +135,16 @@ inline u256 s2u(s256 _u) return u256(c_end + _u); } +inline std::ostream& operator<<(std::ostream& os, bytes const& _bytes) +{ + std::ostringstream ss; + std::copy(_bytes.begin(), _bytes.end(), std::ostream_iterator(ss, ",")); + std::string result = ss.str(); + result.pop_back(); + os << "[" + result + "]"; + return os; +} + template inline u256 exp10() { return exp10() * u256(10); From 74ab62de14faee75151429449d5d3f524f54ee1e Mon Sep 17 00:00:00 2001 From: escull638 Date: Mon, 21 Nov 2016 11:26:58 +0000 Subject: [PATCH 012/185] Fixed spelling mistake in Logs Changed 'maps all they way up to the block level' to 'maps all the way up to the block level'. --- docs/introduction-to-smart-contracts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 4a3de441b..aee1e03b3 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -433,7 +433,7 @@ Logs ==== It is possible to store data in a specially indexed data structure -that maps all they way up to the block level. This feature called **logs** +that maps all the way up to the block level. This feature called **logs** is used by Solidity in order to implement **events**. Contracts cannot access log data after it has been created, but they can be efficiently accessed from outside the blockchain. From b24f4a4d006b69d976b173e058efcbe44387404b Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 12:47:40 +0100 Subject: [PATCH 013/185] docs: some types cannot be the key type for mappings --- docs/types.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index b22ad7d4c..518e82420 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -729,9 +729,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 From 42a84946d2dca1880082a07d6408f5b88b966f9c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 21 Nov 2016 13:11:43 +0000 Subject: [PATCH 014/185] Fix function type examples --- docs/types.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index b22ad7d4c..693e20953 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -314,10 +314,13 @@ followed by the function identifier together in a single ``bytes24`` type. Example that shows how to use internal function types:: + pragma solidity ^0.4.5; + library ArrayUtils { // internal functions can be used in internal library functions because // they will be part of the same code context function map(uint[] memory self, function (uint) returns (uint) f) + internal returns (uint[] memory r) { r = new uint[](self.length); @@ -327,8 +330,9 @@ Example that shows how to use internal function types:: } function reduce( uint[] memory self, - function (uint) returns (uint) f + function (uint x, uint y) returns (uint) f ) + internal returns (uint r) { r = self[0]; @@ -336,7 +340,7 @@ Example that shows how to use internal function types:: r = f(r, self[i]); } } - function range(uint length) returns (uint[] memory r) { + function range(uint length) internal returns (uint[] memory r) { r = new uint[](length); for (uint i = 0; i < r.length; i++) { r[i] = i; @@ -346,7 +350,7 @@ Example that shows how to use internal function types:: contract Pyramid { using ArrayUtils for *; - function pyramid(uint l) return (uint) { + function pyramid(uint l) returns (uint) { return ArrayUtils.range(l).map(square).reduce(sum); } function square(uint x) internal returns (uint) { @@ -359,6 +363,8 @@ Example that shows how to use internal function types:: Another example that uses external function types:: + pragma solidity ^0.4.5; + contract Oracle { struct Request { bytes data; @@ -377,12 +383,12 @@ Another example that uses external function types:: } contract OracleUser { - Oracle constant oracle = 0x1234567; // known contract + Oracle constant oracle = Oracle(0x1234567); // known contract function buySomething() { oracle.query("USD", oracleResponse); } function oracleResponse(bytes response) { - if (msg.sender != oracle) throw; + if (msg.sender != address(oracle)) throw; // Use the data } } From 81eea45c2df6c29cd6e8c2258b10d44b9c058962 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 21 Nov 2016 13:16:35 +0000 Subject: [PATCH 015/185] Fix oracle callback example --- docs/types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 693e20953..9f3b4dc1b 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -368,11 +368,11 @@ Another example that uses external function types:: contract Oracle { struct Request { bytes data; - function(bytes) external callback; + function(bytes memory) external callback; } Request[] requests; event NewRequest(uint); - function query(bytes data, function(bytes) external callback) { + function query(bytes data, function(bytes memory) external callback) { requests.push(Request(data, callback)); NewRequest(requests.length - 1); } From 73eb0235b4bb9673cf653ca834893e33f7410381 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 21 Nov 2016 17:09:08 +0100 Subject: [PATCH 016/185] Fix examples and add explanation. --- docs/types.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index 9f3b4dc1b..1db35ced5 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -312,6 +312,10 @@ 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; @@ -385,7 +389,7 @@ Another example that uses external function types:: contract OracleUser { Oracle constant oracle = Oracle(0x1234567); // known contract function buySomething() { - oracle.query("USD", oracleResponse); + oracle.query("USD", this.oracleResponse); } function oracleResponse(bytes response) { if (msg.sender != address(oracle)) throw; From 9869f1a78bff6b8d84ed0b08e7beb5d425fa5aad Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Mon, 21 Nov 2016 13:53:53 -0600 Subject: [PATCH 017/185] convert individual numbers to hex Signed-off-by: VoR0220 --- libdevcore/Common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index dababe79f..225f38ac0 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -138,6 +138,7 @@ inline u256 s2u(s256 _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(ss, ",")); std::string result = ss.str(); result.pop_back(); From 217f33c252e8562a44c683ff1aae9de538ef475b Mon Sep 17 00:00:00 2001 From: ethers Date: Tue, 22 Nov 2016 00:47:58 -0800 Subject: [PATCH 018/185] Clearer language as suggested by @axic --- docs/style-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/style-guide.rst b/docs/style-guide.rst index eef04099b..9aae3d7be 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -153,7 +153,7 @@ No:: Order of Functions ================== -Ordering helps readers identify which functions they can call, and to find the "specials" (constructor and fallback function). +Ordering helps readers identify which functions they can call and to find the constructor and fallback definitions easier. Functions should be grouped according to their visibility and ordered: From a65473b371334a12a76dbde93ef1b8794fb5e544 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 22 Nov 2016 15:44:48 +0100 Subject: [PATCH 019/185] Set version to 0.4.7 --- CMakeLists.txt | 2 +- docs/conf.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 992ce3920..ee66eebd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.4.6") +set(PROJECT_VERSION "0.4.7") project(solidity VERSION ${PROJECT_VERSION}) # Let's find our dependencies diff --git a/docs/conf.py b/docs/conf.py index bf0accb9e..2bc79fd9f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -56,9 +56,9 @@ copyright = '2016, Ethereum' # built documents. # # The short X.Y version. -version = '0.4.6' +version = '0.4.7' # The full version, including alpha/beta/rc tags. -release = '0.4.6-develop' +release = '0.4.7-develop' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 75686e3d753d86558261ac8dab81564f06a08bfa Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 22 Nov 2016 17:09:22 +0100 Subject: [PATCH 020/185] test: add a test case about returning a struct in memory from a library This fixes #1378 --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 865eb7cec..82384589f 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2817,6 +2817,17 @@ BOOST_AUTO_TEST_CASE(using_for_not_used) BOOST_CHECK(expectError(text) == Error::Type::TypeError); } +BOOST_AUTO_TEST_CASE(library_memory_struct) +{ + char const* text = R"( + library c { + struct S { uint x; } + function f() returns (S ) {} + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) { // Bound to a, but self type does not match. From 622952d4b9e25a2c8afd3fe2e556d98e2ae62d30 Mon Sep 17 00:00:00 2001 From: Ola Date: Tue, 22 Nov 2016 18:21:13 -0500 Subject: [PATCH 021/185] Update types.rst line 349 "returns" not return --- docs/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types.rst b/docs/types.rst index b22ad7d4c..524956fcc 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -346,7 +346,7 @@ Example that shows how to use internal function types:: contract Pyramid { using ArrayUtils for *; - function pyramid(uint l) return (uint) { + function pyramid(uint l) returns (uint) { return ArrayUtils.range(l).map(square).reduce(sum); } function square(uint x) internal returns (uint) { From aa4340ca89de452c67c0f0f9a0b8a5f34af93eb3 Mon Sep 17 00:00:00 2001 From: Jonathan Brown Date: Wed, 23 Nov 2016 17:00:06 +0700 Subject: [PATCH 022/185] Mention when the bug was introduced. --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index eb1e5e72d..468518d2a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,7 @@ ### 0.4.6 (2016-11-22) Bugfixes: - * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs + * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs (introduced in 0.4.5) ### 0.4.5 (2016-11-21) From 3f9f725737dd04485211fedc8533fdac983f2b04 Mon Sep 17 00:00:00 2001 From: VoR0220 Date: Fri, 18 Nov 2016 17:13:20 -0600 Subject: [PATCH 023/185] Fix licensing headers Signed-off-by: VoR0220 --- .travis.yml | 10 +++++----- appveyor.yml | 10 +++++----- libevmasm/Assembly.cpp | 8 ++++---- libevmasm/Assembly.h | 8 ++++---- libevmasm/AssemblyItem.cpp | 8 ++++---- libevmasm/AssemblyItem.h | 8 ++++---- libevmasm/BlockDeduplicator.cpp | 8 ++++---- libevmasm/BlockDeduplicator.h | 8 ++++---- libevmasm/CommonSubexpressionEliminator.cpp | 8 ++++---- libevmasm/CommonSubexpressionEliminator.h | 8 ++++---- libevmasm/ConstantOptimiser.cpp | 8 ++++---- libevmasm/ConstantOptimiser.h | 8 ++++---- libevmasm/ControlFlowGraph.cpp | 8 ++++---- libevmasm/ControlFlowGraph.h | 8 ++++---- libevmasm/EVMSchedule.h | 8 ++++---- libevmasm/Exceptions.h | 8 ++++---- libevmasm/ExpressionClasses.cpp | 8 ++++---- libevmasm/ExpressionClasses.h | 8 ++++---- libevmasm/GasMeter.cpp | 8 ++++---- libevmasm/GasMeter.h | 8 ++++---- libevmasm/Instruction.cpp | 8 ++++---- libevmasm/Instruction.h | 8 ++++---- libevmasm/KnownState.cpp | 8 ++++---- libevmasm/KnownState.h | 8 ++++---- libevmasm/LinkerObject.cpp | 8 ++++---- libevmasm/LinkerObject.h | 8 ++++---- libevmasm/PathGasMeter.cpp | 8 ++++---- libevmasm/PathGasMeter.h | 8 ++++---- libevmasm/PeepholeOptimiser.cpp | 8 ++++---- libevmasm/PeepholeOptimiser.h | 8 ++++---- libevmasm/SemanticInformation.cpp | 8 ++++---- libevmasm/SemanticInformation.h | 8 ++++---- libevmasm/SourceLocation.h | 8 ++++---- libsolidity/analysis/ConstantEvaluator.cpp | 8 ++++---- libsolidity/analysis/ConstantEvaluator.h | 8 ++++---- libsolidity/analysis/DeclarationContainer.cpp | 8 ++++---- libsolidity/analysis/DeclarationContainer.h | 8 ++++---- libsolidity/analysis/DocStringAnalyser.cpp | 8 ++++---- libsolidity/analysis/DocStringAnalyser.h | 8 ++++---- libsolidity/analysis/GlobalContext.cpp | 8 ++++---- libsolidity/analysis/GlobalContext.h | 8 ++++---- libsolidity/analysis/NameAndTypeResolver.cpp | 8 ++++---- libsolidity/analysis/NameAndTypeResolver.h | 8 ++++---- libsolidity/analysis/ReferencesResolver.cpp | 8 ++++---- libsolidity/analysis/ReferencesResolver.h | 8 ++++---- libsolidity/analysis/SemVerHandler.cpp | 8 ++++---- libsolidity/analysis/SemVerHandler.h | 8 ++++---- libsolidity/analysis/SyntaxChecker.cpp | 8 ++++---- libsolidity/analysis/SyntaxChecker.h | 8 ++++---- libsolidity/analysis/TypeChecker.cpp | 8 ++++---- libsolidity/analysis/TypeChecker.h | 8 ++++---- libsolidity/ast/AST.cpp | 8 ++++---- libsolidity/ast/AST.h | 8 ++++---- libsolidity/ast/ASTAnnotations.cpp | 8 ++++---- libsolidity/ast/ASTAnnotations.h | 8 ++++---- libsolidity/ast/ASTForward.h | 8 ++++---- libsolidity/ast/ASTJsonConverter.cpp | 8 ++++---- libsolidity/ast/ASTJsonConverter.h | 8 ++++---- libsolidity/ast/ASTPrinter.cpp | 8 ++++---- libsolidity/ast/ASTPrinter.h | 8 ++++---- libsolidity/ast/ASTUtils.cpp | 8 ++++---- libsolidity/ast/ASTUtils.h | 8 ++++---- libsolidity/ast/ASTVisitor.h | 8 ++++---- libsolidity/ast/AST_accept.h | 8 ++++---- libsolidity/ast/Types.cpp | 8 ++++---- libsolidity/ast/Types.h | 8 ++++---- libsolidity/codegen/ArrayUtils.cpp | 8 ++++---- libsolidity/codegen/ArrayUtils.h | 8 ++++---- libsolidity/codegen/Compiler.cpp | 8 ++++---- libsolidity/codegen/Compiler.h | 8 ++++---- libsolidity/codegen/CompilerContext.cpp | 8 ++++---- libsolidity/codegen/CompilerContext.h | 8 ++++---- libsolidity/codegen/CompilerUtils.cpp | 8 ++++---- libsolidity/codegen/CompilerUtils.h | 8 ++++---- libsolidity/codegen/ContractCompiler.cpp | 8 ++++---- libsolidity/codegen/ContractCompiler.h | 8 ++++---- libsolidity/codegen/ExpressionCompiler.cpp | 8 ++++---- libsolidity/codegen/ExpressionCompiler.h | 8 ++++---- libsolidity/codegen/LValue.cpp | 8 ++++---- libsolidity/codegen/LValue.h | 8 ++++---- libsolidity/formal/Why3Translator.cpp | 8 ++++---- libsolidity/formal/Why3Translator.h | 8 ++++---- libsolidity/inlineasm/AsmCodeGen.cpp | 8 ++++---- libsolidity/inlineasm/AsmCodeGen.h | 8 ++++---- libsolidity/inlineasm/AsmData.h | 8 ++++---- libsolidity/inlineasm/AsmParser.cpp | 8 ++++---- libsolidity/inlineasm/AsmParser.h | 8 ++++---- libsolidity/inlineasm/AsmStack.cpp | 8 ++++---- libsolidity/inlineasm/AsmStack.h | 8 ++++---- libsolidity/interface/CompilerStack.cpp | 8 ++++---- libsolidity/interface/CompilerStack.h | 8 ++++---- libsolidity/interface/Exceptions.cpp | 8 ++++---- libsolidity/interface/Exceptions.h | 8 ++++---- libsolidity/interface/GasEstimator.cpp | 8 ++++---- libsolidity/interface/GasEstimator.h | 8 ++++---- libsolidity/interface/InterfaceHandler.h | 8 ++++---- libsolidity/interface/SourceReferenceFormatter.cpp | 8 ++++---- libsolidity/interface/SourceReferenceFormatter.h | 8 ++++---- libsolidity/interface/Utils.h | 8 ++++---- libsolidity/interface/Version.cpp | 8 ++++---- libsolidity/interface/Version.h | 8 ++++---- libsolidity/parsing/DocStringParser.h | 8 ++++---- libsolidity/parsing/Parser.cpp | 8 ++++---- libsolidity/parsing/Parser.h | 8 ++++---- libsolidity/parsing/ParserBase.cpp | 8 ++++---- libsolidity/parsing/ParserBase.h | 8 ++++---- libsolidity/parsing/Scanner.cpp | 8 ++++---- libsolidity/parsing/Scanner.h | 8 ++++---- libsolidity/parsing/Token.cpp | 8 ++++---- libsolidity/parsing/Token.h | 8 ++++---- solc/CommandLineInterface.cpp | 8 ++++---- solc/CommandLineInterface.h | 8 ++++---- solc/jsonCompiler.cpp | 8 ++++---- solc/main.cpp | 8 ++++---- test/RPCSession.cpp | 8 ++++---- test/RPCSession.h | 8 ++++---- test/TestHelper.cpp | 8 ++++---- test/TestHelper.h | 8 ++++---- test/boostTest.cpp | 8 ++++---- test/contracts/AuctionRegistrar.cpp | 8 ++++---- test/contracts/FixedFeeRegistrar.cpp | 8 ++++---- test/contracts/Wallet.cpp | 8 ++++---- test/libevmasm/SourceLocation.cpp | 8 ++++---- test/libsolidity/ASTJSON.cpp | 8 ++++---- test/libsolidity/Assembly.cpp | 8 ++++---- test/libsolidity/GasMeter.cpp | 8 ++++---- test/libsolidity/Imports.cpp | 8 ++++---- test/libsolidity/InlineAssembly.cpp | 8 ++++---- test/libsolidity/SemVerMatcher.cpp | 8 ++++---- test/libsolidity/SolidityABIJSON.cpp | 8 ++++---- test/libsolidity/SolidityEndToEndTest.cpp | 8 ++++---- test/libsolidity/SolidityExecutionFramework.cpp | 8 ++++---- test/libsolidity/SolidityExecutionFramework.h | 8 ++++---- test/libsolidity/SolidityExpressionCompiler.cpp | 8 ++++---- test/libsolidity/SolidityNameAndTypeResolution.cpp | 8 ++++---- test/libsolidity/SolidityNatspecJSON.cpp | 8 ++++---- test/libsolidity/SolidityOptimizer.cpp | 8 ++++---- test/libsolidity/SolidityParser.cpp | 8 ++++---- test/libsolidity/SolidityScanner.cpp | 8 ++++---- test/libsolidity/SolidityTypes.cpp | 8 ++++---- 140 files changed, 562 insertions(+), 562 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2748c460b..2160d1758 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 +# along with solidity. If not, see # -# (c) 2016 cpp-ethereum contributors. +# (c) 2016 solidity contributors. #------------------------------------------------------------------------------ language: cpp diff --git a/appveyor.yml b/appveyor.yml index 5d6dcb204..85fb36f2b 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 +# along with solidity. If not, see # -# (c) 2016 cpp-ethereum contributors. +# (c) 2016 solidity contributors. #------------------------------------------------------------------------------ branches: diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index c394afa24..963067509 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 . + along with solidity. If not, see . */ /** @file Assembly.cpp * @author Gav Wood diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index f3c56610b..a5fd4d516 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, + solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + along with solidity. If not, see . */ #pragma once diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp index 7bd93eaf7..54e38de80 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 . + along with solidity. If not, see . */ /** @file Assembly.cpp * @author Gav Wood diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 1a2fb1e62..2bc28dbd6 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.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 . + along with solidity. If not, see . */ /** @file Assembly.h * @author Gav Wood diff --git a/libevmasm/BlockDeduplicator.cpp b/libevmasm/BlockDeduplicator.cpp index 18b595cd2..d21be07e7 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 . + along with solidity. If not, see . */ /** * @file BlockDeduplicator.cpp diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h index 5ecab7f3e..797c24763 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 . + along with solidity. If not, see . */ /** * @file BlockDeduplicator.h diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp index 0797dd294..6294e579d 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 . + along with solidity. If not, see . */ /** * @file CommonSubexpressionEliminator.cpp diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h index f6c43c57a..83fc97323 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 . + along with solidity. If not, see . */ /** * @file CommonSubexpressionEliminator.h diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp index 27f630f59..f4a50c2d6 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 . + along with solidity. If not, see . */ /** @file ConstantOptimiser.cpp * @author Christian diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h index e75eff380..b35b2a69d 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 . + along with solidity. If not, see . */ /** @file ConstantOptimiser.cpp * @author Christian diff --git a/libevmasm/ControlFlowGraph.cpp b/libevmasm/ControlFlowGraph.cpp index d48015625..86f16d481 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 . + along with solidity. If not, see . */ /** * @file ControlFlowGraph.cpp diff --git a/libevmasm/ControlFlowGraph.h b/libevmasm/ControlFlowGraph.h index 789982627..ebef543fc 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 . + along with solidity. If not, see . */ /** * @file ControlFlowGraph.h diff --git a/libevmasm/EVMSchedule.h b/libevmasm/EVMSchedule.h index 02a34b168..f882f0068 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 . + along with solidity. If not, see . */ /** @file EVMSchedule.h * @author Gav diff --git a/libevmasm/Exceptions.h b/libevmasm/Exceptions.h index 03b8afdee..06b0ac788 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 . + along with solidity. If not, see . */ /** @file Exceptions.h * @author Christian diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index cf5e6a0ef..e32b2da21 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 . + along with solidity. If not, see . */ /** * @file ExpressionClasses.cpp diff --git a/libevmasm/ExpressionClasses.h b/libevmasm/ExpressionClasses.h index 4bfd7d24a..11a698dd8 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 . + along with solidity. If not, see . */ /** * @file ExpressionClasses.h diff --git a/libevmasm/GasMeter.cpp b/libevmasm/GasMeter.cpp index da8b41e32..21db35655 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 . + along with solidity. If not, see . */ /** @file GasMeter.cpp * @author Christian diff --git a/libevmasm/GasMeter.h b/libevmasm/GasMeter.h index ff1279096..0bc10f1f2 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 . + along with solidity. If not, see . */ /** @file GasMeter.cpp * @author Christian diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index 2aaa6f1d6..5244a91f7 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 . + along with solidity. If not, see . */ /** @file Instruction.cpp * @author Gav Wood diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 0b06a6774..c7fad1c5a 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 . + along with solidity. If not, see . */ /** @file Instruction.h * @author Gav Wood diff --git a/libevmasm/KnownState.cpp b/libevmasm/KnownState.cpp index 0b6e0ac55..6e3130dd9 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 . + along with solidity. If not, see . */ /** * @file KnownState.cpp diff --git a/libevmasm/KnownState.h b/libevmasm/KnownState.h index c1c602dcb..fd6a26c14 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 . + along with solidity. If not, see . */ /** * @file KnownState.h diff --git a/libevmasm/LinkerObject.cpp b/libevmasm/LinkerObject.cpp index ceb864a17..93e4067c9 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 . + along with solidity. If not, see . */ /** @file LinkerObject.cpp * @author Christian R diff --git a/libevmasm/LinkerObject.h b/libevmasm/LinkerObject.h index 83d2bd7e0..d3ec3e972 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 . + along with solidity. If not, see . */ /** @file Assembly.h * @author Gav Wood diff --git a/libevmasm/PathGasMeter.cpp b/libevmasm/PathGasMeter.cpp index 2113008b5..c56e2f8ba 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 . + along with solidity. If not, see . */ /** @file PathGasMeter.cpp * @author Christian diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h index 1ada460aa..0a0fe5d02 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 . + along with solidity. If not, see . */ /** @file PathGasMeter.cpp * @author Christian diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index f42dba487..e93db9ac9 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.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 . + along with solidity. If not, see . */ /** * @file PeepholeOptimiser.h diff --git a/libevmasm/PeepholeOptimiser.h b/libevmasm/PeepholeOptimiser.h index 372e49c5b..a74cc8b30 100644 --- a/libevmasm/PeepholeOptimiser.h +++ b/libevmasm/PeepholeOptimiser.h @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, + solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + along with solidity. If not, see . */ /** * @file PeepholeOptimiser.h diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp index ea579b837..23a00d951 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 . + along with solidity. If not, see . */ /** * @file SemanticInformation.cpp diff --git a/libevmasm/SemanticInformation.h b/libevmasm/SemanticInformation.h index 0eda5ed51..5b02061fc 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 . + along with solidity. If not, see . */ /** * @file SemanticInformation.h diff --git a/libevmasm/SourceLocation.h b/libevmasm/SourceLocation.h index b8f073bb9..b42c3aa98 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 . + along with solidity. If not, see . */ /** * @author Lefteris Karapetsas diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index bdd8f61e5..7057eab7c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index f311efbfe..9ec04ebe5 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/DeclarationContainer.cpp b/libsolidity/analysis/DeclarationContainer.cpp index 042b7a6aa..1599b83ac 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/DeclarationContainer.h b/libsolidity/analysis/DeclarationContainer.h index 5862f7a59..9c7c89e73 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index 4f75f03d6..58261144b 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/DocStringAnalyser.h b/libsolidity/analysis/DocStringAnalyser.h index cdf297e33..bfc8befce 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index d075949ef..e46868be2 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/GlobalContext.h b/libsolidity/analysis/GlobalContext.h index 482391d39..4ed08711c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 26d38cfe0..2a33a5015 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index 89b9818ba..68c3ffa1d 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index a0768a341..66bf1d0e1 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index bfaef2e1f..caa3a78fc 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/SemVerHandler.cpp b/libsolidity/analysis/SemVerHandler.cpp index c7b212b28..421863964 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/SemVerHandler.h b/libsolidity/analysis/SemVerHandler.h index e3b642db5..fae0a764c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index dbaa15edf..0a4943fe4 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 . + along with solidity. If not, see . */ #include diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index ac8ed8723..c24bae092 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 . + along with solidity. If not, see . */ #pragma once diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8b6d45e2f..7235b57aa 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 5874bb502..143b15b26 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 305668e7e..9b4783936 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index a2b70fe9c..89b96f096 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTAnnotations.cpp b/libsolidity/ast/ASTAnnotations.cpp index 416e6b449..0f958a383 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 2a192e47b..768e56db5 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index 52bbf3968..cfeeaa588 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 37dfd3c68..030b32bae 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 . + along with solidity. If not, see . */ /** * @author Lefteris diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index 0a71779c9..277476d59 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 . + along with solidity. If not, see . */ /** * @author Lefteris diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp index 053b9b822..23eb3b64e 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTPrinter.h b/libsolidity/ast/ASTPrinter.h index 9f88a1fdc..4a37f17f8 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTUtils.cpp b/libsolidity/ast/ASTUtils.cpp index e9b70b62f..7d1804900 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTUtils.h b/libsolidity/ast/ASTUtils.h index 237537ec4..f7cacf3e4 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index e72afe697..20be634b5 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h index f521e0929..7c1c64b09 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 4488398f8..b7de3646c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 34fcfc823..b713a7c01 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index b5f5cd8e6..c0eb736a0 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/ArrayUtils.h b/libsolidity/codegen/ArrayUtils.h index 53d36c147..d0ba2892b 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 54639515f..22d256982 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 4a87de0ea..c8bf7861c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index c76db2a64..b99b05485 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 8ccbddfd8..3c6d9d732 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index bfe5386b3..fe2b9c7e1 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 8e4033d63..ff87124fe 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 8d60d6b3f..437c484a3 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h index 10febcf72..38c1e0454 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 7a3285282..58330764f 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index f4ce1fec9..f08bded97 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 2ec7f8005..3f1730d15 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index a2f979db5..f8b68362a 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/formal/Why3Translator.cpp b/libsolidity/formal/Why3Translator.cpp index 5934d5936..2903a4e37 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/formal/Why3Translator.h b/libsolidity/formal/Why3Translator.h index 4fdac3851..03f3bf9cf 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 771f10425..43c3b27a9 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmCodeGen.h b/libsolidity/inlineasm/AsmCodeGen.h index b1fafe154..bd71812ec 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index d6abf67f5..d622ff54c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 8d2c2ed46..ef3da2554 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h index 0a9d51d53..8b56ab902 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmStack.cpp b/libsolidity/inlineasm/AsmStack.cpp index 11c6e28f6..b8e0e8572 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/inlineasm/AsmStack.h b/libsolidity/inlineasm/AsmStack.h index 521f5fe7b..1543cb2a5 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index f1eb2614b..9305c5e3b 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 1fd30c4db..ea7061229 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/Exceptions.cpp b/libsolidity/interface/Exceptions.cpp index 6d72520bf..90a680b4d 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 . + along with solidity. If not, see . */ /** * @author Liana diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h index c651548af..81716c41a 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 1c804b78e..852b392c6 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/GasEstimator.h b/libsolidity/interface/GasEstimator.h index 518e58e4e..bf63df96d 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/InterfaceHandler.h b/libsolidity/interface/InterfaceHandler.h index d4f2eaf4f..b7e1bb003 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 . + along with solidity. If not, see . */ /** * @author Lefteris diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/libsolidity/interface/SourceReferenceFormatter.cpp index f09d2d453..7730a99a1 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/SourceReferenceFormatter.h b/libsolidity/interface/SourceReferenceFormatter.h index 2b908c46b..7034f4ab2 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/Utils.h b/libsolidity/interface/Utils.h index eef8c917a..0027759cc 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index 0dca1cedc..ff66f0398 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/interface/Version.h b/libsolidity/interface/Version.h index fea739976..5b07b3f42 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/parsing/DocStringParser.h b/libsolidity/parsing/DocStringParser.h index f67b8bbd4..c7f81c554 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 . + along with solidity. If not, see . */ /** * @author Lefteris diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 02b7d5e0e..f02a4a45f 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 9295a7fa4..79d1d1d49 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp index 2abf58ccb..87d47f4b1 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h index 9705228fd..dfb7cab7a 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp index 603f3e421..6115101e6 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 . + along with solidity. If not, see . 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 36cba1122..65de8bd4e 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 . + along with solidity. If not, see . 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 0ab979884..66312f692 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 . +// along with solidity. If not, see . #include #include diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h index 5dd429927..3ce0f4244 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 . +// along with solidity. If not, see . #pragma once diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 7b23f886b..c677cf1fb 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 . + along with solidity. If not, see . */ /** * @author Lefteris diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index e240fe96e..33ae6ee6b 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 . + along with solidity. If not, see . */ /** * @author Lefteris diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 771f0df8c..0f95ebe5a 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/solc/main.cpp b/solc/main.cpp index 260107165..28726e267 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp index 0a01ddb2d..44d21d69a 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 . + along with solidity. If not, see . 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 2a9825b0e..fc166b99b 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 . + along with solidity. If not, see . */ /** @file RPCSession.h * @author Dimtiry Khokhlov diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index df35ff53f..0b6904bf7 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 . + along with solidity. If not, see . */ /** @file TestHelper.h * @author Marko Simovic diff --git a/test/TestHelper.h b/test/TestHelper.h index 2cb24fd7b..78a107fd2 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 . + along with solidity. If not, see . */ /** @file TestHelper.h * @author Marko Simovic diff --git a/test/boostTest.cpp b/test/boostTest.cpp index 4ddae0b7c..d1d35be3e 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 . + along with solidity. If not, see . */ /** @file boostTest.cpp * @author Marko Simovic diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 277de4eb2..caa8e9e09 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index 736015fae..8ed34924c 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 4966b26c8..234387d69 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libevmasm/SourceLocation.cpp b/test/libevmasm/SourceLocation.cpp index 64237a4e1..6889b3e67 100644 --- a/test/libevmasm/SourceLocation.cpp +++ b/test/libevmasm/SourceLocation.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - cpp-ethereum is distributed in the hope that it will be useful, + solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with cpp-ethereum. If not, see . + along with solidity. If not, see . */ /** * @author Yoichi Hirai diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp index b88218e78..0972ce820 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index e5ce691b8..cc77bd4cf 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 . + along with solidity. If not, see . */ /** * @author Lefteris Karapetsas diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index fc1033930..bc2242845 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index 1a9e16cc2..bc6adc265 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 185a62158..64073edce 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 80bdf16f7..08ef5277f 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index a8a39b0b1..6fc2bcee2 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 . + along with solidity. If not, see . */ /** * @author Marek Kotewicz diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 4abe0894e..a9a887898 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 02548121a..421fab7f8 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 7d44edaf6..b2ea9c08e 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 91edfefd2..cab9f09fc 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 865eb7cec..7cacbf8fe 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 49844f157..ef69e85c4 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 . + along with solidity. If not, see . */ /** * @author Lefteris Karapetsas diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 017fc0e92..ecb44272e 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 914dbc305..a3217f08e 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 31b75f256..eb2f042c4 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 . + along with solidity. If not, see . */ /** * @author Christian diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 87dda9c2e..dc3143c87 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 . + along with solidity. If not, see . */ /** * @author Christian From 452dbef3dcc27f46d3b7316a5573d2ce907b993c Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 15:47:04 +0100 Subject: [PATCH 024/185] docs: add a section about calldata layout Part of #1390 --- docs/miscellaneous.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 0b3eed38e..15ff374d2 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 +`_. The +ABI specification requires arguments to be padded to multiples of 32 +bytes. The internal function calls use a different convention. + ***************** Esoteric Features ***************** From c33b098e55ee7c330823106f72bb1668522c912f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 23 Nov 2016 16:40:57 +0100 Subject: [PATCH 025/185] docs: add a description about the types of parameters of overriding functions --- docs/contracts.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/contracts.rst b/docs/contracts.rst index 7f8ace448..e82b7495f 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) { From c9293f2f2370e16af239f711b56245cf70c29970 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 23 Nov 2016 15:14:25 +0100 Subject: [PATCH 026/185] Enable the optimizer for test runs. --- scripts/tests.sh | 9 +++++++-- test/TestHelper.cpp | 3 +++ test/TestHelper.h | 1 + test/contracts/AuctionRegistrar.cpp | 1 - test/contracts/FixedFeeRegistrar.cpp | 1 - test/contracts/Wallet.cpp | 1 - test/libsolidity/SolidityExecutionFramework.cpp | 1 + 7 files changed, 12 insertions(+), 5 deletions(-) diff --git a/scripts/tests.sh b/scripts/tests.sh index 5da427d44..dfbda7342 100755 --- a/scripts/tests.sh +++ b/scripts/tests.sh @@ -65,9 +65,14 @@ $ETH_PATH --test -d /tmp/test & # The node needs to get a little way into its startup sequence before the IPC # is available and is ready for the unit-tests to start talking to it. while [ ! -S /tmp/test/geth.ipc ]; do sleep 2; done +echo "--> IPC available." -# And then run the Solidity unit-tests, pointing to that IPC endpoint. -"$REPO_ROOT"/build/test/soltest -- --ipcpath /tmp/test/geth.ipc +# And then run the Solidity unit-tests (once without optimization, once with), +# pointing to that IPC endpoint. +echo "--> Running tests without optimizer..." + "$REPO_ROOT"/build/test/soltest -- --ipcpath /tmp/test/geth.ipc && \ + echo "--> Running tests WITH optimizer..." && \ + "$REPO_ROOT"/build/test/soltest -- --optimize --ipcpath /tmp/test/geth.ipc ERROR_CODE=$? pkill eth || true sleep 4 diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index 0b6904bf7..d670ebff5 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -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 78a107fd2..afe4a68f0 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -106,6 +106,7 @@ namespace test struct Options: boost::noncopyable { std::string ipcPath; + bool optimize = false; static Options const& get(); diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index caa8e9e09..0b573bca0 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -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 8ed34924c..8aabdac2a 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -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 234387d69..935baf5b5 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -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/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 421fab7f8..009433674 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -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); From ab3db782ae9193839a354a626a7d8ee7bdfad63a Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 15 Nov 2016 19:07:33 +0100 Subject: [PATCH 027/185] test: check the error texts by changing parseAnalyseAndReturnError to return the whole Error, not just the type --- libsolidity/interface/Exceptions.h | 9 + .../SolidityNameAndTypeResolution.cpp | 376 +++++++++--------- 2 files changed, 197 insertions(+), 188 deletions(-) diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h index 81716c41a..6f38cba20 100644 --- a/libsolidity/interface/Exceptions.h +++ b/libsolidity/interface/Exceptions.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include #include @@ -57,6 +58,14 @@ public: Type type() const { return m_type; } std::string const& typeName() const { return m_typeName; } + template + bool regex_search(T&& _reg) const + { + if (std::string const* str = boost::get_error_info(*this)) + return std::regex_search(*str, std::regex(std::forward(_reg))); + else + return false; + } /// helper functions static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index b0e0bbb48..6932f852b 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -44,7 +44,7 @@ namespace test namespace { -pair, std::shared_ptr> +pair, std::shared_ptr> parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true) { // Silence compiler version warning @@ -61,7 +61,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, SyntaxChecker syntaxChecker(errors); if (!syntaxChecker.checkSyntax(*sourceUnit)) - return make_pair(sourceUnit, std::make_shared(errors[0]->type())); + return make_pair(sourceUnit, errors[0]); std::shared_ptr globalContext = make_shared(); NameAndTypeResolver resolver(globalContext->declarations(), errors); @@ -96,7 +96,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(currentError->type())); + return make_pair(sourceUnit, currentError); } } catch (InternalCompilerError const& _e) @@ -108,7 +108,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, } catch (Error const& _e) { - return make_pair(sourceUnit, std::make_shared(_e.type())); + return make_pair(sourceUnit, std::make_shared(_e)); } catch (...) { @@ -130,7 +130,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); @@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) " uint256 variable;\n" " uint128 variable;\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(double_function_declaration) @@ -186,7 +186,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); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(double_variable_declaration) @@ -194,7 +194,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); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(name_shadowing) @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) " uint256 variable;\n" " function f(uint256 arg) { f(notfound); }" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(reference_to_later_declaration) @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) " MyStructName x;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) @@ -256,7 +256,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) " MyStructName1 x;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) @@ -303,7 +303,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) @@ -311,7 +311,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(type_checking_function_call) @@ -336,7 +336,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) @@ -372,7 +372,7 @@ BOOST_AUTO_TEST_CASE(balance_invalid) " address(0).balance = 7;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(assignment_to_mapping) @@ -387,7 +387,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_mapping) " data.map = a;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(assignment_to_struct) @@ -411,7 +411,7 @@ BOOST_AUTO_TEST_CASE(returns_in_constructor) " function test() returns (uint a) {\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(forward_function_reference) @@ -499,7 +499,7 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) function foo() { b = new base();} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional) @@ -543,7 +543,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) @@ -667,7 +667,7 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) } function g (C c) external {} })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) @@ -699,7 +699,7 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) g(a); } })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(hash_collision_in_interface) @@ -710,7 +710,7 @@ BOOST_AUTO_TEST_CASE(hash_collision_in_interface) " function tgeo() {\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(inheritance_basic) @@ -744,7 +744,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance) contract A is B { } contract B is A { } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(legal_override_direct) @@ -772,7 +772,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(illegal_override_constness) @@ -781,7 +781,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(complex_inheritance) @@ -851,7 +851,7 @@ BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) function f() { B b = A(1); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(super_excludes_current_contract) @@ -868,7 +868,7 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract) } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_modifier_invocation) @@ -891,7 +891,7 @@ BOOST_AUTO_TEST_CASE(invalid_function_modifier_type) modifier mod1(uint a) { if (a > 0) _; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) @@ -932,7 +932,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(modifier_overrides_function) @@ -941,7 +941,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_overrides_modifier) @@ -950,7 +950,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(modifier_returns_value) @@ -961,7 +961,7 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value) modifier mod(uint a) { _; return 7; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(state_variable_accessors) @@ -1012,7 +1012,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); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(private_state_variable) @@ -1045,7 +1045,7 @@ BOOST_AUTO_TEST_CASE(missing_state_variable) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } @@ -1069,7 +1069,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) Data public data; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member) @@ -1094,7 +1094,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) @@ -1109,7 +1109,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -1131,7 +1131,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) function(uint a) { x = 2; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(fallback_function_in_library) @@ -1141,7 +1141,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_in_library) function() {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) @@ -1151,7 +1151,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) function() returns (uint) { } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) @@ -1162,7 +1162,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) function() constant { x = 2; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(fallback_function_twice) @@ -1174,7 +1174,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice) function() { x = 3; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(fallback_function_inheritance) @@ -1207,7 +1207,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) @@ -1225,7 +1225,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(event_call) @@ -1281,7 +1281,7 @@ BOOST_AUTO_TEST_CASE(access_to_internal_function) contract d { function g() { c(0).f(); } })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) @@ -1293,7 +1293,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) @@ -1314,7 +1314,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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(empty_in_named_args) @@ -1323,7 +1323,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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) @@ -1332,7 +1332,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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) @@ -1341,7 +1341,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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter) @@ -1383,13 +1383,13 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) return 5; } })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) @@ -1412,7 +1412,7 @@ BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) } uint256 a; })"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) @@ -1421,7 +1421,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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(enum_member_access) @@ -1466,7 +1466,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_member_access) ActionChoices choices; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) @@ -1481,7 +1481,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) ActionChoices choices; } )"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) @@ -1532,7 +1532,7 @@ BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay) uint64 b; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) @@ -1547,7 +1547,7 @@ BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(enum_duplicate_values) @@ -1557,7 +1557,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values) enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } } )"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name) @@ -1587,7 +1587,7 @@ BOOST_AUTO_TEST_CASE(private_visibility) function g() { f(); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) @@ -1600,7 +1600,7 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) function g() { base.f(); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_visibility) @@ -1611,7 +1611,7 @@ BOOST_AUTO_TEST_CASE(external_visibility) function g() { f(); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(external_base_visibility) @@ -1624,7 +1624,7 @@ BOOST_AUTO_TEST_CASE(external_base_visibility) function g() { base.f(); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_argument_assign) @@ -1634,7 +1634,7 @@ BOOST_AUTO_TEST_CASE(external_argument_assign) function f(uint a) external { a = 1; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_argument_increment) @@ -1644,7 +1644,7 @@ BOOST_AUTO_TEST_CASE(external_argument_increment) function f(uint a) external { a++; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_argument_delete) @@ -1654,7 +1654,7 @@ BOOST_AUTO_TEST_CASE(external_argument_delete) function f(uint a) external { delete a; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) @@ -1676,7 +1676,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) @@ -1687,7 +1687,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) uint[] b; function f() { b = a; } })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) @@ -1698,7 +1698,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) uint8[] b; function f() { b = a; } })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) @@ -1731,7 +1731,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) @@ -1740,7 +1740,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) contract c { uint8 a = 1000; })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) @@ -1749,7 +1749,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) contract c { uint a = "abc"; })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) @@ -1875,7 +1875,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(complex_const_variable) @@ -1885,7 +1885,7 @@ BOOST_AUTO_TEST_CASE(complex_const_variable) contract Foo { mapping(uint => bool) constant mapVar; })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(uninitialized_const_variable) @@ -1894,7 +1894,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable) contract Foo { uint constant y; })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) @@ -1906,7 +1906,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) function g() returns(uint) { return f(3, 5); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) @@ -1919,7 +1919,7 @@ BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) function g() returns(uint) { return f(1); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function) @@ -1942,7 +1942,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); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_types_clash) @@ -1956,7 +1956,7 @@ BOOST_AUTO_TEST_CASE(external_types_clash) function f(uint8 a) { } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(override_changes_return_types) @@ -1969,7 +1969,7 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types) function f(uint a) returns (uint8) { } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multiple_constructors) @@ -1980,7 +1980,7 @@ BOOST_AUTO_TEST_CASE(multiple_constructors) function test() {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(equal_overload) @@ -1991,7 +1991,7 @@ BOOST_AUTO_TEST_CASE(equal_overload) function test(uint a) external {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(uninitialized_var) @@ -2001,7 +2001,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_var) function f() returns (uint) { var x; return 2; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(string) @@ -2023,7 +2023,7 @@ BOOST_AUTO_TEST_CASE(string_index) function f() { var a = s[2]; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(string_length) @@ -2034,7 +2034,7 @@ BOOST_AUTO_TEST_CASE(string_length) function f() { var a = s.length; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) @@ -2044,7 +2044,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) int8 public i = -129; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_min) @@ -2064,7 +2064,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound) int8 public j = 128; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound_max) @@ -2084,7 +2084,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_unsigned) uint8 public x = -1; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) @@ -2094,7 +2094,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) uint8 public x = 700; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(integer_boolean_operators) @@ -2102,15 +2102,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); + BOOST_CHECK(expectError(sourceCode1).type() == Error::Type::TypeError); char const* sourceCode2 = R"( contract test { function() { uint x = 1; uint y = 2; x && y; } } )"; - BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode2).type() == Error::Type::TypeError); char const* sourceCode3 = R"( contract test { function() { uint x = 1; !x; } } )"; - BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode3).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(exp_signed_variable) @@ -2118,15 +2118,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); + BOOST_CHECK(expectError(sourceCode1).type() == Error::Type::TypeError); char const* sourceCode2 = R"( contract test { function() { uint x = 3; int y = -4; y ** x; } } )"; - BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode2).type() == Error::Type::TypeError); char const* sourceCode3 = R"( contract test { function() { int x = -3; int y = -4; x ** y; } } )"; - BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode3).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(reference_compare_operators) @@ -2134,11 +2134,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); + BOOST_CHECK(expectError(sourceCode1).type() == Error::Type::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); + BOOST_CHECK(expectError(sourceCode2).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) @@ -2148,7 +2148,7 @@ BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) function f(uint[] memory a) external {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) @@ -2158,7 +2158,7 @@ BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) function f(uint[] storage a) external {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(storage_location_local_variables) @@ -2184,7 +2184,7 @@ BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) @@ -2198,7 +2198,7 @@ BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) @@ -2215,7 +2215,7 @@ BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) @@ -2229,7 +2229,7 @@ BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly) @@ -2256,7 +2256,7 @@ BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem) @@ -2285,7 +2285,7 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) @@ -2300,7 +2300,7 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) @@ -2313,7 +2313,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(struct_constructor) @@ -2379,7 +2379,7 @@ BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) @@ -2394,7 +2394,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(string_bytes_conversion) @@ -2420,7 +2420,7 @@ BOOST_AUTO_TEST_CASE(inheriting_from_library) library Lib {} contract Test is Lib {} )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(inheriting_library) @@ -2429,7 +2429,7 @@ BOOST_AUTO_TEST_CASE(inheriting_library) contract Test {} library Lib is Test {} )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(library_having_variables) @@ -2437,7 +2437,7 @@ BOOST_AUTO_TEST_CASE(library_having_variables) char const* text = R"( library Lib { uint x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(valid_library) @@ -2470,7 +2470,7 @@ BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) function f() { var x = new Test(); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(array_out_of_bound_access) @@ -2484,7 +2484,7 @@ BOOST_AUTO_TEST_CASE(array_out_of_bound_access) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) @@ -2494,7 +2494,7 @@ BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) function f() { string x = "abc"; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(non_initialized_references) @@ -2513,7 +2513,7 @@ BOOST_AUTO_TEST_CASE(non_initialized_references) } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Uninitialized storage pointer")); } BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant) @@ -2524,7 +2524,7 @@ BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant) function f() { sha3(2**500); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) @@ -2534,7 +2534,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) @@ -2544,7 +2544,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) @@ -2552,7 +2552,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine) @@ -2583,7 +2583,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) function f() { var (a, b, ) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) { @@ -2593,7 +2593,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) function f() { var (a, , ) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) @@ -2604,7 +2604,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) function f() { var (, , a) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) @@ -2615,7 +2615,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) function f() { var (, a, b) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(tuples) @@ -2642,7 +2642,7 @@ BOOST_AUTO_TEST_CASE(tuples_empty_components) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) @@ -2653,7 +2653,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) function f() { var (,) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) @@ -2664,7 +2664,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) @@ -2707,7 +2707,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_library) using D for uint; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(using_for_function_exists) @@ -2798,7 +2798,7 @@ BOOST_AUTO_TEST_CASE(using_for_mismatch) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(using_for_not_used) @@ -2814,7 +2814,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_used) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(library_memory_struct) @@ -2825,7 +2825,7 @@ BOOST_AUTO_TEST_CASE(library_memory_struct) function f() returns (S ) {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) @@ -2840,7 +2840,7 @@ BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(bound_function_in_var) @@ -2886,7 +2886,7 @@ BOOST_AUTO_TEST_CASE(mapping_in_memory_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(new_for_non_array) @@ -2898,7 +2898,7 @@ BOOST_AUTO_TEST_CASE(new_for_non_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) @@ -2910,7 +2910,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_overload_array_type) @@ -3030,7 +3030,7 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(dynamic_inline_array) @@ -3055,7 +3055,7 @@ BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(break_not_in_loop) @@ -3068,7 +3068,7 @@ BOOST_AUTO_TEST_CASE(break_not_in_loop) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); } BOOST_AUTO_TEST_CASE(continue_not_in_loop) @@ -3081,7 +3081,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); } BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) @@ -3096,7 +3096,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); } BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) @@ -3108,7 +3108,7 @@ BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) @@ -3122,7 +3122,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) @@ -3142,7 +3142,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) @@ -3157,7 +3157,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) @@ -3175,7 +3175,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) @@ -3190,7 +3190,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(conditional_with_all_types) @@ -3287,7 +3287,7 @@ BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count) } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(index_access_for_bytes) @@ -3909,7 +3909,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_send) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); } BOOST_AUTO_TEST_CASE(unused_return_value_call) @@ -3921,7 +3921,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); } BOOST_AUTO_TEST_CASE(unused_return_value_call_value) @@ -3933,7 +3933,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call_value) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); } BOOST_AUTO_TEST_CASE(unused_return_value_callcode) @@ -3945,7 +3945,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_callcode) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); } BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) @@ -3957,7 +3957,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); } BOOST_AUTO_TEST_CASE(modifier_without_underscore) @@ -3967,7 +3967,7 @@ BOOST_AUTO_TEST_CASE(modifier_without_underscore) modifier m() {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); } BOOST_AUTO_TEST_CASE(payable_in_library) @@ -3977,7 +3977,7 @@ BOOST_AUTO_TEST_CASE(payable_in_library) function f() payable {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(payable_external) @@ -3997,7 +3997,7 @@ BOOST_AUTO_TEST_CASE(payable_internal) function f() payable internal {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(payable_private) @@ -4007,7 +4007,7 @@ BOOST_AUTO_TEST_CASE(payable_private) function f() payable private {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(illegal_override_payable) @@ -4016,7 +4016,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) @@ -4025,7 +4025,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(payable_constant_conflict) @@ -4033,7 +4033,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); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(calling_payable) @@ -4057,7 +4057,7 @@ BOOST_AUTO_TEST_CASE(calling_nonpayable) function f() { (new receiver()).nopay.value(10)(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(non_payable_constructor) @@ -4073,7 +4073,7 @@ BOOST_AUTO_TEST_CASE(non_payable_constructor) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) @@ -4082,7 +4082,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(sourceAndError.second->regex_search("Source file does not specify required compiler version!")); } BOOST_AUTO_TEST_CASE(unsatisfied_version) @@ -4090,7 +4090,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) @@ -4100,7 +4100,7 @@ BOOST_AUTO_TEST_CASE(constant_constructor) function test() constant {} } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_constructor) @@ -4110,7 +4110,7 @@ BOOST_AUTO_TEST_CASE(external_constructor) function test() external {} } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(invalid_array_as_statement) @@ -4121,7 +4121,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement) function test(uint k) { S[k]; } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) @@ -4140,7 +4140,7 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_type) @@ -4188,7 +4188,7 @@ BOOST_AUTO_TEST_CASE(private_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(public_function_type) @@ -4200,7 +4200,7 @@ BOOST_AUTO_TEST_CASE(public_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(payable_internal_function_type) @@ -4210,7 +4210,7 @@ BOOST_AUTO_TEST_CASE(payable_internal_function_type) function (uint) internal payable returns (uint) x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) @@ -4223,7 +4223,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) @@ -4233,7 +4233,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) function() external returns (function () internal) x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) @@ -4243,7 +4243,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) function(function () internal) external x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) @@ -4269,7 +4269,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) @@ -4281,7 +4281,7 @@ BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal) @@ -4303,7 +4303,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(function_type_arrays) @@ -4353,7 +4353,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type_invalid) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) @@ -4365,7 +4365,7 @@ BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) @@ -4377,7 +4377,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) @@ -4387,7 +4387,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) uint public a = 0x42 << -8; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) @@ -4397,7 +4397,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) uint public a = 0x42 >> -8; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) @@ -4407,7 +4407,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) uint public a = 0x42 << 0x100000000; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) @@ -4417,7 +4417,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) uint public a = 0x42 >> 0x100000000; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) @@ -4431,7 +4431,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Inline assembly block is not balanced")); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) @@ -4445,7 +4445,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + BOOST_CHECK(expectError(text, true).regex_search("Inline assembly block is not balanced")); } BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier) @@ -4478,7 +4478,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) @@ -4496,7 +4496,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::DeclarationError); } BOOST_AUTO_TEST_CASE(invalid_mobile_type) @@ -4509,7 +4509,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); } BOOST_AUTO_TEST_SUITE_END() From cace51fc470f2ff75e52637e10aa5100f3ca5be6 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 19:31:31 +0100 Subject: [PATCH 028/185] test: wrapping the error message checking in a macro --- libsolidity/interface/Exceptions.h | 5 +- .../SolidityNameAndTypeResolution.cpp | 566 +++++++++--------- 2 files changed, 296 insertions(+), 275 deletions(-) diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h index 6f38cba20..78eb88aa9 100644 --- a/libsolidity/interface/Exceptions.h +++ b/libsolidity/interface/Exceptions.h @@ -58,11 +58,10 @@ public: Type type() const { return m_type; } std::string const& typeName() const { return m_typeName; } - template - bool regex_search(T&& _reg) const + bool regex_search(const std::string& _reg) const { if (std::string const* str = boost::get_error_info(*this)) - return std::regex_search(*str, std::regex(std::forward(_reg))); + return std::regex_search(*str, std::regex(_reg)); else return false; } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 6932f852b..57ee86d64 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -160,6 +160,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(err.regex_search({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 +190,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 +199,7 @@ BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) " uint256 variable;\n" " uint128 variable;\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(double_function_declaration) @@ -186,7 +208,7 @@ BOOST_AUTO_TEST_CASE(double_function_declaration) " function fun() { uint x; }\n" " function fun() { uint x; }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(double_variable_declaration) @@ -194,7 +216,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).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(name_shadowing) @@ -203,7 +225,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 +234,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 +243,7 @@ BOOST_AUTO_TEST_CASE(undeclared_name) " uint256 variable;\n" " function f(uint256 arg) { f(notfound); }" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(reference_to_later_declaration) @@ -230,7 +252,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 +263,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) " MyStructName x;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) @@ -256,7 +278,7 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) " MyStructName1 x;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) @@ -267,7 +289,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 +301,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 +309,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 +317,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 +325,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) @@ -311,7 +333,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_checking_function_call) @@ -320,7 +342,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 +350,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 +358,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) @@ -344,7 +366,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 +374,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 +384,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 +394,7 @@ BOOST_AUTO_TEST_CASE(balance_invalid) " address(0).balance = 7;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_to_mapping) @@ -387,7 +409,7 @@ BOOST_AUTO_TEST_CASE(assignment_to_mapping) " data.map = a;\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_to_struct) @@ -402,7 +424,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 +433,7 @@ BOOST_AUTO_TEST_CASE(returns_in_constructor) " function test() returns (uint a) {\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(forward_function_reference) @@ -426,7 +448,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 +458,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 +521,7 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) function foo() { b = new base();} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional) @@ -543,7 +565,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) @@ -653,7 +675,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 +689,7 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) } function g (C c) external {} })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) @@ -683,7 +705,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 +721,7 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) g(a); } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(hash_collision_in_interface) @@ -710,7 +732,7 @@ BOOST_AUTO_TEST_CASE(hash_collision_in_interface) " function tgeo() {\n" " }\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(inheritance_basic) @@ -722,7 +744,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 +757,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 +766,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance) contract A is B { } contract B is A { } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(legal_override_direct) @@ -753,7 +775,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 +785,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 +794,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_visibility) contract B { function f() internal {} } contract C is B { function f() public {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(illegal_override_constness) @@ -781,7 +803,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_constness) contract B { function f() constant {} } contract C is B { function f() {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(complex_inheritance) @@ -791,7 +813,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 +823,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 +833,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 +842,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 +851,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 +862,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 +873,7 @@ BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) function f() { B b = A(1); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(super_excludes_current_contract) @@ -868,7 +890,7 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract) } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_modifier_invocation) @@ -880,7 +902,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 +913,7 @@ BOOST_AUTO_TEST_CASE(invalid_function_modifier_type) modifier mod1(uint a) { if (a > 0) _; } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) @@ -903,7 +925,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 +936,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 +945,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 +954,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(modifier_overrides_function) @@ -941,7 +963,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_overrides_modifier) @@ -950,7 +972,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(modifier_returns_value) @@ -961,7 +983,7 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value) modifier mod(uint a) { _; return 7; } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(state_variable_accessors) @@ -1012,7 +1034,7 @@ BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) "uint256 foo;\n" " function foo() {}\n" "}\n"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(private_state_variable) @@ -1045,7 +1067,7 @@ BOOST_AUTO_TEST_CASE(missing_state_variable) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } @@ -1058,7 +1080,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) @@ -1080,7 +1102,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 +1116,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) @@ -1109,7 +1131,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -1120,7 +1142,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 +1153,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) function(uint a) { x = 2; } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_in_library) @@ -1141,7 +1163,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_in_library) function() {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) @@ -1151,7 +1173,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) function() returns (uint) { } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) @@ -1162,7 +1184,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) function() constant { x = 2; } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_twice) @@ -1174,7 +1196,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice) function() { x = 3; } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_inheritance) @@ -1188,7 +1210,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 +1220,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 +1229,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) @@ -1216,7 +1238,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 +1247,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(event_call) @@ -1235,7 +1257,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 +1269,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 +1279,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 +1291,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 +1303,7 @@ BOOST_AUTO_TEST_CASE(access_to_internal_function) contract d { function g() { c(0).f(); } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) @@ -1293,7 +1315,7 @@ BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) contract d { function g() { c(0).a(); } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) @@ -1305,7 +1327,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 +1336,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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(empty_in_named_args) @@ -1323,7 +1345,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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) @@ -1332,7 +1354,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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) @@ -1341,7 +1363,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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter) @@ -1351,7 +1373,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 +1383,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 +1394,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 +1405,13 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) return 5; } })"; - BOOST_CHECK(expectError(text).type() == 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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) @@ -1412,7 +1434,7 @@ BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) } uint256 a; })"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) @@ -1421,7 +1443,7 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) contract test { function f() returns(uint d) { return 2 ** 10000000000; } })"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_member_access) @@ -1436,7 +1458,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 +1473,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 +1488,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_member_access) ActionChoices choices; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) @@ -1481,7 +1503,7 @@ BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) ActionChoices choices; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) @@ -1498,7 +1520,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 +1537,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 +1554,7 @@ BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay) uint64 b; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) @@ -1547,7 +1569,7 @@ BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_duplicate_values) @@ -1557,7 +1579,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values) enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name) @@ -1574,7 +1596,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) @@ -1587,7 +1609,7 @@ BOOST_AUTO_TEST_CASE(private_visibility) function g() { f(); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) @@ -1600,7 +1622,7 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) function g() { base.f(); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_visibility) @@ -1611,7 +1633,7 @@ BOOST_AUTO_TEST_CASE(external_visibility) function g() { f(); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(external_base_visibility) @@ -1624,7 +1646,7 @@ BOOST_AUTO_TEST_CASE(external_base_visibility) function g() { base.f(); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_argument_assign) @@ -1634,7 +1656,7 @@ BOOST_AUTO_TEST_CASE(external_argument_assign) function f(uint a) external { a = 1; } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_argument_increment) @@ -1644,7 +1666,7 @@ BOOST_AUTO_TEST_CASE(external_argument_increment) function f(uint a) external { a++; } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_argument_delete) @@ -1654,7 +1676,7 @@ BOOST_AUTO_TEST_CASE(external_argument_delete) function f(uint a) external { delete a; } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) @@ -1676,7 +1698,7 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) contract c { function f(uint a) { uint8[a] x; } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) @@ -1687,7 +1709,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) uint[] b; function f() { b = a; } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) @@ -1698,7 +1720,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) uint8[] b; function f() { b = a; } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) @@ -1709,7 +1731,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) @@ -1720,7 +1742,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) @@ -1731,7 +1753,7 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) uint[80] b; function f() { b = a; } })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) @@ -1740,7 +1762,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) contract c { uint8 a = 1000; })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) @@ -1749,7 +1771,7 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) contract c { uint a = "abc"; })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) @@ -1875,7 +1897,7 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) function changeIt() { x = 9; } uint constant x = 56; })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(complex_const_variable) @@ -1885,7 +1907,7 @@ BOOST_AUTO_TEST_CASE(complex_const_variable) contract Foo { mapping(uint => bool) constant mapVar; })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(uninitialized_const_variable) @@ -1894,7 +1916,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable) contract Foo { uint constant y; })"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) @@ -1906,7 +1928,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) function g() returns(uint) { return f(3, 5); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) @@ -1919,7 +1941,7 @@ BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) function g() returns(uint) { return f(1); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function) @@ -1942,7 +1964,7 @@ BOOST_AUTO_TEST_CASE(assignment_of_overloaded_function) function g() returns(uint) { var x = f; return x(7); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_types_clash) @@ -1956,7 +1978,7 @@ BOOST_AUTO_TEST_CASE(external_types_clash) function f(uint8 a) { } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(override_changes_return_types) @@ -1969,7 +1991,7 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types) function f(uint a) returns (uint8) { } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(multiple_constructors) @@ -1980,7 +2002,7 @@ BOOST_AUTO_TEST_CASE(multiple_constructors) function test() {} } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(equal_overload) @@ -1991,7 +2013,7 @@ BOOST_AUTO_TEST_CASE(equal_overload) function test(uint a) external {} } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::DeclarationError); + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(uninitialized_var) @@ -2001,7 +2023,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_var) function f() returns (uint) { var x; return 2; } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(string) @@ -2023,7 +2045,7 @@ BOOST_AUTO_TEST_CASE(string_index) function f() { var a = s[2]; } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(string_length) @@ -2034,7 +2056,7 @@ BOOST_AUTO_TEST_CASE(string_length) function f() { var a = s.length; } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) @@ -2044,7 +2066,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) int8 public i = -129; } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_min) @@ -2064,7 +2086,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound) int8 public j = 128; } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound_max) @@ -2084,7 +2106,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_unsigned) uint8 public x = -1; } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) @@ -2094,7 +2116,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) uint8 public x = 700; } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(integer_boolean_operators) @@ -2148,7 +2170,7 @@ BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) function f(uint[] memory a) external {} } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) @@ -2158,7 +2180,7 @@ BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) function f(uint[] storage a) external {} } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_location_local_variables) @@ -2184,7 +2206,7 @@ BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) @@ -2198,7 +2220,7 @@ BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) @@ -2215,7 +2237,7 @@ BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) @@ -2229,7 +2251,7 @@ BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly) @@ -2256,7 +2278,7 @@ BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem) @@ -2285,7 +2307,7 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) @@ -2300,7 +2322,7 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) @@ -2313,7 +2335,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_constructor) @@ -2367,7 +2389,7 @@ BOOST_AUTO_TEST_CASE(literal_strings) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp) @@ -2379,7 +2401,7 @@ BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) @@ -2394,7 +2416,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(string_bytes_conversion) @@ -2411,7 +2433,7 @@ BOOST_AUTO_TEST_CASE(string_bytes_conversion) function m() internal { string(b); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inheriting_from_library) @@ -2420,7 +2442,7 @@ BOOST_AUTO_TEST_CASE(inheriting_from_library) library Lib {} contract Test is Lib {} )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(inheriting_library) @@ -2429,7 +2451,7 @@ BOOST_AUTO_TEST_CASE(inheriting_library) contract Test {} library Lib is Test {} )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(library_having_variables) @@ -2437,7 +2459,7 @@ BOOST_AUTO_TEST_CASE(library_having_variables) char const* text = R"( library Lib { uint x; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(valid_library) @@ -2445,7 +2467,7 @@ BOOST_AUTO_TEST_CASE(valid_library) char const* text = R"( library Lib { uint constant x = 9; } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(call_to_library_function) @@ -2460,7 +2482,7 @@ BOOST_AUTO_TEST_CASE(call_to_library_function) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) @@ -2470,7 +2492,7 @@ BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) function f() { var x = new Test(); } } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_out_of_bound_access) @@ -2484,7 +2506,7 @@ BOOST_AUTO_TEST_CASE(array_out_of_bound_access) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) @@ -2494,7 +2516,7 @@ BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) function f() { string x = "abc"; } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(non_initialized_references) @@ -2513,7 +2535,7 @@ BOOST_AUTO_TEST_CASE(non_initialized_references) } )"; - BOOST_CHECK(expectError(text, true).regex_search("Uninitialized storage pointer")); + CHECK_WARNING(text, "Uninitialized storage pointer"); } BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant) @@ -2524,7 +2546,7 @@ BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant) function f() { sha3(2**500); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) @@ -2534,7 +2556,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) contract B { function f() { new C(); } } contract C { function f() { new A(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) @@ -2544,7 +2566,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).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) @@ -2552,7 +2574,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) char const* text = R"( contract C { function f() { var (x,y); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine) @@ -2572,7 +2594,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) @@ -2583,7 +2605,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) function f() { var (a, b, ) = one(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) { @@ -2593,7 +2615,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) function f() { var (a, , ) = one(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) @@ -2604,7 +2626,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) function f() { var (, , a) = one(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) @@ -2615,7 +2637,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) function f() { var (, a, b) = one(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(tuples) @@ -2630,7 +2652,7 @@ BOOST_AUTO_TEST_CASE(tuples) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(tuples_empty_components) @@ -2642,7 +2664,7 @@ BOOST_AUTO_TEST_CASE(tuples_empty_components) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) @@ -2653,7 +2675,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) function f() { var (,) = one(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) @@ -2664,7 +2686,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) function f() { var (a, b, c) = two(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) @@ -2685,7 +2707,7 @@ BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_library) @@ -2696,7 +2718,7 @@ BOOST_AUTO_TEST_CASE(using_for_library) using D for uint; } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_not_library) @@ -2707,7 +2729,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_library) using D for uint; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_for_function_exists) @@ -2721,7 +2743,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_exists) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_function_on_int) @@ -2735,7 +2757,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_function_on_struct) @@ -2750,7 +2772,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_overload) @@ -2769,7 +2791,7 @@ BOOST_AUTO_TEST_CASE(using_for_overload) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_by_name) @@ -2784,7 +2806,7 @@ BOOST_AUTO_TEST_CASE(using_for_by_name) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_mismatch) @@ -2798,7 +2820,7 @@ BOOST_AUTO_TEST_CASE(using_for_mismatch) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_for_not_used) @@ -2814,7 +2836,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_used) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(library_memory_struct) @@ -2840,7 +2862,7 @@ BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(bound_function_in_var) @@ -2856,7 +2878,7 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(create_memory_arrays) @@ -2874,7 +2896,7 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(mapping_in_memory_array) @@ -2886,7 +2908,7 @@ BOOST_AUTO_TEST_CASE(mapping_in_memory_array) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(new_for_non_array) @@ -2898,7 +2920,7 @@ BOOST_AUTO_TEST_CASE(new_for_non_array) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) @@ -2910,7 +2932,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_overload_array_type) @@ -2921,7 +2943,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) @@ -2937,7 +2959,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) @@ -2952,7 +2974,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) @@ -2965,7 +2987,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) @@ -2978,7 +3000,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) @@ -2990,7 +3012,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) @@ -3002,7 +3024,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) @@ -3018,7 +3040,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) @@ -3030,7 +3052,7 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(dynamic_inline_array) @@ -3042,7 +3064,7 @@ BOOST_AUTO_TEST_CASE(dynamic_inline_array) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) @@ -3055,7 +3077,7 @@ BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(break_not_in_loop) @@ -3068,7 +3090,7 @@ BOOST_AUTO_TEST_CASE(break_not_in_loop) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(continue_not_in_loop) @@ -3081,7 +3103,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) @@ -3096,7 +3118,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) @@ -3108,7 +3130,7 @@ BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) @@ -3122,7 +3144,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) @@ -3142,7 +3164,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) @@ -3157,7 +3179,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) @@ -3175,7 +3197,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) @@ -3190,7 +3212,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_with_all_types) @@ -3272,7 +3294,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) @@ -3287,7 +3309,7 @@ BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count) } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(index_access_for_bytes) @@ -3300,7 +3322,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) @@ -3316,7 +3338,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) @@ -3354,7 +3376,7 @@ BOOST_AUTO_TEST_CASE(bytes10abc_is_identifier) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(int10abc_is_identifier) @@ -3367,7 +3389,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) @@ -3451,7 +3473,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) @@ -3464,7 +3486,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) @@ -3477,7 +3499,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) @@ -3503,7 +3525,7 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) @@ -3518,7 +3540,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) @@ -3535,7 +3557,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) @@ -3574,7 +3596,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) @@ -3636,7 +3658,7 @@ BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(fixed_points_inside_structs) @@ -3650,7 +3672,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) @@ -3662,7 +3684,7 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_types) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_rationals) @@ -3674,7 +3696,7 @@ BOOST_AUTO_TEST_CASE(inline_array_rationals) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(rational_index_access) @@ -3705,7 +3727,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) @@ -3749,7 +3771,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) @@ -3761,7 +3783,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) @@ -3773,7 +3795,7 @@ BOOST_AUTO_TEST_CASE(var_handle_divided_integers) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation) @@ -3834,7 +3856,7 @@ BOOST_AUTO_TEST_CASE(zero_handling) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(missing_bool_conversion) @@ -3846,7 +3868,7 @@ BOOST_AUTO_TEST_CASE(missing_bool_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) @@ -3858,7 +3880,7 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(signed_rational_modulus) @@ -3872,7 +3894,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) @@ -3897,7 +3919,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(unused_return_value_send) @@ -3909,7 +3931,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_send) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_call) @@ -3921,7 +3943,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_call_value) @@ -3933,7 +3955,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call_value) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_callcode) @@ -3945,7 +3967,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_callcode) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) @@ -3957,7 +3979,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Return value of low-level calls not used")); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(modifier_without_underscore) @@ -3967,7 +3989,7 @@ BOOST_AUTO_TEST_CASE(modifier_without_underscore) modifier m() {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(payable_in_library) @@ -3977,7 +3999,7 @@ BOOST_AUTO_TEST_CASE(payable_in_library) function f() payable {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_external) @@ -3987,7 +4009,7 @@ BOOST_AUTO_TEST_CASE(payable_external) function f() payable external {} } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(payable_internal) @@ -3997,7 +4019,7 @@ BOOST_AUTO_TEST_CASE(payable_internal) function f() payable internal {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_private) @@ -4007,7 +4029,7 @@ BOOST_AUTO_TEST_CASE(payable_private) function f() payable private {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(illegal_override_payable) @@ -4016,7 +4038,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable) contract B { function f() payable {} } contract C is B { function f() {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) @@ -4025,7 +4047,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) contract B { function f() {} } contract C is B { function f() payable {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_constant_conflict) @@ -4033,7 +4055,7 @@ BOOST_AUTO_TEST_CASE(payable_constant_conflict) char const* text = R"( contract C { function f() payable constant {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(calling_payable) @@ -4046,7 +4068,7 @@ BOOST_AUTO_TEST_CASE(calling_payable) function g() { r.pay.value(10)(); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(calling_nonpayable) @@ -4057,7 +4079,7 @@ BOOST_AUTO_TEST_CASE(calling_nonpayable) function f() { (new receiver()).nopay.value(10)(); } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(non_payable_constructor) @@ -4073,7 +4095,7 @@ BOOST_AUTO_TEST_CASE(non_payable_constructor) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) @@ -4152,7 +4174,7 @@ BOOST_AUTO_TEST_CASE(function_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_type_parameter) @@ -4164,7 +4186,7 @@ BOOST_AUTO_TEST_CASE(function_type_parameter) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_type_returned) @@ -4176,7 +4198,7 @@ BOOST_AUTO_TEST_CASE(function_type_returned) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(private_function_type) @@ -4188,7 +4210,7 @@ BOOST_AUTO_TEST_CASE(private_function_type) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(public_function_type) @@ -4200,7 +4222,7 @@ BOOST_AUTO_TEST_CASE(public_function_type) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_internal_function_type) @@ -4210,7 +4232,7 @@ BOOST_AUTO_TEST_CASE(payable_internal_function_type) function (uint) internal payable returns (uint) x; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) @@ -4223,7 +4245,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) @@ -4233,7 +4255,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) function() external returns (function () internal) x; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) @@ -4243,7 +4265,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) function(function () internal) external x; } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) @@ -4256,7 +4278,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) @@ -4269,7 +4291,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) @@ -4281,7 +4303,7 @@ BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal) @@ -4292,7 +4314,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external) @@ -4303,7 +4325,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external } } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_type_arrays) @@ -4320,7 +4342,7 @@ BOOST_AUTO_TEST_CASE(function_type_arrays) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(delete_function_type) @@ -4341,7 +4363,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(delete_function_type_invalid) @@ -4431,7 +4453,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Inline assembly block is not balanced")); + CHECK_WARNING(text, "Inline assembly block is not balanced"); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) @@ -4445,7 +4467,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) } } )"; - BOOST_CHECK(expectError(text, true).regex_search("Inline assembly block is not balanced")); + CHECK_WARNING(text, "Inline assembly block is not balanced"); } BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier) @@ -4463,7 +4485,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_assembly_storage) @@ -4478,7 +4500,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) @@ -4496,7 +4518,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(invalid_mobile_type) @@ -4509,7 +4531,7 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_SUITE_END() From 2faaddca05549ecf3e716ec83faeffde6e8d4c2f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 22 Nov 2016 11:07:23 +0100 Subject: [PATCH 029/185] interface: fix the substring search --- libsolidity/interface/Exceptions.cpp | 7 +++++++ libsolidity/interface/Exceptions.h | 9 +-------- test/libsolidity/SolidityNameAndTypeResolution.cpp | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libsolidity/interface/Exceptions.cpp b/libsolidity/interface/Exceptions.cpp index 90a680b4d..f4ce8bc8b 100644 --- a/libsolidity/interface/Exceptions.cpp +++ b/libsolidity/interface/Exceptions.cpp @@ -56,3 +56,10 @@ Error::Error(Type _type): m_type(_type) break; } } + +bool Error::searchForSubstring(const std::string& _substr) const +{ + if (const std::string* str = boost::get_error_info(*this)) + return str->find(_substr) != std::string::npos; + return _substr.empty(); +} diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h index 78eb88aa9..a97699444 100644 --- a/libsolidity/interface/Exceptions.h +++ b/libsolidity/interface/Exceptions.h @@ -23,7 +23,6 @@ #pragma once #include -#include #include #include #include @@ -58,13 +57,7 @@ public: Type type() const { return m_type; } std::string const& typeName() const { return m_typeName; } - bool regex_search(const std::string& _reg) const - { - if (std::string const* str = boost::get_error_info(*this)) - return std::regex_search(*str, std::regex(_reg)); - else - return false; - } + bool searchForSubstring(const std::string& _substr) const; /// helper functions static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 57ee86d64..0022dfb22 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -165,7 +165,7 @@ do \ { \ Error err = expectError((text), (warning)); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ - BOOST_CHECK(err.regex_search({substring})); \ + BOOST_CHECK(err.searchForSubstring(substring)); \ } while(0) // [checkError(text, type, substring)] asserts that the compilation down to typechecking @@ -4104,7 +4104,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->regex_search("Source file does not specify required compiler version!")); + BOOST_CHECK(sourceAndError.second->searchForSubstring("Source file does not specify required compiler version!")); } BOOST_AUTO_TEST_CASE(unsatisfied_version) From d49904c92a890b058a46031c0c872f7b4abe936b Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 15 Nov 2016 11:23:43 +0100 Subject: [PATCH 030/185] test: add a test that compares overflown enums --- test/libsolidity/SolidityEndToEndTest.cpp | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index a9a887898..c7c627bec 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4506,6 +4506,39 @@ 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_as_external_ret) { char const* sourceCode = R"( From d4173cd54a7012456267cbabbd6c809f0d6763cb Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 15 Nov 2016 15:29:31 +0100 Subject: [PATCH 031/185] test: add a test about trying to log an event with too big enum values --- test/libsolidity/SolidityEndToEndTest.cpp | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c7c627bec..8b1c4836c 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4539,6 +4539,40 @@ BOOST_AUTO_TEST_CASE(invalid_enum_compared) 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_as_external_ret) { char const* sourceCode = R"( From feb10d015f6c8629ec24fcd2617332d67fb7f097 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 15 Nov 2016 15:37:05 +0100 Subject: [PATCH 032/185] test: add a test that stores an invalid enum value --- test/libsolidity/SolidityEndToEndTest.cpp | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 8b1c4836c..6478ea86a 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4573,6 +4573,35 @@ BOOST_AUTO_TEST_CASE(invalid_enum_logged) 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"( From 5b8a77398608689088938454583d284afd58ab50 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 15 Nov 2016 17:54:09 +0100 Subject: [PATCH 033/185] codegen: cleanup value types before storing them --- libsolidity/codegen/LValue.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 3f1730d15..933c04198 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -221,6 +221,11 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { solAssert(m_dataType->storageBytes() <= 32, "Invalid storage bytes size."); solAssert(m_dataType->storageBytes() > 0, "Invalid storage bytes size."); + + m_context << Instruction::SWAP2; + CompilerUtils(m_context).convertType(*m_dataType, *m_dataType, true); + m_context << Instruction::SWAP2; + if (m_dataType->storageBytes() == 32) { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size."); From 384c4546f172f8a0615036be9555774de6592fbc Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 16:45:17 +0100 Subject: [PATCH 034/185] interface: move searchForSubstring out of Error class into a separate file --- libsolidity/interface/Exceptions.cpp | 7 ---- test/libsolidity/ErrorCheck.cpp | 32 +++++++++++++++++++ test/libsolidity/ErrorCheck.h | 32 +++++++++++++++++++ .../SolidityNameAndTypeResolution.cpp | 5 +-- 4 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 test/libsolidity/ErrorCheck.cpp create mode 100644 test/libsolidity/ErrorCheck.h diff --git a/libsolidity/interface/Exceptions.cpp b/libsolidity/interface/Exceptions.cpp index f4ce8bc8b..90a680b4d 100644 --- a/libsolidity/interface/Exceptions.cpp +++ b/libsolidity/interface/Exceptions.cpp @@ -56,10 +56,3 @@ Error::Error(Type _type): m_type(_type) break; } } - -bool Error::searchForSubstring(const std::string& _substr) const -{ - if (const std::string* str = boost::get_error_info(*this)) - return str->find(_substr) != std::string::npos; - return _substr.empty(); -} diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp new file mode 100644 index 000000000..6dddda704 --- /dev/null +++ b/test/libsolidity/ErrorCheck.cpp @@ -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 . +*/ +/** @file ErrorCheck.cpp + * @author Yoichi Hirai + * @date 2016 + */ + +#include +#include + +#include + +bool dev::solidity::searchErrorMessage(Error const& _err, std::string const& _substr) +{ + if (const std::string* errorMessage = boost::get_error_info(_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 000000000..a309a9d30 --- /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 . +*/ +/** @file ErrorCheck.h + * @author Yoichi Hirai + * @date 2016 + */ + +#pragma once + +#include + +namespace dev +{ +namespace solidity +{ +bool searchErrorMessage(Error const& _err, std::string const& _substr); +} +} diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 0022dfb22..5671b00b6 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -31,6 +31,7 @@ #include #include #include "../TestHelper.h" +#include "ErrorCheck.h" using namespace std; @@ -165,7 +166,7 @@ do \ { \ Error err = expectError((text), (warning)); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ - BOOST_CHECK(err.searchForSubstring(substring)); \ + BOOST_CHECK(searchErrorMessage(err, substring)); \ } while(0) // [checkError(text, type, substring)] asserts that the compilation down to typechecking @@ -4104,7 +4105,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->searchForSubstring("Source file does not specify required compiler version!")); + BOOST_CHECK(searchErrorMessage(*sourceAndError.second, "Source file does not specify required compiler version!")); } BOOST_AUTO_TEST_CASE(unsatisfied_version) From c0fe5fbe9b474a9cd0db10db5e4410e7950d9a93 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 12:17:29 +0100 Subject: [PATCH 035/185] libevmasm: Add another peephole optimization --- libevmasm/AssemblyItem.h | 2 +- libevmasm/PeepholeOptimiser.cpp | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libevmasm/AssemblyItem.h b/libevmasm/AssemblyItem.h index 2bc28dbd6..b5bd3ed89 100644 --- a/libevmasm/AssemblyItem.h +++ b/libevmasm/AssemblyItem.h @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with solidity. If not, see . */ -/** @file Assembly.h +/** @file AssemblyItem.h * @author Gav Wood * @date 2014 */ diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index e93db9ac9..104d97699 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -15,7 +15,7 @@ along with solidity. If not, see . */ /** - * @file PeepholeOptimiser.h + * @file PeepholeOptimiser.cpp * Performs local optimising code changes to assembly. */ @@ -57,6 +57,31 @@ struct PushPop } }; +struct AddPop +{ + static size_t windowSize() { return 2; } + static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + { + if (_in[1] == Instruction::POP && + _in[0].type() == Operation + ) + { + Instruction i0 = _in[0].instruction(); + if (instructionInfo(i0).ret == 1 && + instructionInfo(i0).args == 2 && + !SemanticInformation::invalidatesMemory(i0) && + !SemanticInformation::invalidatesStorage(i0) + ) + { + *_out = Instruction::POP; + *_out = Instruction::POP; + return true; + } + } + return false; + } +}; + struct DoubleSwap { static size_t windowSize() { return 2; } @@ -136,7 +161,7 @@ bool PeepholeOptimiser::optimise() { OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) - applyMethods(state, PushPop(), DoubleSwap(), JumpToNext(), TagConjunctions(), Identity()); + applyMethods(state, PushPop(), AddPop(), DoubleSwap(), JumpToNext(), TagConjunctions(), Identity()); if (m_optimisedItems.size() < m_items.size()) { m_items = std::move(m_optimisedItems); From b6ffb6c8b7a581e1c3d0e7882be0d1606cc37509 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 18:21:57 +0100 Subject: [PATCH 036/185] libevmasm: generalize ADDPOP optimization into ADDMODPOP etc --- libevmasm/PeepholeOptimiser.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 104d97699..901e310ee 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -68,14 +68,15 @@ struct AddPop { Instruction i0 = _in[0].instruction(); if (instructionInfo(i0).ret == 1 && - instructionInfo(i0).args == 2 && !SemanticInformation::invalidatesMemory(i0) && - !SemanticInformation::invalidatesStorage(i0) + !SemanticInformation::invalidatesStorage(i0) && + !SemanticInformation::altersControlFlow(i0) && + !instructionInfo(i0).sideEffects ) { - *_out = Instruction::POP; - *_out = Instruction::POP; - return true; + for (int j = 0; j < instructionInfo(i0).args; j++) + *_out = Instruction::POP; + return true; } } return false; From a81f5563022e409d3e54e70177f2073c698c2238 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 19:22:26 +0100 Subject: [PATCH 037/185] test: various fixes --- test/libsolidity/ErrorCheck.cpp | 4 +- .../SolidityNameAndTypeResolution.cpp | 44 +++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp index 6dddda704..75555c9b5 100644 --- a/test/libsolidity/ErrorCheck.cpp +++ b/test/libsolidity/ErrorCheck.cpp @@ -24,9 +24,11 @@ #include +using namespace std; + bool dev::solidity::searchErrorMessage(Error const& _err, std::string const& _substr) { - if (const std::string* errorMessage = boost::get_error_info(_err)) + if (string const* errorMessage = boost::get_error_info(_err)) return errorMessage->find(_substr) != std::string::npos; return _substr.empty(); } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 5671b00b6..6dc7ac8c8 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -62,7 +62,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, SyntaxChecker syntaxChecker(errors); if (!syntaxChecker.checkSyntax(*sourceUnit)) - return make_pair(sourceUnit, errors[0]); + return make_pair(sourceUnit, errors.at(0)); std::shared_ptr globalContext = make_shared(); NameAndTypeResolver resolver(globalContext->declarations(), errors); @@ -1092,7 +1092,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) Data public data; } )"; - BOOST_CHECK(expectError(sourceCode).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member) @@ -2125,15 +2125,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).type() == 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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode2, TypeError, ""); char const* sourceCode3 = R"( contract test { function() { uint x = 1; !x; } } )"; - BOOST_CHECK(expectError(sourceCode3).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode3, TypeError, ""); } BOOST_AUTO_TEST_CASE(exp_signed_variable) @@ -2141,15 +2141,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).type() == 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).type() == 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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode3, TypeError, ""); } BOOST_AUTO_TEST_CASE(reference_compare_operators) @@ -2157,11 +2157,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).type() == 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).type() == Error::Type::TypeError); + CHECK_ERROR(sourceCode2, TypeError, ""); } BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) @@ -2848,7 +2848,7 @@ BOOST_AUTO_TEST_CASE(library_memory_struct) function f() returns (S ) {} } )"; - BOOST_CHECK(expectError(text).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) @@ -4123,7 +4123,7 @@ BOOST_AUTO_TEST_CASE(constant_constructor) function test() constant {} } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_constructor) @@ -4133,7 +4133,7 @@ BOOST_AUTO_TEST_CASE(external_constructor) function test() external {} } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_array_as_statement) @@ -4144,7 +4144,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement) function test(uint k) { S[k]; } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) @@ -4163,7 +4163,7 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_type) @@ -4376,7 +4376,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type_invalid) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) @@ -4388,7 +4388,7 @@ BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) @@ -4400,7 +4400,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) } } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) @@ -4410,7 +4410,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) uint public a = 0x42 << -8; } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) @@ -4420,7 +4420,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) uint public a = 0x42 >> -8; } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) @@ -4430,7 +4430,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) uint public a = 0x42 << 0x100000000; } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) @@ -4440,7 +4440,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) uint public a = 0x42 >> 0x100000000; } )"; - BOOST_CHECK(expectError(text, false).type() == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) From a87ed2895a5e45bc4edeb1028a17b4390e35487b Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 20:55:33 +0100 Subject: [PATCH 038/185] Remove declaration --- libsolidity/interface/Exceptions.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libsolidity/interface/Exceptions.h b/libsolidity/interface/Exceptions.h index a97699444..81716c41a 100644 --- a/libsolidity/interface/Exceptions.h +++ b/libsolidity/interface/Exceptions.h @@ -57,7 +57,6 @@ public: Type type() const { return m_type; } std::string const& typeName() const { return m_typeName; } - bool searchForSubstring(const std::string& _substr) const; /// helper functions static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type) From 5c662022a795e28f9eeeca6e8de4d0024c0b289c Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 21:48:16 +0100 Subject: [PATCH 039/185] Alpine base docker file. --- scripts/Dockerfile | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 scripts/Dockerfile diff --git a/scripts/Dockerfile b/scripts/Dockerfile new file mode 100644 index 000000000..e34436ed2 --- /dev/null +++ b/scripts/Dockerfile @@ -0,0 +1,12 @@ +FROM alpine +MAINTAINER chriseth + +RUN \ + apk --no-cache --update add build-base cmake boost-dev git && \ + sed -i -E -e 's/include /include /' /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/* From 6b9530399852ef8127c3cdc4e9da2f74450fcd6e Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 23:46:37 +0100 Subject: [PATCH 040/185] Docker documentation. --- docs/installing-solidity.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index ec40e8224..ce6318690 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -44,6 +44,19 @@ To install it, simply use Details about the usage of the Node.js package can be found in the `solc-js repository `_. +Docker +====== + +We provide up to date docker builds for the compiler: + +.. 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 =============== From 936bade46f3f6f44c3d0c0cc079a7de77104e2b9 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 23 Nov 2016 14:47:58 +0100 Subject: [PATCH 041/185] doc: add a section about input parameters and output parameters --- docs/control-structures.rst | 57 ++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index f57e7936e..015e55265 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -2,6 +2,53 @@ Expressions and Control Structures ################################## +.. index:: ! parameter, parameter;input, parameter;output + +Input Parameters and Output Parameters +====================================== + +Like in Javascript and in C, 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 type followed +by name (though unused input parameters do not need names). +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. +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 @@ -16,7 +63,15 @@ Parentheses can *not* be omitted for conditionals, but curly brances can be omit around single-statement bodies. Note that there is no type conversion from non-boolean to boolean types as -there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid Solidity. +there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid +Solidity. + +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 From 0599a14954aa0c22c992ae4585010a97cce63ca1 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 12:22:57 +0100 Subject: [PATCH 042/185] docs: cross-reference returning multiple values --- docs/control-structures.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 015e55265..4879a10e2 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -42,6 +42,9 @@ write:: } 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. @@ -66,6 +69,8 @@ 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. +.. _multi-return: + Returning Multiple Values ------------------------- From fed50403ffdf16806fd4bc0aee1587e22576d4d0 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 18:32:45 +0100 Subject: [PATCH 043/185] docs: cleaning references to C; smoothing parameter syntax description --- docs/control-structures.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 4879a10e2..974a093f2 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -7,15 +7,15 @@ Expressions and Control Structures Input Parameters and Output Parameters ====================================== -Like in Javascript and in C, functions may take parameters as input; +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 type followed -by name (though unused input parameters do not need names). +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:: @@ -57,7 +57,7 @@ of assignment. Control Structures =================== -Most of the control structures from C or JavaScript are available in Solidity +Most of the control structures from JavaScript are available in Solidity except for ``switch`` and ``goto``. So there is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, ``? :``, with the usual semantics known from C or JavaScript. From 76dd85edfacb1909a7de5807d369e69c8558deac Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 23 Nov 2016 15:18:46 +0100 Subject: [PATCH 044/185] docs: a bit more about literals --- docs/types.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 21575cfb2..85309f603 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -169,9 +169,13 @@ Fixed Point Numbers Rational and Integer Literals ----------------------------- -All number literals retain arbitrary precision until they are converted to a non-literal type (i.e. by -using them together with a non-literal type). This means that computations do not overflow but also -divisions do not truncate. +Integer literals and rational number literals belong to a special type. +The number literal type contains not just single literals +but all number literal expressions (i.e. the expressions that contain only number literals and operators). +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,7 +189,7 @@ 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). @@ -200,7 +204,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 +220,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. From a747f1d2c32c691b00f3b24fead8436195eb555e Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 10:54:40 +0100 Subject: [PATCH 045/185] docs: clarify how many number literal types are there --- docs/types.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 85309f603..83b0a0980 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -169,9 +169,13 @@ Fixed Point Numbers Rational and Integer Literals ----------------------------- -Integer literals and rational number literals belong to a special type. -The number literal type contains not just single literals -but all number literal expressions (i.e. the expressions that contain only number literals and operators). +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. + 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 From aaf58a8c4e802b1c3c4098066e0788e55600660a Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 13:13:47 +0100 Subject: [PATCH 046/185] test: add a test case converting an invalid UTF-8 into a string --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 6dc7ac8c8..6181a8a95 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2038,6 +2038,16 @@ BOOST_AUTO_TEST_CASE(string) BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); } +BOOST_AUTO_TEST_CASE(invalid_utf8) +{ + char const* sourceCode = R"( + contract C { + string s = "\xa0\x00"; + } + )"; + CHECK_ERROR(sourceCode, TypeError, "Invalid UTF-8"); +} + BOOST_AUTO_TEST_CASE(string_index) { char const* sourceCode = R"( From e136ec87041cce9d8d472e45f4dfbed9a8d02469 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 13:36:06 +0100 Subject: [PATCH 047/185] ast: string literals that are not valid UTF are not convertible to strings --- libdevcore/UTF8.h | 2 +- libsolidity/ast/Types.cpp | 9 ++++++++- libsolidity/ast/Types.h | 2 ++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libdevcore/UTF8.h b/libdevcore/UTF8.h index 3e39273cd..9bdc2b4f2 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/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index b7de3646c..002ad657b 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -879,7 +879,8 @@ bool StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const else if (auto arrayType = dynamic_cast(&_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(DataLocation::Memory, true); } +bool StringLiteralType::isValidUTF8() const +{ + size_t dontCare {}; + return dev::validate(m_value, dontCare); +} + shared_ptr FixedBytesType::smallestTypeForLiteral(string const& _literal) { if (_literal.length() <= 32) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index b713a7c01..72640a1c4 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -425,6 +425,8 @@ public: virtual std::string toString(bool) const override; virtual TypePointer mobileType() const override; + bool isValidUTF8() const; + std::string const& value() const { return m_value; } private: diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 6181a8a95..cc4da61b0 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2045,7 +2045,7 @@ BOOST_AUTO_TEST_CASE(invalid_utf8) string s = "\xa0\x00"; } )"; - CHECK_ERROR(sourceCode, TypeError, "Invalid UTF-8"); + CHECK_ERROR(sourceCode, TypeError, "invalid UTF-8"); } BOOST_AUTO_TEST_CASE(string_index) From df5d5edd1b7cb2e9f26d3a2491442185e0ffc17a Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 13:54:13 +0100 Subject: [PATCH 048/185] test: add a test about explicitly converting a string literal to string --- Changelog.md | 5 +++++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 468518d2a..0b10cd0ce 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,8 @@ +### 0.4.7 (unreleased) + +Bugfixes: + * Type checker: string literals that are not valid UTF-8 cannot be converted to string type + ### 0.4.6 (2016-11-22) Bugfixes: diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index cc4da61b0..7a132068f 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2038,7 +2038,7 @@ BOOST_AUTO_TEST_CASE(string) BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); } -BOOST_AUTO_TEST_CASE(invalid_utf8) +BOOST_AUTO_TEST_CASE(invalid_utf8_implicit) { char const* sourceCode = R"( contract C { @@ -2048,6 +2048,16 @@ BOOST_AUTO_TEST_CASE(invalid_utf8) 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"( From da566b956e15d1b3b44fd1f3a9dccaee2b7f8b41 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 25 Nov 2016 14:36:44 +0100 Subject: [PATCH 049/185] Indentation. --- libsolidity/ast/Types.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 002ad657b..b22f3c086 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -880,7 +880,7 @@ bool StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const return arrayType->isByteArray() && !(arrayType->dataStoredIn(DataLocation::Storage) && arrayType->isPointer()) && - !(arrayType->isString() && !isValidUTF8()); + !(arrayType->isString() && !isValidUTF8()); else return false; } From a755805879eb3cfb22bbe3845dc61a288f64a0e0 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 14:51:38 +0100 Subject: [PATCH 050/185] Update types.rst --- docs/types.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 83b0a0980..0436fc708 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -169,13 +169,6 @@ Fixed Point Numbers Rational and Integer Literals ----------------------------- -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. - 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 @@ -198,6 +191,14 @@ long as the operands are integers. If any of the two is fractional, bit operatio 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 From 56d664108614fa8fdf63a02d8f605bf5afcd0837 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 16:41:02 +0100 Subject: [PATCH 051/185] codegen: cleanup stored values in a more consistent way --- libsolidity/codegen/LValue.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 933c04198..788545881 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -216,16 +216,14 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _location, bool _move) const { CompilerUtils utils(m_context); + solAssert(m_dataType, ""); + // stack: value storage_key storage_offset if (m_dataType->isValueType()) { solAssert(m_dataType->storageBytes() <= 32, "Invalid storage bytes size."); solAssert(m_dataType->storageBytes() > 0, "Invalid storage bytes size."); - m_context << Instruction::SWAP2; - CompilerUtils(m_context).convertType(*m_dataType, *m_dataType, true); - m_context << Instruction::SWAP2; - if (m_dataType->storageBytes() == 32) { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size."); @@ -233,10 +231,23 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::POP; if (!_move) m_context << Instruction::DUP2 << Instruction::SWAP1; + + m_context << Instruction::SWAP1; + utils.convertType(_sourceType, _sourceType, true); + utils.convertType(*m_dataType, *m_dataType, true); + m_context << Instruction::SWAP1; + m_context << Instruction::SSTORE; } else { + if (_sourceType.sizeOnStack() == 1) + { + m_context << Instruction::SWAP2; + utils.convertType(_sourceType, _sourceType, true); + m_context << Instruction::SWAP2; + } + // OR the value into the other values in the storage slot m_context << u256(0x100) << Instruction::EXP; // stack: value storage_ref multiplier @@ -269,6 +280,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type."); // remove the higher order bits + utils.convertType(*m_dataType, *m_dataType, true); m_context << (u256(1) << (8 * (32 - m_dataType->storageBytes()))) << Instruction::SWAP1 From ea628001d5f34ee1d85398a17f93e7c4f55429fe Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 17:07:10 +0100 Subject: [PATCH 052/185] codegen: add an option to CovertType so that it can truncate sign bits --- libsolidity/codegen/CompilerUtils.cpp | 20 +++++++++++++++++++- libsolidity/codegen/CompilerUtils.h | 2 +- libsolidity/codegen/LValue.cpp | 10 ++-------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index fe2b9c7e1..21dd28406 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -358,7 +358,7 @@ void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function) Instruction::OR; } -void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded) +void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded, bool _chopSignBits) { // For a type extension, we need to remove all higher-order bits that we might have ignored in // previous operations. @@ -370,6 +370,12 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp Type::Category targetTypeCategory = _targetType.category(); bool enumOverflowCheckPending = (targetTypeCategory == Type::Category::Enum || stackTypeCategory == Type::Category::Enum); + bool chopSignBitsPending = _chopSignBits && targetTypeCategory == Type::Category::Integer; + if (chopSignBitsPending) + { + const IntegerType& targetIntegerType = dynamic_cast(_targetType); + chopSignBitsPending = targetIntegerType.isSigned(); + } switch (stackTypeCategory) { @@ -482,6 +488,17 @@ 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) << (256 - typeOnStack.numBits())) + << Instruction::SWAP1 + << Instruction::DUP2 + << Instruction::MUL + << Instruction::DIV; + chopSignBitsPending = false; + } } } break; @@ -728,6 +745,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp } solAssert(!enumOverflowCheckPending, "enum overflow checking missing."); + solAssert(!chopSignBitsPending, "forgot to chop the sign bits."); } void CompilerUtils::pushZeroValue(Type const& _type) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index ff87124fe..977e96d98 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -130,7 +130,7 @@ public: /// if a reference type is converted from calldata or storage to memory. /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be /// necessary. - void convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded = false); + 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/LValue.cpp b/libsolidity/codegen/LValue.cpp index 788545881..df74e836d 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -234,7 +234,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::SWAP1; utils.convertType(_sourceType, _sourceType, true); - utils.convertType(*m_dataType, *m_dataType, true); + utils.convertType(*m_dataType, *m_dataType, true, true); m_context << Instruction::SWAP1; m_context << Instruction::SSTORE; @@ -280,13 +280,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type."); // remove the higher order bits - utils.convertType(*m_dataType, *m_dataType, true); - m_context - << (u256(1) << (8 * (32 - m_dataType->storageBytes()))) - << Instruction::SWAP1 - << Instruction::DUP2 - << Instruction::MUL - << Instruction::DIV; + utils.convertType(*m_dataType, *m_dataType, true, true); } m_context << Instruction::MUL << Instruction::OR; // stack: value storage_ref updated_value From 3fb9625127c869b3d5b4b8e590dc6feb52e4eeec Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 11:31:14 +0100 Subject: [PATCH 053/185] codegen: document _chopSignBits parameter of convertType function --- libsolidity/codegen/CompilerUtils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 977e96d98..4baf48ff1 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -130,6 +130,7 @@ public: /// if a reference type is converted from calldata or storage to memory. /// If @a _cleanupNeeded, high order bits cleanup is also done if no type conversion would be /// necessary. + /// 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 From 9d25b5601e6e2713e14803777390c2d45be3d51c Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 16:49:54 +0100 Subject: [PATCH 054/185] codegen: merge type conversion and cleaning up --- libsolidity/codegen/LValue.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index df74e836d..63729d272 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -233,8 +233,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::DUP2 << Instruction::SWAP1; m_context << Instruction::SWAP1; - utils.convertType(_sourceType, _sourceType, true); - utils.convertType(*m_dataType, *m_dataType, true, true); + utils.convertType(_sourceType, *m_dataType, true); m_context << Instruction::SWAP1; m_context << Instruction::SSTORE; @@ -244,7 +243,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc if (_sourceType.sizeOnStack() == 1) { m_context << Instruction::SWAP2; - utils.convertType(_sourceType, _sourceType, true); + utils.convertType(_sourceType, *m_dataType, true); m_context << Instruction::SWAP2; } From fa486f5b44790e5abda28ddb2b798d0b1408269f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 17:03:17 +0100 Subject: [PATCH 055/185] codegen: shorten the bit truncation --- libsolidity/codegen/CompilerUtils.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 21dd28406..41559a428 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -492,11 +492,8 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp { if (typeOnStack.numBits() < 256) m_context - << (u256(1) << (256 - typeOnStack.numBits())) - << Instruction::SWAP1 - << Instruction::DUP2 - << Instruction::MUL - << Instruction::DIV; + << ((u256(1) << typeOnStack.numBits()) - 1) + << Instruction::AND; chopSignBitsPending = false; } } From 548b7ce42d1650d18ce71c3d11486ab4d27e6c0f Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 15:38:02 +0100 Subject: [PATCH 056/185] codegen: storing of non-value types; add some assertions --- libsolidity/codegen/LValue.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 63729d272..23fe2d4e7 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -240,13 +240,6 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc } else { - if (_sourceType.sizeOnStack() == 1) - { - m_context << Instruction::SWAP2; - utils.convertType(_sourceType, *m_dataType, true); - m_context << Instruction::SWAP2; - } - // OR the value into the other values in the storage slot m_context << u256(0x100) << Instruction::EXP; // stack: value storage_ref multiplier @@ -263,6 +256,7 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc // stack: value storage_ref cleared_value multiplier value if (FunctionType const* fun = dynamic_cast(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); @@ -272,14 +266,17 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc Instruction::AND; } else if (m_dataType->category() == Type::Category::FixedBytes) + { + solAssert(_sourceType.category() == Type::Category::FixedBytes, "source not fixed bytes"); m_context << (u256(0x1) << (256 - 8 * dynamic_cast(*m_dataType).numBytes())) << Instruction::SWAP1 << Instruction::DIV; + } else { solAssert(m_dataType->sizeOnStack() == 1, "Invalid stack size for opaque type."); // remove the higher order bits - utils.convertType(*m_dataType, *m_dataType, true, true); + utils.convertType(_sourceType, *m_dataType, true, true); } m_context << Instruction::MUL << Instruction::OR; // stack: value storage_ref updated_value From 0be58595036d3411124bc8b39f9d151790d950b4 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 15:50:46 +0100 Subject: [PATCH 057/185] codegen: cleanup values to fit in storage bytes --- libsolidity/codegen/CompilerUtils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 41559a428..d5361ac6a 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -738,6 +738,10 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp default: // All other types should not be convertible to non-equal types. solAssert(_typeOnStack == _targetType, "Invalid type conversion requested."); + if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32) + m_context + << ((u256(1) << (8 * _targetType.storageBytes())) - 1) + << Instruction::AND; break; } From f2872bfa9990c483fddc72757ee764cbc79d126c Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 22 Nov 2016 15:43:51 +0100 Subject: [PATCH 058/185] Peephole optimizer for unreacheable code. --- libevmasm/PeepholeOptimiser.cpp | 110 ++++++++++++++++--------- test/libsolidity/SolidityOptimizer.cpp | 48 +++++++++-- 2 files changed, 116 insertions(+), 42 deletions(-) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 901e310ee..16ca95355 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -30,36 +30,55 @@ using namespace dev; // TODO: Extend this to use the tools from ExpressionClasses.cpp -struct Identity +struct OptimiserState { - static size_t windowSize() { return 1; } - static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + AssemblyItems const& items; + size_t i; + std::back_insert_iterator out; +}; + +template +struct SimplePeepholeOptimizerMethod +{ + static bool apply(OptimiserState& _state) + { + if ( + _state.i + WindowSize <= _state.items.size() && + Method::applySimple(_state.items.begin() + _state.i, _state.out) + ) + { + _state.i += WindowSize; + return true; + } + else + return false; + } +}; + +struct Identity: SimplePeepholeOptimizerMethod +{ + static bool applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) { *_out = *_in; return true; } }; -struct PushPop +struct PushPop: SimplePeepholeOptimizerMethod { - static size_t windowSize() { return 2; } - static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator) + static size_t applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator) { auto t = _in[0].type(); - if (_in[1] == Instruction::POP && ( + return _in[1] == Instruction::POP && ( SemanticInformation::isDupInstruction(_in[0]) || t == Push || t == PushString || t == PushTag || t == PushSub || t == PushSubSize || t == PushProgramSize || t == PushData || t == PushLibraryAddress - )) - return true; - else - return false; + ); } }; -struct AddPop +struct AddPop: SimplePeepholeOptimizerMethod { - static size_t windowSize() { return 2; } static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) { if (_in[1] == Instruction::POP && @@ -83,22 +102,17 @@ struct AddPop } }; -struct DoubleSwap +struct DoubleSwap: SimplePeepholeOptimizerMethod { - static size_t windowSize() { return 2; } - static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator) + static size_t applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator) { - if (_in[0] == _in[1] && SemanticInformation::isSwapInstruction(_in[0])) - return true; - else - return false; + return _in[0] == _in[1] && SemanticInformation::isSwapInstruction(_in[0]); } }; -struct JumpToNext +struct JumpToNext: SimplePeepholeOptimizerMethod { - static size_t windowSize() { return 3; } - static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + static size_t applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) { if ( _in[0].type() == PushTag && @@ -117,10 +131,41 @@ struct JumpToNext } }; -struct TagConjunctions +/// Removes everything after a JUMP (or similar) until the next JUMPDEST. +struct UnreachableCode { - static size_t windowSize() { return 3; } - static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + static bool apply(OptimiserState& _state) + { + auto it = _state.items.begin() + _state.i; + auto end = _state.items.end(); + if (it == end) + return false; + if ( + it[0] != Instruction::JUMP && + it[0] != Instruction::RETURN && + it[0] != Instruction::STOP && + it[0] != Instruction::SUICIDE + ) + return false; + + size_t i = 1; + while (it + i != end && it[i].type() != Tag) + i++; + if (i > 1) + { + *_state.out = it[0]; + _state.i += i; + return true; + } + else + return false; + } +}; + + +struct TagConjunctions: SimplePeepholeOptimizerMethod +{ + static bool applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) { if ( _in[0].type() == PushTag && @@ -137,13 +182,6 @@ struct TagConjunctions } }; -struct OptimiserState -{ - AssemblyItems const& items; - size_t i; - std::back_insert_iterator out; -}; - void applyMethods(OptimiserState&) { assertThrow(false, OptimizerException, "Peephole optimizer failed to apply identity."); @@ -152,9 +190,7 @@ void applyMethods(OptimiserState&) template void applyMethods(OptimiserState& _state, Method, OtherMethods... _other) { - if (_state.i + Method::windowSize() <= _state.items.size() && Method::apply(_state.items.begin() + _state.i, _state.out)) - _state.i += Method::windowSize(); - else + if (!Method::apply(_state)) applyMethods(_state, _other...); } @@ -162,7 +198,7 @@ bool PeepholeOptimiser::optimise() { OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) - applyMethods(state, PushPop(), AddPop(), DoubleSwap(), JumpToNext(), TagConjunctions(), Identity()); + applyMethods(state, PushPop(), AddPop(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); if (m_optimisedItems.size() < m_items.size()) { m_items = std::move(m_optimisedItems); diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index ecb44272e..a53a26384 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -20,17 +20,21 @@ * Tests for the Solidity optimizer. */ -#include -#include -#include -#include -#include #include + #include +#include #include #include #include +#include +#include + +#include +#include +#include + using namespace std; using namespace dev::eth; @@ -1121,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"( From 612c1726d9b0dd1cb5bccd9b93ace69f6516f9ea Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 23 Nov 2016 14:50:20 +0100 Subject: [PATCH 059/185] Templatize. --- libevmasm/PeepholeOptimiser.cpp | 112 +++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 16ca95355..c8a28afcb 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -37,6 +37,35 @@ struct OptimiserState std::back_insert_iterator out; }; +template +struct ApplyRule +{ +}; +template +struct ApplyRule +{ + static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + { + return Method::applySimple(_in[0], _in[1], _in[2], _out); + } +}; +template +struct ApplyRule +{ + static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + { + return Method::applySimple(_in[0], _in[1], _out); + } +}; +template +struct ApplyRule +{ + static bool applyRule(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + { + return Method::applySimple(_in[0], _out); + } +}; + template struct SimplePeepholeOptimizerMethod { @@ -44,7 +73,7 @@ struct SimplePeepholeOptimizerMethod { if ( _state.i + WindowSize <= _state.items.size() && - Method::applySimple(_state.items.begin() + _state.i, _state.out) + ApplyRule::applyRule(_state.items.begin() + _state.i, _state.out) ) { _state.i += WindowSize; @@ -57,20 +86,20 @@ struct SimplePeepholeOptimizerMethod struct Identity: SimplePeepholeOptimizerMethod { - static bool applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + static bool applySimple(AssemblyItem const& _item, std::back_insert_iterator _out) { - *_out = *_in; + *_out = _item; return true; } }; struct PushPop: SimplePeepholeOptimizerMethod { - static size_t applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator) + static size_t applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator) { - auto t = _in[0].type(); - return _in[1] == Instruction::POP && ( - SemanticInformation::isDupInstruction(_in[0]) || + 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 ); @@ -104,26 +133,55 @@ struct AddPop: SimplePeepholeOptimizerMethod struct DoubleSwap: SimplePeepholeOptimizerMethod { - static size_t applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator) + static size_t applySimple(AssemblyItem const& _s1, AssemblyItem const& _s2, std::back_insert_iterator) { - return _in[0] == _in[1] && SemanticInformation::isSwapInstruction(_in[0]); + return _s1 == _s2 && SemanticInformation::isSwapInstruction(_s1); } }; struct JumpToNext: SimplePeepholeOptimizerMethod { - static size_t applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + static size_t applySimple( + AssemblyItem const& _pushTag, + AssemblyItem const& _jump, + AssemblyItem const& _tag, + std::back_insert_iterator _out + ) { if ( - _in[0].type() == PushTag && - (_in[1] == Instruction::JUMP || _in[1] == Instruction::JUMPI) && - _in[2].type() == Tag && - _in[0].data() == _in[2].data() + _pushTag.type() == PushTag && + (_jump == Instruction::JUMP || _jump == Instruction::JUMPI) && + _tag.type() == Tag && + _pushTag.data() == _tag.data() ) { - if (_in[1] == Instruction::JUMPI) - *_out = AssemblyItem(Instruction::POP, _in[1].location()); - *_out = _in[2]; + if (_jump == Instruction::JUMPI) + *_out = AssemblyItem(Instruction::POP, _jump.location()); + *_out = _tag; + return true; + } + else + return false; + } +}; + +struct TagConjunctions: SimplePeepholeOptimizerMethod +{ + static bool applySimple( + AssemblyItem const& _pushTag, + AssemblyItem const& _pushConstant, + AssemblyItem const& _and, + std::back_insert_iterator _out + ) + { + if ( + _pushTag.type() == PushTag && + _and == Instruction::AND && + _pushConstant.type() == Push && + (_pushConstant.data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF) + ) + { + *_out = _pushTag; return true; } else @@ -162,26 +220,6 @@ struct UnreachableCode } }; - -struct TagConjunctions: SimplePeepholeOptimizerMethod -{ - static bool applySimple(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) - { - if ( - _in[0].type() == PushTag && - _in[2] == Instruction::AND && - _in[1].type() == Push && - (_in[1].data() & u256(0xFFFFFFFF)) == u256(0xFFFFFFFF) - ) - { - *_out = _in[0]; - return true; - } - else - return false; - } -}; - void applyMethods(OptimiserState&) { assertThrow(false, OptimizerException, "Peephole optimizer failed to apply identity."); From 8a78b1951600a936fadae6ea1644a49e491366f0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 23 Nov 2016 14:53:59 +0100 Subject: [PATCH 060/185] Changelog. --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 0b10cd0ce..b5e48173c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ ### 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 From f5216249527a82834162d66f93f15a50346e38d4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 21:08:30 +0100 Subject: [PATCH 061/185] Integrate AddPop. --- libevmasm/Assembly.cpp | 2 +- libevmasm/PeepholeOptimiser.cpp | 27 ++++++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index 963067509..edbb9828f 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -337,7 +337,7 @@ map Assembly::optimiseInternal(bool _enable, bool _isCreation, size_ count = 0; PeepholeOptimiser peepOpt(m_items); - if (peepOpt.optimise()) + while (peepOpt.optimise()) count++; if (!_enable) diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index c8a28afcb..b96b02950 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -95,7 +95,7 @@ struct Identity: SimplePeepholeOptimizerMethod struct PushPop: SimplePeepholeOptimizerMethod { - static size_t applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator) + static bool applySimple(AssemblyItem const& _push, AssemblyItem const& _pop, std::back_insert_iterator) { auto t = _push.type(); return _pop == Instruction::POP && ( @@ -106,23 +106,20 @@ struct PushPop: SimplePeepholeOptimizerMethod } }; -struct AddPop: SimplePeepholeOptimizerMethod +struct OpPop: SimplePeepholeOptimizerMethod { - static bool apply(AssemblyItems::const_iterator _in, std::back_insert_iterator _out) + static bool applySimple( + AssemblyItem const& _op, + AssemblyItem const& _pop, + std::back_insert_iterator _out + ) { - if (_in[1] == Instruction::POP && - _in[0].type() == Operation - ) + if (_pop == Instruction::POP && _op.type() == Operation) { - Instruction i0 = _in[0].instruction(); - if (instructionInfo(i0).ret == 1 && - !SemanticInformation::invalidatesMemory(i0) && - !SemanticInformation::invalidatesStorage(i0) && - !SemanticInformation::altersControlFlow(i0) && - !instructionInfo(i0).sideEffects - ) + Instruction instr = _op.instruction(); + if (instructionInfo(instr).ret == 1 && !instructionInfo(instr).sideEffects) { - for (int j = 0; j < instructionInfo(i0).args; j++) + for (int j = 0; j < instructionInfo(instr).args; j++) *_out = Instruction::POP; return true; } @@ -236,7 +233,7 @@ bool PeepholeOptimiser::optimise() { OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) - applyMethods(state, PushPop(), AddPop(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); + applyMethods(state, PushPop(), OpPop(), DoubleSwap(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); if (m_optimisedItems.size() < m_items.size()) { m_items = std::move(m_optimisedItems); From cf4e0549c35bf2a4fc4629e427099ca526234790 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 25 Nov 2016 16:21:17 +0100 Subject: [PATCH 062/185] Mention nightly. --- docs/installing-solidity.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index ce6318690..ef38705cb 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -47,7 +47,9 @@ Details about the usage of the Node.js package can be found in the Docker ====== -We provide up to date docker builds for the compiler: +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 From eee10f1af27cb3c9e94b9e4bcb5d78f02cf4192d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 8 Nov 2016 17:16:45 +0000 Subject: [PATCH 063/185] LLL: simplify the LIT parsing code --- liblll/CodeFragment.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 1bf587cec..9257e7390 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -281,18 +281,27 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) bytes data; for (auto const& i: _t) { - if (ii == 1) + if (ii == 0) + { + ii++; + continue; + } + else if (ii == 1) { pos = CodeFragment(i, _s); if (pos.m_asm.deposit() != 1) error(); } - else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::string_type) + else if (i.tag() != 0) + { + error(); + } + else if (i.which() == sp::utree_type::string_type) { auto sr = i.get, sp::utree_type::string_type>>(); data.insert(data.end(), (byte const *)sr.begin(), (byte const*)sr.end()); } - else if (ii >= 2 && !i.tag() && i.which() == sp::utree_type::any_type) + else if (i.which() == sp::utree_type::any_type) { bigint bi = *i.get(); if (bi < 0) @@ -303,9 +312,12 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) data.insert(data.end(), tmp.begin(), tmp.end()); } } - else if (ii) + else + { error(); - ++ii; + } + + ii++; } m_asm.append((u256)data.size()); m_asm.append(Instruction::DUP1); From f1bc979c0f2586b69909f36af48362d7dc9da9e7 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 17 Nov 2016 23:22:09 +0000 Subject: [PATCH 064/185] Use solUnimplemented wherever possible --- libsolidity/codegen/ArrayUtils.cpp | 2 +- libsolidity/codegen/ExpressionCompiler.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index c0eb736a0..2c982982e 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -200,7 +200,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons else if (sourceBaseType->isValueType()) CompilerUtils(m_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false); else - solAssert(false, "Copying of type " + _sourceType.toString(false) + " to storage not yet supported."); + solUnimplemented("Copying of type " + _sourceType.toString(false) + " to storage not yet supported."); // stack: target_ref target_data_end source_data_pos target_data_pos source_data_end [target_byte_offset] [source_byte_offset] ... solAssert( 2 + byteOffsetSize + sourceBaseType->sizeOnStack() <= 16, diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 58330764f..5748d818b 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1252,7 +1252,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) case Type::Category::StringLiteral: break; // will be done during conversion default: - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now.")); + solUnimplemented("Only integer, boolean and string literals implemented for now."); } } @@ -1392,7 +1392,7 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator) void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator) { - BOOST_THROW_EXCEPTION(UnimplementedFeatureError() << errinfo_comment("Shift operators not yet implemented.")); + solUnimplemented("Shift operators not yet implemented."); switch (_operator) { case Token::SHL: From 83892399f08aba920cdd50b36bf928fd20cfff45 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 13:13:42 +0000 Subject: [PATCH 065/185] Explain how to run soltest --- docs/contributing.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/contributing.rst b/docs/contributing.rst index 111fb9322..42204d5c4 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -59,3 +59,18 @@ for this project. Also, even though we do CI testing, please test your code and ensure that it builds locally before submitting a pull request. Thank you for your help! + +Running the compiler tests +========================== + +Solidity includes different types of tests. They are included in the application +called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode. + +To run ``cpp-ethereum`` in testing mode: ``eth --test -d /tmp/testeth``. + +To run the tests: ``soltest -- --ipcpath /tmp/testeth/geth.ipc``. + +To run a subset of tests, filters can be used: +``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc``, where ``TestName`` can be a wildcard ``*``. + +Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests. From c01426efecb82375c7c732f8c385b38cb9259168 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 26 Nov 2016 15:23:32 +0000 Subject: [PATCH 066/185] Make position optional in dev::validate --- libdevcore/UTF8.h | 6 ++++++ libsolidity/ast/ASTJsonConverter.cpp | 3 +-- libsolidity/ast/Types.cpp | 3 +-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libdevcore/UTF8.h b/libdevcore/UTF8.h index 9bdc2b4f2..b82fd1c6d 100644 --- a/libdevcore/UTF8.h +++ b/libdevcore/UTF8.h @@ -32,4 +32,10 @@ namespace dev /// @returns false if it is invalid and the first invalid position in invalidPosition bool validate(std::string const& _input, size_t& _invalidPosition); +inline bool validate(std::string const& _input) +{ + size_t invalidPos; + return validate(_input, invalidPos); +} + } diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 030b32bae..cf60c76a9 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -417,9 +417,8 @@ bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node) bool ASTJsonConverter::visit(Literal const& _node) { char const* tokenString = Token::toString(_node.token()); - size_t invalidPos = 0; Json::Value value{_node.value()}; - if (!dev::validate(_node.value(), invalidPos)) + if (!dev::validate(_node.value())) value = Json::nullValue; Token::Value subdenomination = Token::Value(_node.subDenomination()); addJsonNode(_node, "Literal", { diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index b22f3c086..4c8463b57 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -909,8 +909,7 @@ TypePointer StringLiteralType::mobileType() const bool StringLiteralType::isValidUTF8() const { - size_t dontCare {}; - return dev::validate(m_value, dontCare); + return dev::validate(m_value); } shared_ptr FixedBytesType::smallestTypeForLiteral(string const& _literal) From a9e92cb68601a19d5e0969e4f3336be612edc72e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 22:07:55 +0000 Subject: [PATCH 067/185] Rename dev::validate to dev::validateUTF8 --- libdevcore/UTF8.cpp | 2 +- libdevcore/UTF8.h | 6 +++--- libsolidity/ast/ASTJsonConverter.cpp | 2 +- libsolidity/ast/Types.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libdevcore/UTF8.cpp b/libdevcore/UTF8.cpp index d742fe665..1c7ed17c7 100644 --- a/libdevcore/UTF8.cpp +++ b/libdevcore/UTF8.cpp @@ -28,7 +28,7 @@ namespace dev { -bool validate(std::string const& _input, size_t& _invalidPosition) +bool validateUTF8(std::string const& _input, size_t& _invalidPosition) { const size_t length = _input.length(); bool valid = true; diff --git a/libdevcore/UTF8.h b/libdevcore/UTF8.h index b82fd1c6d..753914e3f 100644 --- a/libdevcore/UTF8.h +++ b/libdevcore/UTF8.h @@ -30,12 +30,12 @@ namespace dev /// Validate an input for UTF8 encoding /// @returns false if it is invalid and the first invalid position in invalidPosition -bool validate(std::string const& _input, size_t& _invalidPosition); +bool validateUTF8(std::string const& _input, size_t& _invalidPosition); -inline bool validate(std::string const& _input) +inline bool validateUTF8(std::string const& _input) { size_t invalidPos; - return validate(_input, invalidPos); + return validateUTF8(_input, invalidPos); } } diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index cf60c76a9..f6b06be66 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -418,7 +418,7 @@ bool ASTJsonConverter::visit(Literal const& _node) { char const* tokenString = Token::toString(_node.token()); Json::Value value{_node.value()}; - if (!dev::validate(_node.value())) + if (!dev::validateUTF8(_node.value())) value = Json::nullValue; Token::Value subdenomination = Token::Value(_node.subDenomination()); addJsonNode(_node, "Literal", { diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 4c8463b57..d9660bc08 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -896,7 +896,7 @@ std::string StringLiteralType::toString(bool) const { size_t invalidSequence; - if (!dev::validate(m_value, invalidSequence)) + if (!dev::validateUTF8(m_value, invalidSequence)) return "literal_string (contains invalid UTF-8 sequence at position " + dev::toString(invalidSequence) + ")"; return "literal_string \"" + m_value + "\""; @@ -909,7 +909,7 @@ TypePointer StringLiteralType::mobileType() const bool StringLiteralType::isValidUTF8() const { - return dev::validate(m_value); + return dev::validateUTF8(m_value); } shared_ptr FixedBytesType::smallestTypeForLiteral(string const& _literal) From 3ec0bb5bfa986bb38c9a3d7a5a2dc43f3a3a9c15 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 21 Nov 2016 22:20:13 +0000 Subject: [PATCH 068/185] LLL: parseLLL to return empty string on failure --- liblll/Compiler.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index 4008022f8..0cec7bc8f 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -99,14 +99,15 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v string dev::eth::parseLLL(string const& _src) { - sp::utree o; try { + sp::utree o; parseTreeLLL(_src, o); + ostringstream ret; + debugOutAST(ret, o); + killBigints(o); + return ret.str(); } catch (...) {} - ostringstream ret; - debugOutAST(ret, o); - killBigints(o); - return ret.str(); + return string(); } From 69eb0ab5e3975e039c42a01bc6dd6657d4706022 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 21 Nov 2016 22:21:13 +0000 Subject: [PATCH 069/185] LLL: add parser tests --- test/liblll/Parser.cpp | 179 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 test/liblll/Parser.cpp diff --git a/test/liblll/Parser.cpp b/test/liblll/Parser.cpp new file mode 100644 index 000000000..fc91f3c54 --- /dev/null +++ b/test/liblll/Parser.cpp @@ -0,0 +1,179 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Alex Beregszaszi + * @date 2016 + * Unit tests for the LLL parser. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace lll +{ +namespace test +{ + +namespace +{ + +bool successParse(std::string const& _source) +{ + std::string ret = eth::parseLLL(_source); + return ret.size() != 0; +} + +std::string parse(std::string const& _source) +{ + return eth::parseLLL(_source); +} + +} + +BOOST_AUTO_TEST_SUITE(LLLParser) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* text = "1"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(string) +{ + char const* text = "\"string\""; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"("string")"); +} + +BOOST_AUTO_TEST_CASE(symbol) +{ + char const* text = "symbol"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"(symbol)"); + + BOOST_CHECK(successParse("'symbol")); + BOOST_CHECK_EQUAL(parse(text), R"(symbol)"); +} + +BOOST_AUTO_TEST_CASE(decimals) +{ + char const* text = "1234"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"(1234)"); +} + +BOOST_AUTO_TEST_CASE(hexadecimals) +{ + char const* text = "0x1234"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"(4660)"); +} + +BOOST_AUTO_TEST_CASE(sequence) +{ + char const* text = "{ 1234 }"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"({ 1234 })"); +} + +BOOST_AUTO_TEST_CASE(empty_sequence) +{ + char const* text = "{}"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"({ })"); +} + +BOOST_AUTO_TEST_CASE(mload) +{ + char const* text = "@0"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"(@ 0)"); + + BOOST_CHECK(successParse("@0x0")); + BOOST_CHECK(successParse("@symbol")); + BOOST_CHECK(!successParse("@")); +} + +BOOST_AUTO_TEST_CASE(sload) +{ + char const* text = "@@0"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"(@@ 0)"); + + BOOST_CHECK(successParse("@@0x0")); + BOOST_CHECK(successParse("@@symbol")); + BOOST_CHECK(!successParse("@@")); +} + +BOOST_AUTO_TEST_CASE(mstore) +{ + char const* text = "[0]:0"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"([ 0 ] 0)"); + + BOOST_CHECK(successParse("[0] 0")); + BOOST_CHECK(successParse("[0x0]:0x0")); + BOOST_CHECK(successParse("[symbol]:symbol")); + BOOST_CHECK(!successParse("[]")); + BOOST_CHECK(!successParse("[0]")); +} + +BOOST_AUTO_TEST_CASE(sstore) +{ + char const* text = "[[0]]:0"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"([[ 0 ]] 0)"); + + BOOST_CHECK(successParse("[[0]] 0")); + BOOST_CHECK(successParse("[[0x0]]:0x0")); + BOOST_CHECK(successParse("[[symbol]]:symbol")); + BOOST_CHECK(!successParse("[[]]")); + BOOST_CHECK(!successParse("[[0x0]]")); +} + +BOOST_AUTO_TEST_CASE(calldataload) +{ + char const* text = "$0"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"($ 0)"); + + BOOST_CHECK(successParse("$0x0")); + BOOST_CHECK(successParse("$symbol")); + BOOST_CHECK(!successParse("$")); +} + +BOOST_AUTO_TEST_CASE(list) +{ + char const* text = "( 1234 )"; + BOOST_CHECK(successParse(text)); + BOOST_CHECK_EQUAL(parse(text), R"(( 1234 ))"); + + BOOST_CHECK(successParse("( 1234 5467 )")); + BOOST_CHECK(successParse("()")); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces From 4af30cc5183d83afd8a112bbc29e5c7beb3b7c1a Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 27 Nov 2016 23:19:10 +0000 Subject: [PATCH 070/185] Add test/liblll to cmake --- test/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 33af9981e..609aaab36 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,7 @@ aux_source_directory(libdevcore SRC_LIST) aux_source_directory(libevmasm SRC_LIST) aux_source_directory(libsolidity SRC_LIST) aux_source_directory(contracts SRC_LIST) +aux_source_directory(liblll SRC_LIST) get_filename_component(TESTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE) @@ -28,7 +29,7 @@ file(GLOB HEADERS "*.h" "*/*.h") set(EXECUTABLE soltest) eth_simple_add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) -eth_use(${EXECUTABLE} REQUIRED Solidity::solidity) +eth_use(${EXECUTABLE} REQUIRED Solidity::solidity Solidity::lll) include_directories(BEFORE ..) target_link_libraries(${EXECUTABLE} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES}) From a226db73384ac1b588e07a28dd8f1ff92cbdf6f7 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 00:21:01 +0000 Subject: [PATCH 071/185] Split out Solidity-specific part of ExecutionFramework --- test/ExecutionFramework.cpp | 137 +++++++++ test/ExecutionFramework.h | 288 ++++++++++++++++++ test/contracts/AuctionRegistrar.cpp | 6 +- test/contracts/FixedFeeRegistrar.cpp | 2 +- test/contracts/Wallet.cpp | 2 +- test/libsolidity/GasMeter.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 3 +- .../SolidityExecutionFramework.cpp | 106 +------ test/libsolidity/SolidityExecutionFramework.h | 242 +-------------- test/libsolidity/SolidityOptimizer.cpp | 2 +- 10 files changed, 441 insertions(+), 349 deletions(-) create mode 100644 test/ExecutionFramework.cpp create mode 100644 test/ExecutionFramework.h diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp new file mode 100644 index 000000000..4ae504626 --- /dev/null +++ b/test/ExecutionFramework.cpp @@ -0,0 +1,137 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Christian + * @date 2016 + * Framework for executing contracts and testing them using RPC. + */ + +#include +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; +using namespace dev::solidity::test; + +namespace // anonymous +{ + h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); +} + +string getIPCSocketPath() +{ + string ipcPath = dev::test::Options::get().ipcPath; + if (ipcPath.empty()) + BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath or the environment variable ETH_TEST_IPC)"); + + return ipcPath; +} + +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); +} + +void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) +{ + RPCSession::TransactionData d; + d.data = "0x" + toHex(_data); + d.from = "0x" + toString(m_sender); + d.gas = toHex(m_gas, HexPrefix::Add); + d.gasPrice = toHex(m_gasPrice, HexPrefix::Add); + d.value = toHex(_value, HexPrefix::Add); + if (!_isCreation) + { + d.to = dev::toString(m_contractAddress); + BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "latest").size() > 2); + // Use eth_call to get the output + m_output = fromHex(m_rpc.eth_call(d, "latest"), WhenError::Throw); + } + + string txHash = m_rpc.eth_sendTransaction(d); + m_rpc.test_mineBlocks(1); + RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash)); + + if (_isCreation) + { + m_contractAddress = Address(receipt.contractAddress); + BOOST_REQUIRE(m_contractAddress); + string code = m_rpc.eth_getCode(receipt.contractAddress, "latest"); + m_output = fromHex(code, WhenError::Throw); + } + + m_gasUsed = u256(receipt.gasUsed); + m_logs.clear(); + for (auto const& log: receipt.logEntries) + { + LogEntry entry; + entry.address = Address(log.address); + for (auto const& topic: log.topics) + entry.topics.push_back(h256(topic)); + entry.data = fromHex(log.data, WhenError::Throw); + m_logs.push_back(entry); + } +} + +void ExecutionFramework::sendEther(Address const& _to, u256 const& _value) +{ + RPCSession::TransactionData d; + d.data = "0x"; + d.from = "0x" + toString(m_sender); + d.gas = toHex(m_gas, HexPrefix::Add); + d.gasPrice = toHex(m_gasPrice, HexPrefix::Add); + d.value = toHex(_value, HexPrefix::Add); + d.to = dev::toString(_to); + + string txHash = m_rpc.eth_sendTransaction(d); + m_rpc.test_mineBlocks(1); +} + +size_t ExecutionFramework::currentTimestamp() +{ + auto latestBlock = m_rpc.rpcCall("eth_getBlockByNumber", {"\"latest\"", "false"}); + return size_t(u256(latestBlock.get("timestamp", "invalid").asString())); +} + +Address ExecutionFramework::account(size_t _i) +{ + return Address(m_rpc.accountCreateIfNotExists(_i)); +} + +bool ExecutionFramework::addressHasCode(Address const& _addr) +{ + string code = m_rpc.eth_getCode(toString(_addr), "latest"); + return !code.empty() && code != "0x"; +} + +u256 ExecutionFramework::balanceAt(Address const& _addr) +{ + return u256(m_rpc.eth_getBalance(toString(_addr), "latest")); +} + +bool ExecutionFramework::storageEmpty(Address const& _addr) +{ + h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest")); + BOOST_CHECK(root); + return root == EmptyTrie; +} diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h new file mode 100644 index 000000000..e487b1061 --- /dev/null +++ b/test/ExecutionFramework.h @@ -0,0 +1,288 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Framework for executing contracts and testing them using RPC. + */ + +#pragma once + +#include + +#include "TestHelper.h" +#include "RPCSession.h" + +#include +#include + +namespace dev +{ +namespace solidity +{ + using rational = boost::rational; + /// An Ethereum address: 20 bytes. + /// @NOTE This is not endian-specific; it's just a bunch of bytes. + using Address = h160; + + // The various denominations; here for ease of use where needed within code. + static const u256 ether = exp10<18>(); + static const u256 finney = exp10<15>(); + static const u256 szabo = exp10<12>(); + static const u256 shannon = exp10<9>(); + static const u256 wei = exp10<0>(); + +namespace test +{ + +class ExecutionFramework +{ + +public: + ExecutionFramework(); + + virtual bytes const& compileAndRunWithoutCheck( + std::string const& _sourceCode, + u256 const& _value = 0, + std::string const& _contractName = "", + bytes const& _arguments = bytes(), + std::map const& _libraryAddresses = std::map() + ) = 0; + + bytes const& compileAndRun( + std::string const& _sourceCode, + u256 const& _value = 0, + std::string const& _contractName = "", + bytes const& _arguments = bytes(), + std::map const& _libraryAddresses = std::map() + ) + { + compileAndRunWithoutCheck(_sourceCode, _value, _contractName, _arguments, _libraryAddresses); + BOOST_REQUIRE(!m_output.empty()); + return m_output; + } + + template + bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments) + { + FixedHash<4> hash(dev::keccak256(_sig)); + sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value); + return m_output; + } + + template + bytes const& callContractFunction(std::string _sig, Args const&... _arguments) + { + return callContractFunctionWithValue(_sig, 0, _arguments...); + } + + template + void testSolidityAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments) + { + bytes solidityResult = callContractFunction(_sig, _arguments...); + bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); + BOOST_CHECK_MESSAGE( + solidityResult == cppResult, + "Computed values do not match.\nSolidity: " + + toHex(solidityResult) + + "\nC++: " + + toHex(cppResult) + ); + } + + template + void testSolidityAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd) + { + for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) + { + bytes solidityResult = callContractFunction(_sig, argument); + bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); + BOOST_CHECK_MESSAGE( + solidityResult == cppResult, + "Computed values do not match.\nSolidity: " + + toHex(solidityResult) + + "\nC++: " + + toHex(cppResult) + + "\nArgument: " + + toHex(encode(argument)) + ); + } + } + + static bytes encode(bool _value) { return encode(byte(_value)); } + static bytes encode(int _value) { return encode(u256(_value)); } + static bytes encode(size_t _value) { return encode(u256(_value)); } + static bytes encode(char const* _value) { return encode(std::string(_value)); } + static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; } + static bytes encode(u256 const& _value) { return toBigEndian(_value); } + /// @returns the fixed-point encoding of a rational number with a given + /// number of fractional bits. + static bytes encode(std::pair const& _valueAndPrecision) + { + rational const& value = _valueAndPrecision.first; + int fractionalBits = _valueAndPrecision.second; + return encode(u256((value.numerator() << fractionalBits) / value.denominator())); + } + static bytes encode(h256 const& _value) { return _value.asBytes(); } + static bytes encode(bytes const& _value, bool _padLeft = true) + { + bytes padding = bytes((32 - _value.size() % 32) % 32, 0); + return _padLeft ? padding + _value : _value + padding; + } + static bytes encode(std::string const& _value) { return encode(asBytes(_value), false); } + template + static bytes encode(std::vector<_T> const& _value) + { + bytes ret; + for (auto const& v: _value) + ret += encode(v); + return ret; + } + + template + static bytes encodeArgs(FirstArg const& _firstArg, Args const&... _followingArgs) + { + return encode(_firstArg) + encodeArgs(_followingArgs...); + } + static bytes encodeArgs() + { + return bytes(); + } + //@todo might be extended in the future + template + static bytes encodeDyn(Arg const& _arg) + { + return encodeArgs(u256(0x20), u256(_arg.size()), _arg); + } + class ContractInterface + { + public: + ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {} + + void setNextValue(u256 const& _value) { m_nextValue = _value; } + + protected: + template + bytes const& call(std::string const& _sig, Args const&... _arguments) + { + auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...); + m_nextValue = 0; + return ret; + } + + void callString(std::string const& _name, std::string const& _arg) + { + BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty()); + } + + void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2) + { + BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); + } + + void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3) + { + BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty()); + } + + void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2) + { + BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); + } + + u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg) + { + bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); + BOOST_REQUIRE(ret.size() == 0x20); + BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12); + return eth::abiOut(ret); + } + + std::string callAddressReturnsString(std::string const& _name, u160 const& _arg) + { + bytesConstRef ret = ref(call(_name + "(address)", _arg)); + BOOST_REQUIRE(ret.size() >= 0x20); + u256 offset = eth::abiOut(ret); + BOOST_REQUIRE_EQUAL(offset, 0x20); + u256 len = eth::abiOut(ret); + BOOST_REQUIRE_EQUAL(ret.size(), ((len + 0x1f) / 0x20) * 0x20); + return ret.cropped(0, size_t(len)).toString(); + } + + h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg) + { + bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); + BOOST_REQUIRE(ret.size() == 0x20); + return eth::abiOut(ret); + } + + private: + u256 m_nextValue; + ExecutionFramework& m_framework; + }; + +private: + template + auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) + -> typename std::enable_if::value, bytes>::type + { + _cppFunction(_arguments...); + return bytes(); + } + template + auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) + -> typename std::enable_if::value, bytes>::type + { + return encode(_cppFunction(_arguments...)); + } + +protected: + void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0); + void sendEther(Address const& _to, u256 const& _value); + size_t currentTimestamp(); + + /// @returns the (potentially newly created) _ith address. + Address account(size_t _i); + + u256 balanceAt(Address const& _addr); + bool storageEmpty(Address const& _addr); + bool addressHasCode(Address const& _addr); + + RPCSession& m_rpc; + + struct LogEntry + { + Address address; + std::vector topics; + bytes data; + }; + + size_t m_optimizeRuns = 200; + bool m_optimize = false; + Address m_sender; + Address m_contractAddress; + u256 const m_gasPrice = 100 * szabo; + u256 const m_gas = 100000000; + bytes m_output; + std::vector m_logs; + u256 m_gasUsed; +}; + +} +} +} // end namespaces + diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index 0b573bca0..c156efd1c 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -213,7 +213,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem { static unique_ptr s_compiledRegistrar; -class AuctionRegistrarTestFramework: public ExecutionFramework +class AuctionRegistrarTestFramework: public SolidityExecutionFramework { protected: void deployRegistrar() @@ -229,11 +229,11 @@ protected: BOOST_REQUIRE(!m_output.empty()); } - using ContractInterface = ExecutionFramework::ContractInterface; + using ContractInterface = SolidityExecutionFramework::ContractInterface; class RegistrarInterface: public ContractInterface { public: - RegistrarInterface(ExecutionFramework& _framework): ContractInterface(_framework) {} + RegistrarInterface(SolidityExecutionFramework& _framework): ContractInterface(_framework) {} void reserve(string const& _name) { callString("reserve", _name); diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index 8aabdac2a..829205d5a 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -125,7 +125,7 @@ contract FixedFeeRegistrar is Registrar { static unique_ptr s_compiledRegistrar; -class RegistrarTestFramework: public ExecutionFramework +class RegistrarTestFramework: public SolidityExecutionFramework { protected: void deployRegistrar() diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 935baf5b5..6fbee6f17 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -435,7 +435,7 @@ contract Wallet is multisig, multiowned, daylimit { static unique_ptr s_compiledWallet; -class WalletTestFramework: public ExecutionFramework +class WalletTestFramework: public SolidityExecutionFramework { protected: void deployWallet( diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index bc2242845..f467d6699 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -40,7 +40,7 @@ namespace solidity namespace test { -class GasMeterTestFramework: public ExecutionFramework +class GasMeterTestFramework: public SolidityExecutionFramework { public: GasMeterTestFramework() { } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 6478ea86a..b5fcdb5ee 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,7 @@ namespace solidity namespace test { -BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, ExecutionFramework) +BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityExecutionFramework) BOOST_AUTO_TEST_CASE(smoke_test) { diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 009433674..fe35087c1 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -22,7 +22,6 @@ #include #include -#include #include using namespace std; @@ -30,108 +29,7 @@ using namespace dev; using namespace dev::solidity; using namespace dev::solidity::test; -namespace // anonymous +SolidityExecutionFramework::SolidityExecutionFramework() : + ExecutionFramework() { - h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); -} - -string getIPCSocketPath() -{ - string ipcPath = dev::test::Options::get().ipcPath; - if (ipcPath.empty()) - BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath or the environment variable ETH_TEST_IPC)"); - - return ipcPath; -} - -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); -} - -void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) -{ - RPCSession::TransactionData d; - d.data = "0x" + toHex(_data); - d.from = "0x" + toString(m_sender); - d.gas = toHex(m_gas, HexPrefix::Add); - d.gasPrice = toHex(m_gasPrice, HexPrefix::Add); - d.value = toHex(_value, HexPrefix::Add); - if (!_isCreation) - { - d.to = dev::toString(m_contractAddress); - BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "latest").size() > 2); - // Use eth_call to get the output - m_output = fromHex(m_rpc.eth_call(d, "latest"), WhenError::Throw); - } - - string txHash = m_rpc.eth_sendTransaction(d); - m_rpc.test_mineBlocks(1); - RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash)); - - if (_isCreation) - { - m_contractAddress = Address(receipt.contractAddress); - BOOST_REQUIRE(m_contractAddress); - string code = m_rpc.eth_getCode(receipt.contractAddress, "latest"); - m_output = fromHex(code, WhenError::Throw); - } - - m_gasUsed = u256(receipt.gasUsed); - m_logs.clear(); - for (auto const& log: receipt.logEntries) - { - LogEntry entry; - entry.address = Address(log.address); - for (auto const& topic: log.topics) - entry.topics.push_back(h256(topic)); - entry.data = fromHex(log.data, WhenError::Throw); - m_logs.push_back(entry); - } -} - -void ExecutionFramework::sendEther(Address const& _to, u256 const& _value) -{ - RPCSession::TransactionData d; - d.data = "0x"; - d.from = "0x" + toString(m_sender); - d.gas = toHex(m_gas, HexPrefix::Add); - d.gasPrice = toHex(m_gasPrice, HexPrefix::Add); - d.value = toHex(_value, HexPrefix::Add); - d.to = dev::toString(_to); - - string txHash = m_rpc.eth_sendTransaction(d); - m_rpc.test_mineBlocks(1); -} - -size_t ExecutionFramework::currentTimestamp() -{ - auto latestBlock = m_rpc.rpcCall("eth_getBlockByNumber", {"\"latest\"", "false"}); - return size_t(u256(latestBlock.get("timestamp", "invalid").asString())); -} - -Address ExecutionFramework::account(size_t _i) -{ - return Address(m_rpc.accountCreateIfNotExists(_i)); -} - -bool ExecutionFramework::addressHasCode(Address const& _addr) -{ - string code = m_rpc.eth_getCode(toString(_addr), "latest"); - return !code.empty() && code != "0x"; -} - -u256 ExecutionFramework::balanceAt(Address const& _addr) -{ - return u256(m_rpc.eth_getBalance(toString(_addr), "latest")); -} - -bool ExecutionFramework::storageEmpty(Address const& _addr) -{ - h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest")); - BOOST_CHECK(root); - return root == EmptyTrie; } diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index b2ea9c08e..16b886f18 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -24,12 +24,7 @@ #include -#include "../TestHelper.h" -#include "../RPCSession.h" - -#include -#include -#include +#include "../ExecutionFramework.h" #include #include @@ -39,34 +34,23 @@ namespace dev { namespace solidity { - using rational = boost::rational; - /// An Ethereum address: 20 bytes. - /// @NOTE This is not endian-specific; it's just a bunch of bytes. - using Address = h160; - - // The various denominations; here for ease of use where needed within code. - static const u256 ether = exp10<18>(); - static const u256 finney = exp10<15>(); - static const u256 szabo = exp10<12>(); - static const u256 shannon = exp10<9>(); - static const u256 wei = exp10<0>(); namespace test { -class ExecutionFramework +class SolidityExecutionFramework: public ExecutionFramework { public: - ExecutionFramework(); + SolidityExecutionFramework(); - bytes const& compileAndRunWithoutCheck( + virtual bytes const& compileAndRunWithoutCheck( std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "", bytes const& _arguments = bytes(), std::map const& _libraryAddresses = std::map() - ) + ) override { // Silence compiler version warning std::string sourceCode = "pragma solidity >=0.0;\n" + _sourceCode; @@ -90,224 +74,8 @@ public: return m_output; } - bytes const& compileAndRun( - std::string const& _sourceCode, - u256 const& _value = 0, - std::string const& _contractName = "", - bytes const& _arguments = bytes(), - std::map const& _libraryAddresses = std::map() - ) - { - compileAndRunWithoutCheck(_sourceCode, _value, _contractName, _arguments, _libraryAddresses); - BOOST_REQUIRE(!m_output.empty()); - return m_output; - } - - template - bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments) - { - FixedHash<4> hash(dev::keccak256(_sig)); - sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value); - return m_output; - } - - template - bytes const& callContractFunction(std::string _sig, Args const&... _arguments) - { - return callContractFunctionWithValue(_sig, 0, _arguments...); - } - - template - void testSolidityAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments) - { - bytes solidityResult = callContractFunction(_sig, _arguments...); - bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); - BOOST_CHECK_MESSAGE( - solidityResult == cppResult, - "Computed values do not match.\nSolidity: " + - toHex(solidityResult) + - "\nC++: " + - toHex(cppResult) - ); - } - - template - void testSolidityAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd) - { - for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) - { - bytes solidityResult = callContractFunction(_sig, argument); - bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); - BOOST_CHECK_MESSAGE( - solidityResult == cppResult, - "Computed values do not match.\nSolidity: " + - toHex(solidityResult) + - "\nC++: " + - toHex(cppResult) + - "\nArgument: " + - toHex(encode(argument)) - ); - } - } - - static bytes encode(bool _value) { return encode(byte(_value)); } - static bytes encode(int _value) { return encode(u256(_value)); } - static bytes encode(size_t _value) { return encode(u256(_value)); } - static bytes encode(char const* _value) { return encode(std::string(_value)); } - static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; } - static bytes encode(u256 const& _value) { return toBigEndian(_value); } - /// @returns the fixed-point encoding of a rational number with a given - /// number of fractional bits. - static bytes encode(std::pair const& _valueAndPrecision) - { - rational const& value = _valueAndPrecision.first; - int fractionalBits = _valueAndPrecision.second; - return encode(u256((value.numerator() << fractionalBits) / value.denominator())); - } - static bytes encode(h256 const& _value) { return _value.asBytes(); } - static bytes encode(bytes const& _value, bool _padLeft = true) - { - bytes padding = bytes((32 - _value.size() % 32) % 32, 0); - return _padLeft ? padding + _value : _value + padding; - } - static bytes encode(std::string const& _value) { return encode(asBytes(_value), false); } - template - static bytes encode(std::vector<_T> const& _value) - { - bytes ret; - for (auto const& v: _value) - ret += encode(v); - return ret; - } - - template - static bytes encodeArgs(FirstArg const& _firstArg, Args const&... _followingArgs) - { - return encode(_firstArg) + encodeArgs(_followingArgs...); - } - static bytes encodeArgs() - { - return bytes(); - } - //@todo might be extended in the future - template - static bytes encodeDyn(Arg const& _arg) - { - return encodeArgs(u256(0x20), u256(_arg.size()), _arg); - } - class ContractInterface - { - public: - ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {} - - void setNextValue(u256 const& _value) { m_nextValue = _value; } - - protected: - template - bytes const& call(std::string const& _sig, Args const&... _arguments) - { - auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...); - m_nextValue = 0; - return ret; - } - - void callString(std::string const& _name, std::string const& _arg) - { - BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty()); - } - - void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2) - { - BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); - } - - void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3) - { - BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty()); - } - - void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2) - { - BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); - } - - u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg) - { - bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); - BOOST_REQUIRE(ret.size() == 0x20); - BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12); - return eth::abiOut(ret); - } - - std::string callAddressReturnsString(std::string const& _name, u160 const& _arg) - { - bytesConstRef ret = ref(call(_name + "(address)", _arg)); - BOOST_REQUIRE(ret.size() >= 0x20); - u256 offset = eth::abiOut(ret); - BOOST_REQUIRE_EQUAL(offset, 0x20); - u256 len = eth::abiOut(ret); - BOOST_REQUIRE_EQUAL(ret.size(), ((len + 0x1f) / 0x20) * 0x20); - return ret.cropped(0, size_t(len)).toString(); - } - - h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg) - { - bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); - BOOST_REQUIRE(ret.size() == 0x20); - return eth::abiOut(ret); - } - - private: - u256 m_nextValue; - ExecutionFramework& m_framework; - }; - -private: - template - auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) - -> typename std::enable_if::value, bytes>::type - { - _cppFunction(_arguments...); - return bytes(); - } - template - auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) - -> typename std::enable_if::value, bytes>::type - { - return encode(_cppFunction(_arguments...)); - } - protected: - void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0); - void sendEther(Address const& _to, u256 const& _value); - size_t currentTimestamp(); - - /// @returns the (potentially newly created) _ith address. - Address account(size_t _i); - - u256 balanceAt(Address const& _addr); - bool storageEmpty(Address const& _addr); - bool addressHasCode(Address const& _addr); - - RPCSession& m_rpc; - - struct LogEntry - { - Address address; - std::vector topics; - bytes data; - }; - - size_t m_optimizeRuns = 200; - bool m_optimize = false; dev::solidity::CompilerStack m_compiler; - Address m_sender; - Address m_contractAddress; - u256 const m_gasPrice = 100 * szabo; - u256 const m_gas = 100000000; - bytes m_output; - std::vector m_logs; - u256 m_gasUsed; }; } diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index a53a26384..15208b412 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -45,7 +45,7 @@ namespace solidity namespace test { -class OptimizerTestFramework: public ExecutionFramework +class OptimizerTestFramework: public SolidityExecutionFramework { public: OptimizerTestFramework() { } From d83dd59178778b5748092f244ce66e37319f4070 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 00:58:07 +0000 Subject: [PATCH 072/185] Move ExecutionFramework to the dev::test namespace --- test/ExecutionFramework.cpp | 3 +-- test/ExecutionFramework.h | 6 +----- test/contracts/AuctionRegistrar.cpp | 1 + test/contracts/FixedFeeRegistrar.cpp | 1 + test/contracts/Wallet.cpp | 1 + test/libsolidity/GasMeter.cpp | 1 + test/libsolidity/SolidityEndToEndTest.cpp | 1 + test/libsolidity/SolidityExecutionFramework.cpp | 3 +-- test/libsolidity/SolidityExecutionFramework.h | 4 ++-- test/libsolidity/SolidityOptimizer.cpp | 1 + 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 4ae504626..0c6e0cff7 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -27,8 +27,7 @@ using namespace std; using namespace dev; -using namespace dev::solidity; -using namespace dev::solidity::test; +using namespace dev::test; namespace // anonymous { diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index e487b1061..6ec1a06b3 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -32,7 +32,7 @@ namespace dev { -namespace solidity +namespace test { using rational = boost::rational; /// An Ethereum address: 20 bytes. @@ -46,9 +46,6 @@ namespace solidity static const u256 shannon = exp10<9>(); static const u256 wei = exp10<0>(); -namespace test -{ - class ExecutionFramework { @@ -282,7 +279,6 @@ protected: u256 m_gasUsed; }; -} } } // end namespaces diff --git a/test/contracts/AuctionRegistrar.cpp b/test/contracts/AuctionRegistrar.cpp index c156efd1c..fb8c1c68c 100644 --- a/test/contracts/AuctionRegistrar.cpp +++ b/test/contracts/AuctionRegistrar.cpp @@ -27,6 +27,7 @@ #include using namespace std; +using namespace dev::test; namespace dev { diff --git a/test/contracts/FixedFeeRegistrar.cpp b/test/contracts/FixedFeeRegistrar.cpp index 829205d5a..39c32eb72 100644 --- a/test/contracts/FixedFeeRegistrar.cpp +++ b/test/contracts/FixedFeeRegistrar.cpp @@ -35,6 +35,7 @@ #include using namespace std; +using namespace dev::test; namespace dev { diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 6fbee6f17..80f06613e 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -35,6 +35,7 @@ #include using namespace std; +using namespace dev::test; namespace dev { diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index f467d6699..0671fb150 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace dev::eth; using namespace dev::solidity; +using namespace dev::test; namespace dev { diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index b5fcdb5ee..930b11c6d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace std::placeholders; +using namespace dev::test; namespace dev { diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index fe35087c1..bb9695d1e 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -24,8 +24,7 @@ #include #include -using namespace std; -using namespace dev; +using namespace dev::test; using namespace dev::solidity; using namespace dev::solidity::test; diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 16b886f18..0fab7aeb0 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -38,7 +38,7 @@ namespace solidity namespace test { -class SolidityExecutionFramework: public ExecutionFramework +class SolidityExecutionFramework: public dev::test::ExecutionFramework { public: @@ -49,7 +49,7 @@ public: u256 const& _value = 0, std::string const& _contractName = "", bytes const& _arguments = bytes(), - std::map const& _libraryAddresses = std::map() + std::map const& _libraryAddresses = std::map() ) override { // Silence compiler version warning diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 15208b412..603105558 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -37,6 +37,7 @@ using namespace std; using namespace dev::eth; +using namespace dev::test; namespace dev { From e26466b729de5bbb4cd578272fab2795cb66aee8 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 00:58:41 +0000 Subject: [PATCH 073/185] LLL: add end-to-end tests --- test/liblll/EndToEndTest.cpp | 49 +++++++++++++++++++++ test/liblll/ExecutionFramework.cpp | 33 ++++++++++++++ test/liblll/ExecutionFramework.h | 70 ++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 test/liblll/EndToEndTest.cpp create mode 100644 test/liblll/ExecutionFramework.cpp create mode 100644 test/liblll/ExecutionFramework.h diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp new file mode 100644 index 000000000..c9b571f38 --- /dev/null +++ b/test/liblll/EndToEndTest.cpp @@ -0,0 +1,49 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Alex Beregszaszi + * @date 2016 + * End to end tests for LLL. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace dev +{ +namespace lll +{ +namespace test +{ + +BOOST_FIXTURE_TEST_SUITE(LLLEndToEndTest, LLLExecutionFramework) + +BOOST_AUTO_TEST_CASE(smoke_test) +{ + char const* sourceCode = "(returnlll { (return \"test\") })"; + compileAndRun(sourceCode); +} + +BOOST_AUTO_TEST_SUITE_END() + +} +} +} // end namespaces diff --git a/test/liblll/ExecutionFramework.cpp b/test/liblll/ExecutionFramework.cpp new file mode 100644 index 000000000..4719c5f50 --- /dev/null +++ b/test/liblll/ExecutionFramework.cpp @@ -0,0 +1,33 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Alex Beregszaszi + * @date 2016 + * Framework for executing LLL contracts and testing them via RPC. + */ + +#include +#include +#include + +using namespace dev::test; +using namespace dev::lll::test; + +LLLExecutionFramework::LLLExecutionFramework() : + ExecutionFramework() +{ +} diff --git a/test/liblll/ExecutionFramework.h b/test/liblll/ExecutionFramework.h new file mode 100644 index 000000000..37162e7fe --- /dev/null +++ b/test/liblll/ExecutionFramework.h @@ -0,0 +1,70 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Alex Beregszaszi + * @date 2016 + * Framework for executing LLL contracts and testing them via RPC. + */ + +#pragma once + +#include + +#include "../ExecutionFramework.h" + +#include + +using namespace dev::test; + +namespace dev +{ +namespace lll +{ + +namespace test +{ + +class LLLExecutionFramework: public ExecutionFramework +{ + +public: + LLLExecutionFramework(); + + virtual bytes const& compileAndRunWithoutCheck( + std::string const& _sourceCode, + u256 const& _value = 0, + std::string const& _contractName = "", + bytes const& _arguments = bytes(), + std::map const& _libraryAddresses = std::map() + ) override + { + std::vector errors; + bytes bytecode = eth::compileLLL(_sourceCode, m_optimize, &errors); + if (!errors.empty()) + { + for (auto const& error: errors) + std::cerr << error << std::endl; + BOOST_ERROR("Compiling contract failed"); + } + sendMessage(bytecode + _arguments, true, _value); + return m_output; + } +}; + +} +} +} // end namespaces From 85ebe4e5c47f47aa46f76043279dc15962b617e4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 11:13:15 +0000 Subject: [PATCH 074/185] LLL: check for return value in LLL smoke test --- test/liblll/EndToEndTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index c9b571f38..9025689ef 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -40,6 +40,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { char const* sourceCode = "(returnlll { (return \"test\") })"; compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("") == encodeArgs(string("test", 4))); } BOOST_AUTO_TEST_SUITE_END() From 94cae6339063fb6c33dc477991ac3d0933dc562f Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 11:19:31 +0000 Subject: [PATCH 075/185] Add callFallback to ExectionFramework --- test/ExecutionFramework.h | 11 +++++++++++ test/liblll/EndToEndTest.cpp | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 6ec1a06b3..6c5a57643 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -73,6 +73,17 @@ public: return m_output; } + bytes const& callFallbackWithValue(u256 const& _value) + { + sendMessage(bytes(), false, _value); + return m_output; + } + + bytes const & callFallback() + { + return callFallbackWithValue(0); + } + template bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments) { diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 9025689ef..b5e32e94f 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) { char const* sourceCode = "(returnlll { (return \"test\") })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("") == encodeArgs(string("test", 4))); + BOOST_CHECK(callFallback() == encodeArgs(string("test", 4))); } BOOST_AUTO_TEST_SUITE_END() From 0f1d0304eef9777c002f86134e4d6ec7b4d53385 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 28 Nov 2016 11:50:07 +0000 Subject: [PATCH 076/185] LLLExecutionFramework doesn't support contractName/libraryAddresses --- test/liblll/ExecutionFramework.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/liblll/ExecutionFramework.h b/test/liblll/ExecutionFramework.h index 37162e7fe..58e1f0add 100644 --- a/test/liblll/ExecutionFramework.h +++ b/test/liblll/ExecutionFramework.h @@ -52,6 +52,9 @@ public: std::map const& _libraryAddresses = std::map() ) override { + BOOST_REQUIRE(_contractName.empty()); + BOOST_REQUIRE(_libraryAddresses.empty()); + std::vector errors; bytes bytecode = eth::compileLLL(_sourceCode, m_optimize, &errors); if (!errors.empty()) From 25c5dd48deae72fc3afc1514271f668f04b6c5a4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 29 Nov 2016 21:46:52 +0000 Subject: [PATCH 077/185] Rename testSolidityAgainstCpp* to testContractAgainstCpp* --- test/ExecutionFramework.h | 20 +-- test/libsolidity/SolidityEndToEndTest.cpp | 150 +++++++++++----------- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 6c5a57643..1274d4006 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -99,30 +99,30 @@ public: } template - void testSolidityAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments) + void testContractAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments) { - bytes solidityResult = callContractFunction(_sig, _arguments...); + bytes contractResult = callContractFunction(_sig, _arguments...); bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); BOOST_CHECK_MESSAGE( - solidityResult == cppResult, - "Computed values do not match.\nSolidity: " + - toHex(solidityResult) + + contractResult == cppResult, + "Computed values do not match.\nContract: " + + toHex(contractResult) + "\nC++: " + toHex(cppResult) ); } template - void testSolidityAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd) + void testContractAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd) { for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) { - bytes solidityResult = callContractFunction(_sig, argument); + bytes contractResult = callContractFunction(_sig, argument); bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); BOOST_CHECK_MESSAGE( - solidityResult == cppResult, - "Computed values do not match.\nSolidity: " + - toHex(solidityResult) + + contractResult == cppResult, + "Computed values do not match.\nContract: " + + toHex(contractResult) + "\nC++: " + toHex(cppResult) + "\nArgument: " + diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 930b11c6d..98ea92cab 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(smoke_test) " function f(uint a) returns(uint d) { return a * 7; }\n" "}\n"; compileAndRun(sourceCode); - testSolidityAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100); + testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100); } BOOST_AUTO_TEST_CASE(empty_contract) @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(exp_operator) function f(uint a) returns(uint d) { return 2 ** a; } })"; compileAndRun(sourceCode); - testSolidityAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to()); }, 0, 16); + testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to()); }, 0, 16); } BOOST_AUTO_TEST_CASE(exp_operator_const) @@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE(recursive_calls) return n * recursive_calls_cpp(n - 1); }; - testSolidityAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(multiple_functions) @@ -352,7 +352,7 @@ BOOST_AUTO_TEST_CASE(while_loop) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5); } @@ -380,7 +380,7 @@ BOOST_AUTO_TEST_CASE(do_while_loop) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(nested_loops) @@ -429,7 +429,7 @@ BOOST_AUTO_TEST_CASE(nested_loops) return n; }; - testSolidityAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); + testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); } BOOST_AUTO_TEST_CASE(for_loop) @@ -451,7 +451,7 @@ BOOST_AUTO_TEST_CASE(for_loop) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(for_loop_empty) @@ -479,7 +479,7 @@ BOOST_AUTO_TEST_CASE(for_loop_empty) return ret; }; - testSolidityAgainstCpp("f()", for_loop_empty_cpp); + testContractAgainstCpp("f()", for_loop_empty_cpp); } BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) @@ -503,7 +503,7 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(for_loop_break_continue) @@ -549,7 +549,7 @@ BOOST_AUTO_TEST_CASE(for_loop_break_continue) return i; }; - testSolidityAgainstCppOnRange("f(uint256)", breakContinue, 0, 10); + testContractAgainstCppOnRange("f(uint256)", breakContinue, 0, 10); } BOOST_AUTO_TEST_CASE(calling_other_functions) @@ -593,11 +593,11 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) return y; }; - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(0)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(1)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(2)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(8)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(127)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(0)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(1)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(2)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(8)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(127)); } BOOST_AUTO_TEST_CASE(many_local_variables) @@ -618,7 +618,7 @@ BOOST_AUTO_TEST_CASE(many_local_variables) u256 y = a + b + c + x1 + x2 + x3; return y + b + x2; }; - testSolidityAgainstCpp("run(uint256,uint256,uint256)", f, u256(0x1000), u256(0x10000), u256(0x100000)); + testContractAgainstCpp("run(uint256,uint256,uint256)", f, u256(0x1000), u256(0x10000), u256(0x100000)); } BOOST_AUTO_TEST_CASE(packing_unpacking_types) @@ -675,7 +675,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting) return n; }; - testSolidityAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2); + testContractAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2); } BOOST_AUTO_TEST_CASE(high_bits_cleaning) @@ -697,7 +697,7 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) return 0; return x; }; - testSolidityAgainstCpp("run()", high_bits_cleaning_cpp); + testContractAgainstCpp("run()", high_bits_cleaning_cpp); } BOOST_AUTO_TEST_CASE(sign_extension) @@ -717,7 +717,7 @@ BOOST_AUTO_TEST_CASE(sign_extension) return 0; return u256(x) * -1; }; - testSolidityAgainstCpp("run()", sign_extension_cpp); + testContractAgainstCpp("run()", sign_extension_cpp); } BOOST_AUTO_TEST_CASE(small_unsigned_types) @@ -736,7 +736,7 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) uint32_t x = t * 0xffffff; return x / 0x100; }; - testSolidityAgainstCpp("run()", small_unsigned_types_cpp); + testContractAgainstCpp("run()", small_unsigned_types_cpp); } BOOST_AUTO_TEST_CASE(small_signed_types) @@ -751,7 +751,7 @@ BOOST_AUTO_TEST_CASE(small_signed_types) { return -int32_t(10) * -int64_t(20); }; - testSolidityAgainstCpp("run()", small_signed_types_cpp); + testContractAgainstCpp("run()", small_signed_types_cpp); } BOOST_AUTO_TEST_CASE(strings) @@ -857,14 +857,14 @@ BOOST_AUTO_TEST_CASE(compound_assign) value2 *= value3 + value1; return value2 += 7; }; - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(0), u256(6)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(1), u256(3)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(2), u256(25)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(3), u256(69)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(4), u256(84)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(5), u256(2)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(6), u256(51)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(7), u256(48)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(0), u256(6)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(1), u256(3)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(2), u256(25)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(3), u256(69)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(4), u256(84)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(5), u256(2)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(6), u256(51)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(7), u256(48)); } BOOST_AUTO_TEST_CASE(simple_mapping) @@ -938,38 +938,38 @@ BOOST_AUTO_TEST_CASE(mapping_state) auto getVoteCount = bind(&Ballot::getVoteCount, &ballot, _1); auto grantVoteRight = bind(&Ballot::grantVoteRight, &ballot, _1); auto vote = bind(&Ballot::vote, &ballot, _1, _2); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // voting without vote right should be rejected - testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // grant vote rights - testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(0)); - testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(1)); + testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(0)); + testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(1)); // vote, should increase 2's vote count - testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // vote again, should be rejected - testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // vote without right to vote - testSolidityAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // grant vote right and now vote again - testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(2)); - testSolidityAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); } BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) @@ -1000,7 +1000,7 @@ BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) table[value]++; return --table[value++]; }; - testSolidityAgainstCppOnRange("f(uint256)", f, 0, 5); + testContractAgainstCppOnRange("f(uint256)", f, 0, 5); } BOOST_AUTO_TEST_CASE(multi_level_mapping) @@ -1020,14 +1020,14 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) if (_z == 0) return table[_x][_y]; else return table[_x][_y] = _z; }; - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); } BOOST_AUTO_TEST_CASE(structs) @@ -1201,8 +1201,8 @@ BOOST_AUTO_TEST_CASE(constructor) { return data[_x]; }; - testSolidityAgainstCpp("get(uint256)", get, u256(6)); - testSolidityAgainstCpp("get(uint256)", get, u256(7)); + testContractAgainstCpp("get(uint256)", get, u256(6)); + testContractAgainstCpp("get(uint256)", get, u256(7)); } BOOST_AUTO_TEST_CASE(simple_accessor) @@ -1723,9 +1723,9 @@ BOOST_AUTO_TEST_CASE(sha3) { return dev::keccak256(toBigEndian(_x)); }; - testSolidityAgainstCpp("a(bytes32)", f, u256(4)); - testSolidityAgainstCpp("a(bytes32)", f, u256(5)); - testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(sha256) @@ -1746,9 +1746,9 @@ BOOST_AUTO_TEST_CASE(sha256) return fromHex("af9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051"); return fromHex(""); }; - testSolidityAgainstCpp("a(bytes32)", f, u256(4)); - testSolidityAgainstCpp("a(bytes32)", f, u256(5)); - testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(ripemd) @@ -1769,9 +1769,9 @@ BOOST_AUTO_TEST_CASE(ripemd) return fromHex("1cf4e77f5966e13e109703cd8a0df7ceda7f3dc3000000000000000000000000"); return fromHex(""); }; - testSolidityAgainstCpp("a(bytes32)", f, u256(4)); - testSolidityAgainstCpp("a(bytes32)", f, u256(5)); - testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(ecrecover) From d82eac3fed6547ddcaac8ecccb15c7f7eaa74d16 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 29 Nov 2016 22:04:51 +0000 Subject: [PATCH 078/185] LLL: parseLLL to be less greedy catching exceptions --- liblll/Compiler.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index 0cec7bc8f..73a82a35b 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -99,15 +99,28 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v string dev::eth::parseLLL(string const& _src) { + bool failed = false; + sp::utree o; + try { - sp::utree o; parseTreeLLL(_src, o); - ostringstream ret; - debugOutAST(ret, o); - killBigints(o); + } + catch (...) + { + failed = true; + } + + ostringstream ret; + debugOutAST(ret, o); + killBigints(o); + + if (failed) + { + return string(); + } + else + { return ret.str(); } - catch (...) {} - return string(); } From 25160bfc26cd5ae4b5104625caba41c1533614ba Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 25 Oct 2016 12:38:37 +0100 Subject: [PATCH 079/185] Add optimiser rule for SUB with 0 --- libevmasm/ExpressionClasses.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index e32b2da21..cb3272528 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -245,17 +245,18 @@ Rules::Rules() // invariants involving known constants {{Instruction::ADD, {X, 0}}, [=]{ return X; }}, + {{Instruction::SUB, {X, 0}}, [=]{ return X; }}, {{Instruction::MUL, {X, 1}}, [=]{ return X; }}, {{Instruction::DIV, {X, 1}}, [=]{ return X; }}, {{Instruction::SDIV, {X, 1}}, [=]{ return X; }}, {{Instruction::OR, {X, 0}}, [=]{ return X; }}, {{Instruction::XOR, {X, 0}}, [=]{ return X; }}, {{Instruction::AND, {X, ~u256(0)}}, [=]{ return X; }}, + {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::MUL, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::DIV, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::MOD, {0, X}}, [=]{ return u256(0); }}, - {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::OR, {X, ~u256(0)}}, [=]{ return ~u256(0); }}, {{Instruction::EQ, {X, 0}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; } }, // operations involving an expression and itself From b8bba6622013a6c0969392a4096a3a7384b8cf62 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 9 Nov 2016 02:22:54 +0000 Subject: [PATCH 080/185] Replace XOR/ISZERO with EQ --- libevmasm/ExpressionClasses.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index cb3272528..29fb6dbc0 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -288,6 +288,10 @@ Rules::Rules() {Instruction::ISZERO, {{Instruction::ISZERO, {{Instruction::ISZERO, {X}}}}}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; } }); + m_rules.push_back({ + {Instruction::ISZERO, {{Instruction::XOR, {X, Y}}}}, + [=]() -> Pattern { return { Instruction::EQ, {X, Y} }; } + }); // Associative operations for (auto const& opFun: vector>>{ {Instruction::ADD, plus()}, From 3fdef92911ea1824f7a84ce556fec48e23a314ad Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 9 Nov 2016 02:25:44 +0000 Subject: [PATCH 081/185] Replace XOR with self with 0 --- libevmasm/ExpressionClasses.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index 29fb6dbc0..bb71be2e7 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -262,6 +262,7 @@ Rules::Rules() // operations involving an expression and itself {{Instruction::AND, {X, X}}, [=]{ return X; }}, {{Instruction::OR, {X, X}}, [=]{ return X; }}, + {{Instruction::XOR, {X, X}}, [=]{ return u256(0); }}, {{Instruction::SUB, {X, X}}, [=]{ return u256(0); }}, {{Instruction::EQ, {X, X}}, [=]{ return u256(1); }}, {{Instruction::LT, {X, X}}, [=]{ return u256(0); }}, From 8d0b80f944c42e871e42c320dfabf92c707ed9b7 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 9 Nov 2016 11:28:53 +0000 Subject: [PATCH 082/185] Add test for SUB with 0 optimisation --- test/libsolidity/SolidityOptimizer.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index a53a26384..90caaab07 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -1304,6 +1304,28 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join) compareVersions("test()"); } +BOOST_AUTO_TEST_CASE(cse_sub_zero) +{ + checkCSE({ + u256(0), + u256(5), + Instruction::SUB + }, { + u256(5) + }); + + checkCSE({ + u256(5), + u256(0), + Instruction::SUB + }, { + u256(5), + u256(0), + Instruction::SUB + }); +} + + BOOST_AUTO_TEST_SUITE_END() } From 4ff89dda1d9d81170b65775b33c1cfbd7e5e6b48 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 14 Nov 2016 13:22:55 +0100 Subject: [PATCH 083/185] Update SolidityOptimizer.cpp --- test/libsolidity/SolidityOptimizer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 90caaab07..00a636fde 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -1308,18 +1308,18 @@ BOOST_AUTO_TEST_CASE(cse_sub_zero) { checkCSE({ u256(0), - u256(5), + Instruction::DUP2, Instruction::SUB }, { u256(5) }); checkCSE({ - u256(5), + Instruction::DUP2, u256(0), Instruction::SUB }, { - u256(5), + Instruction::DUP2, u256(0), Instruction::SUB }); From df4b405f9c1cd3ebfd2787b5f1f6925cabf789d3 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 24 Oct 2016 17:33:57 +0200 Subject: [PATCH 084/185] Add more optimization rules --- libevmasm/ExpressionClasses.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index bb71be2e7..d5ccd7e3c 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -255,6 +255,7 @@ Rules::Rules() {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::MUL, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::DIV, {X, 0}}, [=]{ return u256(0); }}, + {{Instruction::DIV, {0, X}}, [=]{ return u256(0); }}, {{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }}, {{Instruction::MOD, {0, X}}, [=]{ return u256(0); }}, {{Instruction::OR, {X, ~u256(0)}}, [=]{ return ~u256(0); }}, @@ -272,6 +273,11 @@ Rules::Rules() {{Instruction::MOD, {X, X}}, [=]{ return u256(0); }}, {{Instruction::NOT, {{Instruction::NOT, {X}}}}, [=]{ return X; }}, + {{Instruction::XOR, {{{X}, {Instruction::XOR, {X, Y}}}}}, [=]{ return Y; }}, + {{Instruction::OR, {{{X}, {Instruction::AND, {X, Y}}}}}, [=]{ return X; }}, + {{Instruction::AND, {{{X}, {Instruction::OR, {X, Y}}}}}, [=]{ return X; }}, + {{Instruction::AND, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return u256(0); }}, + {{Instruction::OR, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return ~u256(0); }}, }; // Double negation of opcodes with binary result for (auto const& op: vector{ From 9a6a5f219b74097c1a11278aad07df1ffd60ff45 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 11:18:33 +0000 Subject: [PATCH 085/185] Fix sub-0 optimiser test --- test/libsolidity/SolidityOptimizer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 00a636fde..89c89adcf 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -1311,16 +1311,17 @@ BOOST_AUTO_TEST_CASE(cse_sub_zero) Instruction::DUP2, Instruction::SUB }, { - u256(5) + Instruction::DUP1 }); checkCSE({ - Instruction::DUP2, + Instruction::DUP1, u256(0), Instruction::SUB }, { - Instruction::DUP2, u256(0), + Instruction::DUP2, + Instruction::SWAP1, Instruction::SUB }); } From 2962426d5318a42b011543b4b550eb10624de9f7 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 12:20:13 +0000 Subject: [PATCH 086/185] Include the grammar verbatim in the documentation --- {libsolidity => docs}/grammar.txt | 0 docs/miscellaneous.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {libsolidity => docs}/grammar.txt (100%) diff --git a/libsolidity/grammar.txt b/docs/grammar.txt similarity index 100% rename from libsolidity/grammar.txt rename to docs/grammar.txt diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 15ff374d2..9f733979b 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -380,4 +380,4 @@ These keywords are reserved in Solidity. They might become part of the syntax in Language Grammar ================ -The entire language grammar is `available here `_. +.. literalinclude:: grammar.txt From 53d4433484c33b32d4d1063330633a308c0e48dd Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 15:06:13 +0000 Subject: [PATCH 087/185] LLL: simplify error handling in parseLLL --- liblll/Compiler.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp index 73a82a35b..cd909f347 100644 --- a/liblll/Compiler.cpp +++ b/liblll/Compiler.cpp @@ -99,7 +99,6 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v string dev::eth::parseLLL(string const& _src) { - bool failed = false; sp::utree o; try @@ -108,19 +107,12 @@ string dev::eth::parseLLL(string const& _src) } catch (...) { - failed = true; + killBigints(o); + return string(); } ostringstream ret; debugOutAST(ret, o); killBigints(o); - - if (failed) - { - return string(); - } - else - { - return ret.str(); - } + return ret.str(); } From a8696c6d8e1d64f02f65c98818f89532b5694953 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 1 Nov 2016 00:17:53 +0000 Subject: [PATCH 088/185] LLL: do not accept '0x' as 0 --- liblll/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp index 219d4f54b..4d2736baa 100644 --- a/liblll/Parser.cpp +++ b/liblll/Parser.cpp @@ -100,7 +100,7 @@ void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out) qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;$@()[]{}:\n\t") + '\0'))]; qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" $@[]{}:();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; + qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> +qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; qi::rule integer = intstr[qi::_val = px::construct(px::new_(qi::_1))]; qi::rule atom = integer[qi::_val = qi::_1] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; qi::rule seq = '{' > *element > '}'; From 99b803cbcbe4f7a0806db12d53cb7152fde490ef Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 1 Nov 2016 00:19:25 +0000 Subject: [PATCH 089/185] LLL: () requires at least one parameter --- liblll/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp index 4d2736baa..ad5e1885b 100644 --- a/liblll/Parser.cpp +++ b/liblll/Parser.cpp @@ -109,7 +109,7 @@ void dev::eth::parseTreeLLL(string const& _s, sp::utree& o_out) qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; qi::rule calldataload = qi::lit("$") > element; - qi::rule list = '(' > *element > ')'; + qi::rule list = '(' > +element > ')'; qi::rule extra = sload[tagNode<2>()] | mload[tagNode<1>()] | sstore[tagNode<4>()] | mstore[tagNode<3>()] | seq[tagNode<5>()] | calldataload[tagNode<6>()]; element = atom | list | extra; From b1add657b76621952be100b4203dd2c8a466b9a1 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 1 Nov 2016 02:07:20 +0000 Subject: [PATCH 090/185] LLL: throw exceptions on invalid symbols --- liblll/CodeFragment.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 35ad4e590..af7d7f0a6 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -91,15 +91,11 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS { auto it = _s.vars.find(s); if (it == _s.vars.end()) - { - bool ok; - tie(it, ok) = _s.vars.insert(make_pair(s, make_pair(_s.stackSize, 32))); - _s.stackSize += 32; - } + error(std::string("Symbol not found: ") + s); m_asm.append((u256)it->second.first); } else - error(); + error(s); break; } @@ -111,7 +107,9 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompilerState& _s, bool _allowAS m_asm.append((u256)i); break; } - default: break; + default: + error("Unexpected fragment type"); + break; } } @@ -177,11 +175,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) { auto it = _s.vars.find(n); if (it == _s.vars.end()) - { - bool ok; - tie(it, ok) = _s.vars.insert(make_pair(n, make_pair(_s.stackSize, 32))); - _s.stackSize += 32; - } + error(std::string("Symbol not found: ") + s); return it->second.first; }; From 4cecedcb49188a49ed70241f36e19ec8cb542a4c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 00:16:25 +0000 Subject: [PATCH 091/185] LLL: update tests with the strict parser --- test/liblll/Parser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/liblll/Parser.cpp b/test/liblll/Parser.cpp index fc91f3c54..0d5d9ea5a 100644 --- a/test/liblll/Parser.cpp +++ b/test/liblll/Parser.cpp @@ -87,6 +87,8 @@ BOOST_AUTO_TEST_CASE(hexadecimals) char const* text = "0x1234"; BOOST_CHECK(successParse(text)); BOOST_CHECK_EQUAL(parse(text), R"(4660)"); + + BOOST_CHECK(!successParse("0x")); } BOOST_AUTO_TEST_CASE(sequence) @@ -169,7 +171,7 @@ BOOST_AUTO_TEST_CASE(list) BOOST_CHECK_EQUAL(parse(text), R"(( 1234 ))"); BOOST_CHECK(successParse("( 1234 5467 )")); - BOOST_CHECK(successParse("()")); + BOOST_CHECK(!successParse("()")); } BOOST_AUTO_TEST_SUITE_END() From eaab71294476f46513678be2e8cad02589d141dc Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 30 Nov 2016 17:28:07 +0100 Subject: [PATCH 092/185] parser: recognize an end of comment of the form `**/` at the end of a multi-line doc comment This fixes #1433 --- libsolidity/parsing/Scanner.cpp | 7 ++++++- test/libsolidity/SolidityParser.cpp | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp index 6115101e6..3623f23f7 100644 --- a/libsolidity/parsing/Scanner.cpp +++ b/libsolidity/parsing/Scanner.cpp @@ -327,7 +327,12 @@ Token::Value Scanner::scanMultiLineDocComment() if (isLineTerminator(m_char)) { skipWhitespace(); - if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/') + if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '*') + { // it is unknown if this leads to the end of the comment + addCommentLiteralChar('*'); + advance(); + } + else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/') { // skip first '*' in subsequent lines if (charsAdded) addCommentLiteralChar('\n'); diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index a3217f08e..1c616ef66 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -962,6 +962,19 @@ BOOST_AUTO_TEST_CASE(empty_comment) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(comment_end_with_double_star) +{ + char const* text = R"( + contract C1 { + /** + **/ + } + contract C2 {} + )"; + BOOST_CHECK(successParse(text)); +} + + BOOST_AUTO_TEST_CASE(library_simple) { char const* text = R"( From b16cdbb57e2f3bdc99b2cf367e40a7f78b4c72ee Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 10 Nov 2016 11:44:31 +0100 Subject: [PATCH 093/185] test: add a test that witnesses #1318 --- test/libsolidity/SolidityEndToEndTest.cpp | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 98ea92cab..62e9a4572 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4466,6 +4466,34 @@ BOOST_AUTO_TEST_CASE(super_overload) BOOST_CHECK(callContractFunction("h()") == encodeArgs(2)); } +BOOST_AUTO_TEST_CASE(bool_conversion) +{ + char const* sourceCode = R"( + contract C { + function f(bool _b) returns(uint) { + if (_b) + return 1; + else + return 0; + } + function g(bool _in) returns (bool _out) { + _out = _in; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(bool)", 0) == encodeArgs(0)); + BOOST_CHECK(callContractFunction("f(bool)", 1) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(bool)", 2) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(bool)", 3) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(bool)", 255) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 0) == encodeArgs(0)); + BOOST_CHECK(callContractFunction("g(bool)", 1) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 2) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 3) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 255) == encodeArgs(1)); +} + BOOST_AUTO_TEST_CASE(packed_storage_signed) { char const* sourceCode = R"( From 03ccc6df704aae4ea19698f0167798013c14536e Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 10 Nov 2016 11:33:15 +0100 Subject: [PATCH 094/185] codegen: truncate a boolean calldata down to one bit --- Changelog.md | 1 + libsolidity/codegen/CompilerUtils.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index b5e48173c..86e0125af 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Features: Bugfixes: * Type checker: string literals that are not valid UTF-8 cannot be converted to string type + * Code generator: higher bits in a boolean argument are ignored. ### 0.4.6 (2016-11-22) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index d5361ac6a..ff0f8b9c2 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -925,6 +925,8 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda if (leftAligned) m_context << shiftFactor << Instruction::MUL; } + if (_fromCalldata && _type.category() == Type::Category::Bool) + m_context << Instruction::ISZERO << Instruction::ISZERO; return numBytes; } From 0123e74a2eeac35bfa55886d0c6db391c07e7ec6 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 10 Nov 2016 14:41:50 +0100 Subject: [PATCH 095/185] codegen: cleanup booleans before storing them into memory --- libsolidity/codegen/CompilerUtils.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index ff0f8b9c2..ce5bb1d28 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -950,6 +950,8 @@ unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBou else { solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested."); + if (_type.category() == Type::Category::Bool) + m_context << Instruction::ISZERO << Instruction::ISZERO; if (numBytes != 32 && !leftAligned && !_padToWordBoundaries) // shift the value accordingly before storing m_context << (u256(1) << ((32 - numBytes) * 8)) << Instruction::MUL; From fb9babce54f76251b9616f192822e0c015411159 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 10 Nov 2016 15:38:08 +0100 Subject: [PATCH 096/185] codegen: truncate booleans before they enter storage --- libsolidity/codegen/LValue.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 23fe2d4e7..b9e141d86 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -223,7 +223,6 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc { 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."); From 7959ee49beb664238e58dcb589f386b2dff7438c Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 10 Nov 2016 15:56:12 +0100 Subject: [PATCH 097/185] docs: describe when and how overflown values are cleaned --- Changelog.md | 2 +- docs/miscellaneous.rst | 52 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 86e0125af..ea1b1b589 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,7 @@ Features: Bugfixes: * Type checker: string literals that are not valid UTF-8 cannot be converted to string type - * Code generator: higher bits in a boolean argument are ignored. + * Code generator: any non-zero value given as a boolean argument is now converted into 1. ### 0.4.6 (2016-11-22) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 9f733979b..7e9cee44a 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -56,6 +56,8 @@ So for the following contract snippet:: The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``. +.. index: memory layout + **************** Layout in Memory **************** @@ -72,7 +74,8 @@ Solidity always places new objects at the free memory pointer and memory is neve .. warning:: There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifecycle, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one shouldn't expect the free memory to be zeroed out. -.. index: memory layout + +.. index: calldata layout ******************* Layout of Call Data @@ -85,6 +88,53 @@ specification ABI specification requires arguments to be padded to multiples of 32 bytes. The internal function calls use a different convention. + +.. index: overflow + +**************************************** +Internals - Cleaning Up Overflows in EVM +**************************************** + +When a value is shorter than 256-bit, sometimes the remaining bits +must be cleaned. +The Solidity compiler is designed to clean such remaining bits before any operations +that might be broken by the garbage in the remaining bits. For +example, before writing a value to the memory, the remaining bits need +to be cleared because the memory contents can be used for computing +hashes or sent as the data of a message call. Similarly, before +storing a value in the storage, the remaining bits need to be cleaned +because otherwise the garbled value can be observed. + +On the other hand, we do not clean the bits if the immediately +following operation is not affected. For instance, since any non-zero +value is considered ``true`` by ``JUMPI`` instruction, we do not clean +the boolean values before they are used as the condition for +``JUMPI``. + +Different types have different rules for cleaning up overflows: + ++---------------+---------------+------------------+ +|Type |Cleaned Form |Overflow Means | ++===============+===============+==================+ +|enum of n |0 until n - 1 |exception | +|members | | | ++---------------+---------------+------------------+ +|bool |0 or 1 |zero or nonzero | ++---------------+---------------+------------------+ +|signed integers|sign-extended |currently silently| +| |word |wraps; in the | +| | |future exceptions | +| | |will be thrown | +| | | | +| | | | ++---------------+---------------+------------------+ +|unsigned |higher bits |currently silently| +|integers |zeroed |wraps; in the | +| | |future exceptions | +| | |will be thrown | ++---------------+---------------+------------------+ + + ***************** Esoteric Features ***************** From 547deec4be55fc10b44de9ff92bb2d598d5b04f5 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 24 Nov 2016 11:57:28 +0100 Subject: [PATCH 098/185] codegen: clean any data from the input --- docs/miscellaneous.rst | 3 +++ libsolidity/codegen/CompilerUtils.cpp | 4 ++-- test/libsolidity/Assembly.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 7e9cee44a..251d77d2d 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -111,6 +111,9 @@ value is considered ``true`` by ``JUMPI`` instruction, we do not clean the boolean values before they are used as the condition for ``JUMPI``. +In addition to the design principle above, the Solidity compiler +cleans input data when it is loaded onto the stack. + Different types have different rules for cleaning up overflows: +---------------+---------------+------------------+ diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index ce5bb1d28..6763e995e 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -925,8 +925,8 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda if (leftAligned) m_context << shiftFactor << Instruction::MUL; } - if (_fromCalldata && _type.category() == Type::Category::Bool) - m_context << Instruction::ISZERO << Instruction::ISZERO; + if (_fromCalldata) + convertType(_type, _type, true); return numBytes; } diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index cc77bd4cf..ed92ca2be 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr n = make_shared(""); AssemblyItems items = compileContract(sourceCode); vector locations = - vector(16, SourceLocation(2, 75, n)) + + vector(18, SourceLocation(2, 75, n)) + vector(27, SourceLocation(20, 72, n)) + vector{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector(2, SourceLocation(58, 67, n)) + From 5d7a1fda39d29329df675985b0d3e50548348b72 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 10:03:39 +0100 Subject: [PATCH 099/185] docs: remove the word overflow when we are talking about invalid values --- docs/miscellaneous.rst | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 251d77d2d..6e1b575a0 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -114,28 +114,28 @@ the boolean values before they are used as the condition for In addition to the design principle above, the Solidity compiler cleans input data when it is loaded onto the stack. -Different types have different rules for cleaning up overflows: +Different types have different rules for cleaning up invalid values: -+---------------+---------------+------------------+ -|Type |Cleaned Form |Overflow Means | -+===============+===============+==================+ -|enum of n |0 until n - 1 |exception | -|members | | | -+---------------+---------------+------------------+ -|bool |0 or 1 |zero or nonzero | -+---------------+---------------+------------------+ -|signed integers|sign-extended |currently silently| -| |word |wraps; in the | -| | |future exceptions | -| | |will be thrown | -| | | | -| | | | -+---------------+---------------+------------------+ -|unsigned |higher bits |currently silently| -|integers |zeroed |wraps; in the | -| | |future exceptions | -| | |will be thrown | -+---------------+---------------+------------------+ ++---------------+---------------+-------------------+ +|Type |Valid Valies |Invalid Values Mean| ++===============+===============+===================+ +|enum of n |0 until n - 1 |exception | +|members | | | ++---------------+---------------+-------------------+ +|bool |0 or 1 |1 | ++---------------+---------------+-------------------+ +|signed integers|sign-extended |currently silently | +| |word |wraps; in the | +| | |future exceptions | +| | |will be thrown | +| | | | +| | | | ++---------------+---------------+-------------------+ +|unsigned |higher bits |currently silently | +|integers |zeroed |wraps; in the | +| | |future exceptions | +| | |will be thrown | ++---------------+---------------+-------------------+ ***************** From d77c8f730ce6a7c4caa86bb8e3bf1e5ca13b2117 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 25 Nov 2016 10:17:40 +0100 Subject: [PATCH 100/185] codegen: clean not only booleans but all types before storing them into memory --- libsolidity/codegen/CompilerUtils.cpp | 5 ++--- libsolidity/codegen/CompilerUtils.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 6763e995e..edf457a14 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -941,7 +941,7 @@ void CompilerUtils::cleanHigherOrderBits(IntegerType const& _typeOnStack) m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << Instruction::AND; } -unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const +unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) { unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries); bool leftAligned = _type.category() == Type::Category::FixedBytes; @@ -950,8 +950,7 @@ unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBou else { solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested."); - if (_type.category() == Type::Category::Bool) - m_context << Instruction::ISZERO << Instruction::ISZERO; + convertType(_type, _type, true); if (numBytes != 32 && !leftAligned && !_padToWordBoundaries) // shift the value accordingly before storing m_context << (u256(1) << ((32 - numBytes) * 8)) << Instruction::MUL; diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 4baf48ff1..0a5d8e1c5 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -185,7 +185,7 @@ private: void cleanHigherOrderBits(IntegerType const& _typeOnStack); /// Prepares the given type for storing in memory by shifting it if necessary. - unsigned prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) const; + unsigned prepareMemoryStore(Type const& _type, bool _padToWordBoundaries); /// Loads type from memory assuming memory offset is on stack top. unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries); From 868a8a8fa03fc3cf47fd66335a7924d7876f1c0e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 11:00:27 +0000 Subject: [PATCH 101/185] docs: update overflow cleanup wording --- docs/miscellaneous.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 6e1b575a0..963edf26b 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -95,11 +95,11 @@ bytes. The internal function calls use a different convention. Internals - Cleaning Up Overflows in EVM **************************************** -When a value is shorter than 256-bit, sometimes the remaining bits +When a value is shorter than 256-bit, in some cases the remaining bits must be cleaned. The Solidity compiler is designed to clean such remaining bits before any operations -that might be broken by the garbage in the remaining bits. For -example, before writing a value to the memory, the remaining bits need +that might be adversely affected by the potential garbage in the remaining bits. +For example, before writing a value to the memory, the remaining bits need to be cleared because the memory contents can be used for computing hashes or sent as the data of a message call. Similarly, before storing a value in the storage, the remaining bits need to be cleaned @@ -117,7 +117,7 @@ cleans input data when it is loaded onto the stack. Different types have different rules for cleaning up invalid values: +---------------+---------------+-------------------+ -|Type |Valid Valies |Invalid Values Mean| +|Type |Valid Values |Invalid Values Mean| +===============+===============+===================+ |enum of n |0 until n - 1 |exception | |members | | | From 610027cd26dda1cded357f62585e75eed3cb0e48 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 23:54:02 +0000 Subject: [PATCH 102/185] Test that contracts separated by comments are compiled --- test/libsolidity/SolidityEndToEndTest.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 98ea92cab..f2678d5b2 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8378,6 +8378,18 @@ BOOST_AUTO_TEST_CASE(inline_assembly_invalidjumplabel) BOOST_CHECK(callContractFunction("f()") == encodeArgs()); } +BOOST_AUTO_TEST_CASE(contracts_separated_with_comment) +{ + char const* sourceCode = R"( + contract C1 {} + /** + **/ + contract C2 {} + )"; + compileAndRun(sourceCode, 0, "C1"); + compileAndRun(sourceCode, 0, "C2"); +} + BOOST_AUTO_TEST_SUITE_END() } From 6ce41b566d80f3b760ece171e8802e9017c52797 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 1 Dec 2016 00:39:30 -0300 Subject: [PATCH 103/185] Use more R string literals in tests --- test/libsolidity/SolidityEndToEndTest.cpp | 999 ++++++++++++---------- test/libsolidity/SolidityParser.cpp | 652 ++++++++------ 2 files changed, 934 insertions(+), 717 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 98ea92cab..c5f797584 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -44,17 +44,20 @@ BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityExecutionFramework) BOOST_AUTO_TEST_CASE(smoke_test) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + } + )"; compileAndRun(sourceCode); testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100); } BOOST_AUTO_TEST_CASE(empty_contract) { - char const* sourceCode = "contract test {\n" - "}\n"; + char const* sourceCode = R"( + contract test { } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()).empty()); } @@ -64,7 +67,8 @@ BOOST_AUTO_TEST_CASE(exp_operator) char const* sourceCode = R"( contract test { function f(uint a) returns(uint d) { return 2 ** a; } - })"; + } + )"; compileAndRun(sourceCode); testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to()); }, 0, 16); } @@ -74,7 +78,8 @@ BOOST_AUTO_TEST_CASE(exp_operator_const) char const* sourceCode = R"( contract test { function f() returns(uint d) { return 2 ** 3; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(8))); } @@ -84,7 +89,8 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) char const* sourceCode = R"( contract test { function f() returns(int d) { return (-2) ** 3; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(-8))); } @@ -95,8 +101,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) contract test { function f() returns(uint d) { return true ? 5 : 10; - } - })"; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(5))); } @@ -107,8 +114,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) contract test { function f() returns(uint d) { return false ? 5 : 10; - } - })"; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(10))); } @@ -118,12 +126,13 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple) char const* sourceCode = R"( contract test { function f(uint x) returns(uint d) { - return x > 100 ? + return x > 100 ? x > 1000 ? 1000 : 100 : x > 50 ? 50 : 10; - } - })"; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256)", u256(1001)) == toBigEndian(u256(1000))); BOOST_CHECK(callContractFunction("f(uint256)", u256(500)) == toBigEndian(u256(100))); @@ -137,7 +146,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) contract test { function f(bool cond, uint v) returns (uint a, uint b) { cond ? a = v : b = v; - } + } })"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)) == encodeArgs(u256(20), u256(0))); @@ -169,7 +178,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) } return ret; - } + } } )"; compileAndRun(sourceCode); @@ -203,7 +212,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) } return ret; - } + } } )"; compileAndRun(sourceCode); @@ -219,7 +228,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_different_types) uint8 x = 0xcd; uint16 y = 0xabab; return cond ? x : y; - } + } } )"; compileAndRun(sourceCode); @@ -277,12 +286,14 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions) BOOST_AUTO_TEST_CASE(recursive_calls) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " if (n <= 1) return 1;\n" - " else return n * f(n - 1);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + if (n <= 1) return 1; + else return n * f(n - 1); + } + } + )"; compileAndRun(sourceCode); function recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 { @@ -297,12 +308,14 @@ BOOST_AUTO_TEST_CASE(recursive_calls) BOOST_AUTO_TEST_CASE(multiple_functions) { - char const* sourceCode = "contract test {\n" - " function a() returns(uint n) { return 0; }\n" - " function b() returns(uint n) { return 1; }\n" - " function c() returns(uint n) { return 2; }\n" - " function f() returns(uint n) { return 3; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() returns(uint n) { return 0; } + function b() returns(uint n) { return 1; } + function c() returns(uint n) { return 2; } + function f() returns(uint n) { return 3; } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("a()", bytes()) == toBigEndian(u256(0))); BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(1))); @@ -313,33 +326,39 @@ BOOST_AUTO_TEST_CASE(multiple_functions) BOOST_AUTO_TEST_CASE(named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(disorder_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(while_loop) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " var i = 2;\n" - " while (i <= n) nfac *= i++;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + var i = 2; + while (i <= n) nfac *= i++; + } + } + )"; compileAndRun(sourceCode); auto while_loop_cpp = [](u256 const& n) -> u256 @@ -358,13 +377,15 @@ BOOST_AUTO_TEST_CASE(while_loop) BOOST_AUTO_TEST_CASE(do_while_loop) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " var i = 2;\n" - " do { nfac *= i++; } while (i <= n);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + var i = 2; + do { nfac *= i++; } while (i <= n); + } + } + )"; compileAndRun(sourceCode); auto do_while_loop_cpp = [](u256 const& n) -> u256 @@ -386,26 +407,28 @@ BOOST_AUTO_TEST_CASE(do_while_loop) BOOST_AUTO_TEST_CASE(nested_loops) { // tests that break and continue statements in nested loops jump to the correct place - char const* sourceCode = "contract test {\n" - " function f(uint x) returns(uint y) {\n" - " while (x > 1) {\n" - " if (x == 10) break;\n" - " while (x > 5) {\n" - " if (x == 8) break;\n" - " x--;\n" - " if (x == 6) continue;\n" - " return x;\n" - " }\n" - " x--;\n" - " if (x == 3) continue;\n" - " break;\n" - " }\n" - " return x;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint x) returns(uint y) { + while (x > 1) { + if (x == 10) break; + while (x > 5) { + if (x == 8) break; + x--; + if (x == 6) continue; + return x; + } + x--; + if (x == 3) continue; + break; + } + return x; + } + } + )"; compileAndRun(sourceCode); - auto nested_loops_cpp = [](u256 n) -> u256 + auto nested_loops_cpp = [](u256 n) -> u256 { while (n > 1) { @@ -434,13 +457,15 @@ BOOST_AUTO_TEST_CASE(nested_loops) BOOST_AUTO_TEST_CASE(for_loop) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " for (var i = 2; i <= n; i++)\n" - " nfac *= i;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + for (var i = 2; i <= n; i++) + nfac *= i; + } + } + )"; compileAndRun(sourceCode); auto for_loop_cpp = [](u256 const& n) -> u256 @@ -456,16 +481,17 @@ BOOST_AUTO_TEST_CASE(for_loop) BOOST_AUTO_TEST_CASE(for_loop_empty) { - char const* sourceCode = "contract test {\n" - " function f() returns(uint ret) {\n" - " ret = 1;\n" - " for (;;)\n" - " {\n" - " ret += 1;\n" - " if (ret >= 10) break;\n" - " }\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() returns(uint ret) { + ret = 1; + for (;;) { + ret += 1; + if (ret >= 10) break; + } + } + } + )"; compileAndRun(sourceCode); auto for_loop_empty_cpp = []() -> u256 @@ -484,14 +510,16 @@ BOOST_AUTO_TEST_CASE(for_loop_empty) BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " uint256 i;\n" - " for (i = 2; i <= n; i++)\n" - " nfac *= i;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + uint256 i; + for (i = 2; i <= n; i++) + nfac *= i; + } + } + )"; compileAndRun(sourceCode); auto for_loop_simple_init_expr_cpp = [](u256 const& n) -> u256 @@ -554,20 +582,22 @@ BOOST_AUTO_TEST_CASE(for_loop_break_continue) BOOST_AUTO_TEST_CASE(calling_other_functions) { - char const* sourceCode = "contract collatz {\n" - " function run(uint x) returns(uint y) {\n" - " while ((y = x) > 1) {\n" - " if (x % 2 == 0) x = evenStep(x);\n" - " else x = oddStep(x);\n" - " }\n" - " }\n" - " function evenStep(uint x) returns(uint y) {\n" - " return x / 2;\n" - " }\n" - " function oddStep(uint x) returns(uint y) {\n" - " return 3 * x + 1;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract collatz { + function run(uint x) returns(uint y) { + while ((y = x) > 1) { + if (x % 2 == 0) x = evenStep(x); + else x = oddStep(x); + } + } + function evenStep(uint x) returns(uint y) { + return x / 2; + } + function oddStep(uint x) returns(uint y) { + return 3 * x + 1; + } + } + )"; compileAndRun(sourceCode); auto evenStep_cpp = [](u256 const& n) -> u256 @@ -602,13 +632,15 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) BOOST_AUTO_TEST_CASE(many_local_variables) { - char const* sourceCode = "contract test {\n" - " function run(uint x1, uint x2, uint x3) returns(uint y) {\n" - " var a = 0x1; var b = 0x10; var c = 0x100;\n" - " y = a + b + c + x1 + x2 + x3;\n" - " y += b + x2;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(uint x1, uint x2, uint x3) returns(uint y) { + var a = 0x1; var b = 0x10; var c = 0x100; + y = a + b + c + x1 + x2 + x3; + y += b + x2; + } + } + )"; compileAndRun(sourceCode); auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256 { @@ -623,13 +655,15 @@ BOOST_AUTO_TEST_CASE(many_local_variables) BOOST_AUTO_TEST_CASE(packing_unpacking_types) { - char const* sourceCode = "contract test {\n" - " function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n" - " if (a) y = 1;\n" - " y = y * 0x100000000 | ~b;\n" - " y = y * 0x10000000000000000 | ~c;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(bool a, uint32 b, uint64 c) returns(uint256 y) { + if (a) y = 1; + y = y * 0x100000000 | ~b; + y = y * 0x10000000000000000 | ~c; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")) == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); @@ -637,12 +671,14 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) BOOST_AUTO_TEST_CASE(packing_signed_types) { - char const* sourceCode = "contract test {\n" - " function run() returns(int8 y) {\n" - " uint8 x = 0xfa;\n" - " return int8(x);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(int8 y) { + uint8 x = 0xfa; + return int8(x); + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("run()") == fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa")); @@ -650,23 +686,27 @@ BOOST_AUTO_TEST_CASE(packing_signed_types) BOOST_AUTO_TEST_CASE(multiple_return_values) { - char const* sourceCode = "contract test {\n" - " function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) {\n" - " y1 = x2; y2 = x1;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) { + y1 = x2; y2 = x1; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd) == encodeArgs(0xcd, true, 0)); } BOOST_AUTO_TEST_CASE(short_circuiting) { - char const* sourceCode = "contract test {\n" - " function run(uint x) returns(uint y) {\n" - " x == 0 || ((x = 8) > 0);\n" - " return x;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(uint x) returns(uint y) { + x == 0 || ((x = 8) > 0); + return x; + } + } + )"; compileAndRun(sourceCode); auto short_circuiting_cpp = [](u256 n) -> u256 @@ -680,14 +720,16 @@ BOOST_AUTO_TEST_CASE(short_circuiting) BOOST_AUTO_TEST_CASE(high_bits_cleaning) { - char const* sourceCode = "contract test {\n" - " function run() returns(uint256 y) {\n" - " uint32 t = uint32(0xffffffff);\n" - " uint32 x = t + 10;\n" - " if (x >= 0xffffffff) return 0;\n" - " return x;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(uint256 y) { + uint32 t = uint32(0xffffffff); + uint32 x = t + 10; + if (x >= 0xffffffff) return 0; + return x; + } + } + )"; compileAndRun(sourceCode); auto high_bits_cleaning_cpp = []() -> u256 { @@ -702,13 +744,15 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) BOOST_AUTO_TEST_CASE(sign_extension) { - char const* sourceCode = "contract test {\n" - " function run() returns(uint256 y) {\n" - " int64 x = -int32(0xff);\n" - " if (x >= 0xff) return 0;\n" - " return -uint256(x);" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(uint256 y) { + int64 x = -int32(0xff); + if (x >= 0xff) return 0; + return -uint256(x); + } + } + )"; compileAndRun(sourceCode); auto sign_extension_cpp = []() -> u256 { @@ -722,13 +766,15 @@ BOOST_AUTO_TEST_CASE(sign_extension) BOOST_AUTO_TEST_CASE(small_unsigned_types) { - char const* sourceCode = "contract test {\n" - " function run() returns(uint256 y) {\n" - " uint32 t = uint32(0xffffff);\n" - " uint32 x = t * 0xffffff;\n" - " return x / 0x100;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(uint256 y) { + uint32 t = uint32(0xffffff); + uint32 x = t * 0xffffff; + return x / 0x100; + } + } + )"; compileAndRun(sourceCode); auto small_unsigned_types_cpp = []() -> u256 { @@ -741,11 +787,13 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) BOOST_AUTO_TEST_CASE(small_signed_types) { - char const* sourceCode = "contract test {\n" - " function run() returns(int256 y) {\n" - " return -int32(10) * -int64(20);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(int256 y) { + return -int32(10) * -int64(20); + } + } + )"; compileAndRun(sourceCode); auto small_signed_types_cpp = []() -> u256 { @@ -756,15 +804,17 @@ BOOST_AUTO_TEST_CASE(small_signed_types) BOOST_AUTO_TEST_CASE(strings) { - char const* sourceCode = "contract test {\n" - " function fixedBytes() returns(bytes32 ret) {\n" - " return \"abc\\x00\\xff__\";\n" - " }\n" - " function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) {\n" - " oneRet = one;\n" - " large = small;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function fixedBytes() returns(bytes32 ret) { + return "abc\x00\xff__"; + } + function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) { + oneRet = one; + large = small; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("fixedBytes()") == encodeArgs(string("abc\0\xff__", 7))); BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); @@ -809,18 +859,20 @@ BOOST_AUTO_TEST_CASE(bytes_comparison) BOOST_AUTO_TEST_CASE(state_smoke_test) { - char const* sourceCode = "contract test {\n" - " uint256 value1;\n" - " uint256 value2;\n" - " function get(uint8 which) returns (uint256 value) {\n" - " if (which == 0) return value1;\n" - " else return value2;\n" - " }\n" - " function set(uint8 which, uint256 value) {\n" - " if (which == 0) value1 = value;\n" - " else value2 = value;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint256 value1; + uint256 value2; + function get(uint8 which) returns (uint256 value) { + if (which == 0) return value1; + else return value2; + } + function set(uint8 which, uint256 value) { + if (which == 0) value1 = value; + else value2 = value; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0)); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0)); @@ -834,17 +886,19 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) BOOST_AUTO_TEST_CASE(compound_assign) { - char const* sourceCode = "contract test {\n" - " uint value1;\n" - " uint value2;\n" - " function f(uint x, uint y) returns (uint w) {\n" - " uint value3 = y;" - " value1 += x;\n" - " value3 *= x;" - " value2 *= value3 + value1;\n" - " return value2 += 7;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint value1; + uint value2; + function f(uint x, uint y) returns (uint w) { + uint value3 = y; + value1 += x; + value3 *= x; + value2 *= value3 + value1; + return value2 += 7; + } + } + )"; compileAndRun(sourceCode); u256 value1; @@ -869,15 +923,17 @@ BOOST_AUTO_TEST_CASE(compound_assign) BOOST_AUTO_TEST_CASE(simple_mapping) { - char const* sourceCode = "contract test {\n" - " mapping(uint8 => uint8) table;\n" - " function get(uint8 k) returns (uint8 v) {\n" - " return table[k];\n" - " }\n" - " function set(uint8 k, uint8 v) {\n" - " table[k] = v;\n" - " }\n" - "}"; + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) table; + function get(uint8 k) returns (uint8 v) { + return table[k]; + } + function set(uint8 k, uint8 v) { + table[k] = v; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); @@ -899,23 +955,25 @@ BOOST_AUTO_TEST_CASE(simple_mapping) BOOST_AUTO_TEST_CASE(mapping_state) { - char const* sourceCode = "contract Ballot {\n" - " mapping(address => bool) canVote;\n" - " mapping(address => uint) voteCount;\n" - " mapping(address => bool) voted;\n" - " function getVoteCount(address addr) returns (uint retVoteCount) {\n" - " return voteCount[addr];\n" - " }\n" - " function grantVoteRight(address addr) {\n" - " canVote[addr] = true;\n" - " }\n" - " function vote(address voter, address vote) returns (bool success) {\n" - " if (!canVote[voter] || voted[voter]) return false;\n" - " voted[voter] = true;\n" - " voteCount[vote] = voteCount[vote] + 1;\n" - " return true;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract Ballot { + mapping(address => bool) canVote; + mapping(address => uint) voteCount; + mapping(address => bool) voted; + function getVoteCount(address addr) returns (uint retVoteCount) { + return voteCount[addr]; + } + function grantVoteRight(address addr) { + canVote[addr] = true; + } + function vote(address voter, address vote) returns (bool success) { + if (!canVote[voter] || voted[voter]) return false; + voted[voter] = true; + voteCount[vote] = voteCount[vote] + 1; + return true; + } + } + )"; compileAndRun(sourceCode); class Ballot { @@ -974,17 +1032,19 @@ BOOST_AUTO_TEST_CASE(mapping_state) BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) { - char const* sourceCode = "contract test {\n" - " uint value;\n" - " mapping(uint => uint) table;\n" - " function f(uint x) returns (uint y) {\n" - " value = x;\n" - " if (x > 0) table[++value] = 8;\n" - " if (x > 1) value--;\n" - " if (x > 2) table[value]++;\n" - " return --table[value++];\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint value; + mapping(uint => uint) table; + function f(uint x) returns (uint y) { + value = x; + if (x > 0) table[++value] = 8; + if (x > 1) value--; + if (x > 2) table[value]++; + return --table[value++]; + } + } + )"; compileAndRun(sourceCode); u256 value = 0; @@ -1005,13 +1065,15 @@ BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) BOOST_AUTO_TEST_CASE(multi_level_mapping) { - char const* sourceCode = "contract test {\n" - " mapping(uint => mapping(uint => uint)) table;\n" - " function f(uint x, uint y, uint z) returns (uint w) {\n" - " if (z == 0) return table[x][y];\n" - " else return table[x][y] = z;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + mapping(uint => mapping(uint => uint)) table; + function f(uint x, uint y, uint z) returns (uint w) { + if (z == 0) return table[x][y]; + else return table[x][y] = z; + } + } + )"; compileAndRun(sourceCode); map> table; @@ -1032,35 +1094,37 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) BOOST_AUTO_TEST_CASE(structs) { - char const* sourceCode = "contract test {\n" - " struct s1 {\n" - " uint8 x;\n" - " bool y;\n" - " }\n" - " struct s2 {\n" - " uint32 z;\n" - " s1 s1data;\n" - " mapping(uint8 => s2) recursive;\n" - " }\n" - " s2 data;\n" - " function check() returns (bool ok) {\n" - " return data.z == 1 && data.s1data.x == 2 && \n" - " data.s1data.y == true && \n" - " data.recursive[3].recursive[4].z == 5 && \n" - " data.recursive[4].recursive[3].z == 6 && \n" - " data.recursive[0].s1data.y == false && \n" - " data.recursive[4].z == 9;\n" - " }\n" - " function set() {\n" - " data.z = 1;\n" - " data.s1data.x = 2;\n" - " data.s1data.y = true;\n" - " data.recursive[3].recursive[4].z = 5;\n" - " data.recursive[4].recursive[3].z = 6;\n" - " data.recursive[0].s1data.y = false;\n" - " data.recursive[4].z = 9;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + struct s1 { + uint8 x; + bool y; + } + struct s2 { + uint32 z; + s1 s1data; + mapping(uint8 => s2) recursive; + } + s2 data; + function check() returns (bool ok) { + return data.z == 1 && data.s1data.x == 2 && + data.s1data.y == true && + data.recursive[3].recursive[4].z == 5 && + data.recursive[4].recursive[3].z == 6 && + data.recursive[0].s1data.y == false && + data.recursive[4].z == 9; + } + function set() { + data.z = 1; + data.s1data.x = 2; + data.s1data.y = true; + data.recursive[3].recursive[4].z = 5; + data.recursive[4].recursive[3].z = 6; + data.recursive[0].s1data.y = false; + data.recursive[4].z = 9; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); BOOST_CHECK(callContractFunction("set()") == bytes()); @@ -1069,26 +1133,28 @@ BOOST_AUTO_TEST_CASE(structs) BOOST_AUTO_TEST_CASE(struct_reference) { - char const* sourceCode = "contract test {\n" - " struct s2 {\n" - " uint32 z;\n" - " mapping(uint8 => s2) recursive;\n" - " }\n" - " s2 data;\n" - " function check() returns (bool ok) {\n" - " return data.z == 2 && \n" - " data.recursive[0].z == 3 && \n" - " data.recursive[0].recursive[1].z == 0 && \n" - " data.recursive[0].recursive[0].z == 1;\n" - " }\n" - " function set() {\n" - " data.z = 2;\n" - " var map = data.recursive;\n" - " s2 inner = map[0];\n" - " inner.z = 3;\n" - " inner.recursive[0].z = inner.recursive[1].z + 1;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + struct s2 { + uint32 z; + mapping(uint8 => s2) recursive; + } + s2 data; + function check() returns (bool ok) { + return data.z == 2 && + data.recursive[0].z == 3 && + data.recursive[0].recursive[1].z == 0 && + data.recursive[0].recursive[0].z == 1; + } + function set() { + data.z = 2; + var map = data.recursive; + s2 inner = map[0]; + inner.z = 3; + inner.recursive[0].z = inner.recursive[1].z + 1; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); BOOST_CHECK(callContractFunction("set()") == bytes()); @@ -1135,12 +1201,13 @@ BOOST_AUTO_TEST_CASE(deleteStruct) nestedValue = str.nstr.nestedValue; } function getTopMapping(uint index) returns(uint ret) { - ret = str.topMapping[index]; + ret = str.topMapping[index]; } function getNestedMapping(uint index) returns(bool ret) { return str.nstr.nestedMapping[index]; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); @@ -1161,7 +1228,8 @@ BOOST_AUTO_TEST_CASE(deleteLocal) delete v; res = v; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0)); } @@ -1178,22 +1246,25 @@ BOOST_AUTO_TEST_CASE(deleteLocals) res1 = w; res2 = x; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7)); } BOOST_AUTO_TEST_CASE(constructor) { - char const* sourceCode = "contract test {\n" - " mapping(uint => uint) data;\n" - " function test() {\n" - " data[7] = 8;\n" - " }\n" - " function get(uint key) returns (uint value) {\n" - " return data[key];" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + mapping(uint => uint) data; + function test() { + data[7] = 8; + } + function get(uint key) returns (uint value) { + return data[key]; + } + } + )"; compileAndRun(sourceCode); map data; data[7] = 8; @@ -1207,12 +1278,14 @@ BOOST_AUTO_TEST_CASE(constructor) BOOST_AUTO_TEST_CASE(simple_accessor) { - char const* sourceCode = "contract test {\n" - " uint256 public data;\n" - " function test() {\n" - " data = 8;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint256 public data; + function test() { + data = 8; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); } @@ -1254,7 +1327,7 @@ BOOST_AUTO_TEST_CASE(array_accessor) BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) { char const* sourceCode = R"( - contract test { + contract test { mapping(uint => uint[8]) public data; mapping(uint => uint[]) public dynamicData; function test() { @@ -1262,7 +1335,7 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) dynamicData[2].length = 3; dynamicData[2][2] = 8; } - } + } )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data(uint256,uint256)", 2, 2) == encodeArgs(8)); @@ -1273,20 +1346,22 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) { - char const* sourceCode = "contract test {\n" - " uint256 public data;\n" - " bytes6 public name;\n" - " bytes32 public a_hash;\n" - " address public an_address;\n" - " function test() {\n" - " data = 8;\n" - " name = \"Celina\";\n" - " a_hash = sha3(123);\n" - " an_address = address(0x1337);\n" - " super_secret_data = 42;\n" - " }\n" - " uint256 super_secret_data;" - "}\n"; + char const* sourceCode = R"( + contract test { + uint256 public data; + bytes6 public name; + bytes32 public a_hash; + address public an_address; + function test() { + data = 8; + name = "Celina"; + a_hash = sha3(123); + an_address = address(0x1337); + super_secret_data = 42; + } + uint256 super_secret_data; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); @@ -1338,26 +1413,30 @@ BOOST_AUTO_TEST_CASE(struct_accessor) BOOST_AUTO_TEST_CASE(balance) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function getBalance() returns (uint256 balance) {\n" - " return address(this).balance;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function getBalance() returns (uint256 balance) { + return address(this).balance; + } + } + )"; compileAndRun(sourceCode, 23); BOOST_CHECK(callContractFunction("getBalance()") == encodeArgs(23)); } BOOST_AUTO_TEST_CASE(blockchain) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) {\n" - " value = msg.value;\n" - " coinbase = block.coinbase;\n" - " blockNumber = block.number;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) { + value = msg.value; + coinbase = block.coinbase; + blockNumber = block.number; + } + } + )"; BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true); m_rpc.test_mineBlocks(5); compileAndRun(sourceCode, 27); @@ -1395,12 +1474,14 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) BOOST_AUTO_TEST_CASE(now) { - char const* sourceCode = "contract test {\n" - " function someInfo() returns (bool equal, uint val) {\n" - " equal = block.timestamp == now;\n" - " val = now;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function someInfo() returns (bool equal, uint val) { + equal = block.timestamp == now; + val = now; + } + } + )"; m_rpc.test_modifyTimestamp(0x776347e2); compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("someInfo()") == encodeArgs(true, 0x776347e3)); @@ -1413,7 +1494,8 @@ BOOST_AUTO_TEST_CASE(type_conversions_cleanup) char const* sourceCode = R"( contract Test { function test() returns (uint ret) { return uint(address(Test(address(0x11223344556677889900112233445566778899001122)))); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_REQUIRE(callContractFunction("test()") == bytes({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, @@ -1427,7 +1509,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size) function bytesToBytes(bytes4 input) returns (bytes2 ret) { return bytes2(input); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("ab")); } @@ -1439,7 +1522,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) function bytesToBytes(bytes2 input) returns (bytes4 ret) { return bytes4(input); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab") == encodeArgs("ab")); } @@ -1451,7 +1535,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) function bytesToBytes(bytes4 input) returns (bytes4 ret) { return bytes4(input); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("abcd")); } @@ -1464,7 +1549,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size) function bytesToUint(bytes32 s) returns (uint256 h) { return uint(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes32)", string("abc2")) == encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); @@ -1477,7 +1563,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) function bytesToUint(bytes1 s) returns (uint8 h) { return uint8(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes1)", string("a")) == encodeArgs(u256("0x61"))); @@ -1490,7 +1577,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) function bytesToUint(bytes4 s) returns (uint16 h) { return uint16(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == encodeArgs(u256("0x6364"))); @@ -1503,7 +1591,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) function bytesToUint(bytes4 s) returns (uint64 h) { return uint64(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == encodeArgs(u256("0x61626364"))); @@ -1517,7 +1606,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size) function uintToBytes(uint256 h) returns (bytes32 s) { return bytes32(h); } - })"; + } + )"; compileAndRun(sourceCode); u256 a("0x6162630000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK(callContractFunction("uintToBytes(uint256)", a) == encodeArgs(a)); @@ -1530,7 +1620,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) function UintToBytes(uint8 h) returns (bytes1 s) { return bytes1(h); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("UintToBytes(uint8)", u256("0x61")) == encodeArgs(string("a"))); @@ -1543,7 +1634,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) function uintToBytes(uint32 h) returns (bytes2 s) { return bytes2(h); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("uintToBytes(uint32)", u160("0x61626364")) == encodeArgs(string("cd"))); @@ -1556,7 +1648,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) function UintToBytes(uint16 h) returns (bytes8 s) { return bytes8(h); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK( callContractFunction("UintToBytes(uint16)", u256("0x6162")) == @@ -1566,13 +1659,15 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) BOOST_AUTO_TEST_CASE(send_ether) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function a(address addr, uint amount) returns (uint ret) {\n" - " addr.send(amount);\n" - " return address(this).balance;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function a(address addr, uint amount) returns (uint ret) { + addr.send(amount); + return address(this).balance; + } + } + )"; u256 amount(130); compileAndRun(sourceCode, amount + 1); u160 address(23); @@ -1582,11 +1677,13 @@ BOOST_AUTO_TEST_CASE(send_ether) BOOST_AUTO_TEST_CASE(log0) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log0(1);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log0(1); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1597,11 +1694,13 @@ BOOST_AUTO_TEST_CASE(log0) BOOST_AUTO_TEST_CASE(log1) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log1(1, 2);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log1(1, 2); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1613,11 +1712,13 @@ BOOST_AUTO_TEST_CASE(log1) BOOST_AUTO_TEST_CASE(log2) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log2(1, 2, 3);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log2(1, 2, 3); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1630,11 +1731,13 @@ BOOST_AUTO_TEST_CASE(log2) BOOST_AUTO_TEST_CASE(log3) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log3(1, 2, 3, 4);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log3(1, 2, 3, 4); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1647,11 +1750,13 @@ BOOST_AUTO_TEST_CASE(log3) BOOST_AUTO_TEST_CASE(log4) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log4(1, 2, 3, 4, 5);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log4(1, 2, 3, 4, 5); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1664,11 +1769,13 @@ BOOST_AUTO_TEST_CASE(log4) BOOST_AUTO_TEST_CASE(log_in_constructor) { - char const* sourceCode = "contract test {\n" - " function test() {\n" - " log1(1, 2);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() { + log1(1, 2); + } + } + )"; compileAndRun(sourceCode); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); @@ -1679,13 +1786,15 @@ BOOST_AUTO_TEST_CASE(log_in_constructor) BOOST_AUTO_TEST_CASE(suicide) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function a(address receiver) returns (uint ret) {\n" - " suicide(receiver);\n" - " return 10;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function a(address receiver) returns (uint ret) { + suicide(receiver); + return 10; + } + } + )"; u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); @@ -1696,13 +1805,15 @@ BOOST_AUTO_TEST_CASE(suicide) BOOST_AUTO_TEST_CASE(selfdestruct) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function a(address receiver) returns (uint ret) {\n" - " selfdestruct(receiver);\n" - " return 10;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function a(address receiver) returns (uint ret) { + selfdestruct(receiver); + return 10; + } + } + )"; u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); @@ -1713,11 +1824,13 @@ BOOST_AUTO_TEST_CASE(selfdestruct) BOOST_AUTO_TEST_CASE(sha3) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 input) returns (bytes32 sha3hash) {\n" - " return sha3(input);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 sha3hash) { + return sha3(input); + } + } + )"; compileAndRun(sourceCode); auto f = [&](u256 const& _x) -> u256 { @@ -1730,11 +1843,13 @@ BOOST_AUTO_TEST_CASE(sha3) BOOST_AUTO_TEST_CASE(sha256) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 input) returns (bytes32 sha256hash) {\n" - " return sha256(input);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 sha256hash) { + return sha256(input); + } + } + )"; compileAndRun(sourceCode); auto f = [&](u256 const& _x) -> bytes { @@ -1753,11 +1868,13 @@ BOOST_AUTO_TEST_CASE(sha256) BOOST_AUTO_TEST_CASE(ripemd) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 input) returns (bytes32 sha256hash) {\n" - " return ripemd160(input);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 sha256hash) { + return ripemd160(input); + } + } + )"; compileAndRun(sourceCode); auto f = [&](u256 const& _x) -> bytes { @@ -1776,11 +1893,13 @@ BOOST_AUTO_TEST_CASE(ripemd) BOOST_AUTO_TEST_CASE(ecrecover) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) {\n" - " return ecrecover(h, v, r, s);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) { + return ecrecover(h, v, r, s); + } + } + )"; compileAndRun(sourceCode); u256 h("0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"); byte v = 28; @@ -2798,7 +2917,8 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) ret_k = k; ret_g = g; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8)); BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8)); @@ -2811,7 +2931,8 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) function f(uint k) returns(uint){ return k; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9)); } @@ -2824,7 +2945,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) { d = sha3(a, b, c); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( @@ -2842,7 +2964,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals) { d = sha3(a, b, 145); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( @@ -2864,7 +2987,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) { d = sha3(a, b, 145, "foo"); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::keccak256("foo"))); @@ -2890,7 +3014,8 @@ BOOST_AUTO_TEST_CASE(sha3_with_bytes) data[2] = "o"; return sha3(data) == sha3("foo"); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo()") == encodeArgs(true)); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index a3217f08e..d260f4b1f 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -88,72 +88,88 @@ BOOST_AUTO_TEST_SUITE(SolidityParser) BOOST_AUTO_TEST_CASE(smoke_test) { - char const* text = "contract test {\n" - " uint256 stateVariable1;\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVariable1; + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) { - char const* text = "contract test {\n" - " uint256 ;\n" - "}\n"; + char const* text = R"( + contract test { + uint256 ; + } + )"; BOOST_CHECK(!successParse(text)); } BOOST_AUTO_TEST_CASE(empty_function) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function functionName(bytes20 arg1, address addr) constant\n" - " returns (int id)\n" - " { }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function functionName(bytes20 arg1, address addr) constant + returns (int id) + { } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(no_function_params) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function functionName() {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function functionName() {} + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(single_function_param) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function functionName(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function functionName(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(function_no_body) { - char const* text = "contract test {\n" - " function functionName(bytes32 input) returns (bytes32 out);\n" - "}\n"; + char const* text = R"( + contract test { + function functionName(bytes32 input) returns (bytes32 out); + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args) { - char const* text = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({: 1, : 2, : 3}); }\n" - "}\n"; + char const* text = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({: 1, : 2, : 3}); } + } + )"; BOOST_CHECK(!successParse(text)); } BOOST_AUTO_TEST_CASE(missing_argument_in_named_args) { - char const* text = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({a: , b: , c: }); }\n" - "}\n"; + char const* text = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({a: , b: , c: }); } + } + )"; BOOST_CHECK(!successParse(text)); } @@ -184,11 +200,13 @@ BOOST_AUTO_TEST_CASE(overloaded_functions) BOOST_AUTO_TEST_CASE(function_natspec_documentation) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " /// This is a test function\n" - " function functionName(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + /// This is a test function + function functionName(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -202,11 +220,13 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) BOOST_AUTO_TEST_CASE(function_normal_comments) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " // We won't see this comment\n" - " function functionName(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + // We won't see this comment + function functionName(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -219,17 +239,19 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " /// This is test function 1\n" - " function functionName1(bytes32 input) returns (bytes32 out) {}\n" - " /// This is test function 2\n" - " function functionName2(bytes32 input) returns (bytes32 out) {}\n" - " // nothing to see here\n" - " function functionName3(bytes32 input) returns (bytes32 out) {}\n" - " /// This is test function 4\n" - " function functionName4(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + /// This is test function 1 + function functionName1(bytes32 input) returns (bytes32 out) {} + /// This is test function 2 + function functionName2(bytes32 input) returns (bytes32 out) {} + // nothing to see here + function functionName3(bytes32 input) returns (bytes32 out) {} + /// This is test function 4 + function functionName4(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -252,12 +274,14 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) BOOST_AUTO_TEST_CASE(multiline_function_documentation) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " /// This is a test function\n" - " /// and it has 2 lines\n" - " function functionName1(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + /// This is a test function + /// and it has 2 lines + function functionName1(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -270,19 +294,21 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " /// fun1 description\n" - " function fun1(uint256 a) {\n" - " var b;\n" - " /// I should not interfere with actual natspec comments\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " }\n" - " /// This is a test function\n" - " /// and it has 2 lines\n" - " function fun(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + /// fun1 description + function fun1(uint256 a) { + var b; + /// I should not interfere with actual natspec comments + uint256 c; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + } + /// This is a test function + /// and it has 2 lines + function fun(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -299,17 +325,19 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function ///I am in the wrong place \n" - " fun1(uint256 a) {\n" - " var b;\n" - " /// I should not interfere with actual natspec comments\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function ///I am in the wrong place + fun1(uint256 a) { + var b; + /// I should not interfere with actual natspec comments + uint256 c; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + } + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -323,17 +351,19 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function fun1(uint256 a) {\n" - " /// I should have been above the function signature\n" - " var b;\n" - " /// I should not interfere with actual natspec comments\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function fun1(uint256 a) { + /// I should have been above the function signature + var b; + /// I should not interfere with actual natspec comments + uint256 c; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + } + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer contract = parseText(text, errors); @@ -346,71 +376,83 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) BOOST_AUTO_TEST_CASE(struct_definition) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " struct MyStructName {\n" - " address addr;\n" - " uint256 count;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + struct MyStructName { + address addr; + uint256 count; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(mapping) { - char const* text = "contract test {\n" - " mapping(address => bytes32) names;\n" - "}\n"; + char const* text = R"( + contract test { + mapping(address => bytes32) names; + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(mapping_in_struct) { - char const* text = "contract test {\n" - " struct test_struct {\n" - " address addr;\n" - " uint256 count;\n" - " mapping(bytes32 => test_struct) self_reference;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct test_struct { + address addr; + uint256 count; + mapping(bytes32 => test_struct) self_reference; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) { - char const* text = "contract test {\n" - " struct test_struct {\n" - " address addr;\n" - " mapping (uint64 => mapping (bytes32 => uint)) complex_mapping;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct test_struct { + address addr; + mapping (uint64 => mapping (bytes32 => uint)) complex_mapping; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(variable_definition) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " var b;\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " customtype varname;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + var b; + uint256 c; + mapping(address=>bytes32) d; + customtype varname; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(variable_definition_with_initialization) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " var b = 2;\n" - " uint256 c = 0x87;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " customtype varname;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + var b = 2; + uint256 c = 0x87; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + customtype varname; + } + } + )"; BOOST_CHECK(successParse(text)); } @@ -450,21 +492,25 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_return) BOOST_AUTO_TEST_CASE(operator_expression) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 x = (1 + 4) || false && (1 - 12) + -9;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 x = (1 + 4) || false && (1 - 12) + -9; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(complex_expression) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 x = (1 + 4).member(++67)[a/=9] || true;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 x = (1 + 4).member(++67)[a/=9] || true; + } + } + )"; BOOST_CHECK(successParse(text)); } @@ -475,248 +521,294 @@ BOOST_AUTO_TEST_CASE(exp_expression) function fun(uint256 a) { uint256 x = 3 ** a; } - })"; + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(while_loop) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " while (true) { uint256 x = 1; break; continue; } x = 9;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + while (true) { uint256 x = 1; break; continue; } x = 9; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_vardef_initexpr) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " for (uint256 i = 0; i < 10; i++)\n" - " { uint256 x = i; break; continue; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + for (uint256 i = 0; i < 10; i++) { + uint256 x = i; break; continue; + } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 i =0;\n" - " for (i = 0; i < 10; i++)\n" - " { uint256 x = i; break; continue; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 i =0; + for (i = 0; i < 10; i++) { + uint256 x = i; break; continue; + } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 i =0;\n" - " for (;;)\n" - " { uint256 x = i; break; continue; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 i =0; + for (;;) { + uint256 x = i; break; continue; + } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_single_stmt_body) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 i =0;\n" - " for (i = 0; i < 10; i++)\n" - " continue;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 i = 0; + for (i = 0; i < 10; i++) + continue; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(if_statement) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " if (a >= 8) { return 2; } else { var b = 7; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + if (a >= 8) { return 2; } else { var b = 7; } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(else_if_statement) { - char const* text = "contract test {\n" - " function fun(uint256 a) returns (address b) {\n" - " if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) returns (address b) { + if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " uint64[7](3);\n" - " uint64[](3);\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + uint64[7](3); + uint64[](3); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(type_conversion_to_dynamic_array) { - char const* text = "contract test {\n" - " function fun() {\n" - " var x = uint64[](3);\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + var x = uint64[](3); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(import_directive) { - char const* text = "import \"abc\";\n" - "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + import "abc"; + contract test { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(multiple_contracts) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract test2 {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + } + contract test2 { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(multiple_contracts_and_imports) { - char const* text = "import \"abc\";\n" - "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "import \"def\";\n" - "contract test2 {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "import \"ghi\";\n"; + char const* text = R"( + import "abc"; + contract test { + function fun() { + uint64(2); + } + } + import "def"; + contract test2 { + function fun() { + uint64(2); + } + } + import "ghi"; + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(contract_inheritance) { - char const* text = "contract base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract derived is base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract base { + function fun() { + uint64(2); + } + } + contract derived is base { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(contract_multiple_inheritance) { - char const* text = "contract base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract derived is base, nonExisting {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract base { + function fun() { + uint64(2); + } + } + contract derived is base, nonExisting { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(contract_multiple_inheritance_with_arguments) { - char const* text = "contract base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract derived is base(2), nonExisting(\"abc\", \"def\", base.fun()) {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract base { + function fun() { + uint64(2); + } + } + contract derived is base(2), nonExisting("abc", "def", base.fun()) { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(placeholder_in_function_context) { - char const* text = "contract c {\n" - " function fun() returns (uint r) {\n" - " var _ = 8;\n" - " return _ + 1;" - " }\n" - "}\n"; + char const* text = R"( + contract c { + function fun() returns (uint r) { + var _ = 8; + return _ + 1; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(modifier) { - char const* text = "contract c {\n" - " modifier mod { if (msg.sender == 0) _; }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod { if (msg.sender == 0) _; } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(modifier_without_semicolon) { - char const* text = "contract c {\n" - " modifier mod { if (msg.sender == 0) _ }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod { if (msg.sender == 0) _ } + } + )"; BOOST_CHECK(!successParse(text)); } BOOST_AUTO_TEST_CASE(modifier_arguments) { - char const* text = "contract c {\n" - " modifier mod(uint a) { if (msg.sender == a) _; }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod(uint a) { if (msg.sender == a) _; } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(modifier_invocation) { - char const* text = "contract c {\n" - " modifier mod1(uint a) { if (msg.sender == a) _; }\n" - " modifier mod2 { if (msg.sender == 2) _; }\n" - " function f() mod1(7) mod2 { }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod1(uint a) { if (msg.sender == a) _; } + modifier mod2 { if (msg.sender == 2) _; } + function f() mod1(7) mod2 { } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(fallback_function) { - char const* text = "contract c {\n" - " function() { }\n" - "}\n"; + char const* text = R"( + contract c { + function() { } + } + )"; BOOST_CHECK(successParse(text)); } From 29e304d3bc71dd6ec8492978c36d594a1a43f538 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 1 Dec 2016 01:29:30 -0300 Subject: [PATCH 104/185] Fix typos (existant -> existent) --- solc/CommandLineInterface.cpp | 2 +- test/libsolidity/SolidityNatspecJSON.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index c677cf1fb..49fac51c1 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -327,7 +327,7 @@ void CommandLineInterface::readInputFilesAndConfigureRemappings() auto infile = boost::filesystem::path(path); if (!boost::filesystem::exists(infile)) { - cerr << "Skipping non existant input file \"" << infile << "\"" << endl; + cerr << "Skipping non-existent input file \"" << infile << "\"" << endl; continue; } diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index ef69e85c4..85bc22778 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -560,7 +560,7 @@ BOOST_AUTO_TEST_CASE(dev_title_at_function_error) expectNatspecError(sourceCode); } -BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param) +BOOST_AUTO_TEST_CASE(dev_documenting_nonexistent_param) { char const* sourceCode = "contract test {\n" " /// @dev Multiplies a number by 7 and adds second parameter\n" From 3e8a017d4227d0f5f31ebecffddb4a0262e4efe0 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 30 Nov 2016 17:36:02 +0100 Subject: [PATCH 105/185] docs: describe the form of number literals This is a part of #1390 --- docs/types.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/types.rst b/docs/types.rst index 0436fc708..896910ffb 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -169,6 +169,14 @@ Fixed Point Numbers Rational and Integer Literals ----------------------------- +Integer literals are formed from a sequence of numbers in the range 0-9. +They are interpreted as decimals. For example, ``69`` means sixty nine. +Octal literals do not exist in Solidity and leading zeros are ignored. +For example, ``0100`` means one hundred. + +Decimal literals are formed by a ``.`` with at least one number on +one side. Examples include ``1.``, ``.1`` and ``1.3``. + Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. by using them together with a non-literal expression). This means that computations do not overflow and divisions do not truncate From 77bad18648b8426eb2656f93837aa55351f48c98 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 11:31:58 +0100 Subject: [PATCH 106/185] libevmasm: remove an unused variable `total` --- libevmasm/Assembly.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index edbb9828f..b040917d3 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -331,8 +331,7 @@ map Assembly::optimiseInternal(bool _enable, bool _isCreation, size_ } map tagReplacements; - unsigned total = 0; - for (unsigned count = 1; count > 0; total += count) + for (unsigned count = 1; count > 0;) { count = 0; @@ -399,7 +398,7 @@ map Assembly::optimiseInternal(bool _enable, bool _isCreation, size_ } if (_enable) - total += ConstantOptimisationMethod::optimiseConstants( + ConstantOptimisationMethod::optimiseConstants( _isCreation, _isCreation ? 1 : _runs, *this, From dd0bd57d67ffd08df5b6d6a7d59e23ffe34d1663 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 11:53:06 +0100 Subject: [PATCH 107/185] test: change retrieveFunctionBySignature to take a constant reference rather than a pointer The function `retrieveFunctionBySignature` expected the argument to be a non-null pointer. This commit makes this assumption more explicit. --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 7a132068f..34f7033f6 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -151,12 +151,12 @@ static ContractDefinition const* retrieveContract(ASTPointer _source } static FunctionTypePointer retrieveFunctionBySignature( - ContractDefinition const* _contract, + ContractDefinition const& _contract, std::string const& _signature ) { FixedHash<4> hash(dev::keccak256(_signature)); - return _contract->interfaceFunctions()[hash]; + return _contract.interfaceFunctions()[hash]; } } @@ -1002,13 +1002,13 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) ContractDefinition const* contract; ETH_TEST_CHECK_NO_THROW(source = parseAndAnalyse(text), "Parsing and Resolving names failed"); BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr); - FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); + FunctionTypePointer function = retrieveFunctionBySignature(*contract, "foo()"); BOOST_REQUIRE(function && function->hasDeclaration()); auto returnParams = function->returnParameterTypeNames(false); BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK(function->isConstant()); - function = retrieveFunctionBySignature(contract, "map(uint256)"); + function = retrieveFunctionBySignature(*contract, "map(uint256)"); BOOST_REQUIRE(function && function->hasDeclaration()); auto params = function->parameterTypeNames(false); BOOST_CHECK_EQUAL(params.at(0), "uint256"); @@ -1016,7 +1016,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4"); BOOST_CHECK(function->isConstant()); - function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)"); + function = retrieveFunctionBySignature(*contract, "multiple_map(uint256,uint256)"); BOOST_REQUIRE(function && function->hasDeclaration()); params = function->parameterTypeNames(false); BOOST_CHECK_EQUAL(params.at(0), "uint256"); @@ -1053,9 +1053,9 @@ BOOST_AUTO_TEST_CASE(private_state_variable) ETH_TEST_CHECK_NO_THROW(source = parseAndAnalyse(text), "Parsing and Resolving names failed"); BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr); FunctionTypePointer function; - function = retrieveFunctionBySignature(contract, "foo()"); + function = retrieveFunctionBySignature(*contract, "foo()"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist"); - function = retrieveFunctionBySignature(contract, "bar()"); + function = retrieveFunctionBySignature(*contract, "bar()"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist"); } From e29047b24d149e6b27962f9fe89e8275e213c11d Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 11:58:34 +0100 Subject: [PATCH 108/185] codegen: assertion did not assert non-nullness This commit strengthens an assertion so that it makes sure that a pointer is not null. Moreover, `isLocalVariable(variable)` is now positively asserted, following the error message. --- libsolidity/codegen/ContractCompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 437c484a3..124546de0 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -583,7 +583,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly) // lvalue context auto variable = dynamic_cast(decl); solAssert( - !!variable || !m_context.isLocalVariable(variable), + !!variable && m_context.isLocalVariable(variable), "Can only assign to stack variables in inline assembly." ); unsigned size = variable->type()->sizeOnStack(); From 1e791f30aa6283ff16a6850fbbc8774ee60447d1 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 12:03:25 +0100 Subject: [PATCH 109/185] codegen: this commit removes one of duplicate assignments --- libsolidity/codegen/ContractCompiler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 437c484a3..93083e25f 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -862,8 +862,6 @@ void ContractCompiler::appendModifierOrFunctionCode() CompilerUtils::sizeOnStack(modifier.parameters()) + CompilerUtils::sizeOnStack(modifier.localVariables()); codeBlock = &modifier.body(); - - codeBlock = &modifier.body(); } } From 422140f60369a2e69c6cb446528737d5d23a3e3d Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 12:26:52 +0100 Subject: [PATCH 110/185] test: more precise expectation about the error for assigning into storage in inline assembly --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 7a132068f..d8c5924e8 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4521,7 +4521,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage) } } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR(text, DeclarationError, "not found, not unique or not lvalue."); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) From e7760417e83cf9e313c76cdd44f860aeec1b798c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 1 Dec 2016 12:14:21 +0000 Subject: [PATCH 111/185] docs: rename overflow to variable cleanup --- docs/miscellaneous.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 963edf26b..56716dcaf 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -89,11 +89,11 @@ ABI specification requires arguments to be padded to multiples of 32 bytes. The internal function calls use a different convention. -.. index: overflow +.. index: variable cleanup -**************************************** -Internals - Cleaning Up Overflows in EVM -**************************************** +********************************* +Internals - Cleaning Up Variables +********************************* When a value is shorter than 256-bit, in some cases the remaining bits must be cleaned. From 5789eaa78d0e00f6289101e02f7de5e9decdc7e5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 14 Nov 2016 11:46:43 +0100 Subject: [PATCH 112/185] Metadata stamp. --- libdevcore/SwarmHash.cpp | 12 +-- libdevcore/SwarmHash.h | 5 +- libsolidity/ast/AST.cpp | 8 ++ libsolidity/ast/AST.h | 4 + libsolidity/codegen/Compiler.cpp | 10 +-- libsolidity/codegen/Compiler.h | 3 +- libsolidity/codegen/CompilerContext.cpp | 7 ++ libsolidity/codegen/CompilerContext.h | 3 + libsolidity/interface/CompilerStack.cpp | 98 ++++++++++++++++++++----- libsolidity/interface/CompilerStack.h | 20 +++-- libsolidity/parsing/Scanner.h | 4 + solc/CommandLineInterface.cpp | 23 +++++- solc/CommandLineInterface.h | 1 + solc/jsonCompiler.cpp | 1 + test/libdevcore/SwarmHash.cpp | 24 +++--- test/libsolidity/Assembly.cpp | 2 +- 16 files changed, 171 insertions(+), 54 deletions(-) diff --git a/libdevcore/SwarmHash.cpp b/libdevcore/SwarmHash.cpp index e7b844ebf..aa98eafd6 100644 --- a/libdevcore/SwarmHash.cpp +++ b/libdevcore/SwarmHash.cpp @@ -38,13 +38,14 @@ h256 swarmHashSimple(bytesConstRef _data, size_t _size) return keccak256(toLittleEndian(_size) + _data.toBytes()); } -h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length) +h256 swarmHashIntermediate(string const& _input, size_t _offset, size_t _length) { + bytesConstRef ref; + bytes innerNodes; if (_length <= 0x1000) - return swarmHashSimple(bytesConstRef(_input.data() + _offset, _length), _length); + ref = bytesConstRef(_input).cropped(_offset, _length); else { - bytes innerNodes; size_t maxRepresentedSize = 0x1000; while (maxRepresentedSize * (0x1000 / 32) < _length) maxRepresentedSize *= (0x1000 / 32); @@ -53,11 +54,12 @@ h256 swarmHashIntermediate(bytes const& _input, size_t _offset, size_t _length) size_t size = std::min(maxRepresentedSize, _length - i); innerNodes += swarmHashIntermediate(_input, _offset + i, size).asBytes(); } - return swarmHashSimple(bytesConstRef(&innerNodes), _length); + ref = bytesConstRef(&innerNodes); } + return swarmHashSimple(ref, _length); } -h256 dev::swarmHash(bytes const& _input) +h256 dev::swarmHash(string const& _input) { return swarmHashIntermediate(_input, 0, _input.size()); } diff --git a/libdevcore/SwarmHash.h b/libdevcore/SwarmHash.h index 925509ab5..f474ce119 100644 --- a/libdevcore/SwarmHash.h +++ b/libdevcore/SwarmHash.h @@ -20,12 +20,13 @@ #pragma once #include -#include + +#include namespace dev { /// Compute the "swarm hash" of @a _data -h256 swarmHash(bytes const& _data); +h256 swarmHash(std::string const& _data); } diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 9b4783936..f8eb7108e 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -63,6 +63,14 @@ SourceUnitAnnotation& SourceUnit::annotation() const return static_cast(*m_annotation); } +string Declaration::sourceUnitName() const +{ + ASTNode const* scope = m_scope; + while (dynamic_cast(scope) && dynamic_cast(scope)->m_scope) + scope = dynamic_cast(scope)->m_scope; + return dynamic_cast(*scope).annotation().path; +} + ImportAnnotation& ImportDirective::annotation() const { if (!m_annotation) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 89b96f096..ab4be1eaf 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -158,6 +158,10 @@ public: ASTNode const* scope() const { return m_scope; } void setScope(ASTNode const* _scope) { m_scope = _scope; } + /// @returns the source name this declaration is present in. + /// Can be combined with annotation().canonicalName to form a globally unique name. + std::string sourceUnitName() const; + virtual bool isLValue() const { return false; } virtual bool isPartOfExternalInterface() const { return false; } diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 22d256982..168e94623 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -30,7 +30,8 @@ using namespace dev::solidity; void Compiler::compileContract( ContractDefinition const& _contract, - std::map const& _contracts + std::map const& _contracts, + h256 const& _metadataHash ) { ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize); @@ -43,11 +44,8 @@ void Compiler::compileContract( m_context.optimise(m_optimize, m_optimizeRuns); - if (_contract.isLibrary()) - { - solAssert(m_runtimeSub != size_t(-1), ""); - m_context.injectVersionStampIntoSub(m_runtimeSub); - } + solAssert(m_runtimeSub != size_t(-1), ""); + m_context.injectMetadataHashIntoSub(m_runtimeSub, _metadataHash); } void Compiler::compileClone( diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index c8bf7861c..58ef19637 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -42,7 +42,8 @@ public: void compileContract( ContractDefinition const& _contract, - std::map const& _contracts + std::map const& _contracts, + h256 const& _metadataHash ); /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given /// contract at runtime, but contains the full creation-time code. diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index b99b05485..9b921e9d6 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -227,6 +227,13 @@ void CompilerContext::injectVersionStampIntoSub(size_t _subIndex) sub.injectStart(fromBigEndian(binaryVersion())); } +void CompilerContext::injectMetadataHashIntoSub(size_t _subIndex, h256 const& _metadataHash) +{ + eth::Assembly& sub = m_asm->sub(_subIndex); + sub.injectStart(Instruction::POP); + sub.injectStart(u256(_metadataHash)); +} + FunctionDefinition const& CompilerContext::resolveVirtualFunction( FunctionDefinition const& _function, vector::const_iterator _searchStart diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 3c6d9d732..c8a35f93a 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -155,6 +155,9 @@ public: /// Prepends "PUSH POP" void injectVersionStampIntoSub(size_t _subIndex); + /// Prepends "PUSH POP" + void injectMetadataHashIntoSub(size_t _subIndex, h256 const& _metadataHash); + 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. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9305c5e3b..ed44b1091 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -38,7 +38,10 @@ #include #include -#include + +#include + +#include #include #include @@ -79,6 +82,8 @@ void CompilerStack::reset(bool _keepSources) { m_sources.clear(); } + m_optimize = false; + m_optimizeRuns = 200; m_globalContext.reset(); m_sourceOrder.clear(); m_contracts.clear(); @@ -217,17 +222,22 @@ vector CompilerStack::contractNames() const } -bool CompilerStack::compile(bool _optimize, unsigned _runs) +bool CompilerStack::compile(bool _optimize, unsigned _runs, map const& _libraries) { if (!m_parseSuccessful) if (!parse()) return false; + m_optimize = _optimize; + m_optimizeRuns = _runs; + m_libraries = _libraries; + map compiledContracts; for (Source const* source: m_sourceOrder) for (ASTPointer const& node: source->ast->nodes()) if (auto contract = dynamic_cast(node.get())) - compileContract(_optimize, _runs, *contract, compiledContracts); + compileContract(*contract, compiledContracts); + this->link(); return true; } @@ -236,13 +246,13 @@ bool CompilerStack::compile(string const& _sourceCode, bool _optimize) return parse(_sourceCode) && compile(_optimize); } -void CompilerStack::link(const std::map& _libraries) +void CompilerStack::link() { for (auto& contract: m_contracts) { - contract.second.object.link(_libraries); - contract.second.runtimeObject.link(_libraries); - contract.second.cloneObject.link(_libraries); + contract.second.object.link(m_libraries); + contract.second.runtimeObject.link(m_libraries); + contract.second.cloneObject.link(m_libraries); } } @@ -352,24 +362,31 @@ Json::Value const& CompilerStack::interface(string const& _contractName) 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.")); + + return metadata(contract(_contractName), _type); +} + +Json::Value const& CompilerStack::metadata(Contract const& _contract, DocumentationType _type) const { if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); std::unique_ptr* doc; - Contract const& currentContract = contract(_contractName); // checks wheather we already have the documentation switch (_type) { case DocumentationType::NatspecUser: - doc = ¤tContract.userDocumentation; + doc = &_contract.userDocumentation; break; case DocumentationType::NatspecDev: - doc = ¤tContract.devDocumentation; + doc = &_contract.devDocumentation; break; case DocumentationType::ABIInterface: - doc = ¤tContract.interface; + doc = &_contract.interface; break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type.")); @@ -377,11 +394,19 @@ Json::Value const& CompilerStack::metadata(string const& _contractName, Document // caches the result if (!*doc) - doc->reset(new Json::Value(InterfaceHandler::documentation(*currentContract.contract, _type))); + doc->reset(new Json::Value(InterfaceHandler::documentation(*_contract.contract, _type))); return *(*doc); } +string const& CompilerStack::onChainMetadata(string const& _contractName) const +{ + if (!m_parseSuccessful) + BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + + return contract(_contractName).onChainMetadata; +} + Scanner const& CompilerStack::scanner(string const& _sourceName) const { return *source(_sourceName).scanner; @@ -572,8 +597,6 @@ string CompilerStack::absolutePath(string const& _path, string const& _reference } void CompilerStack::compileContract( - bool _optimize, - unsigned _runs, ContractDefinition const& _contract, map& _compiledContracts ) @@ -581,19 +604,21 @@ void CompilerStack::compileContract( if (_compiledContracts.count(&_contract) || !_contract.annotation().isFullyImplemented) return; for (auto const* dependency: _contract.annotation().contractDependencies) - compileContract(_optimize, _runs, *dependency, _compiledContracts); + compileContract(*dependency, _compiledContracts); - shared_ptr compiler = make_shared(_optimize, _runs); - compiler->compileContract(_contract, _compiledContracts); + shared_ptr compiler = make_shared(m_optimize, m_optimizeRuns); Contract& compiledContract = m_contracts.at(_contract.name()); + string onChainMetadata = createOnChainMetadata(compiledContract); + compiler->compileContract(_contract, _compiledContracts, dev::swarmHash(onChainMetadata)); compiledContract.compiler = compiler; compiledContract.object = compiler->assembledObject(); compiledContract.runtimeObject = compiler->runtimeObject(); + compiledContract.onChainMetadata = onChainMetadata; _compiledContracts[compiledContract.contract] = &compiler->assembly(); try { - Compiler cloneCompiler(_optimize, _runs); + Compiler cloneCompiler(m_optimize, m_optimizeRuns); cloneCompiler.compileClone(_contract, _compiledContracts); compiledContract.cloneObject = cloneCompiler.assembledObject(); } @@ -637,6 +662,43 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co return it->second; } +string CompilerStack::createOnChainMetadata(Contract const& _contract) const +{ + Json::Value meta; + meta["version"] = 1; + meta["language"] = "Solidity"; + meta["compiler"]["version"] = VersionString; + meta["compilationTarget"] = + _contract.contract->sourceUnitName() + + ":" + + _contract.contract->annotation().canonicalName; + + for (auto const& s: m_sources) + { + solAssert(s.second.scanner, "Scanner not available"); + meta["sources"][s.first]["swarm"] = + "0x" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes()); + } + meta["settings"]["optimizer"]["enabled"] = m_optimize; + meta["settings"]["optimizer"]["runs"] = m_optimizeRuns; + + set remappings; + for (auto const& r: m_remappings) + remappings.insert(r.context + ":" + r.prefix + "=" + r.target); + for (auto const& r: remappings) + meta["settings"]["remappings"].append(r); + + for (auto const& library: m_libraries) + meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes()); + + meta["output"]["abi"] = metadata(_contract, DocumentationType::ABIInterface); + meta["output"]["natspec"] = metadata(_contract, DocumentationType::NatspecUser); + + Json::FastWriter writer; + writer.omitEndingLineFeed(); + return writer.write(meta); +} + string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) const { string ret; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index ea7061229..74a7dfc57 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -113,14 +113,15 @@ public: /// Compiles the source units that were previously added and parsed. /// @returns false on error. - bool compile(bool _optimize = false, unsigned _runs = 200); + bool compile( + bool _optimize = false, + unsigned _runs = 200, + std::map const& _libraries = std::map{} + ); /// Parses and compiles the given source code. /// @returns false on error. bool compile(std::string const& _sourceCode, bool _optimize = false); - /// Inserts the given addresses into the linker objects of all compiled contracts. - void link(std::map const& _libraries); - /// Tries to translate all source files into a language suitable for formal analysis. /// @param _errors list to store errors - defaults to the internal error list. /// @returns false on error. @@ -170,6 +171,7 @@ public: /// @param type The type of the documentation to get. /// Can be one of 4 types defined at @c DocumentationType Json::Value const& metadata(std::string const& _contractName, DocumentationType _type) const; + std::string const& onChainMetadata(std::string const& _contractName) const; /// @returns the previously used scanner, useful for counting lines during error reporting. Scanner const& scanner(std::string const& _sourceName = "") const; @@ -213,6 +215,7 @@ private: eth::LinkerObject object; eth::LinkerObject runtimeObject; eth::LinkerObject cloneObject; + std::string onChainMetadata; ///< The metadata json that will be hashed into the chain. mutable std::unique_ptr interface; mutable std::unique_ptr userDocumentation; mutable std::unique_ptr devDocumentation; @@ -233,16 +236,18 @@ private: std::string absolutePath(std::string const& _path, std::string const& _reference) const; /// Compile a single contract and put the result in @a _compiledContracts. void compileContract( - bool _optimize, - unsigned _runs, ContractDefinition const& _contract, std::map& _compiledContracts ); + void link(); + Contract const& contract(std::string const& _contractName = "") const; Source const& source(std::string const& _sourceName = "") const; + std::string createOnChainMetadata(Contract const& _contract) const; std::string computeSourceMapping(eth::AssemblyItems const& _items) const; + Json::Value const& metadata(Contract const&, DocumentationType _type) const; struct Remapping { @@ -252,6 +257,9 @@ private: }; ReadFileCallback m_readFile; + bool m_optimize = false; + size_t m_optimizeRuns = 200; + std::map m_libraries; /// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum /// "context:prefix=target" std::vector m_remappings; diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h index 65de8bd4e..d6b48c6f8 100644 --- a/libsolidity/parsing/Scanner.h +++ b/libsolidity/parsing/Scanner.h @@ -80,6 +80,8 @@ public: void reset() { m_position = 0; } + std::string const& source() const { return m_source; } + ///@{ ///@name Error printing helper functions /// Functions that help pretty-printing parse errors @@ -102,6 +104,8 @@ public: explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); } + std::string source() const { return m_source.source(); } + /// Resets the scanner as if newly constructed with _source and _sourceName as input. void reset(CharStream const& _source, std::string const& _sourceName); /// Resets scanner to the start of input. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 49fac51c1..fdfcabb4c 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -78,6 +78,7 @@ static string const g_argCloneBinaryStr = "clone-bin"; static string const g_argOpcodesStr = "opcodes"; static string const g_argNatspecDevStr = "devdoc"; static string const g_argNatspecUserStr = "userdoc"; +static string const g_argMetadata = "metadata"; static string const g_argAddStandard = "add-std"; static string const g_stdinFileName = ""; @@ -91,6 +92,7 @@ static set const g_combinedJsonArgs{ "opcodes", "abi", "interface", + "metadata", "asm", "ast", "userdoc", @@ -117,6 +119,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) for (string const& arg: { g_argAbiStr, g_argSignatureHashes, + g_argMetadata, g_argNatspecUserStr, g_argAstJson, g_argNatspecDevStr, @@ -202,6 +205,18 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) cout << "Function signatures: " << endl << out; } +void CommandLineInterface::handleOnChainMetadata(string const& _contract) +{ + if (!m_args.count(g_argMetadata)) + return; + + string data = m_compiler->onChainMetadata(_contract); + if (m_args.count("output-dir")) + createFile(_contract + ".meta", data); + else + cout << "Metadata: " << endl << data << endl; +} + void CommandLineInterface::handleMeta(DocumentationType _type, string const& _contract) { std::string argName; @@ -467,6 +482,7 @@ Allowed options)", (g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.") (g_argNatspecUserStr.c_str(), "Natspec user documentation of all contracts.") (g_argNatspecDevStr.c_str(), "Natspec developer documentation of all contracts.") + (g_argMetadata.c_str(), "Combined metadata JSON whose swarm hash is stored on-chain.") ("formal", "Translated source suitable for formal analysis."); desc.add(outputComponents); @@ -581,9 +597,7 @@ bool CommandLineInterface::processInput() // TODO: Perhaps we should not compile unless requested bool optimize = m_args.count("optimize") > 0; unsigned runs = m_args["optimize-runs"].as(); - bool successful = m_compiler->compile(optimize, runs); - if (successful) - m_compiler->link(m_libraries); + bool successful = m_compiler->compile(optimize, runs, m_libraries); if (successful && m_args.count("formal")) if (!m_compiler->prepareFormalAnalysis()) @@ -659,6 +673,8 @@ void CommandLineInterface::handleCombinedJSON() Json::Value contractData(Json::objectValue); if (requests.count("abi")) contractData["abi"] = dev::jsonCompactPrint(m_compiler->interface(contractName)); + if (requests.count("metadata")) + contractData["metadata"] = m_compiler->onChainMetadata(contractName); if (requests.count("bin")) contractData["bin"] = m_compiler->object(contractName).toHex(); if (requests.count("bin-runtime")) @@ -918,6 +934,7 @@ void CommandLineInterface::outputCompilationResults() handleBytecode(contract); handleSignatureHashes(contract); + handleOnChainMetadata(contract); handleMeta(DocumentationType::ABIInterface, contract); handleMeta(DocumentationType::NatspecDev, contract); handleMeta(DocumentationType::NatspecUser, contract); diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h index 33ae6ee6b..b8fc1823b 100644 --- a/solc/CommandLineInterface.h +++ b/solc/CommandLineInterface.h @@ -63,6 +63,7 @@ private: void handleOpcode(std::string const& _contract); void handleBytecode(std::string const& _contract); void handleSignatureHashes(std::string const& _contract); + void handleOnChainMetadata(std::string const& _contract); void handleMeta(DocumentationType _type, std::string const& _contract); void handleGasEstimation(std::string const& _contract); void handleFormal(); diff --git a/solc/jsonCompiler.cpp b/solc/jsonCompiler.cpp index 0f95ebe5a..d761b541c 100644 --- a/solc/jsonCompiler.cpp +++ b/solc/jsonCompiler.cpp @@ -218,6 +218,7 @@ string compile(StringMap const& _sources, bool _optimize, CStyleReadFileCallback contractData["bytecode"] = compiler.object(contractName).toHex(); contractData["runtimeBytecode"] = compiler.runtimeObject(contractName).toHex(); contractData["opcodes"] = solidity::disassemble(compiler.object(contractName).bytecode); + contractData["metadata"] = compiler.onChainMetadata(contractName); contractData["functionHashes"] = functionHashes(compiler.contractDefinition(contractName)); contractData["gasEstimates"] = estimateGas(compiler, contractName); auto sourceMap = compiler.sourceMapping(contractName); diff --git a/test/libdevcore/SwarmHash.cpp b/test/libdevcore/SwarmHash.cpp index a23c36fd8..7f3186ace 100644 --- a/test/libdevcore/SwarmHash.cpp +++ b/test/libdevcore/SwarmHash.cpp @@ -31,24 +31,24 @@ namespace test BOOST_AUTO_TEST_SUITE(SwarmHash) -string swarmHashHex(bytes const& _input) +string swarmHashHex(string const& _input) { return toHex(swarmHash(_input).asBytes()); } BOOST_AUTO_TEST_CASE(test_zeros) { - BOOST_CHECK_EQUAL(swarmHashHex(bytes()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000 - 1, 0)), string("32f0faabc4265ac238cd945087133ce3d7e9bb2e536053a812b5373c54043adb")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000, 0)), string("411dd45de7246e94589ff5888362c41e85bd3e582a92d0fda8f0e90b76439bec")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x1000 + 1, 0)), string("69754a0098432bbc2e84fe1205276870748a61a065ab6ef44d6a2e7b13ce044d")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000 - 1, 0)), string("69ad3c581043404f775ffa8d6f1b25ad4a9ee812971190e90209c0966116a321")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000, 0)), string("f00222373ff82d0a178dc6271c78953e9c88f74130a52d401f5ec51475f63c43")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x2000 + 1, 0)), string("86d6773e79e02fd8145ee1aedba89ace0c15f2566db1249654000039a9a134bf")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x80000, 0)), string("cc0854fe2c6b98e920d5c14b1a88e6d4223e55b8f78883f60939aa2485e361bf")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x80020, 0)), string("ee9ffca246e70d3704740ba4df450fa6988d14a1c2439c7e734c7a77a4eb6fd3")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(0x800020, 0)), string("78b90b20c90559fb904535181a7c28929ea2f30a2329dbc25232de579709f12f")); - BOOST_CHECK_EQUAL(swarmHashHex(bytes(2095104, 0)), string("a9958184589fc11b4027a4c233e777ebe2e99c66f96b74aef2a0638a94dd5439")); + BOOST_CHECK_EQUAL(swarmHashHex(string()), string("011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000 - 1, 0)), string("32f0faabc4265ac238cd945087133ce3d7e9bb2e536053a812b5373c54043adb")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000, 0)), string("411dd45de7246e94589ff5888362c41e85bd3e582a92d0fda8f0e90b76439bec")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x1000 + 1, 0)), string("69754a0098432bbc2e84fe1205276870748a61a065ab6ef44d6a2e7b13ce044d")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000 - 1, 0)), string("69ad3c581043404f775ffa8d6f1b25ad4a9ee812971190e90209c0966116a321")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000, 0)), string("f00222373ff82d0a178dc6271c78953e9c88f74130a52d401f5ec51475f63c43")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x2000 + 1, 0)), string("86d6773e79e02fd8145ee1aedba89ace0c15f2566db1249654000039a9a134bf")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x80000, 0)), string("cc0854fe2c6b98e920d5c14b1a88e6d4223e55b8f78883f60939aa2485e361bf")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x80020, 0)), string("ee9ffca246e70d3704740ba4df450fa6988d14a1c2439c7e734c7a77a4eb6fd3")); + BOOST_CHECK_EQUAL(swarmHashHex(string(0x800020, 0)), string("78b90b20c90559fb904535181a7c28929ea2f30a2329dbc25232de579709f12f")); + BOOST_CHECK_EQUAL(swarmHashHex(string(2095104, 0)), string("a9958184589fc11b4027a4c233e777ebe2e99c66f96b74aef2a0638a94dd5439")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index cc77bd4cf..27709086c 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -75,7 +75,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode) if (ContractDefinition* contract = dynamic_cast(node.get())) { Compiler compiler; - compiler.compileContract(*contract, map{}); + compiler.compileContract(*contract, map{}, h256()); return compiler.runtimeAssemblyItems(); } From e666f8cda70ad5e03bc00f4509fc51571fff90a7 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 16 Nov 2016 14:36:19 +0100 Subject: [PATCH 113/185] Incorporate comments. --- libsolidity/interface/CompilerStack.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index ed44b1091..0f8613029 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -40,6 +40,7 @@ #include #include +#include #include @@ -668,19 +669,19 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const meta["version"] = 1; meta["language"] = "Solidity"; meta["compiler"]["version"] = VersionString; - meta["compilationTarget"] = - _contract.contract->sourceUnitName() + - ":" + - _contract.contract->annotation().canonicalName; for (auto const& s: m_sources) { solAssert(s.second.scanner, "Scanner not available"); - meta["sources"][s.first]["swarm"] = - "0x" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes()); + meta["sources"][s.first]["keccak256"] = + "0x" + toHex(dev::keccak256(s.second.scanner->source()).asBytes()); + meta["sources"][s.first]["url"] = + "bzzr://" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes()); } meta["settings"]["optimizer"]["enabled"] = m_optimize; meta["settings"]["optimizer"]["runs"] = m_optimizeRuns; + meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = + _contract.contract->annotation().canonicalName; set remappings; for (auto const& r: m_remappings) @@ -692,11 +693,10 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes()); meta["output"]["abi"] = metadata(_contract, DocumentationType::ABIInterface); - meta["output"]["natspec"] = metadata(_contract, DocumentationType::NatspecUser); + meta["output"]["userdoc"] = metadata(_contract, DocumentationType::NatspecUser); + meta["output"]["devdoc"] = metadata(_contract, DocumentationType::NatspecDev); - Json::FastWriter writer; - writer.omitEndingLineFeed(); - return writer.write(meta); + return jsonCompactPrint(meta); } string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) const From 659b635b2d8274f870ebe487a73b431a2398b741 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 23 Nov 2016 19:04:50 +0100 Subject: [PATCH 114/185] Make sure some keys are present. --- libsolidity/interface/CompilerStack.cpp | 3 +++ solc/CommandLineInterface.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 0f8613029..e77836ef6 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -670,6 +670,7 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const meta["language"] = "Solidity"; meta["compiler"]["version"] = VersionString; + meta["sources"] = Json::objectValue; for (auto const& s: m_sources) { solAssert(s.second.scanner, "Scanner not available"); @@ -683,12 +684,14 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const meta["settings"]["compilationTarget"][_contract.contract->sourceUnitName()] = _contract.contract->annotation().canonicalName; + meta["settings"]["remappings"] = Json::arrayValue; set remappings; for (auto const& r: m_remappings) remappings.insert(r.context + ":" + r.prefix + "=" + r.target); for (auto const& r: remappings) meta["settings"]["remappings"].append(r); + meta["settings"]["libraries"] = Json::objectValue; for (auto const& library: m_libraries) meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes()); diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index fdfcabb4c..419a1de00 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -212,7 +212,7 @@ void CommandLineInterface::handleOnChainMetadata(string const& _contract) string data = m_compiler->onChainMetadata(_contract); if (m_args.count("output-dir")) - createFile(_contract + ".meta", data); + createFile(_contract + "_meta.json", data); else cout << "Metadata: " << endl << data << endl; } From 9b46752cc274154faf3fd9af2ec9587e02eb250a Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 23 Nov 2016 19:04:57 +0100 Subject: [PATCH 115/185] Documentation. --- docs/miscellaneous.rst | 119 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 9f733979b..a09f297a0 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -232,6 +232,125 @@ Either add ``--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"`` to If ``solc`` is called with the option ``--link``, all input files are interpreted to be unlinked binaries (hex-encoded) in the ``__LibraryName____``-format given above and are linked in-place (if the input is read from stdin, it is written to stdout). All options except ``--libraries`` are ignored (including ``-o``) in this case. +***************** +Contract Metadata +***************** + +The Solidity compiler automatically generates an internal json file, the +contract metadata, that contains information about the current contract. +It can be used to query the compiler version, the sourcecode, the ABI +and NatSpec documentation in order to more safely interact with the contract +and to verify its source code. + +The compiler inserts a swarm hash of that file into the bytecode of each +contract, so that you can retrieve the file in an authenticated way +without having to resort to a centralized data provider. + +Specifically, the runtime code for a contract always starts with +``push32 pop``, so you can take a look at the 32 bytes starting at +the second byte of the code of a contract. + +Of course, you have to publish the metadata file to swarm (or some other service) +so that others can access it. The file can be output by using ``solc --metadata``. +It will contain swarm references to the source code, so you have to upload +all source files and the metadata. + +The metadata file has the following format. The example below is presented in a +human-readable way. Properly formatted metadata should use quotes correctly, +reduce whitespace to a minimum and sort the keys of all objects to arrive at a +unique formatting. +Comments are of course also not permitted and used here only for explanatory purposes. + + { + // Required: The version of the metadata format + version: "1", + // Required: Source code language, basically selects a "sub-version" + // of the specification + language: "Solidity", + // Required: Details about the compiler, contents are specific + // to the language. + compiler: { + // Required for Solidity: Version of the compiler + version: "0.4.6+commit.2dabbdf0.Emscripten.clang", + // Optional: Hash of the compiler binary which produced this output + keccak256: "0x123..." + }, + // Required: Compilation source files/source units, keys are file names + sources: + { + "myFile.sol": { + // Required: keccak256 hash of the source file + "keccak256": "0x123...", + // Required (unless "content" is used, see below): URL to the + // source file, protocol is more or less arbitrary, but a swarm + // URL is recommended + "url": "bzzr://56ab..." + }, + "mortal": { + "keccak256": "0x123...", + // Required (unless "url" is used): literal contents of the source file + "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }" + } + }, + // Required: Compiler settings + settings: + { + // Required for Solidity: Sorted list of remappings + remappings: [":g/dir"], + // Optional: Optimizer settings (enabled defaults to false) + optimizer: {enabled: true, runs: 500}, + // Required for Solidity: File and name of the contract or library this + // metadata is created for. + compilationTarget: { + "myFile.sol": "MyContract" + }, + // Required for Solidity: Addresses for libraries + libraries: { + "MyLib": "0x123123..." + } + }, + // Required: Generated information about the contract. + output: + { + // Required: ABI definition of the contract + abi: [ ... ], + // Required: NatSpec user documentation of the contract + userdoc: [ ... ], + // Required: NatSpec developer documentation of the contract + devdoc: [ ... ], + } + } + +Usage for Automatic Interface Generation and NatSpec +---------------------------------------------------- + +The metadata is used in the following way: A component that wants to interact +with a contract (e.g. mist) retrieves the code of the contract +and from that the first 33 bytes. If the first byte decodes into a PUSH32 +instruction, the other 32 bytes are interpreted as the swarm hash of +a file which is then retrieved. +That file is JSON-decoded into a structure like above. + +The component can then use the abi to automatically generate a rudimentary +user interface for the contract. + +Furthermore, mist can use the userdoc to display a confirmation message to the user +whenever they interact with the contract. + +Usage for Source Code Verification +---------------------------------- + +In order to verify the compilation, sources can be retrieved from swarm +via the link in the metadata file. +The compiler of the correct version (which is checked to be part of the "official" compilers) +is invoked on that input with the specified settings. The resulting +bytecode is compared to the data of the creation transaction or CREATE opcode data. +This automatically verifies the metadata since +its hash is part of the bytecode. +Excess data is constructor input data which should be decoded +according to the interface and presented to the user. + + *************** Tips and Tricks *************** From 36c6fe2b698b1a05cae954dcee5d9e0fcea85d05 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 23 Nov 2016 19:09:28 +0100 Subject: [PATCH 116/185] Changelog entry. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index b5e48173c..cb3ccae76 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.7 (unreleased) Features: + * Code generator: Inject the swarm hash of a metadata file into the bytecode. * Optimizer: Some dead code elimination. Bugfixes: From 91ecc4533dffbe67fa27adfaff27780ddf69c21a Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 10:32:52 +0100 Subject: [PATCH 117/185] Add swarm hash to the end of the bytecode. --- docs/miscellaneous.rst | 9 ++------- libevmasm/Assembly.cpp | 10 +++++++--- libevmasm/Assembly.h | 7 ++++++- libsolidity/ast/AST.cpp | 1 + libsolidity/codegen/Compiler.cpp | 4 +--- libsolidity/codegen/CompilerContext.cpp | 7 ------- libsolidity/codegen/CompilerContext.h | 4 ++-- libsolidity/interface/CompilerStack.cpp | 1 + 8 files changed, 20 insertions(+), 23 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index a09f297a0..1f94c387c 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -242,14 +242,10 @@ It can be used to query the compiler version, the sourcecode, the ABI and NatSpec documentation in order to more safely interact with the contract and to verify its source code. -The compiler inserts a swarm hash of that file into the bytecode of each +The compiler appends a swarm hash (32 bytes) of that file to the end of the bytecode of each contract, so that you can retrieve the file in an authenticated way without having to resort to a centralized data provider. -Specifically, the runtime code for a contract always starts with -``push32 pop``, so you can take a look at the 32 bytes starting at -the second byte of the code of a contract. - Of course, you have to publish the metadata file to swarm (or some other service) so that others can access it. The file can be output by using ``solc --metadata``. It will contain swarm references to the source code, so you have to upload @@ -326,8 +322,7 @@ Usage for Automatic Interface Generation and NatSpec The metadata is used in the following way: A component that wants to interact with a contract (e.g. mist) retrieves the code of the contract -and from that the first 33 bytes. If the first byte decodes into a PUSH32 -instruction, the other 32 bytes are interpreted as the swarm hash of +and from that the last 32 bytes, which are interpreted as the swarm hash of a file which is then retrieved. That file is JSON-decoded into a structure like above. diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index b040917d3..fab63840b 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -432,7 +432,7 @@ LinkerObject const& Assembly::assemble() const unsigned bytesPerTag = dev::bytesRequired(bytesRequiredForCode); byte tagPush = (byte)Instruction::PUSH1 - 1 + bytesPerTag; - unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1; + unsigned bytesRequiredIncludingData = bytesRequiredForCode + 1 + m_auxiliaryData.size(); for (auto const& sub: m_subs) bytesRequiredIncludingData += sub->assemble().bytecode.size(); @@ -525,8 +525,9 @@ LinkerObject const& Assembly::assemble() const } } - if (!dataRef.empty() && !subRef.empty()) - ret.bytecode.push_back(0); + // Append a STOP just to be sure. + ret.bytecode.push_back(0); + for (size_t i = 0; i < m_subs.size(); ++i) { auto references = subRef.equal_range(i); @@ -568,6 +569,9 @@ LinkerObject const& Assembly::assemble() const } ret.bytecode += dataItem.second; } + + ret.bytecode += m_auxiliaryData; + for (unsigned pos: sizeRef) { bytesRef r(ret.bytecode.data() + pos, bytesPerDataRef); diff --git a/libevmasm/Assembly.h b/libevmasm/Assembly.h index a5fd4d516..9e7f9f7bd 100644 --- a/libevmasm/Assembly.h +++ b/libevmasm/Assembly.h @@ -71,6 +71,9 @@ public: AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(solidity::Instruction::JUMPI); return ret; } AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); } + /// Appends @a _data literally to the very end of the bytecode. + void appendAuxiliaryDataToEnd(bytes const& _data) { m_auxiliaryData += _data; } + template Assembly& operator<<(T const& _d) { append(_d); return *this; } AssemblyItems const& items() const { return m_items; } AssemblyItem const& back() const { return m_items.back(); } @@ -125,10 +128,12 @@ private: Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const; protected: - // 0 is reserved for exception + /// 0 is reserved for exception unsigned m_usedTags = 1; AssemblyItems m_items; std::map m_data; + /// Data that is appended to the very end of the contract. + bytes m_auxiliaryData; std::vector> m_subs; std::map m_strings; std::map m_libraries; ///< Identifiers of libraries to be linked. diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index f8eb7108e..3cd1dfbea 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -65,6 +65,7 @@ SourceUnitAnnotation& SourceUnit::annotation() const string Declaration::sourceUnitName() const { + solAssert(!!m_scope, ""); ASTNode const* scope = m_scope; while (dynamic_cast(scope) && dynamic_cast(scope)->m_scope) scope = dynamic_cast(scope)->m_scope; diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index 168e94623..b7e0cc64a 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -36,6 +36,7 @@ void Compiler::compileContract( { ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize); runtimeCompiler.compileContract(_contract, _contracts); + m_runtimeContext.appendAuxiliaryData(_metadataHash.asBytes()); // This might modify m_runtimeContext because it can access runtime functions at // creation time. @@ -43,9 +44,6 @@ void Compiler::compileContract( m_runtimeSub = creationCompiler.compileConstructor(_contract, _contracts); m_context.optimise(m_optimize, m_optimizeRuns); - - solAssert(m_runtimeSub != size_t(-1), ""); - m_context.injectMetadataHashIntoSub(m_runtimeSub, _metadataHash); } void Compiler::compileClone( diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 9b921e9d6..b99b05485 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -227,13 +227,6 @@ void CompilerContext::injectVersionStampIntoSub(size_t _subIndex) sub.injectStart(fromBigEndian(binaryVersion())); } -void CompilerContext::injectMetadataHashIntoSub(size_t _subIndex, h256 const& _metadataHash) -{ - eth::Assembly& sub = m_asm->sub(_subIndex); - sub.injectStart(Instruction::POP); - sub.injectStart(u256(_metadataHash)); -} - FunctionDefinition const& CompilerContext::resolveVirtualFunction( FunctionDefinition const& _function, vector::const_iterator _searchStart diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index c8a35f93a..8fdb3e03b 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -155,8 +155,8 @@ public: /// Prepends "PUSH POP" void injectVersionStampIntoSub(size_t _subIndex); - /// Prepends "PUSH POP" - void injectMetadataHashIntoSub(size_t _subIndex, h256 const& _metadataHash); + /// Appends arbitrary data to the end of the bytecode. + void appendAuxiliaryData(bytes const& _data) { m_asm->appendAuxiliaryDataToEnd(_data); } void optimise(bool _fullOptimsation, unsigned _runs = 200) { m_asm->optimise(_fullOptimsation, true, _runs); } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index e77836ef6..357b18bd5 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -375,6 +375,7 @@ Json::Value const& CompilerStack::metadata(Contract const& _contract, Documentat if (!m_parseSuccessful) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); + solAssert(_contract.contract, ""); std::unique_ptr* doc; // checks wheather we already have the documentation From aa1fd6a879eaedc5c4df2951c06e9dc3eb6eaeb4 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 10:55:32 +0100 Subject: [PATCH 118/185] Add test. --- test/libsolidity/SolidityABIJSON.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 6fc2bcee2..f5f8b342e 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -22,8 +22,11 @@ #include "../TestHelper.h" #include -#include + #include +#include + +#include namespace dev { @@ -51,7 +54,7 @@ public: ); } -private: +protected: CompilerStack m_compilerStack; Json::Reader m_reader; }; @@ -731,6 +734,23 @@ BOOST_AUTO_TEST_CASE(function_type) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(metadata_stamp) +{ + // Check that the metadata stamp is at the end of the runtime bytecode. + char const* sourceCode = R"( + pragma solidity >=0.0; + contract test { + function g(function(uint) external returns (uint) x) {} + } + )"; + BOOST_REQUIRE(m_compilerStack.compile(std::string(sourceCode))); + bytes const& bytecode = m_compilerStack.runtimeObject("test").bytecode; + bytes hash = dev::swarmHash(m_compilerStack.onChainMetadata("test")).asBytes(); + BOOST_REQUIRE(hash.size() == 32); + BOOST_REQUIRE(bytecode.size() >= hash.size()); + BOOST_CHECK(std::equal(hash.begin(), hash.end(), bytecode.end() - 32)); +} + BOOST_AUTO_TEST_SUITE_END() } From 1e35526eb6a7c5af074170f6291491d3cb0bd6ba Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 12:32:42 +0100 Subject: [PATCH 119/185] Fix tests. --- libevmasm/Assembly.cpp | 5 +++-- libsolidity/codegen/CompilerContext.cpp | 7 ------- libsolidity/codegen/CompilerContext.h | 3 --- test/libsolidity/SolidityEndToEndTest.cpp | 11 ----------- 4 files changed, 3 insertions(+), 23 deletions(-) diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp index fab63840b..a9ca24dc4 100644 --- a/libevmasm/Assembly.cpp +++ b/libevmasm/Assembly.cpp @@ -525,8 +525,9 @@ LinkerObject const& Assembly::assemble() const } } - // Append a STOP just to be sure. - ret.bytecode.push_back(0); + if (!m_subs.empty() || !m_data.empty() || !m_auxiliaryData.empty()) + // Append a STOP just to be sure. + ret.bytecode.push_back(0); for (size_t i = 0; i < m_subs.size(); ++i) { diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index b99b05485..2de5a3ec2 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -220,13 +220,6 @@ void CompilerContext::appendInlineAssembly( solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), ""); } -void CompilerContext::injectVersionStampIntoSub(size_t _subIndex) -{ - eth::Assembly& sub = m_asm->sub(_subIndex); - sub.injectStart(Instruction::POP); - sub.injectStart(fromBigEndian(binaryVersion())); -} - FunctionDefinition const& CompilerContext::resolveVirtualFunction( FunctionDefinition const& _function, vector::const_iterator _searchStart diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 8fdb3e03b..806715280 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -152,9 +152,6 @@ public: std::map const& _replacements = std::map{} ); - /// Prepends "PUSH POP" - void injectVersionStampIntoSub(size_t _subIndex); - /// Appends arbitrary data to the end of the bytecode. void appendAuxiliaryData(bytes const& _data) { m_asm->appendAuxiliaryDataToEnd(_data); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 47b96dc2b..cebd9dfe4 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6547,17 +6547,6 @@ BOOST_AUTO_TEST_CASE(calldata_offset) BOOST_CHECK(callContractFunction("last()", encodeArgs()) == encodeDyn(string("nd"))); } -BOOST_AUTO_TEST_CASE(version_stamp_for_libraries) -{ - char const* sourceCode = "library lib {}"; - m_optimize = true; - bytes runtimeCode = compileAndRun(sourceCode, 0, "lib"); - BOOST_CHECK(runtimeCode.size() >= 8); - BOOST_CHECK_EQUAL(runtimeCode[0], int(Instruction::PUSH6)); // might change once we switch to 1.x.x - BOOST_CHECK_EQUAL(runtimeCode[1], 4); // might change once we switch away from x.4.x - BOOST_CHECK_EQUAL(runtimeCode[7], int(Instruction::POP)); -} - BOOST_AUTO_TEST_CASE(contract_binary_dependencies) { char const* sourceCode = R"( From 1316c0c872f5b94a73456a8151188dfbef317fdc Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 21:42:57 +0100 Subject: [PATCH 120/185] Fix documentation error. --- docs/miscellaneous.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 1f94c387c..3b8c5232e 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -257,6 +257,8 @@ reduce whitespace to a minimum and sort the keys of all objects to arrive at a unique formatting. Comments are of course also not permitted and used here only for explanatory purposes. +.. code-block:: json + { // Required: The version of the metadata format version: "1", From e0d4a3d518dc742d94571ef1e16b3f95765ec62f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 24 Nov 2016 21:43:57 +0100 Subject: [PATCH 121/185] Fix emscripten build. --- libdevcore/JSON.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcore/JSON.h b/libdevcore/JSON.h index 7876dfb21..0d6e0d2e8 100644 --- a/libdevcore/JSON.h +++ b/libdevcore/JSON.h @@ -28,13 +28,13 @@ namespace dev { /// Serialise the JSON object (@a _input) with identation -std::string jsonPrettyPrint(Json::Value const& _input) +inline std::string jsonPrettyPrint(Json::Value const& _input) { return Json::StyledWriter().write(_input); } /// Serialise theJ SON object (@a _input) without identation -std::string jsonCompactPrint(Json::Value const& _input) +inline std::string jsonCompactPrint(Json::Value const& _input) { Json::FastWriter writer; writer.omitEndingLineFeed(); From 6a7ff039df15be59fbb71dc3dfaad09fb0b8961f Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 29 Nov 2016 17:47:47 +0100 Subject: [PATCH 122/185] Use CBOR encoding. --- docs/miscellaneous.rst | 36 ++++++++++++++++++------- libsolidity/codegen/Compiler.cpp | 4 +-- libsolidity/codegen/Compiler.h | 2 +- libsolidity/interface/CompilerStack.cpp | 9 ++++++- test/libsolidity/Assembly.cpp | 2 +- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 3b8c5232e..5b51c4a90 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -236,20 +236,22 @@ If ``solc`` is called with the option ``--link``, all input files are interprete Contract Metadata ***************** -The Solidity compiler automatically generates an internal json file, the +The Solidity compiler automatically generates a json file, the contract metadata, that contains information about the current contract. It can be used to query the compiler version, the sourcecode, the ABI and NatSpec documentation in order to more safely interact with the contract and to verify its source code. -The compiler appends a swarm hash (32 bytes) of that file to the end of the bytecode of each -contract, so that you can retrieve the file in an authenticated way -without having to resort to a centralized data provider. +The compiler appends a swarm hash (32 bytes) of that file to the end of the +bytecode (for details, see below) of each contract, so that you can retrieve +the file in an authenticated way without having to resort to a centralized +data provider. Of course, you have to publish the metadata file to swarm (or some other service) -so that others can access it. The file can be output by using ``solc --metadata``. +so that others can access it. The file can be output by using ``solc --metadata`` +and the file will be called ``ContractName_meta.json``. It will contain swarm references to the source code, so you have to upload -all source files and the metadata. +all source files and the metadata file. The metadata file has the following format. The example below is presented in a human-readable way. Properly formatted metadata should use quotes correctly, @@ -319,13 +321,29 @@ Comments are of course also not permitted and used here only for explanatory pur } } + +Encoding of the Metadata Hash in the Bytecode +--------------------------------------------- + +Because we might support other ways to retrieve the metadata file in the future, +the mapping ``{"bzzr0": }`` is stored +[CBOR](https://tools.ietf.org/html/rfc7049)-encoded. Since the beginning of that +encoding is not easy to find, its length is added in a two-byte big-endian +encoding. The current version of the Solidity compiler thus adds the following +to the end of the deployed bytecode:: + + 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29 + +So in order to retrieve the data, you can check the end of the deployed +bytecode to match that pattern and use the swarm hash to retrieve the +file. + Usage for Automatic Interface Generation and NatSpec ---------------------------------------------------- The metadata is used in the following way: A component that wants to interact -with a contract (e.g. mist) retrieves the code of the contract -and from that the last 32 bytes, which are interpreted as the swarm hash of -a file which is then retrieved. +with a contract (e.g. mist) retrieves the code of the contract, from that +the swarm hash of a file which is then retrieved. That file is JSON-decoded into a structure like above. The component can then use the abi to automatically generate a rudimentary diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index b7e0cc64a..44264a07a 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -31,12 +31,12 @@ using namespace dev::solidity; void Compiler::compileContract( ContractDefinition const& _contract, std::map const& _contracts, - h256 const& _metadataHash + bytes const& _metadata ) { ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize); runtimeCompiler.compileContract(_contract, _contracts); - m_runtimeContext.appendAuxiliaryData(_metadataHash.asBytes()); + m_runtimeContext.appendAuxiliaryData(_metadata); // This might modify m_runtimeContext because it can access runtime functions at // creation time. diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 58ef19637..eef078c11 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -43,7 +43,7 @@ public: void compileContract( ContractDefinition const& _contract, std::map const& _contracts, - h256 const& _metadataHash + bytes const& _metadata ); /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given /// contract at runtime, but contains the full creation-time code. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 357b18bd5..d79345f05 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -611,7 +611,14 @@ void CompilerStack::compileContract( shared_ptr compiler = make_shared(m_optimize, m_optimizeRuns); Contract& compiledContract = m_contracts.at(_contract.name()); string onChainMetadata = createOnChainMetadata(compiledContract); - compiler->compileContract(_contract, _compiledContracts, dev::swarmHash(onChainMetadata)); + bytes cborEncodedMetadata = + // CBOR-encoding of {"bzzr0": dev::swarmHash(onChainMetadata)} + bytes{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} + + dev::swarmHash(onChainMetadata).asBytes(); + solAssert(cborEncodedMetadata.size() <= 0xffff, "Metadata too large"); + // 16-bit big endian length + cborEncodedMetadata += toCompactBigEndian(cborEncodedMetadata.size(), 2); + compiler->compileContract(_contract, _compiledContracts, cborEncodedMetadata); compiledContract.compiler = compiler; compiledContract.object = compiler->assembledObject(); compiledContract.runtimeObject = compiler->runtimeObject(); diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 27709086c..bdbe7dba4 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -75,7 +75,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode) if (ContractDefinition* contract = dynamic_cast(node.get())) { Compiler compiler; - compiler.compileContract(*contract, map{}, h256()); + compiler.compileContract(*contract, map{}, bytes()); return compiler.runtimeAssemblyItems(); } From 35325ee7c3e1af558caf0a47c8611cdfde959bb3 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 10:12:28 +0000 Subject: [PATCH 123/185] Update metadata documentation --- Changelog.md | 2 +- docs/miscellaneous.rst | 46 ++++++++++++++++++----------------- solc/CommandLineInterface.cpp | 2 +- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Changelog.md b/Changelog.md index cb3ccae76..1058fdf5a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,7 @@ ### 0.4.7 (unreleased) Features: - * Code generator: Inject the swarm hash of a metadata file into the bytecode. + * Code generator: Inject the Swarm hash of a metadata file into the bytecode. * Optimizer: Some dead code elimination. Bugfixes: diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 5b51c4a90..c44b3e9e2 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -236,21 +236,21 @@ If ``solc`` is called with the option ``--link``, all input files are interprete Contract Metadata ***************** -The Solidity compiler automatically generates a json file, the +The Solidity compiler automatically generates a JSON file, the contract metadata, that contains information about the current contract. -It can be used to query the compiler version, the sourcecode, the ABI +It can be used to query the compiler version, the sources used, the ABI and NatSpec documentation in order to more safely interact with the contract and to verify its source code. -The compiler appends a swarm hash (32 bytes) of that file to the end of the +The compiler appends a Swarm hash of the metadata file to the end of the bytecode (for details, see below) of each contract, so that you can retrieve the file in an authenticated way without having to resort to a centralized data provider. -Of course, you have to publish the metadata file to swarm (or some other service) +Of course, you have to publish the metadata file to Swarm (or some other service) so that others can access it. The file can be output by using ``solc --metadata`` and the file will be called ``ContractName_meta.json``. -It will contain swarm references to the source code, so you have to upload +It will contain Swarm references to the source code, so you have to upload all source files and the metadata file. The metadata file has the following format. The example below is presented in a @@ -282,12 +282,13 @@ Comments are of course also not permitted and used here only for explanatory pur // Required: keccak256 hash of the source file "keccak256": "0x123...", // Required (unless "content" is used, see below): URL to the - // source file, protocol is more or less arbitrary, but a swarm + // source file, protocol is more or less arbitrary, but a Swarm // URL is recommended "url": "bzzr://56ab..." }, "mortal": { - "keccak256": "0x123...", + // Required: keccak256 hash of the source file + "keccak256": "0x234...", // Required (unless "url" is used): literal contents of the source file "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }" } @@ -296,15 +297,18 @@ Comments are of course also not permitted and used here only for explanatory pur settings: { // Required for Solidity: Sorted list of remappings - remappings: [":g/dir"], + remappings: [ ":g/dir" ], // Optional: Optimizer settings (enabled defaults to false) - optimizer: {enabled: true, runs: 500}, + optimizer: { + enabled: true, + runs: 500 + }, // Required for Solidity: File and name of the contract or library this // metadata is created for. compilationTarget: { "myFile.sol": "MyContract" }, - // Required for Solidity: Addresses for libraries + // Required for Solidity: Addresses for libraries used libraries: { "MyLib": "0x123123..." } @@ -326,7 +330,7 @@ Encoding of the Metadata Hash in the Bytecode --------------------------------------------- Because we might support other ways to retrieve the metadata file in the future, -the mapping ``{"bzzr0": }`` is stored +the mapping ``{"bzzr0": }`` is stored [CBOR](https://tools.ietf.org/html/rfc7049)-encoded. Since the beginning of that encoding is not easy to find, its length is added in a two-byte big-endian encoding. The current version of the Solidity compiler thus adds the following @@ -334,35 +338,33 @@ to the end of the deployed bytecode:: 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29 -So in order to retrieve the data, you can check the end of the deployed -bytecode to match that pattern and use the swarm hash to retrieve the -file. +So in order to retrieve the data, the end of the deployed bytecode can be checked +to match that pattern and use the Swarm hash to retrieve the file. Usage for Automatic Interface Generation and NatSpec ---------------------------------------------------- The metadata is used in the following way: A component that wants to interact -with a contract (e.g. mist) retrieves the code of the contract, from that -the swarm hash of a file which is then retrieved. +with a contract (e.g. Mist) retrieves the code of the contract, from that +the Swarm hash of a file which is then retrieved. That file is JSON-decoded into a structure like above. -The component can then use the abi to automatically generate a rudimentary +The component can then use the ABI to automatically generate a rudimentary user interface for the contract. -Furthermore, mist can use the userdoc to display a confirmation message to the user +Furthermore, Mist can use the userdoc to display a confirmation message to the user whenever they interact with the contract. Usage for Source Code Verification ---------------------------------- -In order to verify the compilation, sources can be retrieved from swarm +In order to verify the compilation, sources can be retrieved from Swarm via the link in the metadata file. The compiler of the correct version (which is checked to be part of the "official" compilers) is invoked on that input with the specified settings. The resulting bytecode is compared to the data of the creation transaction or CREATE opcode data. -This automatically verifies the metadata since -its hash is part of the bytecode. -Excess data is constructor input data which should be decoded +This automatically verifies the metadata since its hash is part of the bytecode. +Excess data corresponds to the constructor input data, which should be decoded according to the interface and presented to the user. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 419a1de00..6e59099aa 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -482,7 +482,7 @@ Allowed options)", (g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.") (g_argNatspecUserStr.c_str(), "Natspec user documentation of all contracts.") (g_argNatspecDevStr.c_str(), "Natspec developer documentation of all contracts.") - (g_argMetadata.c_str(), "Combined metadata JSON whose swarm hash is stored on-chain.") + (g_argMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.") ("formal", "Translated source suitable for formal analysis."); desc.add(outputComponents); From f91ae3f06b8b6ae273a42020e81f882141a0a78f Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 30 Nov 2016 11:27:46 +0100 Subject: [PATCH 124/185] Fix tests --- test/libsolidity/SolidityABIJSON.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index f5f8b342e..890db241b 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -747,8 +747,11 @@ BOOST_AUTO_TEST_CASE(metadata_stamp) bytes const& bytecode = m_compilerStack.runtimeObject("test").bytecode; bytes hash = dev::swarmHash(m_compilerStack.onChainMetadata("test")).asBytes(); BOOST_REQUIRE(hash.size() == 32); - BOOST_REQUIRE(bytecode.size() >= hash.size()); - BOOST_CHECK(std::equal(hash.begin(), hash.end(), bytecode.end() - 32)); + BOOST_REQUIRE(bytecode.size() >= 2); + size_t metadataCBORSize = (size_t(bytecode.end()[-2]) << 8) + size_t(bytecode.end()[-1]); + BOOST_REQUIRE(metadataCBORSize < bytecode.size() - 2); + bytes expectation = bytes{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} + hash; + BOOST_CHECK(std::equal(expectation.begin(), expectation.end(), bytecode.end() - metadataCBORSize - 2)); } BOOST_AUTO_TEST_SUITE_END() From ea7a6520b283f5dfc47c05d8b8088608d2b5f4f9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 12:16:55 +0000 Subject: [PATCH 125/185] Fix documentation errors Subheadings must use consistent format across a file. The metadata with comments cannot be parsed as JSON. --- docs/miscellaneous.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index c44b3e9e2..1754752d5 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -259,7 +259,7 @@ reduce whitespace to a minimum and sort the keys of all objects to arrive at a unique formatting. Comments are of course also not permitted and used here only for explanatory purposes. -.. code-block:: json +.. code-block:: none { // Required: The version of the metadata format @@ -327,7 +327,7 @@ Comments are of course also not permitted and used here only for explanatory pur Encoding of the Metadata Hash in the Bytecode ---------------------------------------------- +============================================= Because we might support other ways to retrieve the metadata file in the future, the mapping ``{"bzzr0": }`` is stored @@ -342,7 +342,7 @@ So in order to retrieve the data, the end of the deployed bytecode can be checke to match that pattern and use the Swarm hash to retrieve the file. Usage for Automatic Interface Generation and NatSpec ----------------------------------------------------- +==================================================== The metadata is used in the following way: A component that wants to interact with a contract (e.g. Mist) retrieves the code of the contract, from that @@ -356,7 +356,7 @@ Furthermore, Mist can use the userdoc to display a confirmation message to the u whenever they interact with the contract. Usage for Source Code Verification ----------------------------------- +================================== In order to verify the compilation, sources can be retrieved from Swarm via the link in the metadata file. From f869792eec99a38ff5c29b36622e2795fd3c52aa Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 13:00:51 +0000 Subject: [PATCH 126/185] Fix type of optimizeRuns --- libsolidity/interface/CompilerStack.h | 2 +- test/ExecutionFramework.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 74a7dfc57..57c761336 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -258,7 +258,7 @@ private: ReadFileCallback m_readFile; bool m_optimize = false; - size_t m_optimizeRuns = 200; + unsigned m_optimizeRuns = 200; std::map m_libraries; /// list of path prefix remappings, e.g. mylibrary: github.com/ethereum = /usr/local/ethereum /// "context:prefix=target" diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index 1274d4006..f47f2743d 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -279,7 +279,7 @@ protected: bytes data; }; - size_t m_optimizeRuns = 200; + unsigned m_optimizeRuns = 200; bool m_optimize = false; Address m_sender; Address m_contractAddress; From 1ad9640fa3547e30568ad62575961dbc4d1f4d7f Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 13:05:19 +0000 Subject: [PATCH 127/185] Optimizer tests to not interfere with the optimiser flag --- test/libsolidity/SolidityOptimizer.cpp | 35 ++++++++++++++++++-------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 3c1f465a9..123dfe86c 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -50,6 +50,25 @@ class OptimizerTestFramework: public SolidityExecutionFramework { public: OptimizerTestFramework() { } + + bytes const& compileAndRunWithOptimizer( + std::string const& _sourceCode, + u256 const& _value = 0, + std::string const& _contractName = "", + bool const _optimize = true, + unsigned const _optimizeRuns = 200 + ) + { + bool const c_optimize = m_optimize; + unsigned const c_optimizeRuns = m_optimizeRuns; + m_optimize = _optimize; + m_optimizeRuns = _optimizeRuns; + bytes const& ret = compileAndRun(_sourceCode, _value, _contractName); + m_optimize = c_optimize; + m_optimizeRuns = c_optimizeRuns; + return ret; + } + /// Compiles the source code with and without optimizing. void compileBothVersions( std::string const& _sourceCode, @@ -57,11 +76,9 @@ public: std::string const& _contractName = "" ) { - m_optimize = false; - bytes nonOptimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); + bytes nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false); m_nonOptimizedContract = m_contractAddress; - m_optimize = true; - bytes optimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); + bytes optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true); size_t nonOptimizedSize = 0; solidity::eachInstruction(nonOptimizedBytecode, [&](Instruction, u256 const&) { nonOptimizedSize++; @@ -315,8 +332,7 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches) compareVersions("f(uint256,bytes32)", 8, "def"); compareVersions("f(uint256,bytes32)", 10, "ghi"); - m_optimize = true; - bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c"); + bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true); size_t numSHA3s = 0; eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { if (_instr == Instruction::SHA3) @@ -359,8 +375,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) compileBothVersions(sourceCode); compareVersions("f(uint256,bytes32)", 7, "abc"); - m_optimize = true; - bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test"); + bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true); size_t numSHA3s = 0; eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { if (_instr == Instruction::SHA3) @@ -1187,9 +1202,7 @@ BOOST_AUTO_TEST_CASE(computing_constants) compareVersions("set()"); compareVersions("get()"); - m_optimize = true; - m_optimizeRuns = 1; - bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c"); + bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true, 1); bytes complicatedConstant = toBigEndian(u256("0x817416927846239487123469187231298734162934871263941234127518276")); unsigned occurrences = 0; for (auto iter = optimizedBytecode.cbegin(); iter < optimizedBytecode.cend(); ++occurrences) From c88f34c7819f927cec1a2f1f93fc79d5262736bc Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 13:16:59 +0000 Subject: [PATCH 128/185] Remove unneeded optimised test from EndToEndTest --- test/libsolidity/SolidityEndToEndTest.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index cebd9dfe4..aa1eb20a8 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7820,13 +7820,6 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) u160 cAddr = m_contractAddress; compileAndRun(sourceCode, 0, "D"); BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7))); - - m_optimize = true; - - compileAndRun(sourceCode, 0, "C"); - u160 cAddrOpt = m_contractAddress; - compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(calling_uninitialized_function) From 4c15c465efa1af104c368c63ee715fd1051c7ef4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 1 Dec 2016 01:19:28 +0000 Subject: [PATCH 129/185] Submit library addresses to the compiler in tests (and not link afterwards) --- test/libsolidity/SolidityExecutionFramework.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 0fab7aeb0..03e3a881c 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -56,7 +56,7 @@ public: std::string sourceCode = "pragma solidity >=0.0;\n" + _sourceCode; m_compiler.reset(false); m_compiler.addSource("", sourceCode); - if (!m_compiler.compile(m_optimize, m_optimizeRuns)) + if (!m_compiler.compile(m_optimize, m_optimizeRuns, _libraryAddresses)) { for (auto const& error: m_compiler.errors()) SourceReferenceFormatter::printExceptionInformation( @@ -68,7 +68,6 @@ public: BOOST_ERROR("Compiling contract failed"); } eth::LinkerObject obj = m_compiler.object(_contractName); - obj.link(_libraryAddresses); BOOST_REQUIRE(obj.linkReferences.empty()); sendMessage(obj.bytecode + _arguments, true, _value); return m_output; From f1907bbb12ce6a65d781bee1e1faebd6cde261bd Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 1 Dec 2016 11:44:13 +0100 Subject: [PATCH 130/185] Add the `_runs` parameter. --- libsolidity/interface/CompilerStack.cpp | 4 ++-- libsolidity/interface/CompilerStack.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index d79345f05..b4fd6d87c 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -242,9 +242,9 @@ bool CompilerStack::compile(bool _optimize, unsigned _runs, map co return true; } -bool CompilerStack::compile(string const& _sourceCode, bool _optimize) +bool CompilerStack::compile(string const& _sourceCode, bool _optimize, unsigned _runs) { - return parse(_sourceCode) && compile(_optimize); + return parse(_sourceCode) && compile(_optimize, _runs); } void CompilerStack::link() diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 57c761336..f98a457a4 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -120,7 +120,7 @@ public: ); /// Parses and compiles the given source code. /// @returns false on error. - bool compile(std::string const& _sourceCode, bool _optimize = false); + bool compile(std::string const& _sourceCode, bool _optimize = false, unsigned _runs = 200); /// Tries to translate all source files into a language suitable for formal analysis. /// @param _errors list to store errors - defaults to the internal error list. From 5098e1eb15678859d1bd5e9172184d6525e03863 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 1 Dec 2016 16:02:54 +0100 Subject: [PATCH 131/185] Count instructions without metadata hash. --- test/libsolidity/SolidityOptimizer.cpp | 32 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 123dfe86c..2e2e0c6ca 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -79,17 +79,13 @@ public: bytes nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false); m_nonOptimizedContract = m_contractAddress; bytes optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true); - size_t nonOptimizedSize = 0; - solidity::eachInstruction(nonOptimizedBytecode, [&](Instruction, u256 const&) { - nonOptimizedSize++; - }); - size_t optimizedSize = 0; - solidity::eachInstruction(optimizedBytecode, [&](Instruction, u256 const&) { - optimizedSize++; - }); + size_t nonOptimizedSize = numInstructions(nonOptimizedBytecode); + size_t optimizedSize = numInstructions(optimizedBytecode); BOOST_CHECK_MESSAGE( - nonOptimizedSize > optimizedSize, - "Optimizer did not reduce bytecode size." + optimizedSize < nonOptimizedSize, + string("Optimizer did not reduce bytecode size. Non-optimized size: ") + + std::to_string(nonOptimizedSize) + " - optimized size: " + + std::to_string(optimizedSize) ); m_optimizedContract = m_contractAddress; } @@ -173,6 +169,22 @@ public: } protected: + /// @returns the number of intructions in the given bytecode, not taking the metadata hash + /// into account. + size_t numInstructions(bytes const& _bytecode) + { + BOOST_REQUIRE(_bytecode.size() > 5); + size_t metadataSize = (_bytecode[_bytecode.size() - 2] << 8) + _bytecode[_bytecode.size() - 1]; + BOOST_REQUIRE_MESSAGE(metadataSize == 0x29, "Invalid metadata size"); + BOOST_REQUIRE(_bytecode.size() >= metadataSize + 2); + bytes realCode = bytes(_bytecode.begin(), _bytecode.end() - metadataSize - 2); + size_t instructions = 0; + solidity::eachInstruction(realCode, [&](Instruction, u256 const&) { + instructions++; + }); + return instructions; + } + Address m_optimizedContract; Address m_nonOptimizedContract; }; From 50bcc60e6ee492cfbdb06bcf0ae82b918fddc0ac Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 14:45:39 +0100 Subject: [PATCH 132/185] grammar.txt: remove a space from `payable` keyword --- docs/grammar.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/grammar.txt b/docs/grammar.txt index 0aa6690ba..637290db9 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -22,7 +22,7 @@ StructDefinition = 'struct' Identifier '{' ( VariableDeclaration ';' (VariableDeclaration ';')* )? '}' ModifierDefinition = 'modifier' Identifier ParameterList? Block FunctionDefinition = 'function' Identifier? ParameterList - ( FunctionCall | Identifier | 'constant' |' payable' | 'external' | 'public' | 'internal' | 'private' )* + ( FunctionCall | Identifier | 'constant' | 'payable' | 'external' | 'public' | 'internal' | 'private' )* ( 'returns' ParameterList )? Block EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';' From 43b56a61aa734b1abae7dba589b82266cba0fd74 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 15:37:45 +0100 Subject: [PATCH 133/185] parsing: `default` and `null` are reserved keywords --- docs/miscellaneous.rst | 2 +- libsolidity/parsing/Token.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 1754752d5..e479d5f66 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -510,7 +510,7 @@ Reserved Keywords These keywords are reserved in Solidity. They might become part of the syntax in the future: -``abstract``, ``after``, ``case``, ``catch``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``, +``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``, ``null``, ``of``, ``pure``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``, ``view``. Language Grammar diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h index 3ce0f4244..c6d050bb4 100644 --- a/libsolidity/parsing/Token.h +++ b/libsolidity/parsing/Token.h @@ -147,7 +147,6 @@ namespace solidity K(Const, "constant", 0) \ K(Continue, "continue", 0) \ K(Contract, "contract", 0) \ - K(Default, "default", 0) \ K(Do, "do", 0) \ K(Else, "else", 0) \ K(Enum, "enum", 0) \ @@ -208,7 +207,6 @@ namespace solidity T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ \ /* Literals */ \ - K(NullLiteral, "null", 0) \ K(TrueLiteral, "true", 0) \ K(FalseLiteral, "false", 0) \ T(Number, NULL, 0) \ @@ -223,12 +221,14 @@ namespace solidity K(After, "after", 0) \ K(Case, "case", 0) \ K(Catch, "catch", 0) \ + K(Default, "default", 0) \ K(Final, "final", 0) \ K(In, "in", 0) \ K(Inline, "inline", 0) \ K(Interface, "interface", 0) \ K(Let, "let", 0) \ K(Match, "match", 0) \ + K(NullLiteral, "null", 0) \ K(Of, "of", 0) \ K(Pure, "pure", 0) \ K(Relocatable, "relocatable", 0) \ From d94fd636b7ce6f99a4c386b0ad0ba365fad10420 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Thu, 1 Dec 2016 16:24:43 +0100 Subject: [PATCH 134/185] grammar.txt: define inline assembly --- docs/grammar.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/grammar.txt b/docs/grammar.txt index 637290db9..b0c9da98f 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -44,7 +44,7 @@ FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant StorageLocation = 'memory' | 'storage' Block = '{' Statement* '}' -Statement = IfStatement | WhileStatement | ForStatement | Block | +Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement | ( DoWhileStatement | PlaceholderStatement | Continue | Break | Return | Throw | SimpleStatement ) ';' @@ -54,6 +54,7 @@ WhileStatement = 'while' '(' Expression ')' Statement PlaceholderStatement = '_' SimpleStatement = VariableDefinition | ExpressionStatement ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement +InlineAssemblyStatement = 'assembly' InlineAssemblyBlock DoWhileStatement = 'do' Statement 'while' '(' Expression ')' Continue = 'continue' Break = 'break' @@ -108,3 +109,10 @@ Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | Fixed = 'fixed' | 'fixed0x8' | 'fixed0x16' | 'fixed0x24' | 'fixed0x32' | 'fixed0x40' | 'fixed0x48' | 'fixed0x56' | 'fixed0x64' | 'fixed0x72' | 'fixed0x80' | 'fixed0x88' | 'fixed0x96' | 'fixed0x104' | 'fixed0x112' | 'fixed0x120' | 'fixed0x128' | 'fixed0x136' | 'fixed0x144' | 'fixed0x152' | 'fixed0x160' | 'fixed0x168' | 'fixed0x176' | 'fixed0x184' | 'fixed0x192' | 'fixed0x200' | 'fixed0x208' | 'fixed0x216' | 'fixed0x224' | 'fixed0x232' | 'fixed0x240' | 'fixed0x248' | 'fixed0x256' | 'fixed8x8' | 'fixed8x16' | 'fixed8x24' | 'fixed8x32' | 'fixed8x40' | 'fixed8x48' | 'fixed8x56' | 'fixed8x64' | 'fixed8x72' | 'fixed8x80' | 'fixed8x88' | 'fixed8x96' | 'fixed8x104' | 'fixed8x112' | 'fixed8x120' | 'fixed8x128' | 'fixed8x136' | 'fixed8x144' | 'fixed8x152' | 'fixed8x160' | 'fixed8x168' | 'fixed8x176' | 'fixed8x184' | 'fixed8x192' | 'fixed8x200' | 'fixed8x208' | 'fixed8x216' | 'fixed8x224' | 'fixed8x232' | 'fixed8x240' | 'fixed8x248' | 'fixed16x8' | 'fixed16x16' | 'fixed16x24' | 'fixed16x32' | 'fixed16x40' | 'fixed16x48' | 'fixed16x56' | 'fixed16x64' | 'fixed16x72' | 'fixed16x80' | 'fixed16x88' | 'fixed16x96' | 'fixed16x104' | 'fixed16x112' | 'fixed16x120' | 'fixed16x128' | 'fixed16x136' | 'fixed16x144' | 'fixed16x152' | 'fixed16x160' | 'fixed16x168' | 'fixed16x176' | 'fixed16x184' | 'fixed16x192' | 'fixed16x200' | 'fixed16x208' | 'fixed16x216' | 'fixed16x224' | 'fixed16x232' | 'fixed16x240' | 'fixed24x8' | 'fixed24x16' | 'fixed24x24' | 'fixed24x32' | 'fixed24x40' | 'fixed24x48' | 'fixed24x56' | 'fixed24x64' | 'fixed24x72' | 'fixed24x80' | 'fixed24x88' | 'fixed24x96' | 'fixed24x104' | 'fixed24x112' | 'fixed24x120' | 'fixed24x128' | 'fixed24x136' | 'fixed24x144' | 'fixed24x152' | 'fixed24x160' | 'fixed24x168' | 'fixed24x176' | 'fixed24x184' | 'fixed24x192' | 'fixed24x200' | 'fixed24x208' | 'fixed24x216' | 'fixed24x224' | 'fixed24x232' | 'fixed32x8' | 'fixed32x16' | 'fixed32x24' | 'fixed32x32' | 'fixed32x40' | 'fixed32x48' | 'fixed32x56' | 'fixed32x64' | 'fixed32x72' | 'fixed32x80' | 'fixed32x88' | 'fixed32x96' | 'fixed32x104' | 'fixed32x112' | 'fixed32x120' | 'fixed32x128' | 'fixed32x136' | 'fixed32x144' | 'fixed32x152' | 'fixed32x160' | 'fixed32x168' | 'fixed32x176' | 'fixed32x184' | 'fixed32x192' | 'fixed32x200' | 'fixed32x208' | 'fixed32x216' | 'fixed32x224' | 'fixed40x8' | 'fixed40x16' | 'fixed40x24' | 'fixed40x32' | 'fixed40x40' | 'fixed40x48' | 'fixed40x56' | 'fixed40x64' | 'fixed40x72' | 'fixed40x80' | 'fixed40x88' | 'fixed40x96' | 'fixed40x104' | 'fixed40x112' | 'fixed40x120' | 'fixed40x128' | 'fixed40x136' | 'fixed40x144' | 'fixed40x152' | 'fixed40x160' | 'fixed40x168' | 'fixed40x176' | 'fixed40x184' | 'fixed40x192' | 'fixed40x200' | 'fixed40x208' | 'fixed40x216' | 'fixed48x8' | 'fixed48x16' | 'fixed48x24' | 'fixed48x32' | 'fixed48x40' | 'fixed48x48' | 'fixed48x56' | 'fixed48x64' | 'fixed48x72' | 'fixed48x80' | 'fixed48x88' | 'fixed48x96' | 'fixed48x104' | 'fixed48x112' | 'fixed48x120' | 'fixed48x128' | 'fixed48x136' | 'fixed48x144' | 'fixed48x152' | 'fixed48x160' | 'fixed48x168' | 'fixed48x176' | 'fixed48x184' | 'fixed48x192' | 'fixed48x200' | 'fixed48x208' | 'fixed56x8' | 'fixed56x16' | 'fixed56x24' | 'fixed56x32' | 'fixed56x40' | 'fixed56x48' | 'fixed56x56' | 'fixed56x64' | 'fixed56x72' | 'fixed56x80' | 'fixed56x88' | 'fixed56x96' | 'fixed56x104' | 'fixed56x112' | 'fixed56x120' | 'fixed56x128' | 'fixed56x136' | 'fixed56x144' | 'fixed56x152' | 'fixed56x160' | 'fixed56x168' | 'fixed56x176' | 'fixed56x184' | 'fixed56x192' | 'fixed56x200' | 'fixed64x8' | 'fixed64x16' | 'fixed64x24' | 'fixed64x32' | 'fixed64x40' | 'fixed64x48' | 'fixed64x56' | 'fixed64x64' | 'fixed64x72' | 'fixed64x80' | 'fixed64x88' | 'fixed64x96' | 'fixed64x104' | 'fixed64x112' | 'fixed64x120' | 'fixed64x128' | 'fixed64x136' | 'fixed64x144' | 'fixed64x152' | 'fixed64x160' | 'fixed64x168' | 'fixed64x176' | 'fixed64x184' | 'fixed64x192' | 'fixed72x8' | 'fixed72x16' | 'fixed72x24' | 'fixed72x32' | 'fixed72x40' | 'fixed72x48' | 'fixed72x56' | 'fixed72x64' | 'fixed72x72' | 'fixed72x80' | 'fixed72x88' | 'fixed72x96' | 'fixed72x104' | 'fixed72x112' | 'fixed72x120' | 'fixed72x128' | 'fixed72x136' | 'fixed72x144' | 'fixed72x152' | 'fixed72x160' | 'fixed72x168' | 'fixed72x176' | 'fixed72x184' | 'fixed80x8' | 'fixed80x16' | 'fixed80x24' | 'fixed80x32' | 'fixed80x40' | 'fixed80x48' | 'fixed80x56' | 'fixed80x64' | 'fixed80x72' | 'fixed80x80' | 'fixed80x88' | 'fixed80x96' | 'fixed80x104' | 'fixed80x112' | 'fixed80x120' | 'fixed80x128' | 'fixed80x136' | 'fixed80x144' | 'fixed80x152' | 'fixed80x160' | 'fixed80x168' | 'fixed80x176' | 'fixed88x8' | 'fixed88x16' | 'fixed88x24' | 'fixed88x32' | 'fixed88x40' | 'fixed88x48' | 'fixed88x56' | 'fixed88x64' | 'fixed88x72' | 'fixed88x80' | 'fixed88x88' | 'fixed88x96' | 'fixed88x104' | 'fixed88x112' | 'fixed88x120' | 'fixed88x128' | 'fixed88x136' | 'fixed88x144' | 'fixed88x152' | 'fixed88x160' | 'fixed88x168' | 'fixed96x8' | 'fixed96x16' | 'fixed96x24' | 'fixed96x32' | 'fixed96x40' | 'fixed96x48' | 'fixed96x56' | 'fixed96x64' | 'fixed96x72' | 'fixed96x80' | 'fixed96x88' | 'fixed96x96' | 'fixed96x104' | 'fixed96x112' | 'fixed96x120' | 'fixed96x128' | 'fixed96x136' | 'fixed96x144' | 'fixed96x152' | 'fixed96x160' | 'fixed104x8' | 'fixed104x16' | 'fixed104x24' | 'fixed104x32' | 'fixed104x40' | 'fixed104x48' | 'fixed104x56' | 'fixed104x64' | 'fixed104x72' | 'fixed104x80' | 'fixed104x88' | 'fixed104x96' | 'fixed104x104' | 'fixed104x112' | 'fixed104x120' | 'fixed104x128' | 'fixed104x136' | 'fixed104x144' | 'fixed104x152' | 'fixed112x8' | 'fixed112x16' | 'fixed112x24' | 'fixed112x32' | 'fixed112x40' | 'fixed112x48' | 'fixed112x56' | 'fixed112x64' | 'fixed112x72' | 'fixed112x80' | 'fixed112x88' | 'fixed112x96' | 'fixed112x104' | 'fixed112x112' | 'fixed112x120' | 'fixed112x128' | 'fixed112x136' | 'fixed112x144' | 'fixed120x8' | 'fixed120x16' | 'fixed120x24' | 'fixed120x32' | 'fixed120x40' | 'fixed120x48' | 'fixed120x56' | 'fixed120x64' | 'fixed120x72' | 'fixed120x80' | 'fixed120x88' | 'fixed120x96' | 'fixed120x104' | 'fixed120x112' | 'fixed120x120' | 'fixed120x128' | 'fixed120x136' | 'fixed128x8' | 'fixed128x16' | 'fixed128x24' | 'fixed128x32' | 'fixed128x40' | 'fixed128x48' | 'fixed128x56' | 'fixed128x64' | 'fixed128x72' | 'fixed128x80' | 'fixed128x88' | 'fixed128x96' | 'fixed128x104' | 'fixed128x112' | 'fixed128x120' | 'fixed128x128' | 'fixed136x8' | 'fixed136x16' | 'fixed136x24' | 'fixed136x32' | 'fixed136x40' | 'fixed136x48' | 'fixed136x56' | 'fixed136x64' | 'fixed136x72' | 'fixed136x80' | 'fixed136x88' | 'fixed136x96' | 'fixed136x104' | 'fixed136x112' | 'fixed136x120' | 'fixed144x8' | 'fixed144x16' | 'fixed144x24' | 'fixed144x32' | 'fixed144x40' | 'fixed144x48' | 'fixed144x56' | 'fixed144x64' | 'fixed144x72' | 'fixed144x80' | 'fixed144x88' | 'fixed144x96' | 'fixed144x104' | 'fixed144x112' | 'fixed152x8' | 'fixed152x16' | 'fixed152x24' | 'fixed152x32' | 'fixed152x40' | 'fixed152x48' | 'fixed152x56' | 'fixed152x64' | 'fixed152x72' | 'fixed152x80' | 'fixed152x88' | 'fixed152x96' | 'fixed152x104' | 'fixed160x8' | 'fixed160x16' | 'fixed160x24' | 'fixed160x32' | 'fixed160x40' | 'fixed160x48' | 'fixed160x56' | 'fixed160x64' | 'fixed160x72' | 'fixed160x80' | 'fixed160x88' | 'fixed160x96' | 'fixed168x8' | 'fixed168x16' | 'fixed168x24' | 'fixed168x32' | 'fixed168x40' | 'fixed168x48' | 'fixed168x56' | 'fixed168x64' | 'fixed168x72' | 'fixed168x80' | 'fixed168x88' | 'fixed176x8' | 'fixed176x16' | 'fixed176x24' | 'fixed176x32' | 'fixed176x40' | 'fixed176x48' | 'fixed176x56' | 'fixed176x64' | 'fixed176x72' | 'fixed176x80' | 'fixed184x8' | 'fixed184x16' | 'fixed184x24' | 'fixed184x32' | 'fixed184x40' | 'fixed184x48' | 'fixed184x56' | 'fixed184x64' | 'fixed184x72' | 'fixed192x8' | 'fixed192x16' | 'fixed192x24' | 'fixed192x32' | 'fixed192x40' | 'fixed192x48' | 'fixed192x56' | 'fixed192x64' | 'fixed200x8' | 'fixed200x16' | 'fixed200x24' | 'fixed200x32' | 'fixed200x40' | 'fixed200x48' | 'fixed200x56' | 'fixed208x8' | 'fixed208x16' | 'fixed208x24' | 'fixed208x32' | 'fixed208x40' | 'fixed208x48' | 'fixed216x8' | 'fixed216x16' | 'fixed216x24' | 'fixed216x32' | 'fixed216x40' | 'fixed224x8' | 'fixed224x16' | 'fixed224x24' | 'fixed224x32' | 'fixed232x8' | 'fixed232x16' | 'fixed232x24' | 'fixed240x8' | 'fixed240x16' | 'fixed248x8' Ufixed = 'ufixed' | 'ufixed0x8' | 'ufixed0x16' | 'ufixed0x24' | 'ufixed0x32' | 'ufixed0x40' | 'ufixed0x48' | 'ufixed0x56' | 'ufixed0x64' | 'ufixed0x72' | 'ufixed0x80' | 'ufixed0x88' | 'ufixed0x96' | 'ufixed0x104' | 'ufixed0x112' | 'ufixed0x120' | 'ufixed0x128' | 'ufixed0x136' | 'ufixed0x144' | 'ufixed0x152' | 'ufixed0x160' | 'ufixed0x168' | 'ufixed0x176' | 'ufixed0x184' | 'ufixed0x192' | 'ufixed0x200' | 'ufixed0x208' | 'ufixed0x216' | 'ufixed0x224' | 'ufixed0x232' | 'ufixed0x240' | 'ufixed0x248' | 'ufixed0x256' | 'ufixed8x8' | 'ufixed8x16' | 'ufixed8x24' | 'ufixed8x32' | 'ufixed8x40' | 'ufixed8x48' | 'ufixed8x56' | 'ufixed8x64' | 'ufixed8x72' | 'ufixed8x80' | 'ufixed8x88' | 'ufixed8x96' | 'ufixed8x104' | 'ufixed8x112' | 'ufixed8x120' | 'ufixed8x128' | 'ufixed8x136' | 'ufixed8x144' | 'ufixed8x152' | 'ufixed8x160' | 'ufixed8x168' | 'ufixed8x176' | 'ufixed8x184' | 'ufixed8x192' | 'ufixed8x200' | 'ufixed8x208' | 'ufixed8x216' | 'ufixed8x224' | 'ufixed8x232' | 'ufixed8x240' | 'ufixed8x248' | 'ufixed16x8' | 'ufixed16x16' | 'ufixed16x24' | 'ufixed16x32' | 'ufixed16x40' | 'ufixed16x48' | 'ufixed16x56' | 'ufixed16x64' | 'ufixed16x72' | 'ufixed16x80' | 'ufixed16x88' | 'ufixed16x96' | 'ufixed16x104' | 'ufixed16x112' | 'ufixed16x120' | 'ufixed16x128' | 'ufixed16x136' | 'ufixed16x144' | 'ufixed16x152' | 'ufixed16x160' | 'ufixed16x168' | 'ufixed16x176' | 'ufixed16x184' | 'ufixed16x192' | 'ufixed16x200' | 'ufixed16x208' | 'ufixed16x216' | 'ufixed16x224' | 'ufixed16x232' | 'ufixed16x240' | 'ufixed24x8' | 'ufixed24x16' | 'ufixed24x24' | 'ufixed24x32' | 'ufixed24x40' | 'ufixed24x48' | 'ufixed24x56' | 'ufixed24x64' | 'ufixed24x72' | 'ufixed24x80' | 'ufixed24x88' | 'ufixed24x96' | 'ufixed24x104' | 'ufixed24x112' | 'ufixed24x120' | 'ufixed24x128' | 'ufixed24x136' | 'ufixed24x144' | 'ufixed24x152' | 'ufixed24x160' | 'ufixed24x168' | 'ufixed24x176' | 'ufixed24x184' | 'ufixed24x192' | 'ufixed24x200' | 'ufixed24x208' | 'ufixed24x216' | 'ufixed24x224' | 'ufixed24x232' | 'ufixed32x8' | 'ufixed32x16' | 'ufixed32x24' | 'ufixed32x32' | 'ufixed32x40' | 'ufixed32x48' | 'ufixed32x56' | 'ufixed32x64' | 'ufixed32x72' | 'ufixed32x80' | 'ufixed32x88' | 'ufixed32x96' | 'ufixed32x104' | 'ufixed32x112' | 'ufixed32x120' | 'ufixed32x128' | 'ufixed32x136' | 'ufixed32x144' | 'ufixed32x152' | 'ufixed32x160' | 'ufixed32x168' | 'ufixed32x176' | 'ufixed32x184' | 'ufixed32x192' | 'ufixed32x200' | 'ufixed32x208' | 'ufixed32x216' | 'ufixed32x224' | 'ufixed40x8' | 'ufixed40x16' | 'ufixed40x24' | 'ufixed40x32' | 'ufixed40x40' | 'ufixed40x48' | 'ufixed40x56' | 'ufixed40x64' | 'ufixed40x72' | 'ufixed40x80' | 'ufixed40x88' | 'ufixed40x96' | 'ufixed40x104' | 'ufixed40x112' | 'ufixed40x120' | 'ufixed40x128' | 'ufixed40x136' | 'ufixed40x144' | 'ufixed40x152' | 'ufixed40x160' | 'ufixed40x168' | 'ufixed40x176' | 'ufixed40x184' | 'ufixed40x192' | 'ufixed40x200' | 'ufixed40x208' | 'ufixed40x216' | 'ufixed48x8' | 'ufixed48x16' | 'ufixed48x24' | 'ufixed48x32' | 'ufixed48x40' | 'ufixed48x48' | 'ufixed48x56' | 'ufixed48x64' | 'ufixed48x72' | 'ufixed48x80' | 'ufixed48x88' | 'ufixed48x96' | 'ufixed48x104' | 'ufixed48x112' | 'ufixed48x120' | 'ufixed48x128' | 'ufixed48x136' | 'ufixed48x144' | 'ufixed48x152' | 'ufixed48x160' | 'ufixed48x168' | 'ufixed48x176' | 'ufixed48x184' | 'ufixed48x192' | 'ufixed48x200' | 'ufixed48x208' | 'ufixed56x8' | 'ufixed56x16' | 'ufixed56x24' | 'ufixed56x32' | 'ufixed56x40' | 'ufixed56x48' | 'ufixed56x56' | 'ufixed56x64' | 'ufixed56x72' | 'ufixed56x80' | 'ufixed56x88' | 'ufixed56x96' | 'ufixed56x104' | 'ufixed56x112' | 'ufixed56x120' | 'ufixed56x128' | 'ufixed56x136' | 'ufixed56x144' | 'ufixed56x152' | 'ufixed56x160' | 'ufixed56x168' | 'ufixed56x176' | 'ufixed56x184' | 'ufixed56x192' | 'ufixed56x200' | 'ufixed64x8' | 'ufixed64x16' | 'ufixed64x24' | 'ufixed64x32' | 'ufixed64x40' | 'ufixed64x48' | 'ufixed64x56' | 'ufixed64x64' | 'ufixed64x72' | 'ufixed64x80' | 'ufixed64x88' | 'ufixed64x96' | 'ufixed64x104' | 'ufixed64x112' | 'ufixed64x120' | 'ufixed64x128' | 'ufixed64x136' | 'ufixed64x144' | 'ufixed64x152' | 'ufixed64x160' | 'ufixed64x168' | 'ufixed64x176' | 'ufixed64x184' | 'ufixed64x192' | 'ufixed72x8' | 'ufixed72x16' | 'ufixed72x24' | 'ufixed72x32' | 'ufixed72x40' | 'ufixed72x48' | 'ufixed72x56' | 'ufixed72x64' | 'ufixed72x72' | 'ufixed72x80' | 'ufixed72x88' | 'ufixed72x96' | 'ufixed72x104' | 'ufixed72x112' | 'ufixed72x120' | 'ufixed72x128' | 'ufixed72x136' | 'ufixed72x144' | 'ufixed72x152' | 'ufixed72x160' | 'ufixed72x168' | 'ufixed72x176' | 'ufixed72x184' | 'ufixed80x8' | 'ufixed80x16' | 'ufixed80x24' | 'ufixed80x32' | 'ufixed80x40' | 'ufixed80x48' | 'ufixed80x56' | 'ufixed80x64' | 'ufixed80x72' | 'ufixed80x80' | 'ufixed80x88' | 'ufixed80x96' | 'ufixed80x104' | 'ufixed80x112' | 'ufixed80x120' | 'ufixed80x128' | 'ufixed80x136' | 'ufixed80x144' | 'ufixed80x152' | 'ufixed80x160' | 'ufixed80x168' | 'ufixed80x176' | 'ufixed88x8' | 'ufixed88x16' | 'ufixed88x24' | 'ufixed88x32' | 'ufixed88x40' | 'ufixed88x48' | 'ufixed88x56' | 'ufixed88x64' | 'ufixed88x72' | 'ufixed88x80' | 'ufixed88x88' | 'ufixed88x96' | 'ufixed88x104' | 'ufixed88x112' | 'ufixed88x120' | 'ufixed88x128' | 'ufixed88x136' | 'ufixed88x144' | 'ufixed88x152' | 'ufixed88x160' | 'ufixed88x168' | 'ufixed96x8' | 'ufixed96x16' | 'ufixed96x24' | 'ufixed96x32' | 'ufixed96x40' | 'ufixed96x48' | 'ufixed96x56' | 'ufixed96x64' | 'ufixed96x72' | 'ufixed96x80' | 'ufixed96x88' | 'ufixed96x96' | 'ufixed96x104' | 'ufixed96x112' | 'ufixed96x120' | 'ufixed96x128' | 'ufixed96x136' | 'ufixed96x144' | 'ufixed96x152' | 'ufixed96x160' | 'ufixed104x8' | 'ufixed104x16' | 'ufixed104x24' | 'ufixed104x32' | 'ufixed104x40' | 'ufixed104x48' | 'ufixed104x56' | 'ufixed104x64' | 'ufixed104x72' | 'ufixed104x80' | 'ufixed104x88' | 'ufixed104x96' | 'ufixed104x104' | 'ufixed104x112' | 'ufixed104x120' | 'ufixed104x128' | 'ufixed104x136' | 'ufixed104x144' | 'ufixed104x152' | 'ufixed112x8' | 'ufixed112x16' | 'ufixed112x24' | 'ufixed112x32' | 'ufixed112x40' | 'ufixed112x48' | 'ufixed112x56' | 'ufixed112x64' | 'ufixed112x72' | 'ufixed112x80' | 'ufixed112x88' | 'ufixed112x96' | 'ufixed112x104' | 'ufixed112x112' | 'ufixed112x120' | 'ufixed112x128' | 'ufixed112x136' | 'ufixed112x144' | 'ufixed120x8' | 'ufixed120x16' | 'ufixed120x24' | 'ufixed120x32' | 'ufixed120x40' | 'ufixed120x48' | 'ufixed120x56' | 'ufixed120x64' | 'ufixed120x72' | 'ufixed120x80' | 'ufixed120x88' | 'ufixed120x96' | 'ufixed120x104' | 'ufixed120x112' | 'ufixed120x120' | 'ufixed120x128' | 'ufixed120x136' | 'ufixed128x8' | 'ufixed128x16' | 'ufixed128x24' | 'ufixed128x32' | 'ufixed128x40' | 'ufixed128x48' | 'ufixed128x56' | 'ufixed128x64' | 'ufixed128x72' | 'ufixed128x80' | 'ufixed128x88' | 'ufixed128x96' | 'ufixed128x104' | 'ufixed128x112' | 'ufixed128x120' | 'ufixed128x128' | 'ufixed136x8' | 'ufixed136x16' | 'ufixed136x24' | 'ufixed136x32' | 'ufixed136x40' | 'ufixed136x48' | 'ufixed136x56' | 'ufixed136x64' | 'ufixed136x72' | 'ufixed136x80' | 'ufixed136x88' | 'ufixed136x96' | 'ufixed136x104' | 'ufixed136x112' | 'ufixed136x120' | 'ufixed144x8' | 'ufixed144x16' | 'ufixed144x24' | 'ufixed144x32' | 'ufixed144x40' | 'ufixed144x48' | 'ufixed144x56' | 'ufixed144x64' | 'ufixed144x72' | 'ufixed144x80' | 'ufixed144x88' | 'ufixed144x96' | 'ufixed144x104' | 'ufixed144x112' | 'ufixed152x8' | 'ufixed152x16' | 'ufixed152x24' | 'ufixed152x32' | 'ufixed152x40' | 'ufixed152x48' | 'ufixed152x56' | 'ufixed152x64' | 'ufixed152x72' | 'ufixed152x80' | 'ufixed152x88' | 'ufixed152x96' | 'ufixed152x104' | 'ufixed160x8' | 'ufixed160x16' | 'ufixed160x24' | 'ufixed160x32' | 'ufixed160x40' | 'ufixed160x48' | 'ufixed160x56' | 'ufixed160x64' | 'ufixed160x72' | 'ufixed160x80' | 'ufixed160x88' | 'ufixed160x96' | 'ufixed168x8' | 'ufixed168x16' | 'ufixed168x24' | 'ufixed168x32' | 'ufixed168x40' | 'ufixed168x48' | 'ufixed168x56' | 'ufixed168x64' | 'ufixed168x72' | 'ufixed168x80' | 'ufixed168x88' | 'ufixed176x8' | 'ufixed176x16' | 'ufixed176x24' | 'ufixed176x32' | 'ufixed176x40' | 'ufixed176x48' | 'ufixed176x56' | 'ufixed176x64' | 'ufixed176x72' | 'ufixed176x80' | 'ufixed184x8' | 'ufixed184x16' | 'ufixed184x24' | 'ufixed184x32' | 'ufixed184x40' | 'ufixed184x48' | 'ufixed184x56' | 'ufixed184x64' | 'ufixed184x72' | 'ufixed192x8' | 'ufixed192x16' | 'ufixed192x24' | 'ufixed192x32' | 'ufixed192x40' | 'ufixed192x48' | 'ufixed192x56' | 'ufixed192x64' | 'ufixed200x8' | 'ufixed200x16' | 'ufixed200x24' | 'ufixed200x32' | 'ufixed200x40' | 'ufixed200x48' | 'ufixed200x56' | 'ufixed208x8' | 'ufixed208x16' | 'ufixed208x24' | 'ufixed208x32' | 'ufixed208x40' | 'ufixed208x48' | 'ufixed216x8' | 'ufixed216x16' | 'ufixed216x24' | 'ufixed216x32' | 'ufixed216x40' | 'ufixed224x8' | 'ufixed224x16' | 'ufixed224x24' | 'ufixed224x32' | 'ufixed232x8' | 'ufixed232x16' | 'ufixed232x24' | 'ufixed240x8' | 'ufixed240x16' | 'ufixed248x8' + +InlineAssemblyBlock = '{' AssemblyItem* '}' + +AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | Identifier | NumberLiteral | StringLiteral | HexLiteral +AssemblyLocalBinding = 'let' Identifier ':=' FunctionalAssemblyExpression +AssemblyAssignment = Identifier ':=' FunctionalAssemblyExpression | '=:' Identifier +FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')' From 86d54c02cdebba32a6a8fba1d74bad17667d46cd Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 2 Dec 2016 13:18:39 +0000 Subject: [PATCH 135/185] Throw if calling the identity precompile (memoryCopy) failed --- Changelog.md | 1 + libsolidity/codegen/CompilerUtils.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 1058fdf5a..58cf14843 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Features: * Optimizer: Some dead code elimination. Bugfixes: + * Code generator: throw if calling the identity precompile failed during memory (array) copying. * Type checker: string literals that are not valid UTF-8 cannot be converted to string type ### 0.4.6 (2016-11-22) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index d5361ac6a..a82996261 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -312,7 +312,8 @@ void CompilerUtils::memoryCopy() m_context << Instruction::DIV << u256(c_identityWordGas) << Instruction::MUL; m_context << u256(c_identityGas) << Instruction::ADD; m_context << Instruction::CALL; - m_context << Instruction::POP; // ignore return value + m_context << Instruction::ISZERO; + m_context.appendConditionalJumpTo(m_context.errorTag()); } void CompilerUtils::splitExternalFunctionType(bool _leftAligned) From 70d246c834658cc87bdd1ff674d263ef76bd950c Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Sat, 3 Dec 2016 17:52:51 -0300 Subject: [PATCH 136/185] Migrate remaining source code in tests to R literals --- test/libsolidity/SolidityABIJSON.cpp | 114 ++- .../SolidityExpressionCompiler.cpp | 126 +-- .../SolidityNameAndTypeResolution.cpp | 820 ++++++++++-------- test/libsolidity/SolidityNatspecJSON.cpp | 342 ++++---- 4 files changed, 810 insertions(+), 592 deletions(-) diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index 890db241b..043d74ed4 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -63,9 +63,11 @@ BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, JSONInterfaceChecker) BOOST_AUTO_TEST_CASE(basic_test) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + } + )"; char const* interface = R"([ { @@ -93,8 +95,9 @@ BOOST_AUTO_TEST_CASE(basic_test) BOOST_AUTO_TEST_CASE(empty_contract) { - char const* sourceCode = "contract test {\n" - "}\n"; + char const* sourceCode = R"( + contract test { } + )"; char const* interface = "[]"; checkInterface(sourceCode, interface); @@ -102,10 +105,12 @@ BOOST_AUTO_TEST_CASE(empty_contract) BOOST_AUTO_TEST_CASE(multiple_methods) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - " function g(uint b) returns(uint e) { return b * 8; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + function g(uint b) returns(uint e) { return b * 8; } + } + )"; char const* interface = R"([ { @@ -151,9 +156,11 @@ BOOST_AUTO_TEST_CASE(multiple_methods) BOOST_AUTO_TEST_CASE(multiple_params) { - char const* sourceCode = "contract test {\n" - " function f(uint a, uint b) returns(uint d) { return a + b; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a, uint b) returns(uint d) { return a + b; } + } + )"; char const* interface = R"([ { @@ -186,10 +193,12 @@ BOOST_AUTO_TEST_CASE(multiple_params) BOOST_AUTO_TEST_CASE(multiple_methods_order) { // methods are expected to be in alpabetical order - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - " function c(uint b) returns(uint e) { return b * 8; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + function c(uint b) returns(uint e) { return b * 8; } + } + )"; char const* interface = R"([ { @@ -235,10 +244,12 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) BOOST_AUTO_TEST_CASE(const_function) { - char const* sourceCode = "contract test {\n" - " function foo(uint a, uint b) returns(uint d) { return a + b; }\n" - " function boo(uint32 a) constant returns(uint b) { return a * 4; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function foo(uint a, uint b) returns(uint d) { return a + b; } + function boo(uint32 a) constant returns(uint b) { return a * 4; } + } + )"; char const* interface = R"([ { @@ -286,11 +297,13 @@ BOOST_AUTO_TEST_CASE(const_function) BOOST_AUTO_TEST_CASE(events) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - " event e1(uint b, address indexed c); \n" - " event e2(); \n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + event e1(uint b, address indexed c); + event e2(); + } + )"; char const* interface = R"([ { "name": "f", @@ -341,9 +354,11 @@ BOOST_AUTO_TEST_CASE(events) BOOST_AUTO_TEST_CASE(events_anonymous) { - char const* sourceCode = "contract test {\n" - " event e() anonymous; \n" - "}\n"; + char const* sourceCode = R"( + contract test { + event e() anonymous; + } + )"; char const* interface = R"([ { "name": "e", @@ -359,15 +374,16 @@ BOOST_AUTO_TEST_CASE(events_anonymous) BOOST_AUTO_TEST_CASE(inherited) { - char const* sourceCode = - " contract Base { \n" - " function baseFunction(uint p) returns (uint i) { return p; } \n" - " event baseEvent(bytes32 indexed evtArgBase); \n" - " } \n" - " contract Derived is Base { \n" - " function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } \n" - " event derivedEvent(uint indexed evtArgDerived); \n" - " }"; + char const* sourceCode = R"( + contract Base { + function baseFunction(uint p) returns (uint i) { return p; } + event baseEvent(bytes32 indexed evtArgBase); + } + contract Derived is Base { + function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } + event derivedEvent(uint indexed evtArgDerived); + } + )"; char const* interface = R"([ { @@ -431,13 +447,14 @@ BOOST_AUTO_TEST_CASE(inherited) BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* sourceCode = R"( - contract test { - function f(uint, uint k) returns(uint ret_k, uint ret_g){ - uint g = 8; - ret_k = k; - ret_g = g; + contract test { + function f(uint, uint k) returns(uint ret_k, uint ret_g) { + uint g = 8; + ret_k = k; + ret_g = g; + } } - })"; + )"; char const* interface = R"([ { @@ -475,10 +492,11 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) { char const* sourceCode = R"( contract test { - function f(uint k) returns(uint){ - return k; + function f(uint k) returns(uint) { + return k; + } } - })"; + )"; char const* interface = R"([ { @@ -542,7 +560,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) contract test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } function test(ActionChoices param) {} - function ret() returns(ActionChoices){ + function ret() returns(ActionChoices) { ActionChoices action = ActionChoices.GoLeft; return action; } @@ -612,7 +630,7 @@ BOOST_AUTO_TEST_CASE(library_function) char const* sourceCode = R"( library test { struct StructType { uint a; } - function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f){} + function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f) {} } )"; diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index cab9f09fc..0c5a09c3e 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -168,9 +168,11 @@ BOOST_AUTO_TEST_SUITE(SolidityExpressionCompiler) BOOST_AUTO_TEST_CASE(literal_true) { - char const* sourceCode = "contract test {\n" - " function f() { var x = true; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = true; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x1}); @@ -179,9 +181,11 @@ BOOST_AUTO_TEST_CASE(literal_true) BOOST_AUTO_TEST_CASE(literal_false) { - char const* sourceCode = "contract test {\n" - " function f() { var x = false; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = false; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x0}); @@ -190,9 +194,11 @@ BOOST_AUTO_TEST_CASE(literal_false) BOOST_AUTO_TEST_CASE(int_literal) { - char const* sourceCode = "contract test {\n" - " function f() { var x = 0x12345678901234567890; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = 0x12345678901234567890; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, @@ -204,11 +210,11 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () - { + function test () { var x = 1 wei; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x1}); @@ -219,11 +225,11 @@ BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () - { + function test () { var x = 1 szabo; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00}); @@ -249,11 +255,11 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () - { + function test () { var x = 1 ether; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}); @@ -262,9 +268,11 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination) BOOST_AUTO_TEST_CASE(comparison) { - char const* sourceCode = "contract test {\n" - " function f() { var x = (0x10aa < 0x11aa) != true; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = (0x10aa < 0x11aa) != true; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x1, byte(Instruction::ISZERO), byte(Instruction::ISZERO), @@ -278,9 +286,11 @@ BOOST_AUTO_TEST_CASE(comparison) BOOST_AUTO_TEST_CASE(short_circuiting) { - char const* sourceCode = "contract test {\n" - " function f() { var x = true != (4 <= 8 + 10 || 9 != 2); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = true != (4 <= 8 + 10 || 9 != 2); } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x12, // 8 + 10 @@ -305,9 +315,11 @@ BOOST_AUTO_TEST_CASE(short_circuiting) BOOST_AUTO_TEST_CASE(arithmetics) { - char const* sourceCode = "contract test {\n" - " function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}}); bytes expectation({byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0x2, @@ -339,9 +351,11 @@ BOOST_AUTO_TEST_CASE(arithmetics) BOOST_AUTO_TEST_CASE(unary_operators) { - char const* sourceCode = "contract test {\n" - " function f(int y) { var x = !(~+- y == 2); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(int y) { var x = !(~+- y == 2); } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}}); bytes expectation({byte(Instruction::PUSH1), 0x2, @@ -356,9 +370,11 @@ BOOST_AUTO_TEST_CASE(unary_operators) BOOST_AUTO_TEST_CASE(unary_inc_dec) { - char const* sourceCode = "contract test {\n" - " function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}}); // Stack: a, x @@ -406,9 +422,11 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec) BOOST_AUTO_TEST_CASE(assignment) { - char const* sourceCode = "contract test {\n" - " function f(uint a, uint b) { (a += b) * 2; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a, uint b) { (a += b) * 2; } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}}); // Stack: a, b @@ -427,9 +445,11 @@ BOOST_AUTO_TEST_CASE(assignment) BOOST_AUTO_TEST_CASE(negative_literals_8bits) { - char const* sourceCode = "contract test {\n" - " function f() { int8 x = -0x80; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { int8 x = -0x80; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80)); @@ -438,9 +458,11 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits) BOOST_AUTO_TEST_CASE(negative_literals_16bits) { - char const* sourceCode = "contract test {\n" - " function f() { int64 x = ~0xabc; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { int64 x = ~0xabc; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43}); @@ -451,9 +473,11 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) { // first literal itself is too large for 256 bits but it fits after all constant operations // have been applied - char const* sourceCode = "contract test {\n" - " function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation(bytes({byte(Instruction::PUSH1), 0xbf})); @@ -462,11 +486,13 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) BOOST_AUTO_TEST_CASE(blockhash) { - char const* sourceCode = "contract test {\n" - " function f() {\n" - " block.blockhash(3);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { + block.blockhash(3); + } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {}, {make_shared("block", make_shared(MagicType::Kind::Block))}); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 627aaa2fb..cf0d41dd7 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -187,98 +187,123 @@ BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) BOOST_AUTO_TEST_CASE(smoke_test) { - char const* text = "contract test {\n" - " uint256 stateVariable1;\n" - " function fun(uint256 arg1) { uint256 y; }" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVariable1; + function fun(uint256 arg1) { uint256 y; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " uint128 variable;\n" - "}\n"; + char const* text = R"( + contract test { + uint256 variable; + uint128 variable; + } + )"; CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(double_function_declaration) { - char const* text = "contract test {\n" - " function fun() { uint x; }\n" - " function fun() { uint x; }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { uint x; } + function fun() { uint x; } + } + )"; CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(double_variable_declaration) { - char const* text = "contract test {\n" - " function f() { uint256 x; if (true) { uint256 x; } }\n" - "}\n"; + char const* text = R"( + contract test { + function f() { + uint256 x; + if (true) { uint256 x; } + } + } + )"; CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(name_shadowing) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " function f() { uint32 variable ; }" - "}\n"; + char const* text = R"( + contract test { + uint256 variable; + function f() { uint32 variable; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(name_references) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " function f(uint256 arg) returns (uint out) { f(variable); test; out; }" - "}\n"; + char const* text = R"( + contract test { + uint256 variable; + function f(uint256 arg) returns (uint out) { f(variable); test; out; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(undeclared_name) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " function f(uint256 arg) { f(notfound); }" - "}\n"; + char const* text = R"( + contract test { + uint256 variable; + function f(uint256 arg) { + f(notfound); + } + } + )"; CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(reference_to_later_declaration) { - char const* text = "contract test {\n" - " function g() { f(); }" - " function f() { }" - "}\n"; + char const* text = R"( + contract test { + function g() { f(); } + function f() {} + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) { - char const* text = "contract test {\n" - " struct MyStructName {\n" - " address addr;\n" - " MyStructName x;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct MyStructName { + address addr; + MyStructName x; + } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) { - char const* text = "contract test {\n" - " struct MyStructName1 {\n" - " address addr;\n" - " uint256 count;\n" - " MyStructName2 x;\n" - " }\n" - " struct MyStructName2 {\n" - " MyStructName1 x;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2 x; + } + struct MyStructName2 { + MyStructName1 x; + } + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -295,179 +320,216 @@ BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) { - char const* text = "contract test {\n" - " struct MyStructName1 {\n" - " address addr;\n" - " uint256 count;\n" - " mapping(uint => MyStructName1) x;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct MyStructName1 { + address addr; + uint256 count; + mapping(uint => MyStructName1) x; + } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_inference_smoke_test) { - char const* text = "contract test {\n" - " function f(uint256 arg1, uint32 arg2) returns (bool ret) { var x = arg1 + arg2 == 8; ret = x; }" - "}\n"; + char const* text = R"( + contract test { + function f(uint256 arg1, uint32 arg2) returns (bool ret) { + var x = arg1 + arg2 == 8; ret = x; + } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_checking_return) { - char const* text = "contract test {\n" - " function f() returns (bool r) { return 1 >= 2; }" - "}\n"; + char const* text = R"( + contract test { + function f() returns (bool r) { return 1 >= 2; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number) { - char const* text = "contract test {\n" - " function f() returns (bool r1, bool r2) { return 1 >= 2; }" - "}\n"; + char const* text = R"( + contract test { + function f() returns (bool r1, bool r2) { return 1 >= 2; } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) { - char const* text = "contract test {\n" - " function f() returns (uint256 r) { return 1 >= 2; }" - "}\n"; + char const* text = R"( + contract test { + function f() returns (uint256 r) { return 1 >= 2; } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_checking_function_call) { - char const* text = "contract test {\n" - " function f() returns (bool r) { return g(12, true) == 3; }\n" - " function g(uint256 a, bool b) returns (uint256 r) { }\n" - "}\n"; + char const* text = R"( + contract test { + function f() returns (bool r) { return g(12, true) == 3; } + function g(uint256 a, bool b) returns (uint256 r) { } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_conversion_for_comparison) { - char const* text = "contract test {\n" - " function f() { uint32(2) == int64(2); }" - "}\n"; + char const* text = R"( + contract test { + function f() { uint32(2) == int64(2); } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid) { - char const* text = "contract test {\n" - " function f() { int32(2) == uint64(2); }" - "}\n"; + char const* text = R"( + contract test { + function f() { int32(2) == uint64(2); } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) { - char const* text = "contract test {\n" - " function f() returns (int256 r) { var x = int256(uint32(2)); return x; }" - "}\n"; + char const* text = R"( + contract test { + function f() returns (int256 r) { var x = int256(uint32(2)); return x; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(large_string_literal) { - char const* text = "contract test {\n" - " function f() { var x = \"123456789012345678901234567890123\"; }" - "}\n"; + char const* text = R"( + contract test { + function f() { var x = "123456789012345678901234567890123"; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(balance) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint256 x = address(0).balance;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint256 x = address(0).balance; + } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(balance_invalid) { - char const* text = "contract test {\n" - " function fun() {\n" - " address(0).balance = 7;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + address(0).balance = 7; + } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_to_mapping) { - char const* text = "contract test {\n" - " struct str {\n" - " mapping(uint=>uint) map;\n" - " }\n" - " str data;" - " function fun() {\n" - " var a = data.map;\n" - " data.map = a;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() { + var a = data.map; + data.map = a; + } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_to_struct) { - char const* text = "contract test {\n" - " struct str {\n" - " mapping(uint=>uint) map;\n" - " }\n" - " str data;" - " function fun() {\n" - " var a = data;\n" - " data = a;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() { + var a = data; + data = a; + } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(returns_in_constructor) { - char const* text = "contract test {\n" - " function test() returns (uint a) {\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function test() returns (uint a) { } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(forward_function_reference) { - char const* text = "contract First {\n" - " function fun() returns (bool ret) {\n" - " return Second(1).fun(1, true, 3) > 0;\n" - " }\n" - "}\n" - "contract Second {\n" - " function fun(uint a, bool b, uint c) returns (uint ret) {\n" - " if (First(2).fun() == true) return 1;\n" - " }\n" - "}\n"; + char const* text = R"( + contract First { + function fun() returns (bool ret) { + return Second(1).fun(1, true, 3) > 0; + } + } + contract Second { + function fun(uint a, bool b, uint c) returns (uint ret) { + if (First(2).fun() == true) return 1; + } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) { - char const* text = "contract First {\n" - " function fun() returns (bool ret) {\n" - " return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6;\n" - " }\n" - "}\n"; + char const* text = R"( + contract First { + function fun() returns (bool ret) { + return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6; + } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_no_implementation) { ASTPointer sourceUnit; - char const* text = "contract test {\n" - " function functionName(bytes32 input) returns (bytes32 out);\n" - "}\n"; + char const* text = R"( + contract test { + function functionName(bytes32 input) returns (bytes32 out); + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); std::vector> nodes = sourceUnit->nodes(); ContractDefinition* contract = dynamic_cast(nodes[1].get()); @@ -482,7 +544,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract) char const* text = R"( contract base { function foo(); } contract derived is base { function foo() {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); std::vector> nodes = sourceUnit->nodes(); ContractDefinition* base = dynamic_cast(nodes[1].get()); @@ -501,7 +563,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload) char const* text = R"( contract base { function foo(bool); } contract derived is base { function foo(uint) {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); std::vector> nodes = sourceUnit->nodes(); ContractDefinition* base = dynamic_cast(nodes[1].get()); @@ -519,9 +581,9 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) contract base { function foo(); } contract derived { base b; - function foo() { b = new base();} - } - )"; + function foo() { b = new base(); } + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -535,7 +597,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional) function derived(uint i) BaseBase(i){} function foo() {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Parsing and name resolving failed"); } @@ -549,7 +611,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided) function derived(uint i) {} function foo() {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name resolving failed"); std::vector> nodes = sourceUnit->nodes(); BOOST_CHECK_EQUAL(nodes.size(), 4); @@ -565,7 +627,7 @@ BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) contract base { function foo(); } contract derived is base { function foo() {} } contract wrong is derived { function foo(); } - )"; + )"; CHECK_ERROR(text, TypeError, ""); } @@ -587,11 +649,13 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) BOOST_AUTO_TEST_CASE(function_canonical_signature) { ASTPointer sourceUnit; - char const* text = "contract Test {\n" - " function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) {\n" - " ret = arg1 + arg2;\n" - " }\n" - "}\n"; + char const* text = R"( + contract Test { + function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) { + ret = arg1 + arg2; + } + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) @@ -604,11 +668,13 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature) BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) { ASTPointer sourceUnit; - char const* text = "contract Test {\n" - " function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) {\n" - " ret = 5;\n" - " }\n" - "}\n"; + char const* text = R"( + contract Test { + function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) { + ret = 5; + } + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) @@ -629,9 +695,10 @@ BOOST_AUTO_TEST_CASE(function_external_types) } contract Test { function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg, address[] addresses) external returns (uint ret) { - ret = 5; + ret = 5; } - })"; + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) @@ -653,7 +720,8 @@ BOOST_AUTO_TEST_CASE(enum_external_type) function boo(ActionChoices enumArg) external returns (uint ret) { ret = 5; } - })"; + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast(node.get())) @@ -670,12 +738,13 @@ BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion) char const* text = R"( contract C {} contract Test { - function externalCall() { + function externalCall() { C arg; this.g(arg); } function g (C c) external {} - })"; + } + )"; CHECK_SUCCESS(text); } @@ -684,12 +753,13 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) char const* text = R"( contract C {} contract Test { - function externalCall() { + function externalCall() { address arg; this.g(arg); } function g (C c) external {} - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -705,7 +775,8 @@ BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) function internalCall() { g(a); } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -721,18 +792,19 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) function internalCall() { g(a); } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(hash_collision_in_interface) { - char const* text = "contract test {\n" - " function gsf() {\n" - " }\n" - " function tgeo() {\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function gsf() { } + function tgeo() { } + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -989,14 +1061,16 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value) BOOST_AUTO_TEST_CASE(state_variable_accessors) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "uint256 public foo;\n" - "mapping(uint=>bytes4) public map;\n" - "mapping(uint=>mapping(uint=>bytes4)) public multiple_map;\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + uint256 public foo; + mapping(uint=>bytes4) public map; + mapping(uint=>mapping(uint=>bytes4)) public multiple_map; + } + )"; ASTPointer source; ContractDefinition const* contract; @@ -1028,25 +1102,29 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "uint256 foo;\n" - " function foo() {}\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + uint256 foo; + function foo() {} + } + )"; CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(private_state_variable) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "uint256 private foo;\n" - "uint256 internal bar;\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + uint256 private foo; + uint256 internal bar; + } + )"; ASTPointer source; ContractDefinition const* contract; @@ -1075,12 +1153,14 @@ BOOST_AUTO_TEST_CASE(missing_state_variable) BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor) { // test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126 - char const* text = "contract Parent {\n" - " uint256 public m_aMember;\n" - "}\n" - "contract Child is Parent{\n" - " function foo() returns (uint256) { return Parent.m_aMember; }\n" - "}\n"; + char const* text = R"( + contract Parent { + uint256 public m_aMember; + } + contract Child is Parent { + function foo() returns (uint256) { return Parent.m_aMember; } + } + )"; CHECK_SUCCESS(text); } @@ -1088,7 +1168,7 @@ BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) { char const* sourceCode = R"( contract test { - struct Data { uint[15] m_array; } + struct Data { uint[15] m_array; } Data public data; } )"; @@ -1097,41 +1177,47 @@ BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member) { - char const* text = "contract Parent {\n" - " uint256 internal m_aMember;\n" - "}\n" - "contract Child is Parent{\n" - " function foo() returns (uint256) { return Parent.m_aMember; }\n" - "}\n"; + char const* text = R"( + contract Parent { + uint256 internal m_aMember; + } + contract Child is Parent{ + function foo() returns (uint256) { return Parent.m_aMember; } + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1) { - char const* text = "contract Parent1 {\n" - " uint256 internal m_aMember1;\n" - "}\n" - "contract Parent2 is Parent1{\n" - " uint256 internal m_aMember2;\n" - "}\n" - "contract Child is Parent2{\n" - " function foo() returns (uint256) { return Parent2.m_aMember1; }\n" - "}\n"; + char const* text = R"( + contract Parent1 { + uint256 internal m_aMember1; + } + contract Parent2 is Parent1{ + uint256 internal m_aMember2; + } + contract Child is Parent2{ + function foo() returns (uint256) { return Parent2.m_aMember1; } + } + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) { - char const* text = "contract Parent1 {\n" - " uint256 internal m_aMember1;\n" - "}\n" - "contract Parent2 is Parent1{\n" - " uint256 internal m_aMember2;\n" - "}\n" - "contract Child is Parent2{\n" - " function foo() returns (uint256) { return Child.m_aMember2; }\n" - " uint256 public m_aMember3;\n" - "}\n"; + char const* text = R"( + contract Parent1 { + uint256 internal m_aMember1; + } + contract Parent2 is Parent1 { + uint256 internal m_aMember2; + } + contract Child is Parent2 { + function foo() returns (uint256) { return Child.m_aMember2; } + uint256 public m_aMember3; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1220,7 +1306,8 @@ BOOST_AUTO_TEST_CASE(event) contract c { event e(uint indexed a, bytes3 indexed s, bool indexed b); function f() { e(2, "abc", true); } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1229,7 +1316,8 @@ BOOST_AUTO_TEST_CASE(event_too_many_indexed) char const* text = R"( contract c { event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d); - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1238,7 +1326,8 @@ BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) char const* text = R"( contract c { event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d) anonymous; - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1247,7 +1336,8 @@ BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed) char const* text = R"( contract c { event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous; - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1257,7 +1347,8 @@ BOOST_AUTO_TEST_CASE(event_call) contract c { event e(uint a, bytes3 indexed s, bool indexed b); function f() { e(2, "abc", true); } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1269,7 +1360,8 @@ BOOST_AUTO_TEST_CASE(event_inheritance) } contract c is base { function f() { e(2, "abc", true); } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1279,7 +1371,8 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash) contract c { event e1(uint a, uint e1, uint e2); event e2(uint a, uint e1, uint e2); - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1291,7 +1384,8 @@ BOOST_AUTO_TEST_CASE(access_to_default_function_visibility) } contract d { function g() { c(0).f(); } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1303,7 +1397,8 @@ BOOST_AUTO_TEST_CASE(access_to_internal_function) } contract d { function g() { c(0).f(); } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1315,7 +1410,8 @@ BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) } contract d { function g() { c(0).a(); } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1327,43 +1423,68 @@ BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) } contract d { function g() { c(0).a(); } - })"; + } + )"; CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(error_count_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({a: 1}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({a: 1}); + } + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(empty_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({}); + } + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({a: 1, a: 2}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({a: 1, a: 2}); + } + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({a: 1, c: 2}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({a: 1, c: 2}); + } + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1371,9 +1492,9 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter) { char const* text = R"( contract test { - function f(uint){ + function f(uint) { } } - })"; + )"; CHECK_SUCCESS(text); } @@ -1381,9 +1502,9 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) { char const* text = R"( contract test { - function f() returns(bool){ + function f() returns(bool) { } } - })"; + )"; CHECK_SUCCESS(text); } @@ -1391,10 +1512,11 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* text = R"( contract test { - function f(uint, uint k) returns(uint ret_k){ + function f(uint, uint k) returns(uint ret_k) { return k; + } } - })"; + )"; CHECK_SUCCESS(text); } @@ -1402,16 +1524,21 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) { char const* text = R"( contract test { - function f() returns(uint ret_k, uint){ + function f() returns(uint ret_k, uint) { return 5; + } } - })"; + )"; CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) { - char const* sourceCode = "contract c { function f() { var (x) = f(); } }"; + char const* sourceCode = R"( + contract c { + function f() { var (x) = f(); } + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1419,22 +1546,22 @@ BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) { char const* sourceCodeFine = R"( contract c { - function c () - { - a = 115792089237316195423570985008687907853269984665640564039458; + function c () { + a = 115792089237316195423570985008687907853269984665640564039458; } uint256 a; - })"; + } + )"; ETH_TEST_CHECK_NO_THROW(parseAndAnalyse(sourceCodeFine), "Parsing and Resolving names failed"); char const* sourceCode = R"( contract c { - function c () - { + function c () { a = 115792089237316195423570985008687907853269984665640564039458 ether; } uint256 a; - })"; + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1443,21 +1570,22 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) char const* sourceCode = R"( contract test { function f() returns(uint d) { return 2 ** 10000000000; } - })"; + } + )"; CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_member_access) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = ActionChoices.GoStraight; - } - ActionChoices choices; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() + { + choices = ActionChoices.GoStraight; } + ActionChoices choices; + } )"; CHECK_SUCCESS(text); } @@ -1465,14 +1593,14 @@ BOOST_AUTO_TEST_CASE(enum_member_access) BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts) { char const* text = R"( - contract Interface { - enum MyEnum { One, Two } - } - contract Impl { - function test() returns (Interface.MyEnum) { - return Interface.MyEnum.One; - } + contract Interface { + enum MyEnum { One, Two } + } + contract Impl { + function test() returns (Interface.MyEnum) { + return Interface.MyEnum.One; } + } )"; CHECK_SUCCESS(text); } @@ -1480,14 +1608,13 @@ BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts) BOOST_AUTO_TEST_CASE(enum_invalid_member_access) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = ActionChoices.RunAroundWavingYourHands; - } - ActionChoices choices; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + choices = ActionChoices.RunAroundWavingYourHands; } + ActionChoices choices; + } )"; CHECK_ERROR(text, TypeError, ""); } @@ -1495,14 +1622,13 @@ BOOST_AUTO_TEST_CASE(enum_invalid_member_access) BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = Sit; - } - ActionChoices choices; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + choices = Sit; } + ActionChoices choices; + } )"; CHECK_ERROR(text, DeclarationError, ""); } @@ -1510,16 +1636,15 @@ BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - a = uint256(ActionChoices.GoStraight); - b = uint64(ActionChoices.Sit); - } - uint256 a; - uint64 b; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + a = uint256(ActionChoices.GoStraight); + b = uint64(ActionChoices.Sit); } + uint256 a; + uint64 b; + } )"; CHECK_SUCCESS(text); } @@ -1527,16 +1652,15 @@ BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - a = 2; - b = ActionChoices(a); - } - uint256 a; - ActionChoices b; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + a = 2; + b = ActionChoices(a); } + uint256 a; + ActionChoices b; + } )"; CHECK_SUCCESS(text); } @@ -1544,16 +1668,15 @@ BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay) BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - a = ActionChoices.GoStraight; - b = ActionChoices.Sit; - } - uint256 a; - uint64 b; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + a = ActionChoices.GoStraight; + b = ActionChoices.Sit; } + uint256 a; + uint64 b; + } )"; CHECK_ERROR(text, TypeError, ""); } @@ -1564,8 +1687,7 @@ BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) contract test { enum Paper { Up, Down, Left, Right } enum Ground { North, South, West, East } - function test() - { + function test() { Ground(Paper.Up); } } @@ -1609,7 +1731,7 @@ BOOST_AUTO_TEST_CASE(private_visibility) contract derived is base { function g() { f(); } } - )"; + )"; CHECK_ERROR(sourceCode, DeclarationError, ""); } @@ -1622,7 +1744,7 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) contract derived is base { function g() { base.f(); } } - )"; + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1633,7 +1755,7 @@ BOOST_AUTO_TEST_CASE(external_visibility) function f() external {} function g() { f(); } } - )"; + )"; CHECK_ERROR(sourceCode, DeclarationError, ""); } @@ -1646,7 +1768,7 @@ BOOST_AUTO_TEST_CASE(external_base_visibility) contract derived is base { function g() { base.f(); } } - )"; + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1656,7 +1778,7 @@ BOOST_AUTO_TEST_CASE(external_argument_assign) contract c { function f(uint a) external { a = 1; } } - )"; + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1666,7 +1788,7 @@ BOOST_AUTO_TEST_CASE(external_argument_increment) contract c { function f(uint a) external { a++; } } - )"; + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1676,7 +1798,7 @@ BOOST_AUTO_TEST_CASE(external_argument_delete) contract c { function f(uint a) external { delete a; } } - )"; + )"; CHECK_ERROR(sourceCode, TypeError, ""); } @@ -1689,7 +1811,7 @@ BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) contract Bike is Vehicle { function f(bytes _a) external returns (uint256 r) {r = 42;} } - )"; + )"; ETH_TEST_CHECK_NO_THROW(parseAndAnalyse(sourceCode), "Parsing and Name Resolving failed"); } @@ -1698,7 +1820,8 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) char const* text = R"( contract c { function f(uint a) { uint8[a] x; } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1709,7 +1832,8 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) bytes a; uint[] b; function f() { b = a; } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1720,7 +1844,8 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) uint32[] a; uint8[] b; function f() { b = a; } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1731,7 +1856,8 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) uint32[] a; uint8[] b; function f() { a = b; } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1742,7 +1868,8 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic) uint32[] a; uint8[80] b; function f() { a = b; } - })"; + } + )"; CHECK_SUCCESS(text); } @@ -1753,7 +1880,8 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) uint[] a; uint[80] b; function f() { b = a; } - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1762,7 +1890,8 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) char const* text = R"( contract c { uint8 a = 1000; - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1771,7 +1900,8 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) char const* text = R"( contract c { uint a = "abc"; - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1887,7 +2017,8 @@ BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1) contract c { bytes arr; function f() { byte a = arr[0];} - })"; + } + )"; ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Type resolving failed"); } @@ -1897,7 +2028,8 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) contract Foo { function changeIt() { x = 9; } uint constant x = 56; - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1907,7 +2039,8 @@ BOOST_AUTO_TEST_CASE(complex_const_variable) char const* text = R"( contract Foo { mapping(uint => bool) constant mapVar; - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -1916,7 +2049,8 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable) char const* text = R"( contract Foo { uint constant y; - })"; + } + )"; CHECK_ERROR(text, TypeError, ""); } @@ -4161,7 +4295,7 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement) char const* text = R"( contract test { struct S { uint x; } - function test(uint k) { S[k]; } + function test(uint k) { S[k]; } } )"; CHECK_ERROR(text, TypeError, ""); diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 85bc22778..e32264c4d 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -76,10 +76,12 @@ BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker) BOOST_AUTO_TEST_CASE(user_basic_test) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 + function mul(uint a) returns(uint d) { return a * 7; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -91,11 +93,13 @@ BOOST_AUTO_TEST_CASE(user_basic_test) BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7\n" - " /// @dev Multiplies a number by 7\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 + /// @dev Multiplies a number by 7 + function mul(uint a) returns(uint d) { return a * 7; } + } + )"; char const* devNatspec = "{" "\"methods\":{" @@ -116,14 +120,15 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) BOOST_AUTO_TEST_CASE(user_multiline_comment) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7\n" - " /// and then adds `b`\n" - " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" - " {\n" - " return (a * 7) + b;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 + /// and then adds `b` + function mul_and_add(uint a, uint256 b) returns(uint256 d) { + return (a * 7) + b; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -135,24 +140,24 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) BOOST_AUTO_TEST_CASE(user_multiple_functions) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7 and then adds `b`\n" - " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" - " {\n" - " return (a * 7) + b;\n" - " }\n" - "\n" - " /// @notice Divides `input` by `div`\n" - " function divide(uint input, uint div) returns(uint d)\n" - " {\n" - " return input / div;\n" - " }\n" - " /// @notice Subtracts 3 from `input`\n" - " function sub(int input) returns(int d)\n" - " {\n" - " return input - 3;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 and then adds `b` + function mul_and_add(uint a, uint256 b) returns(uint256 d) { + return (a * 7) + b; + } + + /// @notice Divides `input` by `div` + function divide(uint input, uint div) returns(uint d) { + return input / div; + } + + /// @notice Subtracts 3 from `input` + function sub(int input) returns(int d) { + return input - 3; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -166,8 +171,9 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions) BOOST_AUTO_TEST_CASE(user_empty_contract) { - char const* sourceCode = "contract test {\n" - "}\n"; + char const* sourceCode = R"( + contract test { } + )"; char const* natspec = "{\"methods\":{} }"; @@ -176,13 +182,16 @@ BOOST_AUTO_TEST_CASE(user_empty_contract) BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) { - char const* sourceCode = "contract test {\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - " function sub(int input) returns(int d)\n" - " {\n" - " return input - 3;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function mul(uint a) returns(uint d) { + return a * 7; + } + function sub(int input) returns(int d) { + return input - 3; + } + } + )"; char const* devNatspec = "{\"methods\":{}}"; char const* userNatspec = "{\"methods\":{}}"; @@ -193,13 +202,15 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) BOOST_AUTO_TEST_CASE(dev_desc_after_nl) { - char const* sourceCode = "contract test {\n" - " /// @dev\n" - " /// Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev + /// Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -217,12 +228,14 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl) BOOST_AUTO_TEST_CASE(dev_multiple_params) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -240,13 +253,15 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -264,26 +279,27 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) BOOST_AUTO_TEST_CASE(dev_multiple_functions) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - " \n" - " /// @dev Divides 2 numbers\n" - " /// @param input Documentation for the input parameter\n" - " /// @param div Documentation for the div parameter\n" - " function divide(uint input, uint div) returns(uint d)\n" - " {\n" - " return input / div;\n" - " }\n" - " /// @dev Subtracts 3 from `input`\n" - " /// @param input Documentation for the input parameter\n" - " function sub(int input) returns(int d)\n" - " {\n" - " return input - 3;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + /// @dev Divides 2 numbers + /// @param input Documentation for the input parameter + /// @param div Documentation for the div parameter + function divide(uint input, uint div) returns(uint d) { + return input / div; + } + /// @dev Subtracts 3 from `input` + /// @param input Documentation for the input parameter + function sub(int input) returns(int d) { + return input - 3; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -314,14 +330,16 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions) BOOST_AUTO_TEST_CASE(dev_return) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " /// @return The result of the multiplication\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return The result of the multiplication + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -339,15 +357,19 @@ BOOST_AUTO_TEST_CASE(dev_return) } BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " /// @return\n" - " /// The result of the multiplication\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return + /// The result of the multiplication + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -367,15 +389,19 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) BOOST_AUTO_TEST_CASE(dev_multiline_return) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " /// @return The result of the multiplication\n" - " /// and cookies with nutella\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return The result of the multiplication + /// and cookies with nutella + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -394,17 +420,21 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) BOOST_AUTO_TEST_CASE(dev_multiline_comment) { - char const* sourceCode = "contract test {\n" - " /**\n" - " * @dev Multiplies a number by 7 and adds second parameter\n" - " * @param a Documentation for the first parameter starts here.\n" - " * Since it's a really complicated parameter we need 2 lines\n" - " * @param second Documentation for the second parameter\n" - " * @return The result of the multiplication\n" - " * and cookies with nutella\n" - " */" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /** + * @dev Multiplies a number by 7 and adds second parameter + * @param a Documentation for the first parameter starts here. + * Since it's a really complicated parameter we need 2 lines + * @param second Documentation for the second parameter + * @return The result of the multiplication + * and cookies with nutella + */ + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -423,10 +453,12 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment) BOOST_AUTO_TEST_CASE(dev_contract_no_doc) { - char const* sourceCode = "contract test {\n" - " /// @dev Mul function\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Mul function + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" " \"methods\":{" @@ -441,12 +473,14 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc) BOOST_AUTO_TEST_CASE(dev_contract_doc) { - char const* sourceCode = " /// @author Lefteris\n" - " /// @title Just a test contract\n" - "contract test {\n" - " /// @dev Mul function\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + /// @author Lefteris + /// @title Just a test contract + contract test { + /// @dev Mul function + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" " \"author\": \"Lefteris\"," @@ -463,13 +497,15 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc) BOOST_AUTO_TEST_CASE(dev_author_at_function) { - char const* sourceCode = " /// @author Lefteris\n" - " /// @title Just a test contract\n" - "contract test {\n" - " /// @dev Mul function\n" - " /// @author John Doe\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + /// @author Lefteris + /// @title Just a test contract + contract test { + /// @dev Mul function + /// @author John Doe + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" " \"author\": \"Lefteris\"," @@ -549,25 +585,29 @@ BOOST_AUTO_TEST_CASE(empty_comment) BOOST_AUTO_TEST_CASE(dev_title_at_function_error) { - char const* sourceCode = " /// @author Lefteris\n" - " /// @title Just a test contract\n" - "contract test {\n" - " /// @dev Mul function\n" - " /// @title I really should not be here\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + /// @author Lefteris + /// @title Just a test contract + contract test { + /// @dev Mul function + /// @title I really should not be here + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; expectNatspecError(sourceCode); } BOOST_AUTO_TEST_CASE(dev_documenting_nonexistent_param) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param not_existing Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param not_existing Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; expectNatspecError(sourceCode); } From 01215694f67600f446498f403c3314ef6266a346 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 21 Nov 2016 15:26:05 +0100 Subject: [PATCH 137/185] test: disallow more than one errors in name and type tests --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index cf0d41dd7..3f8307d9d 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -62,7 +62,11 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, SyntaxChecker syntaxChecker(errors); if (!syntaxChecker.checkSyntax(*sourceUnit)) + { + if (errors.size() > 1) + BOOST_FAIL("Multiple errors found after checking syntax."); return make_pair(sourceUnit, errors.at(0)); + } std::shared_ptr globalContext = make_shared(); NameAndTypeResolver resolver(globalContext->declarations(), errors); @@ -89,8 +93,12 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, TypeChecker typeChecker(errors); bool success = typeChecker.checkTypeRequirements(*contract); BOOST_CHECK(success || !errors.empty()); + if (errors.size() > 1) + BOOST_FAIL("Multiple errors found after checking type requirements"); } + if (errors.size() > 1) + BOOST_FAIL("Multiple errors found"); for (auto const& currentError: errors) { if ( From 1f345e527ddb80d6c4b943e4d712338a2afd69d9 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 5 Dec 2016 15:40:35 +0100 Subject: [PATCH 138/185] test: either fix tests to raise just one error, or mark them as raising multiple errors --- .../SolidityNameAndTypeResolution.cpp | 144 ++++++++++++++---- 1 file changed, 112 insertions(+), 32 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 3f8307d9d..151deda80 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -46,7 +46,7 @@ namespace { pair, std::shared_ptr> -parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true) +parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true, bool _allowMultipleErrors = false) { // Silence compiler version warning string source = _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source; @@ -62,11 +62,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, SyntaxChecker syntaxChecker(errors); if (!syntaxChecker.checkSyntax(*sourceUnit)) - { - if (errors.size() > 1) - BOOST_FAIL("Multiple errors found after checking syntax."); return make_pair(sourceUnit, errors.at(0)); - } std::shared_ptr globalContext = make_shared(); NameAndTypeResolver resolver(globalContext->declarations(), errors); @@ -93,11 +89,9 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, TypeChecker typeChecker(errors); bool success = typeChecker.checkTypeRequirements(*contract); BOOST_CHECK(success || !errors.empty()); - if (errors.size() > 1) - BOOST_FAIL("Multiple errors found after checking type requirements"); } - if (errors.size() > 1) + if (errors.size() > 1 && !_allowMultipleErrors) BOOST_FAIL("Multiple errors found"); for (auto const& currentError: errors) { @@ -139,9 +133,9 @@ bool success(string const& _source) return !parseAnalyseAndReturnError(_source).second; } -Error expectError(std::string const& _source, bool _warning = false) +Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false) { - auto sourceAndError = parseAnalyseAndReturnError(_source, _warning); + auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple); BOOST_REQUIRE(!!sourceAndError.second); BOOST_REQUIRE(!!sourceAndError.first); return *sourceAndError.second; @@ -169,10 +163,10 @@ static FunctionTypePointer retrieveFunctionBySignature( } -#define CHECK_ERROR_OR_WARNING(text, typ, substring, warning) \ +#define CHECK_ERROR_OR_WARNING(text, typ, substring, warning, allowMulti) \ do \ { \ - Error err = expectError((text), (warning)); \ + Error err = expectError((text), (warning), (allowMulti)); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ BOOST_CHECK(searchErrorMessage(err, substring)); \ } while(0) @@ -180,12 +174,17 @@ do \ // [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) +CHECK_ERROR_OR_WARNING(text, type, substring, false, false) + +// [checkError(text, type, substring)] asserts that the compilation down to typechecking +// emits an error of type [type] and with a message containing [substring]. +#define CHECK_ERROR_ALLOW_MULTI(text, type, substring) \ +CHECK_ERROR_OR_WARNING(text, type, substring, false, true) // [checkWarning(text, type, substring)] asserts that the compilation down to typechecking // emits a warning of type [type] and with a message containing [substring]. #define CHECK_WARNING(text, substring) \ -CHECK_ERROR_OR_WARNING(text, Warning, substring, true) +CHECK_ERROR_OR_WARNING(text, Warning, substring, true, false) // [checkSuccess(text)] asserts that the compilation down to typechecking succeeds. #define CHECK_SUCCESS(text) do { BOOST_CHECK(success((text))); } while(0) @@ -847,7 +846,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance) contract A is B { } contract B is A { } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(legal_override_direct) @@ -1291,7 +1290,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice) function() { x = 3; } } )"; - CHECK_ERROR(text, DeclarationError, ""); + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_inheritance) @@ -1673,16 +1672,28 @@ BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay) +BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_256) { char const* text = R"( contract test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } function test() { a = ActionChoices.GoStraight; - b = ActionChoices.Sit; } uint256 a; + } + )"; + CHECK_ERROR(text, TypeError, ""); +} + +BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_64) +{ + char const* text = R"( + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + b = ActionChoices.Sit; + } uint64 b; } )"; @@ -2046,7 +2057,8 @@ BOOST_AUTO_TEST_CASE(complex_const_variable) //for now constant specifier is valid only for uint bytesXX and enums char const* text = R"( contract Foo { - mapping(uint => bool) constant mapVar; + mapping(uint => bool) x; + mapping(uint => bool) constant mapVar = x; } )"; CHECK_ERROR(text, TypeError, ""); @@ -2151,12 +2163,12 @@ BOOST_AUTO_TEST_CASE(multiple_constructors) BOOST_AUTO_TEST_CASE(equal_overload) { char const* sourceCode = R"( - contract test { + contract C { function test(uint a) returns (uint b) { } function test(uint a) external {} } )"; - CHECK_ERROR(sourceCode, DeclarationError, ""); + CHECK_ERROR_ALLOW_MULTI(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(uninitialized_var) @@ -3307,7 +3319,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) @@ -3321,8 +3333,8 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) uint x; } function f() { - s1 x; - s2 y; + s1 memory x; + s2 memory y; true ? x : y; } } @@ -3803,7 +3815,7 @@ BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion) char const* text = R"( contract test { function f() { - fixed a = 3.2; + fixed a = 3.25; bytes32 c = a; } } @@ -3893,14 +3905,47 @@ BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(rational_as_exponent_value) +BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_decimal) { char const* text = R"( contract test { function f() { fixed g = 2 ** -2.2; + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_as_exponent_value_pos_decimal) +{ + char const* text = R"( + contract test { + function f() { ufixed b = 3 ** 2.5; + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_as_exponent_half) +{ + char const* text = R"( + contract test { + function f() { ufixed24x24 b = 2 ** (1/2); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_quarter) +{ + char const* text = R"( + contract test { + function f() { fixed40x40 c = 42 ** (-1/4); } } @@ -3908,15 +3953,48 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value) BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents) +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_15) { char const* text = R"( contract test { function f() { ufixed a = 3 ** ufixed(1.5); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_half) +{ + char const* text = R"( + contract test { + function f() { ufixed b = 2 ** ufixed(1/2); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg) +{ + char const* text = R"( + contract test { + function f() { fixed c = 42 ** fixed(-1/4); - fixed d = 16 ** fixed(-0.33); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg_decimal) +{ + char const* text = R"( + contract test { + function f() { + fixed d = 16 ** fixed(-0.5); } } )"; @@ -3966,7 +4044,7 @@ BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation) char const* text = R"( contract test { function f() { - fixed a = ~3.56; + fixed a = ~3.5; } } )"; @@ -3978,7 +4056,7 @@ BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation) char const* text = R"( contract test { function f() { - fixed a = 1.56 | 3; + fixed a = 1.5 | 3; } } )"; @@ -3990,7 +4068,7 @@ BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation) char const* text = R"( contract test { function f() { - fixed a = 1.56 ^ 3; + fixed a = 1.75 ^ 3; } } )"; @@ -4002,7 +4080,7 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation) char const* text = R"( contract test { function f() { - fixed a = 1.56 & 3; + fixed a = 1.75 & 3; } } )"; @@ -4659,6 +4737,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage) function f() { assembly { x := 2 + pop } } } @@ -4674,6 +4753,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) modifier m { assembly { x := 2 + pop } _; } From 1b6861e6c99ff244180eec8aac9dee50d6e45520 Mon Sep 17 00:00:00 2001 From: Daniel Ellison Date: Fri, 2 Dec 2016 07:45:42 -0500 Subject: [PATCH 139/185] Added 'panic' tests. --- test/liblll/EndToEndTest.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index b5e32e94f..824e53cd5 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -43,6 +43,20 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_CHECK(callFallback() == encodeArgs(string("test", 4))); } +BOOST_AUTO_TEST_CASE(bare_panic) +{ + char const* sourceCode = "(panic)"; + compileAndRunWithoutCheck(sourceCode); + BOOST_REQUIRE(m_output.empty()); +} + +BOOST_AUTO_TEST_CASE(enclosed_panic) +{ + char const* sourceCode = "(seq (panic))"; + compileAndRunWithoutCheck(sourceCode); + BOOST_REQUIRE(m_output.empty()); +} + BOOST_AUTO_TEST_SUITE_END() } From a91b712ab8bfc5928428e308855244fb77766ca3 Mon Sep 17 00:00:00 2001 From: Daniel Ellison Date: Fri, 2 Dec 2016 09:00:33 -0500 Subject: [PATCH 140/185] Added tests for exponent operator. --- test/liblll/EndToEndTest.cpp | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 824e53cd5..980f8d10c 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -57,6 +57,43 @@ BOOST_AUTO_TEST_CASE(enclosed_panic) BOOST_REQUIRE(m_output.empty()); } +BOOST_AUTO_TEST_CASE(exp_operator_const) +{ + char const* sourceCode = R"( + (returnlll + (return (exp 2 3))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == toBigEndian(u256(8))); +} + +BOOST_AUTO_TEST_CASE(exp_operator_const_signed) +{ + char const* sourceCode = R"( + (returnlll + (return (exp (- 0 2) 3))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == toBigEndian(u256(-8))); +} + +BOOST_AUTO_TEST_CASE(exp_operator_parameter) +{ + char const* sourceCode = R"( + (seq + (def 'function (function-hash code-body) + (when (= (div (calldataload 0x00) (exp 2 224)) function-hash) + code-body)) + (returnlll + (seq + (function 0xb3de648b + (return (exp 2 (calldataload 0x04)))) + (jump 0x02)))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256)", u256(16)) == toBigEndian(u256(65536))); +} + BOOST_AUTO_TEST_SUITE_END() } From 1152d2d2d4eefe36a08f7026be6d9d7031722c2e Mon Sep 17 00:00:00 2001 From: Daniel Ellison Date: Fri, 2 Dec 2016 09:26:35 -0500 Subject: [PATCH 141/185] Simplified exp_operator_on_range test and changed to tedting a range. --- test/liblll/EndToEndTest.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 980f8d10c..6a5a223e4 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -77,21 +77,17 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) BOOST_CHECK(callFallback() == toBigEndian(u256(-8))); } -BOOST_AUTO_TEST_CASE(exp_operator_parameter) +BOOST_AUTO_TEST_CASE(exp_operator_on_range) { char const* sourceCode = R"( - (seq - (def 'function (function-hash code-body) - (when (= (div (calldataload 0x00) (exp 2 224)) function-hash) - code-body)) - (returnlll - (seq - (function 0xb3de648b - (return (exp 2 (calldataload 0x04)))) - (jump 0x02)))) + (returnlll + (seq + (when (= (div (calldataload 0x00) (exp 2 224)) 0xb3de648b) + (return (exp 2 (calldataload 0x04)))) + (jump 0x02))) )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f(uint256)", u256(16)) == toBigEndian(u256(65536))); + testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to()); }, 0, 16); } BOOST_AUTO_TEST_SUITE_END() From 20a098e205020ce682c2bfe79e749167e87d41e1 Mon Sep 17 00:00:00 2001 From: Daniel Ellison Date: Fri, 2 Dec 2016 10:31:00 -0500 Subject: [PATCH 142/185] Removed enclosed_panic test until assembler bug is fixed. --- test/liblll/EndToEndTest.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 6a5a223e4..f4e9e4144 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -50,13 +50,6 @@ BOOST_AUTO_TEST_CASE(bare_panic) BOOST_REQUIRE(m_output.empty()); } -BOOST_AUTO_TEST_CASE(enclosed_panic) -{ - char const* sourceCode = "(seq (panic))"; - compileAndRunWithoutCheck(sourceCode); - BOOST_REQUIRE(m_output.empty()); -} - BOOST_AUTO_TEST_CASE(exp_operator_const) { char const* sourceCode = R"( From e23ef9db0265391e5a08d3ed432e0085faa78df1 Mon Sep 17 00:00:00 2001 From: Daniel Ellison Date: Fri, 2 Dec 2016 11:45:58 -0500 Subject: [PATCH 143/185] Added tests for LLL constructors. Fixed a few tab issues. --- test/liblll/EndToEndTest.cpp | 54 ++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index f4e9e4144..5acf7822d 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -55,9 +55,9 @@ BOOST_AUTO_TEST_CASE(exp_operator_const) char const* sourceCode = R"( (returnlll (return (exp 2 3))) - )"; + )"; compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == toBigEndian(u256(8))); + BOOST_CHECK(callFallback() == toBigEndian(u256(8))); } BOOST_AUTO_TEST_CASE(exp_operator_const_signed) @@ -65,9 +65,9 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) char const* sourceCode = R"( (returnlll (return (exp (- 0 2) 3))) - )"; + )"; compileAndRun(sourceCode); - BOOST_CHECK(callFallback() == toBigEndian(u256(-8))); + BOOST_CHECK(callFallback() == toBigEndian(u256(-8))); } BOOST_AUTO_TEST_CASE(exp_operator_on_range) @@ -78,11 +78,55 @@ BOOST_AUTO_TEST_CASE(exp_operator_on_range) (when (= (div (calldataload 0x00) (exp 2 224)) 0xb3de648b) (return (exp 2 (calldataload 0x04)))) (jump 0x02))) - )"; + )"; compileAndRun(sourceCode); testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to()); }, 0, 16); } +BOOST_AUTO_TEST_CASE(constructor_argument_internal_numeric) +{ + char const* sourceCode = R"( + (seq + (sstore 0x00 65535) + (returnlll + (return @@0x00))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(65535))); +} + +BOOST_AUTO_TEST_CASE(constructor_argument_internal_string) +{ + char const* sourceCode = R"( + (seq + (sstore 0x00 "test") + (returnlll + (return @@0x00))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs("test")); +} + +BOOST_AUTO_TEST_CASE(constructor_arguments_external) +{ + char const* sourceCode = R"( + (seq + (codecopy 0x00 (bytecodesize) 64) + (sstore 0x00 @0x00) + (sstore 0x01 @0x20) + (returnlll + (seq + (when (= (div (calldataload 0x00) (exp 2 224)) 0xf2c9ecd8) + (return @@0x00)) + (when (= (div (calldataload 0x00) (exp 2 224)) 0x89ea642f) + (return @@0x01)) + (jump 0x02)))) + )"; + compileAndRun(sourceCode, 0, "", encodeArgs(u256(65535), "test")); + BOOST_CHECK(callContractFunction("getNumber()") == encodeArgs(u256(65535))); + BOOST_CHECK(callContractFunction("getString()") == encodeArgs("test")); +} + BOOST_AUTO_TEST_SUITE_END() } From 94536ccec8a296a7a17ff9fc795f4a0b8720467b Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 6 Dec 2016 10:35:56 +0100 Subject: [PATCH 144/185] test: check error messages in parser tests --- .../SolidityNameAndTypeResolution.cpp | 2 +- test/libsolidity/SolidityParser.cpp | 71 +++++++++++++------ 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index cf0d41dd7..4caccf6dd 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -166,7 +166,7 @@ do \ { \ Error err = expectError((text), (warning)); \ BOOST_CHECK(err.type() == (Error::Type::typ)); \ - BOOST_CHECK(searchErrorMessage(err, substring)); \ + BOOST_CHECK(searchErrorMessage(err, (substring))); \ } while(0) // [checkError(text, type, substring)] asserts that the compilation down to typechecking diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 5e3c69d27..a3bfab757 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -26,6 +26,7 @@ #include #include #include "../TestHelper.h" +#include "ErrorCheck.h" using namespace std; @@ -71,6 +72,22 @@ bool successParse(std::string const& _source) return true; } +Error getError(std::string const& _source) +{ + ErrorList errors; + try + { + parseText(_source, errors); + } + catch (FatalError const& /*_exception*/) + { + // no-op + } + Error const* error = Error::containsErrorOfType(errors, Error::Type::ParserError); + BOOST_REQUIRE(error); + return *error; +} + void checkFunctionNatspec( FunctionDefinition const* _function, std::string const& _expectedDoc @@ -83,6 +100,14 @@ void checkFunctionNatspec( } +#define CHECK_PARSE_ERROR(source, substring) \ +do \ +{\ + Error err = getError((source)); \ + BOOST_CHECK(searchErrorMessage(err, (substring))); \ +}\ +while(0) + BOOST_AUTO_TEST_SUITE(SolidityParser) @@ -103,7 +128,7 @@ BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) uint256 ; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(empty_function) @@ -159,7 +184,7 @@ BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args) function b() returns (uint r) { r = a({: 1, : 2, : 3}); } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(missing_argument_in_named_args) @@ -170,7 +195,7 @@ BOOST_AUTO_TEST_CASE(missing_argument_in_named_args) function b() returns (uint r) { r = a({a: , b: , c: }); } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected primary expression"); } BOOST_AUTO_TEST_CASE(two_exact_functions) @@ -463,7 +488,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_parameter) function fun(var a) {} } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected explicit type name"); } BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) @@ -475,7 +500,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected elementary type name for mapping key type"); } BOOST_AUTO_TEST_CASE(variable_definition_in_function_return) @@ -487,7 +512,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_return) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected explicit type name"); } BOOST_AUTO_TEST_CASE(operator_expression) @@ -777,14 +802,14 @@ BOOST_AUTO_TEST_CASE(modifier_without_semicolon) modifier mod { if (msg.sender == 0) _ } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token Semicolon got"); } BOOST_AUTO_TEST_CASE(modifier_arguments) { char const* text = R"( contract c { - modifier mod(uint a) { if (msg.sender == a) _; } + modifier mod(address a) { if (msg.sender == a) _; } } )"; BOOST_CHECK(successParse(text)); @@ -861,7 +886,7 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers) contract c { uint private internal a; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Visibility already specified"); } BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) @@ -916,7 +941,7 @@ BOOST_AUTO_TEST_CASE(empty_enum_declaration) contract c { enum foo { } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "enum with no members is not allowed"); } BOOST_AUTO_TEST_CASE(malformed_enum_declaration) @@ -925,7 +950,7 @@ BOOST_AUTO_TEST_CASE(malformed_enum_declaration) contract c { enum foo { WARNING,} })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected Identifier after"); } BOOST_AUTO_TEST_CASE(external_function) @@ -943,7 +968,7 @@ BOOST_AUTO_TEST_CASE(external_variable) contract c { uint external x; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(arrays_in_storage) @@ -991,7 +1016,7 @@ BOOST_AUTO_TEST_CASE(constant_is_keyword) contract Foo { uint constant = 4; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(var_array) @@ -1000,7 +1025,7 @@ BOOST_AUTO_TEST_CASE(var_array) contract Foo { function f() { var[] a; } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(location_specifiers_for_params) @@ -1032,7 +1057,7 @@ BOOST_AUTO_TEST_CASE(location_specifiers_for_state) contract Foo { uint[] memory x; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(location_specifiers_with_var) @@ -1041,7 +1066,7 @@ BOOST_AUTO_TEST_CASE(location_specifiers_with_var) contract Foo { function f() { var memory x; } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Location specifier needs explicit type name"); } BOOST_AUTO_TEST_CASE(empty_comment) @@ -1088,7 +1113,7 @@ BOOST_AUTO_TEST_CASE(local_const_variable) return local; } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token Semicolon"); } BOOST_AUTO_TEST_CASE(multi_variable_declaration) @@ -1207,7 +1232,7 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_lvalue) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected expression"); } BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue) @@ -1220,7 +1245,7 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected expression"); } BOOST_AUTO_TEST_CASE(conditional_true_false_literal) @@ -1321,7 +1346,7 @@ BOOST_AUTO_TEST_CASE(no_double_radix_in_fixed_literal) fixed40x40 pi = 3.14.15; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token Semicolon"); } BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check) @@ -1333,7 +1358,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected primary expression"); } BOOST_AUTO_TEST_CASE(payable_accessor) @@ -1343,7 +1368,7 @@ BOOST_AUTO_TEST_CASE(payable_accessor) uint payable x; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(function_type_in_expression) @@ -1376,7 +1401,7 @@ BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_modifiers) function (uint, uint) modifier1() returns (uint) f1; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token LBrace"); } BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_assignment) From 86953ca3e48bc9620e8d34ae965ba1fa65aaf4eb Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Dec 2016 18:38:59 +0100 Subject: [PATCH 145/185] Option to show messages in tests. --- test/ExecutionFramework.cpp | 11 +++++++++++ test/ExecutionFramework.h | 1 + test/TestHelper.cpp | 2 ++ test/TestHelper.h | 1 + 4 files changed, 15 insertions(+) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 0c6e0cff7..9d6d56752 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -46,6 +46,7 @@ string getIPCSocketPath() ExecutionFramework::ExecutionFramework() : m_rpc(RPCSession::instance(getIPCSocketPath())), m_optimize(dev::test::Options::get().optimize), + m_showMessages(dev::test::Options::get().showMessages), m_sender(m_rpc.account(0)) { m_rpc.test_rewindToBlock(0); @@ -53,6 +54,13 @@ ExecutionFramework::ExecutionFramework() : void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) { + if (m_showMessages) + { + if (_isCreation) + cout << "CREATE " << toHex(m_sender) << ": " << toHex(_data) << endl; + else + cout << "CALL " << toHex(m_sender) << " -> " << toHex(m_contractAddress) << ": " << toHex(_data) << endl; + } RPCSession::TransactionData d; d.data = "0x" + toHex(_data); d.from = "0x" + toString(m_sender); @@ -79,6 +87,9 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 m_output = fromHex(code, WhenError::Throw); } + if (m_showMessages) + cout << " -> " << toHex(m_output) << endl; + m_gasUsed = u256(receipt.gasUsed); m_logs.clear(); for (auto const& log: receipt.logEntries) diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index f47f2743d..733fd56dc 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -281,6 +281,7 @@ protected: unsigned m_optimizeRuns = 200; bool m_optimize = false; + bool m_showMessages = false; Address m_sender; Address m_contractAddress; u256 const m_gasPrice = 100 * szabo; diff --git a/test/TestHelper.cpp b/test/TestHelper.cpp index d670ebff5..0c0857c91 100644 --- a/test/TestHelper.cpp +++ b/test/TestHelper.cpp @@ -41,6 +41,8 @@ Options::Options() } else if (string(suite.argv[i]) == "--optimize") optimize = true; + else if (string(suite.argv[i]) == "--show-messages") + showMessages = true; if (ipcPath.empty()) if (auto path = getenv("ETH_TEST_IPC")) diff --git a/test/TestHelper.h b/test/TestHelper.h index afe4a68f0..8f05eead6 100644 --- a/test/TestHelper.h +++ b/test/TestHelper.h @@ -106,6 +106,7 @@ namespace test struct Options: boost::noncopyable { std::string ipcPath; + bool showMessages = false; bool optimize = false; static Options const& get(); From 7a46e15efd13a15788278627fef3394a8fd0e349 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Tue, 6 Dec 2016 19:21:10 -0300 Subject: [PATCH 146/185] Rename isolateTests.py script to isolate_tests.py --- scripts/{isolateTests.py => isolate_tests.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{isolateTests.py => isolate_tests.py} (100%) diff --git a/scripts/isolateTests.py b/scripts/isolate_tests.py similarity index 100% rename from scripts/isolateTests.py rename to scripts/isolate_tests.py From 72f9a4a73eba906f349ccb3e577899d0f9add963 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Tue, 6 Dec 2016 19:21:38 -0300 Subject: [PATCH 147/185] Cleanup and fix scripts/isolate_tests.py --- scripts/isolate_tests.py | 52 +++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py index fed779d37..91900aa6e 100755 --- a/scripts/isolate_tests.py +++ b/scripts/isolate_tests.py @@ -4,21 +4,41 @@ # multi-line strings into individual files. # This can be used to extract the Solidity test cases # into files for e.g. fuzz testing as -# scripts/isolateTests.py tests/libsolidity/SolidityEndToEndTest.cpp +# scripts/isolate_tests.py test/libsolidity/* import sys -lines = sys.stdin.read().split('\n') -inside = False -tests = [] -for l in lines: - if inside: - if l.strip().endswith(')";'): - inside = False - else: - tests[-1] += l + '\n' - else: - if l.strip().endswith('R"('): - inside = True - tests += [''] -for i in range(len(tests)): - open('test%d.sol' % i, 'w').write(tests[i]) + + +def extract_cases(path): + lines = open(path).read().splitlines() + + inside = False + tests = [] + + for l in lines: + if inside: + if l.strip().endswith(')";'): + inside = False + else: + tests[-1] += l + '\n' + else: + if l.strip().endswith('R"('): + inside = True + tests += [''] + + return tests + + +def write_cases(tests, start=0): + for i, test in enumerate(tests, start=start): + open('test%d.sol' % i, 'w').write(test) + + +if __name__ == '__main__': + files = sys.argv[1:] + + i = 0 + for path in files: + cases = extract_cases(path) + write_cases(cases, start=i) + i += len(cases) From d1c71b78268e56ad0c98c8c71325c8a7b399b604 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Dec 2016 23:52:39 +0100 Subject: [PATCH 148/185] Also provide value and format slightly differently. --- test/ExecutionFramework.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 9d6d56752..9e3ecac39 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -57,9 +57,12 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 if (m_showMessages) { if (_isCreation) - cout << "CREATE " << toHex(m_sender) << ": " << toHex(_data) << endl; + cout << "CREATE " << m_sender.hex() << ":" << endl; else - cout << "CALL " << toHex(m_sender) << " -> " << toHex(m_contractAddress) << ": " << toHex(_data) << endl; + cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << endl; + if (_value > 0) + cout << " value: " << _value << endl; + cout << " in: " << toHex(_data) << endl; } RPCSession::TransactionData d; d.data = "0x" + toHex(_data); @@ -88,7 +91,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 } if (m_showMessages) - cout << " -> " << toHex(m_output) << endl; + cout << " out: " << toHex(m_output) << endl; m_gasUsed = u256(receipt.gasUsed); m_logs.clear(); From 0f304d2d898259f61418bdabdb83572579791674 Mon Sep 17 00:00:00 2001 From: Daniel Ellison Date: Tue, 6 Dec 2016 11:11:57 -0500 Subject: [PATCH 149/185] Removed 'panic' from 'constructor_arguments_external' and added specific test for fallback and fallthrough. Added one test for 'lit'. Added tests for arithmetic/binary/unary operations. Added the start of tests for assembler instructions within LLL source. --- test/liblll/EndToEndTest.cpp | 149 ++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp index 5acf7822d..77c1f7409 100644 --- a/test/liblll/EndToEndTest.cpp +++ b/test/liblll/EndToEndTest.cpp @@ -119,14 +119,159 @@ BOOST_AUTO_TEST_CASE(constructor_arguments_external) (when (= (div (calldataload 0x00) (exp 2 224)) 0xf2c9ecd8) (return @@0x00)) (when (= (div (calldataload 0x00) (exp 2 224)) 0x89ea642f) - (return @@0x01)) - (jump 0x02)))) + (return @@0x01))))) )"; compileAndRun(sourceCode, 0, "", encodeArgs(u256(65535), "test")); BOOST_CHECK(callContractFunction("getNumber()") == encodeArgs(u256(65535))); BOOST_CHECK(callContractFunction("getString()") == encodeArgs("test")); } +BOOST_AUTO_TEST_CASE(fallback_and_invalid_function) +{ + char const* sourceCode = R"( + (returnlll + (seq + (when (= (div (calldataload 0x00) (exp 2 224)) 0xab5ed150) + (return "one")) + (when (= (div (calldataload 0x00) (exp 2 224)) 0xee784123) + (return "two")) + (return "three"))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("getOne()") == encodeArgs("one")); + BOOST_CHECK(callContractFunction("getTwo()") == encodeArgs("two")); + BOOST_CHECK(callContractFunction("invalidFunction()") == encodeArgs("three")); + BOOST_CHECK(callFallback() == encodeArgs("three")); +} + +BOOST_AUTO_TEST_CASE(lit_string) +{ + char const* sourceCode = R"( + (returnlll + (seq + (lit 0x00 "abcdef") + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(string("abcdef"))); +} + +BOOST_AUTO_TEST_CASE(arithmetic) +{ + char const* sourceCode = R"( + (returnlll + (seq + (mstore8 0x00 (+ 160 22)) + (mstore8 0x01 (- 223 41)) + (mstore8 0x02 (* 33 2)) + (mstore8 0x03 (/ 10 2)) + (mstore8 0x04 (% 67 2)) + (mstore8 0x05 (& 15 8)) + (mstore8 0x06 (| 18 8)) + (mstore8 0x07 (^ 26 6)) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("b6b6420501081a1c000000000000000000000000000000000000000000000000"))); +} + +BOOST_AUTO_TEST_CASE(binary) +{ + char const* sourceCode = R"( + (returnlll + (seq + (mstore8 0x00 (< 53 87)) + (mstore8 0x01 (< 73 42)) + (mstore8 0x02 (<= 37 94)) + (mstore8 0x03 (<= 37 37)) + (mstore8 0x04 (<= 183 34)) + (mstore8 0x05 (S< (- 0 53) 87)) + (mstore8 0x06 (S< 73 (- 0 42))) + (mstore8 0x07 (S<= (- 0 37) 94)) + (mstore8 0x08 (S<= (- 0 37) (- 0 37))) + (mstore8 0x09 (S<= 183 (- 0 34))) + (mstore8 0x0a (> 73 42)) + (mstore8 0x0b (> 53 87)) + (mstore8 0x0c (>= 94 37)) + (mstore8 0x0d (>= 94 94)) + (mstore8 0x0e (>= 34 183)) + (mstore8 0x0f (S> 73 (- 0 42))) + (mstore8 0x10 (S> (- 0 53) 87)) + (mstore8 0x11 (S>= 94 (- 0 37))) + (mstore8 0x12 (S>= (- 0 94) (- 0 94))) + (mstore8 0x13 (S>= (- 0 34) 183)) + (mstore8 0x14 (= 53 53)) + (mstore8 0x15 (= 73 42)) + (mstore8 0x16 (!= 37 94)) + (mstore8 0x17 (!= 37 37)) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("0100010100010001010001000101000100010100010001000000000000000000"))); +} + +BOOST_AUTO_TEST_CASE(unary) +{ + char const* sourceCode = R"( + (returnlll + (seq + (mstore8 0x00 (! (< 53 87))) + (mstore8 0x01 (! (>= 42 73))) + (mstore8 0x02 (~ 0x7f)) + (mstore8 0x03 (~ 0xaa)) + (return 0x00 0x20))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs( + fromHex("0001805500000000000000000000000000000000000000000000000000000000"))); +} + +BOOST_AUTO_TEST_CASE(assembly_mload_mstore) +{ + char const* sourceCode = R"( + (returnlll + (asm + 0x07 0x00 mstore + "abcdef" 0x20 mstore + 0x00 mload 0x40 mstore + 0x20 mload 0x60 mstore + 0x40 0x40 return)) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(7), string("abcdef"))); +} + +BOOST_AUTO_TEST_CASE(assembly_sload_sstore) +{ + char const* sourceCode = R"( + (returnlll + (asm + 0x07 0x00 sstore + "abcdef" 0x01 sstore + 0x00 sload 0x00 mstore + 0x01 sload 0x20 mstore + 0x40 0x00 return)) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(u256(7), string("abcdef"))); +} + +BOOST_AUTO_TEST_CASE(assembly_codecopy) +{ + char const* sourceCode = R"( + (returnlll + (seq + (lit 0x00 "abcdef") + (asm + 0x06 0x16 0x20 codecopy + 0x20 0x20 return))) + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callFallback() == encodeArgs(string("abcdef"))); +} + BOOST_AUTO_TEST_SUITE_END() } From 926a252961806a5a70079bd046c85bfe9f7c8a9a Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Wed, 7 Dec 2016 22:00:16 -0300 Subject: [PATCH 150/185] Remove duplicate Identifier from AssemblyItem grammar rule --- docs/grammar.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/grammar.txt b/docs/grammar.txt index b0c9da98f..d15fbaf7c 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -112,7 +112,7 @@ Ufixed = 'ufixed' | 'ufixed0x8' | 'ufixed0x16' | 'ufixed0x24' | 'ufixed0x32' | ' InlineAssemblyBlock = '{' AssemblyItem* '}' -AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | Identifier | NumberLiteral | StringLiteral | HexLiteral +AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | NumberLiteral | StringLiteral | HexLiteral AssemblyLocalBinding = 'let' Identifier ':=' FunctionalAssemblyExpression AssemblyAssignment = Identifier ':=' FunctionalAssemblyExpression | '=:' Identifier FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')' From db42294a20ad65710f202b731b9e96a3caa2b2e4 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Thu, 20 Oct 2016 23:07:03 +0300 Subject: [PATCH 151/185] - fixed a misprint. --- libsolidity/interface/CompilerStack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index b4fd6d87c..c243ccb8a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -145,7 +145,7 @@ bool CompilerStack::parse() } } if (!Error::containsOnlyWarnings(m_errors)) - // errors while parsing. sould stop before type checking + // errors while parsing. should stop before type checking return false; resolveImports(); From f1cf9eb1ead6530ce2b4d0626a8b40e880fd58cb Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Sat, 22 Oct 2016 18:02:28 +0300 Subject: [PATCH 152/185] - moved string constants into common place; - replaced string literals with string constants. --- solc/CommandLineInterface.cpp | 317 +++++++++++++++++++--------------- 1 file changed, 181 insertions(+), 136 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 6e59099aa..8e56b38ef 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -65,38 +65,83 @@ namespace dev namespace solidity { -static string const g_argAbiStr = "abi"; -static string const g_argSignatureHashes = "hashes"; -static string const g_argGas = "gas"; -static string const g_argAsmStr = "asm"; -static string const g_argAsmJsonStr = "asm-json"; -static string const g_argAstStr = "ast"; -static string const g_argAstJson = "ast-json"; -static string const g_argBinaryStr = "bin"; -static string const g_argRuntimeBinaryStr = "bin-runtime"; -static string const g_argCloneBinaryStr = "clone-bin"; -static string const g_argOpcodesStr = "opcodes"; -static string const g_argNatspecDevStr = "devdoc"; -static string const g_argNatspecUserStr = "userdoc"; -static string const g_argMetadata = "metadata"; -static string const g_argAddStandard = "add-std"; -static string const g_stdinFileName = ""; +static string const g_strAbi = "abi"; +static string const g_strSignatureHashes = "hashes"; +static string const g_strGas = "gas"; +static string const g_strAsm = "asm"; +static string const g_strAsmJson = "asm-json"; +static string const g_strAst = "ast"; +static string const g_strAstJson = "ast-json"; +static string const g_strBinary = "bin"; +static string const g_strBinaryRuntime = "bin-runtime"; +static string const g_strCloneBinary = "clone-bin"; +static string const g_strOpcodes = "opcodes"; +static string const g_strNatspecDev = "devdoc"; +static string const g_strNatspecUser = "userdoc"; +static string const g_strMetadata = "metadata"; +static string const g_strAddStandard = "add-std"; +static string const g_strSrcMap = "srcmap"; +static string const g_strSrcMapRuntime = "srcmap-runtime"; +static string const g_strInterface = "interface"; +static string const g_strFormal = "formal"; +static string const g_strOutputDir = "output-dir"; +static string const g_strInputFile = "input-file"; +static string const g_strHelp = "help"; +static string const g_strVersion = "version"; +static string const g_strOptimize = "optimize"; +static string const g_strOptimizeRuns = "optimize-runs"; +static string const g_strLibraries = "libraries"; +static string const g_strCombinedJson = "combined-json"; +static string const g_strAssemble = "assemble"; +static string const g_strLink = "link"; +static string const g_strContracts = "contracts"; +static string const g_strSources = "sources"; +static string const g_strSourceList = "sourceList"; +static string const g_stdinFileNameStr = ""; + +static string const g_argAbi = g_strAbi; +static string const g_argSignatureHashes = g_strSignatureHashes; +static string const g_argGas = g_strGas; +static string const g_argAsm = g_strAsm; +static string const g_argAsmJson = g_strAsmJson; +static string const g_argAst = g_strAst; +static string const g_argAstJson = g_strAstJson; +static string const g_argBinary = g_strBinary; +static string const g_argBinaryRuntime = g_strBinaryRuntime; +static string const g_argCloneBinary = g_strCloneBinary; +static string const g_argMetadata = g_strMetadata; +static string const g_argOpcodes = g_strOpcodes; +static string const g_argNatspecDev = g_strNatspecDev; +static string const g_argNatspecUser = g_strNatspecUser; +static string const g_argAddStandard = g_strAddStandard; +static string const g_argFormal = g_strFormal; +static string const g_argOutputDir = g_strOutputDir; +static string const g_argInputFile = g_strInputFile; +static string const g_argHelp = g_strHelp; +static string const g_argVersion = g_strVersion; +static string const g_argOptimize = g_strOptimize; +static string const g_argOptimizeRuns = g_strOptimizeRuns; +static string const g_argLibraries = g_strLibraries; +static string const g_argCombinedJson = g_strCombinedJson; +static string const g_argAssemble = g_strAssemble; +static string const g_argLink = g_strLink; +static string const g_stdinFileName = g_stdinFileNameStr; /// Possible arguments to for --combined-json static set const g_combinedJsonArgs{ - "bin", - "bin-runtime", - "clone-bin", - "srcmap", - "srcmap-runtime", - "opcodes", - "abi", - "interface", - "metadata", - "asm", - "ast", - "userdoc", - "devdoc" + g_strBinary, + g_strBinaryRuntime, + g_strCloneBinary, + g_strSrcMap, + g_strSrcMapRuntime, + g_strOpcodes, + g_strAbi, + g_strInterface, + g_strMetadata, + g_strAsm, + g_strAst, + g_strNatspecUser, + g_strNatspecDev }; static void version() @@ -114,22 +159,22 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) { if (_args.count(g_argGas)) return true; - if (_args.count("output-dir")) + if (_args.count(g_argOutputDir)) return false; for (string const& arg: { - g_argAbiStr, + g_argAbi, g_argSignatureHashes, g_argMetadata, - g_argNatspecUserStr, + g_argNatspecUser, g_argAstJson, - g_argNatspecDevStr, - g_argAsmStr, - g_argAsmJsonStr, - g_argOpcodesStr, - g_argBinaryStr, - g_argRuntimeBinaryStr, - g_argCloneBinaryStr, - string("formal") + g_argNatspecDev, + g_argAsm, + g_argAsmJson, + g_argOpcodes, + g_argBinary, + g_argBinaryRuntime, + g_argCloneBinary, + g_argFormal }) if (_args.count(arg)) return true; @@ -138,9 +183,9 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) void CommandLineInterface::handleBinary(string const& _contract) { - if (m_args.count(g_argBinaryStr)) + if (m_args.count(g_argBinary)) { - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile(_contract + ".bin", m_compiler->object(_contract).toHex()); else { @@ -148,9 +193,9 @@ void CommandLineInterface::handleBinary(string const& _contract) cout << m_compiler->object(_contract).toHex() << endl; } } - if (m_args.count(g_argCloneBinaryStr)) + if (m_args.count(g_argCloneBinary)) { - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile(_contract + ".clone_bin", m_compiler->cloneObject(_contract).toHex()); else { @@ -158,9 +203,9 @@ void CommandLineInterface::handleBinary(string const& _contract) cout << m_compiler->cloneObject(_contract).toHex() << endl; } } - if (m_args.count(g_argRuntimeBinaryStr)) + if (m_args.count(g_argBinaryRuntime)) { - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile(_contract + ".bin-runtime", m_compiler->runtimeObject(_contract).toHex()); else { @@ -172,7 +217,7 @@ void CommandLineInterface::handleBinary(string const& _contract) void CommandLineInterface::handleOpcode(string const& _contract) { - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile(_contract + ".opcode", solidity::disassemble(m_compiler->object(_contract).bytecode)); else { @@ -184,9 +229,9 @@ void CommandLineInterface::handleOpcode(string const& _contract) void CommandLineInterface::handleBytecode(string const& _contract) { - if (m_args.count(g_argOpcodesStr)) + if (m_args.count(g_argOpcodes)) handleOpcode(_contract); - if (m_args.count(g_argBinaryStr) || m_args.count(g_argCloneBinaryStr) || m_args.count(g_argRuntimeBinaryStr)) + if (m_args.count(g_argBinary) || m_args.count(g_argCloneBinary) || m_args.count(g_argBinaryRuntime)) handleBinary(_contract); } @@ -199,7 +244,7 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract) for (auto const& it: m_compiler->contractDefinition(_contract).interfaceFunctions()) out += toHex(it.first.ref()) + ": " + it.second->externalSignature() + "\n"; - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile(_contract + ".signatures", out); else cout << "Function signatures: " << endl << out; @@ -225,17 +270,17 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co switch(_type) { case DocumentationType::ABIInterface: - argName = g_argAbiStr; + argName = g_argAbi; suffix = ".abi"; title = "Contract JSON ABI"; break; case DocumentationType::NatspecUser: - argName = g_argNatspecUserStr; + argName = g_argNatspecUser; suffix = ".docuser"; title = "User Documentation"; break; case DocumentationType::NatspecDev: - argName = g_argNatspecDevStr; + argName = g_argNatspecDev; suffix = ".docdev"; title = "Developer Documentation"; break; @@ -252,7 +297,7 @@ void CommandLineInterface::handleMeta(DocumentationType _type, string const& _co else output = dev::jsonPrettyPrint(m_compiler->metadata(_contract, _type)); - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile(_contract + suffix, output); else { @@ -314,10 +359,10 @@ void CommandLineInterface::handleGasEstimation(string const& _contract) void CommandLineInterface::handleFormal() { - if (!m_args.count("formal")) + if (!m_args.count(g_argFormal)) return; - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) createFile("solidity.mlw", m_compiler->formalTranslation()); else cout << "Formal version:" << endl << m_compiler->formalTranslation() << endl; @@ -327,10 +372,10 @@ void CommandLineInterface::readInputFilesAndConfigureRemappings() { vector inputFiles; bool addStdin = false; - if (!m_args.count("input-file")) + if (!m_args.count(g_argInputFile)) addStdin = true; else - for (string path: m_args["input-file"].as>()) + for (string path: m_args[g_argInputFile].as>()) { auto eq = find(path.begin(), path.end(), '='); if (eq != path.end()) @@ -405,7 +450,7 @@ void CommandLineInterface::createFile(string const& _fileName, string const& _da { namespace fs = boost::filesystem; // create directory if not existent - fs::path p(m_args.at("output-dir").as()); + fs::path p(m_args.at(g_argOutputDir).as()); fs::create_directories(p); string pathName = (p / _fileName).string(); ofstream outFile(pathName); @@ -432,66 +477,66 @@ Allowed options)", po::options_description::m_default_line_length, po::options_description::m_default_line_length - 23); desc.add_options() - ("help", "Show help message and exit.") - ("version", "Show version and exit.") - ("optimize", "Enable bytecode optimizer.") + (g_argHelp.c_str(), "Show help message and exit.") + (g_argVersion.c_str(), "Show version and exit.") + (g_argOptimize.c_str(), "Enable bytecode optimizer.") ( - "optimize-runs", + g_argOptimizeRuns.c_str(), po::value()->value_name("n")->default_value(200), "Estimated number of contract runs for optimizer tuning." ) (g_argAddStandard.c_str(), "Add standard contracts.") ( - "libraries", + g_argLibraries.c_str(), po::value>()->value_name("libs"), "Direct string or file containing library addresses. Syntax: " ":
[, or whitespace] ...\n" "Address is interpreted as a hex string optionally prefixed by 0x." ) ( - "output-dir,o", + (g_argOutputDir + ",o").c_str(), po::value()->value_name("path"), "If given, creates one file per component and contract/file at the specified directory." ) ( - "combined-json", + g_argCombinedJson.c_str(), po::value()->value_name(boost::join(g_combinedJsonArgs, ",")), "Output a single json document containing the specified information." ) (g_argGas.c_str(), "Print an estimate of the maximal gas usage for each function.") ( - "assemble", + g_argAssemble.c_str(), "Switch to assembly mode, ignoring all options and assumes input is assembly." ) ( - "link", + g_argLink.c_str(), "Switch to linker mode, ignoring all options apart from --libraries " "and modify binaries in place." ); po::options_description outputComponents("Output Components"); outputComponents.add_options() - (g_argAstStr.c_str(), "AST of all source files.") + (g_argAst.c_str(), "AST of all source files.") (g_argAstJson.c_str(), "AST of all source files in JSON format.") - (g_argAsmStr.c_str(), "EVM assembly of the contracts.") - (g_argAsmJsonStr.c_str(), "EVM assembly of the contracts in JSON format.") - (g_argOpcodesStr.c_str(), "Opcodes of the contracts.") - (g_argBinaryStr.c_str(), "Binary of the contracts in hex.") - (g_argRuntimeBinaryStr.c_str(), "Binary of the runtime part of the contracts in hex.") - (g_argCloneBinaryStr.c_str(), "Binary of the clone contracts in hex.") - (g_argAbiStr.c_str(), "ABI specification of the contracts.") + (g_argAsm.c_str(), "EVM assembly of the contracts.") + (g_argAsmJson.c_str(), "EVM assembly of the contracts in JSON format.") + (g_argOpcodes.c_str(), "Opcodes of the contracts.") + (g_argBinary.c_str(), "Binary of the contracts in hex.") + (g_argBinaryRuntime.c_str(), "Binary of the runtime part of the contracts in hex.") + (g_argCloneBinary.c_str(), "Binary of the clone contracts in hex.") + (g_argAbi.c_str(), "ABI specification of the contracts.") (g_argSignatureHashes.c_str(), "Function signature hashes of the contracts.") - (g_argNatspecUserStr.c_str(), "Natspec user documentation of all contracts.") - (g_argNatspecDevStr.c_str(), "Natspec developer documentation of all contracts.") + (g_argNatspecUser.c_str(), "Natspec user documentation of all contracts.") + (g_argNatspecDev.c_str(), "Natspec developer documentation of all contracts.") (g_argMetadata.c_str(), "Combined Metadata JSON whose Swarm hash is stored on-chain.") - ("formal", "Translated source suitable for formal analysis."); + (g_argFormal.c_str(), "Translated source suitable for formal analysis."); desc.add(outputComponents); po::options_description allOptions = desc; - allOptions.add_options()("input-file", po::value>(), "input file"); + allOptions.add_options()(g_argInputFile.c_str(), po::value>(), "input file"); // All positional options should be interpreted as input files po::positional_options_description filesPositions; - filesPositions.add("input-file", -1); + filesPositions.add(g_argInputFile.c_str(), -1); // parse the compiler arguments try @@ -506,22 +551,22 @@ Allowed options)", return false; } - if (m_args.count("help") || (isatty(fileno(stdin)) && _argc == 1)) + if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1)) { cout << desc; return false; } - if (m_args.count("version")) + if (m_args.count(g_argVersion)) { version(); return false; } - if (m_args.count("combined-json")) + if (m_args.count(g_argCombinedJson)) { vector requests; - for (string const& item: boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(","))) + for (string const& item: boost::split(requests, m_args[g_argCombinedJson].as(), boost::is_any_of(","))) if (!g_combinedJsonArgs.count(item)) { cerr << "Invalid option to --combined-json: " << item << endl; @@ -537,18 +582,18 @@ bool CommandLineInterface::processInput() { readInputFilesAndConfigureRemappings(); - if (m_args.count("libraries")) - for (string const& library: m_args["libraries"].as>()) + if (m_args.count(g_argLibraries)) + for (string const& library: m_args[g_argLibraries].as>()) if (!parseLibraryOption(library)) return false; - if (m_args.count("assemble")) + if (m_args.count(g_argAssemble)) { // switch to assembly mode m_onlyAssemble = true; return assemble(); } - if (m_args.count("link")) + if (m_args.count(g_argLink)) { // switch to linker mode m_onlyLink = true; @@ -590,16 +635,16 @@ bool CommandLineInterface::processInput() auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); }; try { - if (m_args.count("input-file")) - m_compiler->setRemappings(m_args["input-file"].as>()); + if (m_args.count(g_argInputFile)) + m_compiler->setRemappings(m_args[g_argInputFile].as>()); for (auto const& sourceCode: m_sourceCodes) m_compiler->addSource(sourceCode.first, sourceCode.second); // TODO: Perhaps we should not compile unless requested - bool optimize = m_args.count("optimize") > 0; - unsigned runs = m_args["optimize-runs"].as(); + bool optimize = m_args.count(g_argOptimize) > 0; + unsigned runs = m_args[g_argOptimizeRuns].as(); bool successful = m_compiler->compile(optimize, runs, m_libraries); - if (successful && m_args.count("formal")) + if (successful && m_args.count(g_argFormal)) if (!m_compiler->prepareFormalAnalysis()) successful = false; @@ -656,73 +701,73 @@ bool CommandLineInterface::processInput() void CommandLineInterface::handleCombinedJSON() { - if (!m_args.count("combined-json")) + if (!m_args.count(g_argCombinedJson)) return; Json::Value output(Json::objectValue); - output["version"] = ::dev::solidity::VersionString; + output[g_strVersion] = ::dev::solidity::VersionString; set requests; - boost::split(requests, m_args["combined-json"].as(), boost::is_any_of(",")); + boost::split(requests, m_args[g_argCombinedJson].as(), boost::is_any_of(",")); vector contracts = m_compiler->contractNames(); if (!contracts.empty()) - output["contracts"] = Json::Value(Json::objectValue); + output[g_strContracts] = Json::Value(Json::objectValue); for (string const& contractName: contracts) { Json::Value contractData(Json::objectValue); - if (requests.count("abi")) - contractData["abi"] = dev::jsonCompactPrint(m_compiler->interface(contractName)); + if (requests.count(g_strAbi)) + contractData[g_strAbi] = dev::jsonCompactPrint(m_compiler->interface(contractName)); if (requests.count("metadata")) contractData["metadata"] = m_compiler->onChainMetadata(contractName); - if (requests.count("bin")) - contractData["bin"] = m_compiler->object(contractName).toHex(); - if (requests.count("bin-runtime")) - contractData["bin-runtime"] = m_compiler->runtimeObject(contractName).toHex(); - if (requests.count("clone-bin")) - contractData["clone-bin"] = m_compiler->cloneObject(contractName).toHex(); - if (requests.count("opcodes")) - contractData["opcodes"] = solidity::disassemble(m_compiler->object(contractName).bytecode); - if (requests.count("asm")) + if (requests.count(g_strBinary)) + contractData[g_strBinary] = m_compiler->object(contractName).toHex(); + if (requests.count(g_strBinaryRuntime)) + contractData[g_strBinaryRuntime] = m_compiler->runtimeObject(contractName).toHex(); + if (requests.count(g_strCloneBinary)) + contractData[g_strCloneBinary] = m_compiler->cloneObject(contractName).toHex(); + if (requests.count(g_strOpcodes)) + contractData[g_strOpcodes] = solidity::disassemble(m_compiler->object(contractName).bytecode); + if (requests.count(g_strAsm)) { ostringstream unused; - contractData["asm"] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true); + contractData[g_strAsm] = m_compiler->streamAssembly(unused, contractName, m_sourceCodes, true); } - if (requests.count("srcmap")) + if (requests.count(g_strSrcMap)) { auto map = m_compiler->sourceMapping(contractName); - contractData["srcmap"] = map ? *map : ""; + contractData[g_strSrcMap] = map ? *map : ""; } - if (requests.count("srcmap-runtime")) + if (requests.count(g_strSrcMapRuntime)) { auto map = m_compiler->runtimeSourceMapping(contractName); - contractData["srcmap-runtime"] = map ? *map : ""; + contractData[g_strSrcMapRuntime] = map ? *map : ""; } - if (requests.count("devdoc")) - contractData["devdoc"] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecDev)); - if (requests.count("userdoc")) - contractData["userdoc"] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecUser)); - output["contracts"][contractName] = contractData; + if (requests.count(g_strNatspecDev)) + contractData[g_strNatspecDev] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecDev)); + if (requests.count(g_strNatspecUser)) + contractData[g_strNatspecUser] = dev::jsonCompactPrint(m_compiler->metadata(contractName, DocumentationType::NatspecUser)); + output[g_strContracts][contractName] = contractData; } - bool needsSourceList = requests.count("ast") || requests.count("srcmap") || requests.count("srcmap-runtime"); + bool needsSourceList = requests.count(g_strAst) || requests.count(g_strSrcMap) || requests.count(g_strSrcMapRuntime); if (needsSourceList) { // Indices into this array are used to abbreviate source names in source locations. - output["sourceList"] = Json::Value(Json::arrayValue); + output[g_strSourceList] = Json::Value(Json::arrayValue); for (auto const& source: m_compiler->sourceNames()) - output["sourceList"].append(source); + output[g_strSourceList].append(source); } - if (requests.count("ast")) + if (requests.count(g_strAst)) { - output["sources"] = Json::Value(Json::objectValue); + output[g_strSources] = Json::Value(Json::objectValue); for (auto const& sourceCode: m_sourceCodes) { ASTJsonConverter converter(m_compiler->ast(sourceCode.first), m_compiler->sourceIndices()); - output["sources"][sourceCode.first] = Json::Value(Json::objectValue); - output["sources"][sourceCode.first]["AST"] = converter.json(); + output[g_strSources][sourceCode.first] = Json::Value(Json::objectValue); + output[g_strSources][sourceCode.first]["AST"] = converter.json(); } } cout << dev::jsonCompactPrint(output) << endl; @@ -732,7 +777,7 @@ void CommandLineInterface::handleAst(string const& _argStr) { string title; - if (_argStr == g_argAstStr) + if (_argStr == g_argAst) title = "Syntax trees:"; else if (_argStr == g_argAstJson) title = "JSON AST:"; @@ -752,13 +797,13 @@ void CommandLineInterface::handleAst(string const& _argStr) asts ); - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) { for (auto const& sourceCode: m_sourceCodes) { stringstream data; string postfix = ""; - if (_argStr == g_argAstStr) + if (_argStr == g_argAst) { ASTPrinter printer(m_compiler->ast(sourceCode.first), sourceCode.second); printer.print(data); @@ -779,7 +824,7 @@ void CommandLineInterface::handleAst(string const& _argStr) for (auto const& sourceCode: m_sourceCodes) { cout << endl << "======= " << sourceCode.first << " =======" << endl; - if (_argStr == g_argAstStr) + if (_argStr == g_argAst) { ASTPrinter printer( m_compiler->ast(sourceCode.first), @@ -904,7 +949,7 @@ void CommandLineInterface::outputCompilationResults() handleCombinedJSON(); // do we need AST output? - handleAst(g_argAstStr); + handleAst(g_argAst); handleAst(g_argAstJson); vector contracts = m_compiler->contractNames(); @@ -914,18 +959,18 @@ void CommandLineInterface::outputCompilationResults() cout << endl << "======= " << contract << " =======" << endl; // do we need EVM assembly? - if (m_args.count(g_argAsmStr) || m_args.count(g_argAsmJsonStr)) + if (m_args.count(g_argAsm) || m_args.count(g_argAsmJson)) { - if (m_args.count("output-dir")) + if (m_args.count(g_argOutputDir)) { stringstream data; - m_compiler->streamAssembly(data, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); - createFile(contract + (m_args.count(g_argAsmJsonStr) ? "_evm.json" : ".evm"), data.str()); + m_compiler->streamAssembly(data, contract, m_sourceCodes, m_args.count(g_argAsmJson)); + createFile(contract + (m_args.count(g_argAsmJson) ? "_evm.json" : ".evm"), data.str()); } else { cout << "EVM assembly:" << endl; - m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJsonStr)); + m_compiler->streamAssembly(cout, contract, m_sourceCodes, m_args.count(g_argAsmJson)); } } From e5a992937c80c91c9b217bc53802d78d0d9069b7 Mon Sep 17 00:00:00 2001 From: Danil Nemirovsky Date: Sat, 22 Oct 2016 18:17:49 +0300 Subject: [PATCH 153/185] - alphabetically sorted string constants per name. --- solc/CommandLineInterface.cpp | 90 +++++++++++++++++------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 8e56b38ef..01f5462b5 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -66,82 +66,82 @@ namespace solidity { static string const g_strAbi = "abi"; -static string const g_strSignatureHashes = "hashes"; -static string const g_strGas = "gas"; +static string const g_strAddStandard = "add-std"; static string const g_strAsm = "asm"; static string const g_strAsmJson = "asm-json"; +static string const g_strAssemble = "assemble"; static string const g_strAst = "ast"; static string const g_strAstJson = "ast-json"; static string const g_strBinary = "bin"; static string const g_strBinaryRuntime = "bin-runtime"; static string const g_strCloneBinary = "clone-bin"; -static string const g_strOpcodes = "opcodes"; +static string const g_strCombinedJson = "combined-json"; +static string const g_strContracts = "contracts"; +static string const g_strFormal = "formal"; +static string const g_strGas = "gas"; +static string const g_strHelp = "help"; +static string const g_strInputFile = "input-file"; +static string const g_strInterface = "interface"; +static string const g_strLibraries = "libraries"; +static string const g_strLink = "link"; +static string const g_strMetadata = "metadata"; static string const g_strNatspecDev = "devdoc"; static string const g_strNatspecUser = "userdoc"; -static string const g_strMetadata = "metadata"; -static string const g_strAddStandard = "add-std"; -static string const g_strSrcMap = "srcmap"; -static string const g_strSrcMapRuntime = "srcmap-runtime"; -static string const g_strInterface = "interface"; -static string const g_strFormal = "formal"; -static string const g_strOutputDir = "output-dir"; -static string const g_strInputFile = "input-file"; -static string const g_strHelp = "help"; -static string const g_strVersion = "version"; +static string const g_strOpcodes = "opcodes"; static string const g_strOptimize = "optimize"; static string const g_strOptimizeRuns = "optimize-runs"; -static string const g_strLibraries = "libraries"; -static string const g_strCombinedJson = "combined-json"; -static string const g_strAssemble = "assemble"; -static string const g_strLink = "link"; -static string const g_strContracts = "contracts"; +static string const g_strOutputDir = "output-dir"; +static string const g_strSignatureHashes = "hashes"; static string const g_strSources = "sources"; static string const g_strSourceList = "sourceList"; +static string const g_strSrcMap = "srcmap"; +static string const g_strSrcMapRuntime = "srcmap-runtime"; +static string const g_strVersion = "version"; static string const g_stdinFileNameStr = ""; static string const g_argAbi = g_strAbi; -static string const g_argSignatureHashes = g_strSignatureHashes; -static string const g_argGas = g_strGas; +static string const g_argAddStandard = g_strAddStandard; static string const g_argAsm = g_strAsm; static string const g_argAsmJson = g_strAsmJson; +static string const g_argAssemble = g_strAssemble; static string const g_argAst = g_strAst; static string const g_argAstJson = g_strAstJson; static string const g_argBinary = g_strBinary; static string const g_argBinaryRuntime = g_strBinaryRuntime; static string const g_argCloneBinary = g_strCloneBinary; +static string const g_argCombinedJson = g_strCombinedJson; +static string const g_argFormal = g_strFormal; +static string const g_argGas = g_strGas; +static string const g_argHelp = g_strHelp; +static string const g_argInputFile = g_strInputFile; +static string const g_argLibraries = g_strLibraries; +static string const g_argLink = g_strLink; static string const g_argMetadata = g_strMetadata; -static string const g_argOpcodes = g_strOpcodes; static string const g_argNatspecDev = g_strNatspecDev; static string const g_argNatspecUser = g_strNatspecUser; -static string const g_argAddStandard = g_strAddStandard; -static string const g_argFormal = g_strFormal; -static string const g_argOutputDir = g_strOutputDir; -static string const g_argInputFile = g_strInputFile; -static string const g_argHelp = g_strHelp; -static string const g_argVersion = g_strVersion; +static string const g_argOpcodes = g_strOpcodes; static string const g_argOptimize = g_strOptimize; static string const g_argOptimizeRuns = g_strOptimizeRuns; -static string const g_argLibraries = g_strLibraries; -static string const g_argCombinedJson = g_strCombinedJson; -static string const g_argAssemble = g_strAssemble; -static string const g_argLink = g_strLink; +static string const g_argOutputDir = g_strOutputDir; +static string const g_argSignatureHashes = g_strSignatureHashes; +static string const g_argVersion = g_strVersion; static string const g_stdinFileName = g_stdinFileNameStr; /// Possible arguments to for --combined-json static set const g_combinedJsonArgs{ + g_strAbi, + g_strAsm, + g_strAst, g_strBinary, g_strBinaryRuntime, g_strCloneBinary, - g_strSrcMap, - g_strSrcMapRuntime, - g_strOpcodes, - g_strAbi, g_strInterface, g_strMetadata, - g_strAsm, - g_strAst, g_strNatspecUser, - g_strNatspecDev + g_strNatspecDev, + g_strOpcodes, + g_strSrcMap, + g_strSrcMapRuntime }; static void version() @@ -163,18 +163,18 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) return false; for (string const& arg: { g_argAbi, - g_argSignatureHashes, - g_argMetadata, - g_argNatspecUser, - g_argAstJson, - g_argNatspecDev, g_argAsm, g_argAsmJson, - g_argOpcodes, + g_argAstJson, g_argBinary, g_argBinaryRuntime, g_argCloneBinary, - g_argFormal + g_argFormal, + g_argMetadata, + g_argNatspecUser, + g_argNatspecDev, + g_argOpcodes, + g_argSignatureHashes }) if (_args.count(arg)) return true; From 05139500fb44c1ff574756b3a5d10d46674c236d Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 1 Dec 2016 10:55:02 -0300 Subject: [PATCH 154/185] Warn about using msg.value in non-payable function --- libsolidity/analysis/StaticAnalyzer.cpp | 78 ++++++++++++++++ libsolidity/analysis/StaticAnalyzer.h | 72 +++++++++++++++ libsolidity/ast/Types.h | 2 + libsolidity/interface/CompilerStack.cpp | 10 +++ .../SolidityNameAndTypeResolution.cpp | 90 ++++++++++++++++++- 5 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 libsolidity/analysis/StaticAnalyzer.cpp create mode 100644 libsolidity/analysis/StaticAnalyzer.h diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp new file mode 100644 index 000000000..c39f874e4 --- /dev/null +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -0,0 +1,78 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Federico Bond + * @date 2016 + * Static analyzer and checker. + */ + +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; + + +bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit) +{ + _sourceUnit.accept(*this); + return Error::containsOnlyWarnings(m_errors); +} + +bool StaticAnalyzer::visit(ContractDefinition const& _contract) +{ + m_library = _contract.isLibrary(); + return true; +} + +void StaticAnalyzer::endVisit(ContractDefinition const&) +{ + m_library = false; +} + +bool StaticAnalyzer::visit(FunctionDefinition const& _function) +{ + m_nonPayablePublic = _function.isPublic() && !_function.isPayable(); + return true; +} + +void StaticAnalyzer::endVisit(FunctionDefinition const&) +{ + m_nonPayablePublic = false; +} + +bool StaticAnalyzer::visit(MemberAccess const& _memberAccess) +{ + if (m_nonPayablePublic && !m_library) + if (MagicType const* type = dynamic_cast(_memberAccess.expression().annotation().type.get())) + if (type->kind() == MagicType::Kind::Message && _memberAccess.memberName() == "value") + warning(_memberAccess.location(), "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?"); + + return true; +} + +void StaticAnalyzer::warning(SourceLocation const& _location, string const& _description) +{ + auto err = make_shared(Error::Type::Warning); + *err << + errinfo_sourceLocation(_location) << + errinfo_comment(_description); + + m_errors.push_back(err); +} diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h new file mode 100644 index 000000000..b6cf783ee --- /dev/null +++ b/libsolidity/analysis/StaticAnalyzer.h @@ -0,0 +1,72 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * @author Federico Bond + * @date 2016 + * Static analyzer and checker. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace dev +{ +namespace solidity +{ + + +/** + * The module that performs static analysis on the AST. + */ +class StaticAnalyzer: private ASTConstVisitor +{ +public: + /// @param _errors the reference to the list of errors and warnings to add them found during static analysis. + explicit StaticAnalyzer(ErrorList& _errors): m_errors(_errors) {} + + /// Performs static analysis on the given source unit and all of its sub-nodes. + /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings + bool analyze(SourceUnit const& _sourceUnit); + +private: + /// Adds a new warning to the list of errors. + void warning(SourceLocation const& _location, std::string const& _description); + + virtual bool visit(ContractDefinition const& _contract) override; + virtual void endVisit(ContractDefinition const& _contract) override; + + virtual bool visit(FunctionDefinition const& _function) override; + virtual void endVisit(FunctionDefinition const& _function) override; + + virtual bool visit(MemberAccess const& _memberAccess) override; + + ErrorList& m_errors; + + /// Flag that indicates whether the current contract definition is a library. + bool m_library = false; + + /// Flag that indicates whether a public function does not contain the "payable" modifier. + bool m_nonPayablePublic = false; +}; + +} +} diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 72640a1c4..26e2b8f29 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1117,6 +1117,8 @@ public: virtual std::string toString(bool _short) const override; + Kind kind() const { return m_kind; } + private: Kind m_kind; }; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index b4fd6d87c..eb588fc2e 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -202,6 +203,15 @@ bool CompilerStack::parse() m_contracts[contract->name()].contract = contract; } + + if (noErrors) + { + StaticAnalyzer staticAnalyzer(m_errors); + for (Source const* source: m_sourceOrder) + if (!staticAnalyzer.analyze(*source->ast)) + noErrors = false; + } + m_parseSuccessful = noErrors; return m_parseSuccessful; } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 11c381149..a4e601f74 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -89,8 +90,12 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, TypeChecker typeChecker(errors); bool success = typeChecker.checkTypeRequirements(*contract); BOOST_CHECK(success || !errors.empty()); - } + if (success) + { + StaticAnalyzer staticAnalyzer(errors); + staticAnalyzer.analyze(*sourceUnit); + } if (errors.size() > 1 && !_allowMultipleErrors) BOOST_FAIL("Multiple errors found"); for (auto const& currentError: errors) @@ -189,6 +194,14 @@ CHECK_ERROR_OR_WARNING(text, Warning, substring, true, false) // [checkSuccess(text)] asserts that the compilation down to typechecking succeeds. #define CHECK_SUCCESS(text) do { BOOST_CHECK(success((text))); } while(0) +#define CHECK_SUCCESS_NO_WARNINGS(text) \ +do \ +{ \ + auto sourceAndError = parseAnalyseAndReturnError((text), true); \ + BOOST_CHECK(sourceAndError.second == nullptr); \ +} \ +while(0) + BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) @@ -4777,6 +4790,81 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) CHECK_ERROR(text, TypeError, ""); } +BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) +{ + char const* text = R"( + contract C { + function f() { + msg.value; + } + } + )"; + CHECK_WARNING(text, "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?"); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_payable_function) +{ + char const* text = R"( + contract C { + function f() payable { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_internal_function) +{ + char const* text = R"( + contract C { + function f() internal { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_library) +{ + char const* text = R"( + library C { + function f() { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_non_magic_msg_value) +{ + char const* text = R"( + contract C { + struct msg { + uint256 value; + } + + function f() { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_public_function) +{ + char const* text = R"( + contract c { + function f() { } + modifier m() { msg.value; _; } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + BOOST_AUTO_TEST_SUITE_END() } From 6a40318138f297d179fc20dfc3c713296e74212f Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Dec 2016 14:18:10 +0100 Subject: [PATCH 155/185] Display tx hash for debugging. --- test/ExecutionFramework.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 9e3ecac39..ddcd9cb68 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -62,7 +62,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << endl; if (_value > 0) cout << " value: " << _value << endl; - cout << " in: " << toHex(_data) << endl; + cout << " in: " << toHex(_data) << endl; } RPCSession::TransactionData d; d.data = "0x" + toHex(_data); @@ -91,7 +91,10 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 } if (m_showMessages) - cout << " out: " << toHex(m_output) << endl; + { + cout << " out: " << toHex(m_output) << endl; + cout << " tx hash: " << txHash << endl; + } m_gasUsed = u256(receipt.gasUsed); m_logs.clear(); From dac95ce39814e20cd86e5d759ae046b011ab11c1 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Sun, 11 Dec 2016 00:41:41 -0300 Subject: [PATCH 156/185] Remove unused variable inputFiles --- solc/CommandLineInterface.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 6e59099aa..c83432ca2 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -325,7 +325,6 @@ void CommandLineInterface::handleFormal() void CommandLineInterface::readInputFilesAndConfigureRemappings() { - vector inputFiles; bool addStdin = false; if (!m_args.count("input-file")) addStdin = true; From df762302400ad95218ea3205d8e30332ec567028 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Sun, 11 Dec 2016 02:07:08 -0300 Subject: [PATCH 157/185] Fix names of JSON AST nodes --- libsolidity/ast/ASTJsonConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index f6b06be66..493707b9c 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -318,7 +318,7 @@ bool ASTJsonConverter::visit(Throw const& _node) bool ASTJsonConverter::visit(VariableDeclarationStatement const& _node) { - addJsonNode(_node, "VariableDefinitionStatement", {}, true); + addJsonNode(_node, "VariableDeclarationStatement", {}, true); return true; } @@ -407,7 +407,7 @@ bool ASTJsonConverter::visit(Identifier const& _node) bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node) { - addJsonNode(_node, "ElementaryTypenameExpression", { + addJsonNode(_node, "ElementaryTypeNameExpression", { make_pair("value", _node.typeName().toString()), make_pair("type", type(_node)) }); From b6fcc5ffb0af6c3dd9bdf6f1b784e6fea076a594 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Sun, 11 Dec 2016 12:11:04 -0300 Subject: [PATCH 158/185] Fix typos in comments --- libdevcore/JSON.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libdevcore/JSON.h b/libdevcore/JSON.h index 0d6e0d2e8..9f7d9a038 100644 --- a/libdevcore/JSON.h +++ b/libdevcore/JSON.h @@ -27,13 +27,13 @@ namespace dev { -/// Serialise the JSON object (@a _input) with identation +/// Serialise the JSON object (@a _input) with indentation inline std::string jsonPrettyPrint(Json::Value const& _input) { return Json::StyledWriter().write(_input); } -/// Serialise theJ SON object (@a _input) without identation +/// Serialise the JSON object (@a _input) without indentation inline std::string jsonCompactPrint(Json::Value const& _input) { Json::FastWriter writer; From d0542f0e369a95ed2ae2a02cec2a199e3844c885 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sun, 11 Dec 2016 16:46:58 +0100 Subject: [PATCH 159/185] Warn if msg.value is used in non-payable function. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index c76d10e17..1eb90c222 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.7 (unreleased) Features: + * Type checker: Warn when ``msg.value`` is used in non-payable function. * Code generator: Inject the Swarm hash of a metadata file into the bytecode. * Optimizer: Some dead code elimination. From 4abc8ab5a9c1d2505cf781796f65de457028514d Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 20 Oct 2016 00:02:44 +0100 Subject: [PATCH 160/185] Add usingIdentity option to CompilerUtils::memoryCopy --- libsolidity/codegen/CompilerUtils.cpp | 9 ++++++++- libsolidity/codegen/CompilerUtils.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 7c159ff7d..461803fa8 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -298,9 +298,16 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type) m_context << Instruction::SWAP1 << Instruction::POP; } -void CompilerUtils::memoryCopy() +void CompilerUtils::memoryCopy(bool _useIdentityPrecompile) { // Stack here: size target source + + if (!_useIdentityPrecompile) + { + // FIXME + return; + } + // stack for call: outsize target size source value contract gas //@TODO do not use ::CALL if less than 32 bytes? m_context << Instruction::DUP3 << Instruction::SWAP1; diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 0a5d8e1c5..fdcd1dfc8 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -112,7 +112,7 @@ public: /// Uses a CALL to the identity contract to perform a memory-to-memory copy. /// Stack pre: /// Stack post: - void memoryCopy(); + void memoryCopy(bool _useIdentityPrecompile = true); /// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true) /// external function type
into two stack slots: From 1bf412d9fd9a4d55802ebe4eb006cf835d371d90 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 30 Nov 2016 22:44:33 +0000 Subject: [PATCH 161/185] Implement CompilerUtils::memoryCopy using inline assembly --- libsolidity/codegen/CompilerUtils.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 461803fa8..634474a12 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -304,7 +304,32 @@ void CompilerUtils::memoryCopy(bool _useIdentityPrecompile) if (!_useIdentityPrecompile) { - // FIXME + m_context.appendInlineAssembly(R"( + { + // expects three locals: src, dst, len + + // copy 32 bytes at once + start32: + jumpi(end32, lt(len, 32)) + mstore(dst, mload(src)) + dst := add(dst, 32) + src := add(src, 32) + len := sub(len, 32) + jump(start32) + end32: + + // copy the remainder (0 < len < 32) + let mask := sub(exp(256, sub(32, len)), 1) + let srcpart := and(mload(src), not(mask)) + let dstpart := and(mload(dst), mask) + mstore(dst, or(srcpart, dstpart)) + } + )", + { "len", "dst", "src" } + ); + m_context << Instruction::POP; + m_context << Instruction::POP; + m_context << Instruction::POP; return; } From bf5dac1fb255a54825952219c852869b8c2663e9 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 2 Dec 2016 10:23:41 +0000 Subject: [PATCH 162/185] Turn off the identity precompile for testing --- libsolidity/codegen/CompilerUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index fdcd1dfc8..52b5b0d62 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -112,7 +112,7 @@ public: /// Uses a CALL to the identity contract to perform a memory-to-memory copy. /// Stack pre: /// Stack post: - void memoryCopy(bool _useIdentityPrecompile = true); + void memoryCopy(bool _useIdentityPrecompile = false); /// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true) /// external function type
into two stack slots: From b93589b3b62ca12fe5446d7caed0c0964158cd6e Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 2 Dec 2016 13:14:18 +0000 Subject: [PATCH 163/185] Implement identity call in inline assembly --- libsolidity/codegen/CompilerUtils.cpp | 35 ++++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 634474a12..8b94bd0de 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -300,6 +300,8 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type) void CompilerUtils::memoryCopy(bool _useIdentityPrecompile) { + //@TODO do not use ::CALL if less than 32 bytes? + // Stack here: size target source if (!_useIdentityPrecompile) @@ -332,20 +334,25 @@ void CompilerUtils::memoryCopy(bool _useIdentityPrecompile) m_context << Instruction::POP; return; } - - // stack for call: outsize target size source value contract gas - //@TODO do not use ::CALL if less than 32 bytes? - m_context << Instruction::DUP3 << Instruction::SWAP1; - m_context << u256(0) << u256(identityContractAddress); - // compute gas costs - m_context << u256(32) << Instruction::DUP5 << u256(31) << Instruction::ADD; - static unsigned c_identityGas = 15; - static unsigned c_identityWordGas = 3; - m_context << Instruction::DIV << u256(c_identityWordGas) << Instruction::MUL; - m_context << u256(c_identityGas) << Instruction::ADD; - m_context << Instruction::CALL; - m_context << Instruction::ISZERO; - m_context.appendConditionalJumpTo(m_context.errorTag()); + else + { + m_context.appendInlineAssembly(R"( + { + let words := div(add(len, 31), 32) + let cost := add(15, mul(3, words)) + jump(invalidJumpLabel, iszero(call(cost, $identityContractAddress, 0, src, len, dst, len))) + } + )", + { "len", "dst", "src" }, + map { + { "$identityContractAddress", toString(identityContractAddress) } + } + ); + m_context << Instruction::POP; + m_context << Instruction::POP; + m_context << Instruction::POP; + return; + } } void CompilerUtils::splitExternalFunctionType(bool _leftAligned) From 4a11200a272278383a003262361d865689d1c87b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 3 Dec 2016 00:21:29 +0000 Subject: [PATCH 164/185] Better assert message for appendInlineAssembnly --- libsolidity/codegen/CompilerContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 2de5a3ec2..3a70e5235 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -217,7 +217,7 @@ void CompilerContext::appendInlineAssembly( return true; }; - solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), ""); + solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), "Failed to assemble inline assembly block."); } FunctionDefinition const& CompilerContext::resolveVirtualFunction( From efd7b4bfbb5fef99bcf4ee7c98c2ade4c1467f87 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 3 Dec 2016 00:21:46 +0000 Subject: [PATCH 165/185] Reset stack height after inline assembly block --- libsolidity/codegen/CompilerContext.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 3a70e5235..597505045 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -218,6 +218,7 @@ void CompilerContext::appendInlineAssembly( }; solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), "Failed to assemble inline assembly block."); + setStackOffset(startStackHeight); } FunctionDefinition const& CompilerContext::resolveVirtualFunction( From 4184525d4ad7aff3acb2d521c3cdc21054e36eff Mon Sep 17 00:00:00 2001 From: chriseth Date: Sun, 11 Dec 2016 17:50:59 +0100 Subject: [PATCH 166/185] Fix inline assembly. --- libsolidity/codegen/CompilerContext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 597505045..c14ab845d 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -202,6 +202,8 @@ void CompilerContext::appendInlineAssembly( return false; unsigned stackDepth = _localVariables.end() - it; int stackDiff = _assembly.deposit() - startStackHeight + stackDepth; + if (_context == assembly::CodeGenerator::IdentifierContext::LValue) + stackDiff -= 1; if (stackDiff < 1 || stackDiff > 16) BOOST_THROW_EXCEPTION( CompilerError() << @@ -218,7 +220,6 @@ void CompilerContext::appendInlineAssembly( }; solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, *m_asm, identifierAccess), "Failed to assemble inline assembly block."); - setStackOffset(startStackHeight); } FunctionDefinition const& CompilerContext::resolveVirtualFunction( From bfa4f451160bff14d79bf6e25d969b1f586a8b00 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sun, 11 Dec 2016 17:51:17 +0100 Subject: [PATCH 167/185] Split memcopy into three functions. --- libsolidity/codegen/ArrayUtils.cpp | 9 ++- libsolidity/codegen/CompilerUtils.cpp | 112 ++++++++++++++------------ libsolidity/codegen/CompilerUtils.h | 10 ++- 3 files changed, 78 insertions(+), 53 deletions(-) diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 2c982982e..352c7177a 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -335,9 +335,14 @@ void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWord if (baseSize > 1) m_context << u256(baseSize) << Instruction::MUL; // stack: - //@TODO do not use ::CALL if less than 32 bytes? m_context << Instruction::DUP1 << Instruction::DUP4 << Instruction::DUP4; - utils.memoryCopy(); + // We can resort to copying full 32 bytes only if + // - the length is known to be a multiple of 32 or + // - we will pad to full 32 bytes later anyway. + if (((baseSize % 32) == 0) || _padToWordBoundaries) + utils.memoryCopy32(); + else + utils.memoryCopy(); m_context << Instruction::SWAP1 << Instruction::POP; // stack: diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 8b94bd0de..da2e78e83 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -298,61 +298,73 @@ void CompilerUtils::zeroInitialiseMemoryArray(ArrayType const& _type) m_context << Instruction::SWAP1 << Instruction::POP; } -void CompilerUtils::memoryCopy(bool _useIdentityPrecompile) +void CompilerUtils::memoryCopyPrecompile() { - //@TODO do not use ::CALL if less than 32 bytes? - // Stack here: size target source - if (!_useIdentityPrecompile) - { - m_context.appendInlineAssembly(R"( - { - // expects three locals: src, dst, len + m_context.appendInlineAssembly(R"( + { + let words := div(add(len, 31), 32) + let cost := add(15, mul(3, words)) + jumpi(invalidJumpLabel, iszero(call(cost, $identityContractAddress, 0, src, len, dst, len))) + } + )", + { "len", "dst", "src" }, + map { + { "$identityContractAddress", toString(identityContractAddress) } + } + ); + m_context << Instruction::POP << Instruction::POP << Instruction::POP; +} - // copy 32 bytes at once - start32: - jumpi(end32, lt(len, 32)) - mstore(dst, mload(src)) - dst := add(dst, 32) - src := add(src, 32) - len := sub(len, 32) - jump(start32) - end32: +void CompilerUtils::memoryCopy32() +{ + // Stack here: size target source - // copy the remainder (0 < len < 32) - let mask := sub(exp(256, sub(32, len)), 1) - let srcpart := and(mload(src), not(mask)) - let dstpart := and(mload(dst), mask) - mstore(dst, or(srcpart, dstpart)) - } - )", - { "len", "dst", "src" } - ); - m_context << Instruction::POP; - m_context << Instruction::POP; - m_context << Instruction::POP; - return; - } - else - { - m_context.appendInlineAssembly(R"( - { - let words := div(add(len, 31), 32) - let cost := add(15, mul(3, words)) - jump(invalidJumpLabel, iszero(call(cost, $identityContractAddress, 0, src, len, dst, len))) - } - )", - { "len", "dst", "src" }, - map { - { "$identityContractAddress", toString(identityContractAddress) } - } - ); - m_context << Instruction::POP; - m_context << Instruction::POP; - m_context << Instruction::POP; - return; - } + m_context.appendInlineAssembly(R"( + { + jumpi(end, eq(len, 0)) + start: + mstore(dst, mload(src)) + jumpi(end, iszero(gt(len, 32))) + dst := add(dst, 32) + src := add(src, 32) + len := sub(len, 32) + jump(start) + end: + } + )", + { "len", "dst", "src" } + ); + m_context << Instruction::POP << Instruction::POP << Instruction::POP; +} + +void CompilerUtils::memoryCopy() +{ + // Stack here: size target source + + m_context.appendInlineAssembly(R"( + { + // copy 32 bytes at once + start32: + jumpi(end32, lt(len, 32)) + mstore(dst, mload(src)) + dst := add(dst, 32) + src := add(src, 32) + len := sub(len, 32) + jump(start32) + end32: + + // copy the remainder (0 < len < 32) + let mask := sub(exp(256, sub(32, len)), 1) + let srcpart := and(mload(src), not(mask)) + let dstpart := and(mload(dst), mask) + mstore(dst, or(srcpart, dstpart)) + } + )", + { "len", "dst", "src" } + ); + m_context << Instruction::POP << Instruction::POP << Instruction::POP; } void CompilerUtils::splitExternalFunctionType(bool _leftAligned) diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 52b5b0d62..ad53efea4 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -112,7 +112,15 @@ public: /// Uses a CALL to the identity contract to perform a memory-to-memory copy. /// Stack pre: /// Stack post: - void memoryCopy(bool _useIdentityPrecompile = false); + void memoryCopyPrecompile(); + /// Copies full 32 byte words in memory (regions cannot overlap), i.e. may copy more than length. + /// Stack pre: + /// Stack post: + void memoryCopy32(); + /// Copies data in memory (regions cannot overlap). + /// Stack pre: + /// Stack post: + void memoryCopy(); /// Converts the combined and left-aligned (right-aligned if @a _rightAligned is true) /// external function type
into two stack slots: From 81d7e0233aa24a2d38103b2bf746cef5eb12a893 Mon Sep 17 00:00:00 2001 From: chriseth Date: Sun, 11 Dec 2016 17:58:22 +0100 Subject: [PATCH 168/185] Changelog entry. --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 1eb90c222..c3b3f5fad 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Features: * Type checker: Warn when ``msg.value`` is used in non-payable function. * Code generator: Inject the Swarm hash of a metadata file into the bytecode. + * Code generator: Replace expensive memcpy precompile by simple assembly loop. * Optimizer: Some dead code elimination. Bugfixes: From b8b4f5e9f9a89eac1218551b5da322b41c7813f4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sat, 30 Apr 2016 00:15:22 +0100 Subject: [PATCH 169/185] Support bitshifting in variables --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 5 + libsolidity/codegen/ExpressionCompiler.cpp | 49 +++- libsolidity/codegen/ExpressionCompiler.h | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 298 +++++++++++++++++++++ 5 files changed, 346 insertions(+), 9 deletions(-) diff --git a/Changelog.md b/Changelog.md index 1eb90c222..9bc465ee8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.4.7 (unreleased) Features: + * Bitshift operators. * Type checker: Warn when ``msg.value`` is used in non-payable function. * Code generator: Inject the Swarm hash of a metadata file into the bytecode. * Optimizer: Some dead code elimination. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index d9660bc08..6b4dd4327 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -347,6 +347,11 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe // All integer types can be compared if (Token::isCompareOp(_operator)) return commonType; + // Disable >>> here. + if (_operator == Token::SHR) + return TypePointer(); + if (Token::isShiftOp(_operator) && !isAddress()) // && !_other->isAddress()) + return shared_from_this(); if (Token::isBooleanOp(_operator)) return TypePointer(); if (auto intType = dynamic_pointer_cast(commonType)) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 5748d818b..d28ffed8f 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -211,6 +211,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) Token::Value op = _assignment.assignmentOperator(); if (op != Token::Assign) // compound assignment { + Token::Value target_op = Token::AssignmentToBinaryOp(op); solUnimplementedAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types."); unsigned lvalueSize = m_currentLValue->sizeOnStack(); unsigned itemSize = _assignment.annotation().type->sizeOnStack(); @@ -221,7 +222,11 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) // value lvalue_ref value lvalue_ref } m_currentLValue->retrieveValue(_assignment.location(), true); - appendOrdinaryBinaryOperatorCode(Token::AssignmentToBinaryOp(op), *_assignment.annotation().type); + if (Token::isShiftOp(target_op)) + // shift only cares about the signedness of both sides + appendShiftOperatorCode(target_op, *_assignment.leftHandSide().annotation().type, *_assignment.rightHandSide().annotation().type); + else + appendOrdinaryBinaryOperatorCode(target_op, *_assignment.annotation().type); if (lvalueSize > 0) { solAssert(itemSize + lvalueSize <= 16, "Stack too deep, try removing local variables."); @@ -361,7 +366,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) else { bool cleanupNeeded = false; - if (Token::isCompareOp(c_op)) + if (Token::isCompareOp(c_op) || Token::isShiftOp(c_op)) cleanupNeeded = true; if (commonType.category() == Type::Category::Integer && (c_op == Token::Div || c_op == Token::Mod)) cleanupNeeded = true; @@ -386,7 +391,10 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) leftExpression.accept(*this); utils().convertType(*leftExpression.annotation().type, commonType, cleanupNeeded); } - if (Token::isCompareOp(c_op)) + if (Token::isShiftOp(c_op)) + // shift only cares about the signedness of both sides + appendShiftOperatorCode(c_op, *leftExpression.annotation().type, *rightExpression.annotation().type); + else if (Token::isCompareOp(c_op)) appendCompareOperatorCode(c_op, commonType); else appendOrdinaryBinaryOperatorCode(c_op, commonType); @@ -1326,8 +1334,6 @@ void ExpressionCompiler::appendOrdinaryBinaryOperatorCode(Token::Value _operator appendArithmeticOperatorCode(_operator, _type); else if (Token::isBitOp(_operator)) appendBitOperatorCode(_operator); - else if (Token::isShiftOp(_operator)) - appendShiftOperatorCode(_operator); else BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown binary operator.")); } @@ -1390,17 +1396,44 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator) } } -void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator) +void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type const& _leftType, Type const& _rightType) { - solUnimplemented("Shift operators not yet implemented."); + // stack: rvalue lvalue + + bool c_leftSigned = false; + if (auto leftType = dynamic_cast(&_leftType)) + c_leftSigned = leftType->isSigned(); + else + solUnimplemented("Only IntegerType can be shifted."); + + // The RValue can be a RationalNumberType too. + bool c_rightSigned = false; + if (auto rightType = dynamic_cast(&_rightType)) + { + solAssert(rightType->integerType(), "integerType() called for fractional number."); + c_rightSigned = rightType->integerType()->isSigned(); + } + else if (auto rightType = dynamic_cast(&_rightType)) + c_rightSigned = rightType->isSigned(); + else + solUnimplemented("Not implemented yet - FixedPointType."); + + // shift with negative rvalue throws exception + if (c_rightSigned) + { + m_context << u256(0) << Instruction::DUP3 << Instruction::SLT; + m_context.appendConditionalJumpTo(m_context.errorTag()); + } + switch (_operator) { case Token::SHL: + m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::MUL; break; case Token::SAR: + m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_leftSigned ? Instruction::SDIV : Instruction::DIV); break; case Token::SHR: - break; default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown shift operator.")); } diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index f08bded97..e6cf382c2 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -91,7 +91,7 @@ private: void appendArithmeticOperatorCode(Token::Value _operator, Type const& _type); void appendBitOperatorCode(Token::Value _operator); - void appendShiftOperatorCode(Token::Value _operator); + void appendShiftOperatorCode(Token::Value _operator, Type const& _leftType, Type const& _rightType); /// @} /// Appends code to call a function of the given type with the given arguments. diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 2df6e9f25..837caa2d6 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8456,6 +8456,304 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_right) BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x42))); } +BOOST_AUTO_TEST_CASE(shift_left) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_uint32) +{ + char const* sourceCode = R"( + contract C { + function f(uint32 a, uint32 b) returns (uint) { + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_uint8) +{ + char const* sourceCode = R"( + contract C { + function f(uint8 a, uint8 b) returns (uint) { + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + a <<= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_garbled) +{ + char const* sourceCode = R"( + contract C { + function f(uint8 a, uint8 b) returns (uint) { + assembly { + a := 0xffffffff + } + // Higher bits should be cleared before the shift + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); +} + +BOOST_AUTO_TEST_CASE(shift_right_uint32) +{ + char const* sourceCode = R"( + contract C { + function f(uint32 a, uint32 b) returns (uint) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_uint8) +{ + char const* sourceCode = R"( + contract C { + function f(uint8 a, uint8 b) returns (uint) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0x0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + a >>= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + a >>= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_negative_rvalue) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + return a << b; + } + function g(int a, int b) returns (int) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + a <<= b; + return a; + } + function g(int a, int b) returns (int) { + a >>= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint a) { + a = 0x42; + a <<= 8; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x4200))); +} + +BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint a) { + a = 0x4200; + a >>= 8; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x42))); +} + +BOOST_AUTO_TEST_CASE(shift_cleanup) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint16 x) { + x = 0xffff; + x += 32; + x <<= 8; + x >>= 16; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); +} + +BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint8 x) { + assembly { + x := 0xffff + } + x >>= 8; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); +} + +BOOST_AUTO_TEST_CASE(shift_overflow) +{ + char const* sourceCode = R"( + contract C { + function leftU(uint8 x, uint8 y) returns (uint8) { + return x << y; + } + function leftS(int8 x, int8 y) returns (int8) { + return x << y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1) == encodeArgs(u256(254))); + BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0) == encodeArgs(u256(255))); + + BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(128))); + BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); +} + BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) { char const* sourceCode = R"( From 2df60bec923e1bac74cde00ae9bda641ca29d6c1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 5 Dec 2016 18:40:50 +0100 Subject: [PATCH 170/185] Type after shift should be type of left operand. --- libsolidity/ast/Types.cpp | 47 ++++++++++++++++++++--- test/libsolidity/SolidityEndToEndTest.cpp | 15 ++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 6b4dd4327..896d51fad 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -340,6 +340,28 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe _other->category() != category() ) return TypePointer(); + if (Token::isShiftOp(_operator)) + { + // Disable >>> here. + if (_operator == Token::SHR) + return TypePointer(); + + // Shifts are not symmetric with respect to the type + if (isAddress()) + return TypePointer(); + if (IntegerType const* otherInt = dynamic_cast(_other.get())) + { + if (!otherInt->isAddress()) + return shared_from_this(); + } + else if (RationalNumberType const* otherRat = dynamic_cast(_other.get())) + { + if (!otherRat->isFractional()) + return shared_from_this(); + } + return TypePointer(); + } + auto commonType = Type::commonType(shared_from_this(), _other); //might be a integer or fixed point if (!commonType) return TypePointer(); @@ -347,11 +369,6 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe // All integer types can be compared if (Token::isCompareOp(_operator)) return commonType; - // Disable >>> here. - if (_operator == Token::SHR) - return TypePointer(); - if (Token::isShiftOp(_operator) && !isAddress()) // && !_other->isAddress()) - return shared_from_this(); if (Token::isBooleanOp(_operator)) return TypePointer(); if (auto intType = dynamic_pointer_cast(commonType)) @@ -959,6 +976,26 @@ TypePointer FixedBytesType::unaryOperatorResult(Token::Value _operator) const TypePointer FixedBytesType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const { + if (Token::isShiftOp(_operator)) + { + // Disable >>> here. + if (_operator == Token::SHR) + return TypePointer(); + + // Shifts are not symmetric with respect to the type + if (IntegerType const* otherInt = dynamic_cast(_other.get())) + { + if (!otherInt->isAddress()) + return shared_from_this(); + } + else if (RationalNumberType const* otherRat = dynamic_cast(_other.get())) + { + if (!otherRat->isFractional()) + return shared_from_this(); + } + return TypePointer(); + } + auto commonType = dynamic_pointer_cast(Type::commonType(shared_from_this(), _other)); if (!commonType) return TypePointer(); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 837caa2d6..0ac88a819 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8505,6 +8505,21 @@ BOOST_AUTO_TEST_CASE(shift_left_uint8) BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0))); } +BOOST_AUTO_TEST_CASE(shift_left_larger_type) +{ + char const* sourceCode = R"( + contract C { + function f() returns (int8) { + uint8 x = 255; + int8 y = 1; + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1) << 255)); +} + BOOST_AUTO_TEST_CASE(shift_left_assignment) { char const* sourceCode = R"( From 273804503096d8d5d0c9d1fcece48da871f2d90f Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 6 Dec 2016 23:45:17 +0100 Subject: [PATCH 171/185] Cleaner shift handling and type conversion for binary operations. --- libsolidity/ast/Types.cpp | 50 ++++----- libsolidity/codegen/ExpressionCompiler.cpp | 119 +++++++++++++-------- libsolidity/codegen/ExpressionCompiler.h | 6 +- test/libsolidity/SolidityEndToEndTest.cpp | 25 ++++- 4 files changed, 122 insertions(+), 78 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 896d51fad..03ff84718 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -251,6 +251,19 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition return members; } +bool isValidShiftAndAmountType(Token::Value _operator, Type const& _shiftAmountType) +{ + // Disable >>> here. + if (_operator == Token::SHR) + return false; + else if (IntegerType const* otherInt = dynamic_cast(&_shiftAmountType)) + return !otherInt->isAddress(); + else if (RationalNumberType const* otherRat = dynamic_cast(&_shiftAmountType)) + return otherRat->integerType() && !otherRat->integerType()->isSigned(); + else + return false; +} + IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): m_bits(_bits), m_modifier(_modifier) { @@ -342,24 +355,13 @@ TypePointer IntegerType::binaryOperatorResult(Token::Value _operator, TypePointe return TypePointer(); if (Token::isShiftOp(_operator)) { - // Disable >>> here. - if (_operator == Token::SHR) - return TypePointer(); - // Shifts are not symmetric with respect to the type if (isAddress()) return TypePointer(); - if (IntegerType const* otherInt = dynamic_cast(_other.get())) - { - if (!otherInt->isAddress()) - return shared_from_this(); - } - else if (RationalNumberType const* otherRat = dynamic_cast(_other.get())) - { - if (!otherRat->isFractional()) - return shared_from_this(); - } - return TypePointer(); + if (isValidShiftAndAmountType(_operator, *_other)) + return shared_from_this(); + else + return TypePointer(); } auto commonType = Type::commonType(shared_from_this(), _other); //might be a integer or fixed point @@ -978,22 +980,10 @@ TypePointer FixedBytesType::binaryOperatorResult(Token::Value _operator, TypePoi { if (Token::isShiftOp(_operator)) { - // Disable >>> here. - if (_operator == Token::SHR) + if (isValidShiftAndAmountType(_operator, *_other)) + return shared_from_this(); + else return TypePointer(); - - // Shifts are not symmetric with respect to the type - if (IntegerType const* otherInt = dynamic_cast(_other.get())) - { - if (!otherInt->isAddress()) - return shared_from_this(); - } - else if (RationalNumberType const* otherRat = dynamic_cast(_other.get())) - { - if (!otherRat->isFractional()) - return shared_from_this(); - } - return TypePointer(); } auto commonType = dynamic_pointer_cast(Type::commonType(shared_from_this(), _other)); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index d28ffed8f..afe91c5ce 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -197,22 +197,37 @@ bool ExpressionCompiler::visit(Conditional const& _condition) bool ExpressionCompiler::visit(Assignment const& _assignment) { CompilerContext::LocationSetter locationSetter(m_context, _assignment); + Token::Value op = _assignment.assignmentOperator(); + Token::Value binOp = op == Token::Assign ? op : Token::AssignmentToBinaryOp(op); + Type const& leftType = *_assignment.leftHandSide().annotation().type; + if (leftType.category() == Type::Category::Tuple) + { + solAssert(*_assignment.annotation().type == TupleType(), ""); + solAssert(op == Token::Assign, ""); + } + else + solAssert(*_assignment.annotation().type == leftType, ""); + bool cleanupNeeded = false; + if (op != Token::Assign) + cleanupNeeded = cleanupNeededForOp(leftType.category(), binOp); _assignment.rightHandSide().accept(*this); // Perform some conversion already. This will convert storage types to memory and literals // to their actual type, but will not convert e.g. memory to storage. - TypePointer type = _assignment.rightHandSide().annotation().type->closestTemporaryType( - _assignment.leftHandSide().annotation().type - ); - utils().convertType(*_assignment.rightHandSide().annotation().type, *type); + TypePointer rightIntermediateType; + if (op != Token::Assign && Token::isShiftOp(binOp)) + rightIntermediateType = _assignment.rightHandSide().annotation().type->mobileType(); + else + rightIntermediateType = _assignment.rightHandSide().annotation().type->closestTemporaryType( + _assignment.leftHandSide().annotation().type + ); + utils().convertType(*_assignment.rightHandSide().annotation().type, *rightIntermediateType, cleanupNeeded); _assignment.leftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); - Token::Value op = _assignment.assignmentOperator(); if (op != Token::Assign) // compound assignment { - Token::Value target_op = Token::AssignmentToBinaryOp(op); - solUnimplementedAssert(_assignment.annotation().type->isValueType(), "Compound operators not implemented for non-value types."); + solAssert(leftType.isValueType(), "Compound operators only available for value types."); unsigned lvalueSize = m_currentLValue->sizeOnStack(); unsigned itemSize = _assignment.annotation().type->sizeOnStack(); if (lvalueSize > 0) @@ -222,11 +237,17 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) // value lvalue_ref value lvalue_ref } m_currentLValue->retrieveValue(_assignment.location(), true); - if (Token::isShiftOp(target_op)) - // shift only cares about the signedness of both sides - appendShiftOperatorCode(target_op, *_assignment.leftHandSide().annotation().type, *_assignment.rightHandSide().annotation().type); + utils().convertType(leftType, leftType, cleanupNeeded); + + Token::Value targetOp = Token::AssignmentToBinaryOp(op); + + if (Token::isShiftOp(targetOp)) + appendShiftOperatorCode(targetOp, leftType, *rightIntermediateType); else - appendOrdinaryBinaryOperatorCode(target_op, *_assignment.annotation().type); + { + solAssert(leftType == *rightIntermediateType, ""); + appendOrdinaryBinaryOperatorCode(targetOp, leftType); + } if (lvalueSize > 0) { solAssert(itemSize + lvalueSize <= 16, "Stack too deep, try removing local variables."); @@ -235,7 +256,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP; } } - m_currentLValue->storeValue(*type, _assignment.location()); + m_currentLValue->storeValue(*rightIntermediateType, _assignment.location()); m_currentLValue.reset(); return false; } @@ -356,20 +377,19 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) Expression const& leftExpression = _binaryOperation.leftExpression(); Expression const& rightExpression = _binaryOperation.rightExpression(); solAssert(!!_binaryOperation.annotation().commonType, ""); - Type const& commonType = *_binaryOperation.annotation().commonType; + TypePointer const& commonType = _binaryOperation.annotation().commonType; Token::Value const c_op = _binaryOperation.getOperator(); if (c_op == Token::And || c_op == Token::Or) // special case: short-circuiting appendAndOrOperatorCode(_binaryOperation); - else if (commonType.category() == Type::Category::RationalNumber) - m_context << commonType.literalValue(nullptr); + else if (commonType->category() == Type::Category::RationalNumber) + m_context << commonType->literalValue(nullptr); else { - bool cleanupNeeded = false; - if (Token::isCompareOp(c_op) || Token::isShiftOp(c_op)) - cleanupNeeded = true; - if (commonType.category() == Type::Category::Integer && (c_op == Token::Div || c_op == Token::Mod)) - cleanupNeeded = true; + bool cleanupNeeded = cleanupNeededForOp(commonType->category(), c_op); + + TypePointer leftTargetType = commonType; + TypePointer rightTargetType = Token::isShiftOp(c_op) ? rightExpression.annotation().type->mobileType() : commonType; // for commutative operators, push the literal as late as possible to allow improved optimization auto isLiteral = [](Expression const& _e) @@ -380,24 +400,24 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) if (swap) { leftExpression.accept(*this); - utils().convertType(*leftExpression.annotation().type, commonType, cleanupNeeded); + utils().convertType(*leftExpression.annotation().type, *leftTargetType, cleanupNeeded); rightExpression.accept(*this); - utils().convertType(*rightExpression.annotation().type, commonType, cleanupNeeded); + utils().convertType(*rightExpression.annotation().type, *rightTargetType, cleanupNeeded); } else { rightExpression.accept(*this); - utils().convertType(*rightExpression.annotation().type, commonType, cleanupNeeded); + utils().convertType(*rightExpression.annotation().type, *rightTargetType, cleanupNeeded); leftExpression.accept(*this); - utils().convertType(*leftExpression.annotation().type, commonType, cleanupNeeded); + utils().convertType(*leftExpression.annotation().type, *leftTargetType, cleanupNeeded); } if (Token::isShiftOp(c_op)) // shift only cares about the signedness of both sides - appendShiftOperatorCode(c_op, *leftExpression.annotation().type, *rightExpression.annotation().type); + appendShiftOperatorCode(c_op, *leftTargetType, *rightTargetType); else if (Token::isCompareOp(c_op)) - appendCompareOperatorCode(c_op, commonType); + appendCompareOperatorCode(c_op, *commonType); else - appendOrdinaryBinaryOperatorCode(c_op, commonType); + appendOrdinaryBinaryOperatorCode(c_op, *commonType); } // do not visit the child nodes, we already did that explicitly @@ -1396,30 +1416,31 @@ void ExpressionCompiler::appendBitOperatorCode(Token::Value _operator) } } -void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type const& _leftType, Type const& _rightType) +void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type const& _valueType, Type const& _shiftAmountType) { - // stack: rvalue lvalue + // stack: shift_amount value_to_shift - bool c_leftSigned = false; - if (auto leftType = dynamic_cast(&_leftType)) - c_leftSigned = leftType->isSigned(); + bool c_valueSigned = false; + if (auto valueType = dynamic_cast(&_valueType)) + c_valueSigned = valueType->isSigned(); else - solUnimplemented("Only IntegerType can be shifted."); + solAssert(dynamic_cast(&_valueType), "Only integer and fixed bytes type supported for shifts."); - // The RValue can be a RationalNumberType too. - bool c_rightSigned = false; - if (auto rightType = dynamic_cast(&_rightType)) + // The amount can be a RationalNumberType too. + bool c_amountSigned = false; + if (auto amountType = dynamic_cast(&_shiftAmountType)) { - solAssert(rightType->integerType(), "integerType() called for fractional number."); - c_rightSigned = rightType->integerType()->isSigned(); + // This should be handled by the type checker. + solAssert(amountType->integerType(), ""); + solAssert(!amountType->integerType()->isSigned(), ""); } - else if (auto rightType = dynamic_cast(&_rightType)) - c_rightSigned = rightType->isSigned(); + else if (auto amountType = dynamic_cast(&_shiftAmountType)) + c_amountSigned = amountType->isSigned(); else - solUnimplemented("Not implemented yet - FixedPointType."); + solAssert(false, "Invalid shift amount type."); - // shift with negative rvalue throws exception - if (c_rightSigned) + // shift by negative amount throws exception + if (c_amountSigned) { m_context << u256(0) << Instruction::DUP3 << Instruction::SLT; m_context.appendConditionalJumpTo(m_context.errorTag()); @@ -1431,7 +1452,7 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type co m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::MUL; break; case Token::SAR: - m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_leftSigned ? Instruction::SDIV : Instruction::DIV); + m_context << Instruction::SWAP1 << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_valueSigned ? Instruction::SDIV : Instruction::DIV); break; case Token::SHR: default: @@ -1721,6 +1742,16 @@ void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression) setLValue(_expression, *_expression.annotation().type); } +bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _op) +{ + if (Token::isCompareOp(_op) || Token::isShiftOp(_op)) + return true; + else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod)) + return true; + else + return false; +} + CompilerUtils ExpressionCompiler::utils() { return CompilerUtils(m_context); diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index e6cf382c2..d0a8ac159 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -91,7 +91,7 @@ private: void appendArithmeticOperatorCode(Token::Value _operator, Type const& _type); void appendBitOperatorCode(Token::Value _operator); - void appendShiftOperatorCode(Token::Value _operator, Type const& _leftType, Type const& _rightType); + void appendShiftOperatorCode(Token::Value _operator, Type const& _valueType, Type const& _shiftAmountType); /// @} /// Appends code to call a function of the given type with the given arguments. @@ -117,6 +117,10 @@ private: template void setLValue(Expression const& _expression, _Arguments const&... _arguments); + /// @returns true if the operator applied to the given type requires a cleanup prior to the + /// operation. + bool cleanupNeededForOp(Type::Category _type, Token::Value _op); + /// @returns the CompilerUtils object containing the current context. CompilerUtils utils(); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 0ac88a819..3d38516d8 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8507,17 +8507,18 @@ BOOST_AUTO_TEST_CASE(shift_left_uint8) BOOST_AUTO_TEST_CASE(shift_left_larger_type) { + // This basically tests proper cleanup and conversion. It should not convert x to int8. char const* sourceCode = R"( contract C { function f() returns (int8) { - uint8 x = 255; + uint8 x = 254; int8 y = 1; - return a << b; + return y << x; } } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(1) << 255)); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); } BOOST_AUTO_TEST_CASE(shift_left_assignment) @@ -8570,6 +8571,7 @@ BOOST_AUTO_TEST_CASE(shift_right_garbled) )"; compileAndRun(sourceCode, 0, "C"); BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf))); } BOOST_AUTO_TEST_CASE(shift_right_uint32) @@ -8769,6 +8771,23 @@ BOOST_AUTO_TEST_CASE(shift_overflow) BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); } +BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) +{ + char const* sourceCode = R"( + contract C { + function test() returns (uint, uint) { + uint32 a = 0xffffffff; + uint16 x = uint16(a); + uint16 y = x; + x /= 0x100; + return (x, y); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0xff), u256(0xff))); +} + BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) { char const* sourceCode = R"( From ffccbd432a36a9fae0857961d44d0455fce93c1c Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Dec 2016 14:18:10 +0100 Subject: [PATCH 172/185] Display tx hash for debugging. --- test/ExecutionFramework.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index 9e3ecac39..ddcd9cb68 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -62,7 +62,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 cout << "CALL " << m_sender.hex() << " -> " << m_contractAddress.hex() << ":" << endl; if (_value > 0) cout << " value: " << _value << endl; - cout << " in: " << toHex(_data) << endl; + cout << " in: " << toHex(_data) << endl; } RPCSession::TransactionData d; d.data = "0x" + toHex(_data); @@ -91,7 +91,10 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 } if (m_showMessages) - cout << " out: " << toHex(m_output) << endl; + { + cout << " out: " << toHex(m_output) << endl; + cout << " tx hash: " << txHash << endl; + } m_gasUsed = u256(receipt.gasUsed); m_logs.clear(); From 7bc2ecf30afe8fde3a178a9f9f298a56c845a078 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Dec 2016 18:42:55 +0100 Subject: [PATCH 173/185] Correct test expectations. --- test/libsolidity/SolidityEndToEndTest.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 3d38516d8..ff128330e 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8570,8 +8570,8 @@ BOOST_AUTO_TEST_CASE(shift_right_garbled) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf))); } BOOST_AUTO_TEST_CASE(shift_right_uint32) @@ -8767,7 +8767,8 @@ BOOST_AUTO_TEST_CASE(shift_overflow) BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1) == encodeArgs(u256(254))); BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0) == encodeArgs(u256(255))); - BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(128))); + // Result is -128 and output is sign-extended, not zero-padded. + BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(0) - 128)); BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); } @@ -8780,6 +8781,7 @@ BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) uint16 x = uint16(a); uint16 y = x; x /= 0x100; + y = y / 0x100; return (x, y); } } From 2fac1d23a78d898ab78f1a8e347c40ae673c039c Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Dec 2016 20:18:24 +0100 Subject: [PATCH 174/185] Tests for bytes. --- test/libsolidity/SolidityEndToEndTest.cpp | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ff128330e..9e2c41afc 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8772,6 +8772,44 @@ BOOST_AUTO_TEST_CASE(shift_overflow) BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); } +BOOST_AUTO_TEST_CASE(shift_bytes) +{ + char const* sourceCode = R"( + contract C { + function left(bytes20 x, uint8 y) returns (bytes20) { + return x << y; + } + function right(bytes20 x, uint8 y) returns (bytes20) { + return x >> y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); + BOOST_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); +} + +BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) +{ + char const* sourceCode = R"( + contract C { + function left(uint8 y) returns (bytes20) { + bytes20 x; + assembly { x := "12345678901234567890abcde" } + return x << y; + } + function right(uint8 y) returns (bytes20) { + bytes20 x; + assembly { x := "12345678901234567890abcde" } + return x >> y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("left(uint8)", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); + BOOST_CHECK(callContractFunction("right(uint8)", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); +} + BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) { char const* sourceCode = R"( From cc117399281361124714dfd0914fa92e6aec78ef Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 9 Dec 2016 20:18:37 +0100 Subject: [PATCH 175/185] Documentation. --- docs/control-structures.rst | 19 ++++++++++--------- docs/types.rst | 13 +++++++++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 974a093f2..0802c0851 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -382,17 +382,18 @@ In the following example, we show how ``throw`` can be used to easily revert an } } -Currently, there are situations, where exceptions happen automatically in Solidity: +Currently, Solidity automatically generates a runtime exception in the following situations: 1. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``). -2. If you access a fixed-length ``bytesN`` at a too large or negative index. -3. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``. -4. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly"). -5. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``). -6. If you convert a value too big or negative into an enum type. -7. If you perform an external function call targeting a contract that contains no code. -8. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function). -9. If your contract receives Ether via a public accessor function. +1. If you access a fixed-length ``bytesN`` at a too large or negative index. +1. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``. +1. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly"). +1. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``). +1. If you shift by a negative amount. +1. If you convert a value too big or negative into an enum type. +1. If you perform an external function call targeting a contract that contains no code. +1. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function). +1. If your contract receives Ether via a public accessor function. Internally, Solidity performs an "invalid jump" when an exception is thrown and thus causes the EVM to revert all changes made to the state. The reason for this is that there is no safe way to continue execution, because an expected effect did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction (or at least call) without effect. diff --git a/docs/types.rst b/docs/types.rst index 896910ffb..59b9771bf 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -51,7 +51,7 @@ Integers Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) +* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) * Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation) Division always truncates (it just maps to the DIV opcode of the EVM), but it does not truncate if both @@ -59,6 +59,11 @@ operators are :ref:`literals` (or literal expressions). Division by zero and modulus with zero throws an exception. +The result of a shift operation is the type of the left operand. The +expression ``x << y`` is equivalent to ``x * 2**y`` and ``x >> y`` is +equivalent to ``x / 2**y``. This means that shifting negative numbers +sign extends. Shifting by a negative amount throws an exception. + .. index:: address, balance, send, call, callcode, delegatecall .. _address: @@ -136,9 +141,13 @@ Fixed-size byte arrays Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) +* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) * Index access: If ``x`` is of type ``bytesI``, then ``x[k]`` for ``0 <= k < I`` returns the ``k`` th byte (read-only). +The shifting operator wors with any integer type as right operand (bit will +return the type of the left operand). Shifting by a negative amount will cause +a runtime exception. + Members: * ``.length`` yields the fixed length of the byte array (read-only). From 9ed65f2ab9d5d6e67e07219006434356ce5c64ee Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Mon, 12 Dec 2016 16:21:57 -0300 Subject: [PATCH 176/185] Include visibility level for functions in AST --- libsolidity/ast/ASTJsonConverter.cpp | 28 +++++++++++++++++++++------- libsolidity/ast/ASTJsonConverter.h | 1 + 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 493707b9c..abaad0fdf 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace std; @@ -173,9 +174,9 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node) { addJsonNode(_node, "FunctionDefinition", { make_pair("name", _node.name()), - make_pair("public", _node.isPublic()), make_pair("constant", _node.isDeclaredConst()), - make_pair("payable", _node.isPayable()) + make_pair("payable", _node.isPayable()), + make_pair("visibility", visibility(_node.visibility())) }, true); return true; } @@ -228,13 +229,9 @@ bool ASTJsonConverter::visit(UserDefinedTypeName const& _node) bool ASTJsonConverter::visit(FunctionTypeName const& _node) { - string visibility = "internal"; - if (_node.visibility() == Declaration::Visibility::External) - visibility = "external"; - addJsonNode(_node, "FunctionTypeName", { make_pair("payable", _node.isPayable()), - make_pair("visibility", visibility), + make_pair("visibility", visibility(_node.visibility())), make_pair("constant", _node.isDeclaredConst()) }, true); return true; @@ -656,6 +653,23 @@ void ASTJsonConverter::process() processed = true; } +string ASTJsonConverter::visibility(Declaration::Visibility const& _visibility) +{ + switch (_visibility) + { + case Declaration::Visibility::Private: + return "private"; + case Declaration::Visibility::Internal: + return "internal"; + case Declaration::Visibility::Public: + return "public"; + case Declaration::Visibility::External: + return "external"; + default: + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown declaration visibility.")); + } +} + string ASTJsonConverter::type(Expression const& _expression) { return _expression.annotation().type ? _expression.annotation().type->toString() : "Unknown"; diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index 277476d59..49f23f999 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -152,6 +152,7 @@ private: bool _hasChildren ); std::string sourceLocationToString(SourceLocation const& _location) const; + std::string visibility(Declaration::Visibility const& _visibility); std::string type(Expression const& _expression); std::string type(VariableDeclaration const& _varDecl); inline void goUp() From 0e0d5d47c0bb3edbc1558679c678ce9178a80cb9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 12 Dec 2016 21:45:33 +0100 Subject: [PATCH 177/185] Renamed padToWordBoundaries -> padToWords --- libsolidity/codegen/CompilerUtils.cpp | 10 +++++----- libsolidity/codegen/CompilerUtils.h | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index da2e78e83..7d382aba8 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -952,9 +952,9 @@ void CompilerUtils::storeStringData(bytesConstRef _data) } } -unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries) +unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWords) { - unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries); + unsigned numBytes = _type.calldataEncodedSize(_padToWords); bool isExternalFunctionType = false; if (auto const* funType = dynamic_cast(&_type)) if (funType->location() == FunctionType::Location::External) @@ -993,9 +993,9 @@ void CompilerUtils::cleanHigherOrderBits(IntegerType const& _typeOnStack) m_context << ((u256(1) << _typeOnStack.numBits()) - 1) << Instruction::AND; } -unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBoundaries) +unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords) { - unsigned numBytes = _type.calldataEncodedSize(_padToWordBoundaries); + unsigned numBytes = _type.calldataEncodedSize(_padToWords); bool leftAligned = _type.category() == Type::Category::FixedBytes; if (numBytes == 0) m_context << Instruction::POP; @@ -1003,7 +1003,7 @@ unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWordBou { solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested."); convertType(_type, _type, true); - if (numBytes != 32 && !leftAligned && !_padToWordBoundaries) + if (numBytes != 32 && !leftAligned && !_padToWords) // shift the value accordingly before storing m_context << (u256(1) << ((32 - numBytes) * 8)) << Instruction::MUL; } diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index ad53efea4..b9ed67570 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -52,13 +52,13 @@ public: /// @param _offset offset in memory (or calldata) /// @param _type data type to load /// @param _fromCalldata if true, load from calldata, not from memory - /// @param _padToWordBoundaries if true, assume the data is padded to word (32 byte) boundaries + /// @param _padToWords if true, assume the data is padded to full words (32 bytes) /// @returns the number of bytes consumed in memory. unsigned loadFromMemory( unsigned _offset, Type const& _type = IntegerType(256), bool _fromCalldata = false, - bool _padToWordBoundaries = false + bool _padToWords = false ); /// Dynamic version of @see loadFromMemory, expects the memory offset on the stack. /// Stack pre: memory_offset @@ -66,7 +66,7 @@ public: void loadFromMemoryDynamic( Type const& _type, bool _fromCalldata = false, - bool _padToWordBoundaries = true, + bool _padToWords = true, bool _keepUpdatedMemoryOffset = true ); /// Stores a 256 bit integer from stack in memory. @@ -76,11 +76,11 @@ public: /// Dynamic version of @see storeInMemory, expects the memory offset below the value on the stack /// and also updates that. For reference types, only copies the data pointer. Fails for /// non-memory-references. - /// @param _padToWordBoundaries if true, adds zeros to pad to multiple of 32 bytes. Array elements + /// @param _padToWords if true, adds zeros to pad to multiple of 32 bytes. Array elements /// are always padded (except for byte arrays), regardless of this parameter. /// Stack pre: memory_offset value... /// Stack post: (memory_offset+length) - void storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries = true); + void storeInMemoryDynamic(Type const& _type, bool _padToWords = true); /// Copies values (of types @a _givenTypes) given on the stack to a location in memory given /// at the stack top, encoding them according to the ABI as the given types @a _targetTypes. @@ -88,7 +88,7 @@ public: /// Stack pre: ... /// Stack post: /// Does not touch the memory-free pointer. - /// @param _padToWordBoundaries if false, all values are concatenated without padding. + /// @param _padToWords if false, all values are concatenated without padding. /// @param _copyDynamicDataInPlace if true, dynamic types is stored (without length) /// together with fixed-length data. /// @param _encodeAsLibraryTypes if true, encodes for a library function, e.g. does not @@ -98,7 +98,7 @@ public: void encodeToMemory( TypePointers const& _givenTypes = {}, TypePointers const& _targetTypes = {}, - bool _padToWordBoundaries = true, + bool _padToWords = true, bool _copyDynamicDataInPlace = false, bool _encodeAsLibraryTypes = false ); @@ -193,9 +193,9 @@ private: void cleanHigherOrderBits(IntegerType const& _typeOnStack); /// Prepares the given type for storing in memory by shifting it if necessary. - unsigned prepareMemoryStore(Type const& _type, bool _padToWordBoundaries); + unsigned prepareMemoryStore(Type const& _type, bool _padToWords); /// Loads type from memory assuming memory offset is on stack top. - unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWordBoundaries); + unsigned loadFromMemoryHelper(Type const& _type, bool _fromCalldata, bool _padToWords); CompilerContext& m_context; }; From de720e643d8c54c613356bfcdcb6c49984460a17 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Mon, 12 Dec 2016 23:59:53 -0300 Subject: [PATCH 178/185] Improve error message when trying to modify constant variables --- libsolidity/analysis/TypeChecker.cpp | 7 ++++++- libsolidity/ast/ASTAnnotations.h | 2 ++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7235b57aa..e414e27c4 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1529,6 +1529,8 @@ bool TypeChecker::visit(Identifier const& _identifier) !!annotation.referencedDeclaration, "Referenced declaration is null after overload resolution." ); + auto variableDeclaration = dynamic_cast(annotation.referencedDeclaration); + annotation.isConstant = variableDeclaration != nullptr && variableDeclaration->isConstant(); annotation.isLValue = annotation.referencedDeclaration->isLValue(); annotation.type = annotation.referencedDeclaration->type(); if (!annotation.type) @@ -1612,7 +1614,10 @@ void TypeChecker::requireLValue(Expression const& _expression) { _expression.annotation().lValueRequested = true; _expression.accept(*this); - if (!_expression.annotation().isLValue) + + if (_expression.annotation().isConstant) + typeError(_expression.location(), "Cannot assign to a constant variable."); + else if (!_expression.annotation().isLValue) typeError(_expression.location(), "Expression has to be an lvalue."); } diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index 768e56db5..9c4c3ae8b 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -154,6 +154,8 @@ struct ExpressionAnnotation: ASTAnnotation { /// Inferred type of the expression. TypePointer type; + /// Whether the expression is a constant variable + bool isConstant = false; /// Whether it is an LValue (i.e. something that can be assigned to). bool isLValue = false; /// Whether the expression is used in a context where the LValue is actually required. diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index a4e601f74..576421fdf 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4865,6 +4865,17 @@ BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_p CHECK_SUCCESS_NO_WARNINGS(text); } +BOOST_AUTO_TEST_CASE(assignment_to_constant) +{ + char const* text = R"( + contract c { + uint constant a = 1; + function f() { a = 2; } + } + )"; + CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); +} + BOOST_AUTO_TEST_SUITE_END() } From 932e7887bde0ac84b86c257d321a48647b024e6d Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 13 Dec 2016 16:35:42 +0100 Subject: [PATCH 179/185] test: add tests that tries different types on <<= --- test/libsolidity/SolidityEndToEndTest.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 9e2c41afc..fd547f4e0 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8540,6 +8540,24 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment) BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); } +BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint8 b) returns (uint) { + a <<= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); +} + BOOST_AUTO_TEST_CASE(shift_right) { char const* sourceCode = R"( From 56a027bedc88305fe05b09859cbab408d44a0106 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Dec 2016 16:36:01 +0100 Subject: [PATCH 180/185] Use multiple URLs for metadata. --- docs/miscellaneous.rst | 8 ++++---- libsolidity/interface/CompilerStack.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 81e39a265..4a9dad873 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -334,10 +334,10 @@ Comments are of course also not permitted and used here only for explanatory pur "myFile.sol": { // Required: keccak256 hash of the source file "keccak256": "0x123...", - // Required (unless "content" is used, see below): URL to the - // source file, protocol is more or less arbitrary, but a Swarm - // URL is recommended - "url": "bzzr://56ab..." + // Required (unless "content" is used, see below): Sorted URL(s) + // to the source file, protocol is more or less arbitrary, but a + // Swarm URL is recommended + "urls": [ "bzzr://56ab..." ] }, "mortal": { // Required: keccak256 hash of the source file diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 0b8cecc76..4095844f7 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -694,8 +694,10 @@ string CompilerStack::createOnChainMetadata(Contract const& _contract) const solAssert(s.second.scanner, "Scanner not available"); meta["sources"][s.first]["keccak256"] = "0x" + toHex(dev::keccak256(s.second.scanner->source()).asBytes()); - meta["sources"][s.first]["url"] = - "bzzr://" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes()); + meta["sources"][s.first]["urls"] = Json::arrayValue; + meta["sources"][s.first]["urls"].append( + "bzzr://" + toHex(dev::swarmHash(s.second.scanner->source()).asBytes()) + ); } meta["settings"]["optimizer"]["enabled"] = m_optimize; meta["settings"]["optimizer"]["runs"] = m_optimizeRuns; From f7e219ed91f256ee076b72c47a1168e32a1ef705 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Dec 2016 16:43:16 +0100 Subject: [PATCH 181/185] Update documentation. --- docs/types.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/types.rst b/docs/types.rst index 59b9771bf..069a91905 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -51,18 +51,18 @@ Integers Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) -* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation) +* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) +* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift) Division always truncates (it just maps to the DIV opcode of the EVM), but it does not truncate if both operators are :ref:`literals` (or literal expressions). -Division by zero and modulus with zero throws an exception. +Division by zero and modulus with zero throws a runtime exception. The result of a shift operation is the type of the left operand. The expression ``x << y`` is equivalent to ``x * 2**y`` and ``x >> y`` is equivalent to ``x / 2**y``. This means that shifting negative numbers -sign extends. Shifting by a negative amount throws an exception. +sign extends. Shifting by a negative amount throws a runtime exception. .. index:: address, balance, send, call, callcode, delegatecall @@ -144,9 +144,9 @@ Operators: * Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) * Index access: If ``x`` is of type ``bytesI``, then ``x[k]`` for ``0 <= k < I`` returns the ``k`` th byte (read-only). -The shifting operator wors with any integer type as right operand (bit will -return the type of the left operand). Shifting by a negative amount will cause -a runtime exception. +The shifting operator works with any integer type as right operand (but will +return the type of the left operand), which denotes the number of bits to shift by. +Shifting by a negative amount will cause a runtime exception. Members: From e9d3327ad6883acc6db8306bb7fa5ccbd802af9c Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Dec 2016 16:50:50 +0100 Subject: [PATCH 182/185] Use correct type for storing. --- libsolidity/codegen/ExpressionCompiler.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index afe91c5ce..a7fb8408c 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -225,7 +225,9 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) _assignment.leftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); - if (op != Token::Assign) // compound assignment + if (op == Token::Assign) + m_currentLValue->storeValue(*rightIntermediateType, _assignment.location()); + else // compound assignment { solAssert(leftType.isValueType(), "Compound operators only available for value types."); unsigned lvalueSize = m_currentLValue->sizeOnStack(); @@ -239,14 +241,12 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) m_currentLValue->retrieveValue(_assignment.location(), true); utils().convertType(leftType, leftType, cleanupNeeded); - Token::Value targetOp = Token::AssignmentToBinaryOp(op); - - if (Token::isShiftOp(targetOp)) - appendShiftOperatorCode(targetOp, leftType, *rightIntermediateType); + if (Token::isShiftOp(binOp)) + appendShiftOperatorCode(binOp, leftType, *rightIntermediateType); else { solAssert(leftType == *rightIntermediateType, ""); - appendOrdinaryBinaryOperatorCode(targetOp, leftType); + appendOrdinaryBinaryOperatorCode(binOp, leftType); } if (lvalueSize > 0) { @@ -255,8 +255,8 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) for (unsigned i = 0; i < itemSize; ++i) m_context << swapInstruction(itemSize + lvalueSize) << Instruction::POP; } + m_currentLValue->storeValue(*_assignment.annotation().type, _assignment.location()); } - m_currentLValue->storeValue(*rightIntermediateType, _assignment.location()); m_currentLValue.reset(); return false; } From 08a11e309f241e602cc4754b6322e4bb0da57b17 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 13 Dec 2016 17:02:28 +0100 Subject: [PATCH 183/185] Fix tests. --- test/libsolidity/SolidityEndToEndTest.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index fd547f4e0..94d4fb7f6 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8551,11 +8551,11 @@ BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); - BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); } BOOST_AUTO_TEST_CASE(shift_right) From ff40338a344b202036ad7e4e4e0e3f516d184a7b Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 14 Dec 2016 18:10:14 +0100 Subject: [PATCH 184/185] Changelog: add entries for #1497 and #1503 --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index dfeaa3819..a8b5cca5d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,9 @@ Bugfixes: * Code generator: throw if calling the identity precompile failed during memory (array) copying. * Type checker: string literals that are not valid UTF-8 cannot be converted to string type * Code generator: any non-zero value given as a boolean argument is now converted into 1. + * AST Json Converter: replace "VariableDefinitionStatement" nodes with "VariableDeclarationStatement" + * AST Json Converter: fix the camel case in "ElementaryTypeNameExpression" + * AST Json Converter: replace "public" field with "visibility" in the function definition nodes ### 0.4.6 (2016-11-22) From 11b9abfff3de9dfdcd0bd68ce31dff0d510f21cb Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 15 Dec 2016 12:15:09 +0100 Subject: [PATCH 185/185] Update changelog for release. --- Changelog.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index a8b5cca5d..096c72d48 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,4 @@ -### 0.4.7 (unreleased) +### 0.4.7 (2016-12-15) Features: * Bitshift operators. @@ -11,9 +11,9 @@ Bugfixes: * Code generator: throw if calling the identity precompile failed during memory (array) copying. * Type checker: string literals that are not valid UTF-8 cannot be converted to string type * Code generator: any non-zero value given as a boolean argument is now converted into 1. - * AST Json Converter: replace "VariableDefinitionStatement" nodes with "VariableDeclarationStatement" - * AST Json Converter: fix the camel case in "ElementaryTypeNameExpression" - * AST Json Converter: replace "public" field with "visibility" in the function definition nodes + * AST Json Converter: replace ``VariableDefinitionStatement`` nodes with ``VariableDeclarationStatement`` + * AST Json Converter: fix the camel case in ``ElementaryTypeNameExpression`` + * AST Json Converter: replace ``public`` field with ``visibility`` in the function definition nodes ### 0.4.6 (2016-11-22)