aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--docs/050-breaking-changes.rst4
-rw-r--r--docs/assembly.rst10
-rw-r--r--docs/contracts.rst6
-rw-r--r--docs/control-structures.rst2
-rw-r--r--docs/frequently-asked-questions.rst2
-rw-r--r--docs/introduction-to-smart-contracts.rst7
-rw-r--r--docs/miscellaneous.rst29
-rw-r--r--docs/solidity-by-example.rst2
-rw-r--r--docs/yul.rst10
-rw-r--r--libdevcore/CommonData.h33
-rw-r--r--libdevcore/CommonIO.cpp1
-rw-r--r--libjulia/optimiser/ExpressionBreaker.cpp105
-rw-r--r--libjulia/optimiser/ExpressionBreaker.h86
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp4
-rw-r--r--libsolidity/analysis/TypeChecker.cpp2
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp4
-rw-r--r--libsolidity/ast/Types.cpp12
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp2
-rw-r--r--libsolidity/formal/SMTChecker.cpp2
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp4
-rw-r--r--libsolidity/interface/CompilerStack.cpp2
-rw-r--r--libsolidity/interface/StandardCompiler.cpp2
-rw-r--r--libsolidity/parsing/Parser.cpp7
-rw-r--r--libsolidity/parsing/Scanner.cpp6
-rw-r--r--libsolidity/parsing/Token.h2
-rw-r--r--test/cmdlineErrorReports/too_long_line.sol.ref1
-rw-r--r--test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref1
-rw-r--r--test/cmdlineErrorReports/too_long_line_edge_in.sol.ref1
-rw-r--r--test/cmdlineErrorReports/too_long_line_edge_out.sol.ref1
-rw-r--r--test/cmdlineErrorReports/too_long_line_left_short.sol.ref1
-rw-r--r--test/cmdlineErrorReports/too_long_line_right_short.sol.ref1
-rwxr-xr-xtest/cmdlineTests.sh7
-rw-r--r--test/libdevcore/IterateReplacing.cpp97
-rw-r--r--test/libjulia/ExpressionBreaker.cpp156
-rw-r--r--test/libsolidity/ASTJSON/address_payable.json2
-rw-r--r--test/libsolidity/ASTJSON/address_payable_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/constructor.json70
-rw-r--r--test/libsolidity/ASTJSON/constructor.sol4
-rw-r--r--test/libsolidity/ASTJSON/constructor_legacy.json110
-rw-r--r--test/libsolidity/ASTJSON/documentation.json2
-rw-r--r--test/libsolidity/ASTJSON/documentation_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/fallback.json70
-rw-r--r--test/libsolidity/ASTJSON/fallback.sol4
-rw-r--r--test/libsolidity/ASTJSON/fallback_legacy.json110
-rw-r--r--test/libsolidity/ASTJSON/fallback_payable.json70
-rw-r--r--test/libsolidity/ASTJSON/fallback_payable.sol3
-rw-r--r--test/libsolidity/ASTJSON/fallback_payable_legacy.json110
-rw-r--r--test/libsolidity/ASTJSON/function_type.json2
-rw-r--r--test/libsolidity/ASTJSON/function_type_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/long_type_name_binary_operation.json2
-rw-r--r--test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/long_type_name_identifier.json2
-rw-r--r--test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/modifier_definition.json2
-rw-r--r--test/libsolidity/ASTJSON/modifier_definition_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/modifier_invocation.json2
-rw-r--r--test/libsolidity/ASTJSON/modifier_invocation_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/non_utf8.json2
-rw-r--r--test/libsolidity/ASTJSON/non_utf8_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/short_type_name.json2
-rw-r--r--test/libsolidity/ASTJSON/short_type_name_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/short_type_name_ref.json2
-rw-r--r--test/libsolidity/ASTJSON/short_type_name_ref_legacy.json1
-rw-r--r--test/libsolidity/ASTJSON/source_location.json2
-rw-r--r--test/libsolidity/ASTJSON/source_location_legacy.json1
-rw-r--r--test/libsolidity/ASTJSONTest.cpp1
-rw-r--r--test/libsolidity/LibSolc.cpp4
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp25
-rw-r--r--test/libsolidity/SolidityScanner.cpp12
-rw-r--r--test/libsolidity/SyntaxTest.cpp1
-rw-r--r--test/libsolidity/syntaxTests/types/rational_number_huge.sol10
-rw-r--r--test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol8
-rw-r--r--test/tools/fuzzer.cpp2
74 files changed, 1183 insertions, 77 deletions
diff --git a/Changelog.md b/Changelog.md
index fbb41ece..2d6f518c 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -36,6 +36,7 @@ Breaking Changes:
* General: C99-style scoping rules are enforced now. This was already the case in the experimental 0.5.0 mode.
* General: Disallow combining hex numbers with unit denominations (e.g. ``0x1e wei``). This was already the case in the experimental 0.5.0 mode.
* JSON AST: Remove ``constant`` and ``payable`` fields (the information is encoded in the ``stateMutability`` field).
+ * JSON AST: Replace the ``isConstructor`` field by a new ``kind`` field, which can be ``constructor``, ``fallback`` or ``function``.
* Interface: Remove "clone contract" feature. The ``--clone-bin`` and ``--combined-json clone-bin`` commandline options are not available anymore.
* Name Resolver: Do not exclude public state variables when looking for conflicting declarations.
* Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence.
diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst
index 9094000e..93f099ca 100644
--- a/docs/050-breaking-changes.rst
+++ b/docs/050-breaking-changes.rst
@@ -154,6 +154,10 @@ Command Line and JSON Interfaces
* The JSON AST fields ``constant`` and ``payable`` were removed. The
information is now present in the ``stateMutability`` field.
+* The JSON AST field ``isConstructor`` of the ``FunctionDefinition``
+ node was replaced by a field called ``kind`` which can have the
+ value ``"constructor"``, ``"fallback"`` or ``"function"``.
+
Constructors
------------
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 20fb0cd5..5bb9825a 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -282,14 +282,14 @@ In the grammar, opcodes are represented as pre-defined identifiers.
+-------------------------+-----+---+-----------------------------------------------------------------+
| extcodehash(a) | | C | code hash of address a |
+-------------------------+-----+---+-----------------------------------------------------------------+
-| create(v, p, s) | | F | create new contract with code mem[p...(p+s)) and send v wei |
+| create(v, p, n) | | F | create new contract with code mem[p...(p+n)) and send v wei |
| | | | and return the new address |
+-------------------------+-----+---+-----------------------------------------------------------------+
-| create2(v, n, p, s) | | C | create new contract with code mem[p...(p+s)) at address |
-| | | | keccak256(0xff . self . n . keccak256(mem[p...(p+s))) |
+| create2(v, p, n, s) | | C | create new contract with code mem[p...(p+n)) at address |
+| | | | keccak256(0xff . this . s . keccak256(mem[p...(p+n))) |
| | | | and send v wei and return the new address, where ``0xff`` is a |
-| | | | 8 byte value, ``self`` is the current contract's address |
-| | | | as a 20 byte value and ``n`` is a big-endian 256-bit value |
+| | | | 8 byte value, ``this`` is the current contract's address |
+| | | | as a 20 byte value and ``s`` is a big-endian 256-bit value |
+-------------------------+-----+---+-----------------------------------------------------------------+
| call(g, a, v, in, | | F | call contract at address a with input mem[in...(in+insize)) |
| insize, out, outsize) | | | providing g gas and v wei and output area |
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 8fa2b041..d4160eac 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -490,7 +490,11 @@ Functions can be declared ``view`` in which case they promise not to modify the
.. note::
If the compiler's EVM target is Byzantium or newer (default) the opcode
``STATICCALL`` is used for ``view`` functions which enforces the state
- to stay unmodified as part of the EVM execution.
+ to stay unmodified as part of the EVM execution. For library ``view`` functions
+ ``DELEGATECALL`` is used, because there is no combined ``DELEGATECALL`` and ``STATICCALL``.
+ This means library ``view`` functions do not have run-time checks that prevent state
+ modifications. This should not impact security negatively because library code is
+ usually known at compile-time and the static checker performs compile-time checks.
The following statements are considered modifying the state:
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 80311a63..353bb61d 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -279,7 +279,7 @@ groupings of expressions.
::
- pragma solidity >0.4.23 <0.5.0;
+ pragma solidity >0.4.23 <0.6.0;
contract C {
uint[] data;
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index a474f905..0f8b34f8 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -173,7 +173,7 @@ situation.
If you do not want to throw, you can return a pair::
- pragma solidity >0.4.23 <0.5.0;
+ pragma solidity >0.4.23 <0.6.0;
contract C {
uint[] counters;
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index f5d5f89e..c8a45d30 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -332,14 +332,15 @@ Transactions
============
A transaction is a message that is sent from one account to another
-account (which might be the same or the special zero-account, see below).
+account (which might be the same or empty, see below).
It can include binary data (which is called "payload") and Ether.
If the target account contains code, that code is executed and
the payload is provided as input data.
-If the target account is the zero-account (the account with the
-address ``0``), the transaction creates a **new contract**.
+If the target account is not set (the transaction does not have
+a recipient or the recipient is set to ``null``), the transaction
+creates a **new contract**.
As already mentioned, the address of that contract is not
the zero address but an address derived from the sender and
its number of transactions sent (the "nonce"). The payload
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 12603f2e..8cc52c8f 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -34,18 +34,20 @@ Statically-sized variables (everything except mapping and dynamically-sized arra
The elements of structs and arrays are stored after each other, just as if they were given explicitly.
+Mappings and Dynamic Arrays
+===========================
+
Due to their unpredictable size, mapping and dynamically-sized array types use a Keccak-256 hash
computation to find the starting position of the value or the array data. These starting positions are always full stack slots.
-The mapping or the dynamic array itself
-occupies an (unfilled) slot in storage at some position ``p`` according to the above rule (or by
-recursively applying this rule for mappings to mappings or arrays of arrays). For a dynamic array, this slot stores the number of elements in the array (byte arrays and strings are an exception here, see below). For a mapping, the slot is unused (but it is needed so that two equal mappings after each other will use a different hash distribution).
-Array data is located at ``keccak256(p)`` and the value corresponding to a mapping key
+The mapping or the dynamic array itself occupies a slot in storage at some position ``p``
+according to the above rule (or by recursively applying this rule for mappings of mappings or arrays of arrays). For dynamic arrays,
+this slot stores the number of elements in the array (byte arrays and strings are an exception, see :ref:`below <bytes-and-string>`).
+For mappings, the slot is unused (but it is needed so that two equal mappings after each other will use a different
+hash distribution). Array data is located at ``keccak256(p)`` and the value corresponding to a mapping key
``k`` is located at ``keccak256(k . p)`` where ``.`` is concatenation. If the value is again a
non-elementary type, the positions are found by adding an offset of ``keccak256(k . p)``.
-``bytes`` and ``string`` store their data in the same slot where also the length is stored if they are short. In particular: If the data is at most ``31`` bytes long, it is stored in the higher-order bytes (left aligned) and the lowest-order byte stores ``length * 2``. If it is longer, the main slot stores ``length * 2 + 1`` and the data is stored as usual in ``keccak256(slot)``.
-
So for the following contract snippet::
pragma solidity >=0.4.0 <0.6.0;
@@ -58,6 +60,21 @@ So for the following contract snippet::
The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``.
+.. _bytes-and-string:
+
+``bytes`` and ``string``
+------------------------
+
+``bytes`` and ``string`` are encoded identically. For short byte arrays, they store their data in the same
+slot where the length is also stored. In particular: if the data is at most ``31`` bytes long, it is stored
+in the higher-order bytes (left aligned) and the lowest-order byte stores ``length * 2``.
+For byte arrays that store data which is ``32`` or more bytes long, the main slot stores ``length * 2 + 1`` and the data is
+stored as usual in ``keccak256(slot)``. This means that you can distinguish a short array from a long array
+by checking if the lowest bit is set: short (not set) and long (set).
+
+.. note::
+ Handling invalidly encoded slots is currently not supported but may be added in the future.
+
.. index: memory layout
****************
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 1bbd42f8..8f58f339 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -389,7 +389,7 @@ high or low invalid bids.
::
- pragma solidity >0.4.23 <0.5.0;
+ pragma solidity >0.4.23 <0.6.0;
contract BlindAuction {
struct Bid {
diff --git a/docs/yul.rst b/docs/yul.rst
index cfeec4db..a55445f3 100644
--- a/docs/yul.rst
+++ b/docs/yul.rst
@@ -415,14 +415,14 @@ The following functions must be available:
+---------------------------------------------+-----------------------------------------------------------------+
| *Execution control* |
+---------------------------------------------+-----------------------------------------------------------------+
-| create(v:u256, p:u256, s:u256) | create new contract with code mem[p..(p+s)) and send v wei |
+| create(v:u256, p:u256, n:u256) | create new contract with code mem[p..(p+n)) and send v wei |
| | and return the new address |
+---------------------------------------------+-----------------------------------------------------------------+
-| create2(v:u256, n:u256, p:u256, s:u256) | create new contract with code mem[p...(p+s)) at address |
-| | keccak256(0xff . self . n . keccak256(mem[p...(p+s))) |
+| create2(v:u256, p:u256, n:u256, s:u256) | create new contract with code mem[p...(p+n)) at address |
+| | keccak256(0xff . this . s . keccak256(mem[p...(p+n))) |
| | and send v wei and return the new address, where ``0xff`` is a |
-| | 8 byte value, ``self`` is the current contract's address |
-| | as a 20 byte value and ``n`` is a big-endian 256-bit value |
+| | 8 byte value, ``this`` is the current contract's address |
+| | as a 20 byte value and ``s`` is a big-endian 256-bit value |
+---------------------------------------------+-----------------------------------------------------------------+
| call(g:u256, a:u256, v:u256, in:u256, | call contract at address a with input mem[in..(in+insize)) |
| insize:u256, out:u256, | providing g gas and v wei and output area |
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index e410af5c..98136b44 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -25,11 +25,14 @@
#include <libdevcore/Common.h>
+#include <boost/optional.hpp>
+
#include <vector>
#include <type_traits>
#include <cstring>
#include <string>
#include <set>
+#include <functional>
namespace dev
{
@@ -229,6 +232,36 @@ bool contains(T const& _t, V const& _v)
return std::end(_t) != std::find(std::begin(_t), std::end(_t), _v);
}
+
+/// Function that iterates over a vector, calling a function on each of its
+/// elements. If that function returns a vector, the element is replaced by
+/// the returned vector. During the iteration, the original vector is only valid
+/// on the current element and after that. The actual replacement takes
+/// place at the end, but already visited elements might be invalidated.
+/// If nothing is replaced, no copy is performed.
+template <class T>
+void iterateReplacing(std::vector<T>& _vector, std::function<boost::optional<std::vector<T>>(T&)> _f)
+{
+ bool useModified = false;
+ std::vector<T> modifiedVector;
+ for (size_t i = 0; i < _vector.size(); ++i)
+ {
+ if (boost::optional<std::vector<T>> r = _f(_vector[i]))
+ {
+ if (!useModified)
+ {
+ std::move(_vector.begin(), _vector.begin() + i, back_inserter(modifiedVector));
+ useModified = true;
+ }
+ modifiedVector += std::move(*r);
+ }
+ else if (useModified)
+ modifiedVector.emplace_back(std::move(_vector[i]));
+ }
+ if (useModified)
+ _vector = std::move(modifiedVector);
+}
+
/// @returns true iff @a _str passess the hex address checksum test.
/// @param _strict if false, hex strings with only uppercase or only lowercase letters
/// are considered valid.
diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp
index 9693d02a..2005d087 100644
--- a/libdevcore/CommonIO.cpp
+++ b/libdevcore/CommonIO.cpp
@@ -23,7 +23,6 @@
#include <iostream>
#include <cstdlib>
#include <fstream>
-#include <stdio.h>
#if defined(_WIN32)
#include <windows.h>
#else
diff --git a/libjulia/optimiser/ExpressionBreaker.cpp b/libjulia/optimiser/ExpressionBreaker.cpp
new file mode 100644
index 00000000..2273fa98
--- /dev/null
+++ b/libjulia/optimiser/ExpressionBreaker.cpp
@@ -0,0 +1,105 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Optimiser component that turns complex expressions into multiple variable
+ * declarations.
+ */
+
+#include <libjulia/optimiser/ExpressionBreaker.h>
+
+#include <libjulia/optimiser/ASTWalker.h>
+
+#include <libsolidity/inlineasm/AsmData.h>
+
+#include <libdevcore/CommonData.h>
+
+#include <boost/range/adaptor/reversed.hpp>
+
+using namespace std;
+using namespace dev;
+using namespace dev::julia;
+using namespace dev::solidity;
+
+void ExpressionBreaker::operator()(FunctionalInstruction& _instruction)
+{
+ for (auto& arg: _instruction.arguments | boost::adaptors::reversed)
+ outlineExpression(arg);
+}
+
+void ExpressionBreaker::operator()(FunctionCall& _funCall)
+{
+ for (auto& arg: _funCall.arguments | boost::adaptors::reversed)
+ outlineExpression(arg);
+}
+
+void ExpressionBreaker::operator()(If& _if)
+{
+ outlineExpression(*_if.condition);
+ (*this)(_if.body);
+}
+
+void ExpressionBreaker::operator()(Switch& _switch)
+{
+ outlineExpression(*_switch.expression);
+ for (auto& _case: _switch.cases)
+ // Do not visit the case expression, nothing to break there.
+ (*this)(_case.body);
+}
+
+void ExpressionBreaker::operator()(ForLoop& _loop)
+{
+ (*this)(_loop.pre);
+ // Do not visit the condition because we cannot break expressions there.
+ (*this)(_loop.post);
+ (*this)(_loop.body);
+}
+
+void ExpressionBreaker::operator()(Block& _block)
+{
+ vector<Statement> saved;
+ swap(saved, m_statementsToPrefix);
+
+ function<boost::optional<vector<Statement>>(Statement&)> f =
+ [&](Statement& _statement) -> boost::optional<vector<Statement>> {
+ m_statementsToPrefix.clear();
+ visit(_statement);
+ if (m_statementsToPrefix.empty())
+ return {};
+ m_statementsToPrefix.emplace_back(std::move(_statement));
+ return std::move(m_statementsToPrefix);
+ };
+ iterateReplacing(_block.statements, f);
+
+ swap(saved, m_statementsToPrefix);
+}
+
+void ExpressionBreaker::outlineExpression(Expression& _expr)
+{
+ if (_expr.type() != typeid(FunctionalInstruction) && _expr.type() != typeid(FunctionCall))
+ return;
+
+ visit(_expr);
+
+ SourceLocation location = locationOf(_expr);
+ string var = m_nameDispenser.newName("");
+ m_statementsToPrefix.emplace_back(VariableDeclaration{
+ location,
+ {{TypedName{location, var, ""}}},
+ make_shared<Expression>(std::move(_expr))
+ });
+ _expr = Identifier{location, var};
+}
diff --git a/libjulia/optimiser/ExpressionBreaker.h b/libjulia/optimiser/ExpressionBreaker.h
new file mode 100644
index 00000000..28cfdbc9
--- /dev/null
+++ b/libjulia/optimiser/ExpressionBreaker.h
@@ -0,0 +1,86 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Optimiser component that turns complex expressions into multiple variable
+ * declarations.
+ */
+#pragma once
+
+#include <libjulia/ASTDataForward.h>
+
+#include <libjulia/optimiser/ASTWalker.h>
+#include <libjulia/optimiser/NameDispenser.h>
+
+#include <vector>
+
+namespace dev
+{
+namespace julia
+{
+
+class NameCollector;
+
+
+/**
+ * Optimiser component that modifies an AST in place, turning complex
+ * expressions into simple expressions and multiple variable declarations.
+ *
+ * Code of the form
+ *
+ * sstore(mul(x, 4), mload(y))
+ *
+ * is transformed into
+ *
+ * let a1 := mload(y)
+ * let a2 := mul(x, 4)
+ * sstore(a2, a1)
+ *
+ * The transformation is not applied to loop conditions, because the loop control flow
+ * does not allow "outlining" the inner expressions in all cases.
+ *
+ * The final program should be in a form such that with the exception of a loop condition,
+ * function calls can only appear in the right-hand side of a variable declaration,
+ * assignments or expression statements and all arguments have to be constants or variables.
+ */
+class ExpressionBreaker: public ASTModifier
+{
+public:
+ explicit ExpressionBreaker(NameDispenser& _nameDispenser):
+ m_nameDispenser(_nameDispenser)
+ { }
+
+ virtual void operator()(FunctionalInstruction&) override;
+ virtual void operator()(FunctionCall&) override;
+ virtual void operator()(If&) override;
+ virtual void operator()(Switch&) override;
+ virtual void operator()(ForLoop&) override;
+ virtual void operator()(Block& _block) override;
+
+private:
+ /// Replaces the expression by a variable if it is a function call or functional
+ /// instruction. The declaration of the variable is appended to m_statementsToPrefix.
+ /// Recurses via visit().
+ void outlineExpression(Expression& _expr);
+
+ /// List of statements that should go in front of the currently visited AST element,
+ /// at the statement level.
+ std::vector<Statement> m_statementsToPrefix;
+ NameDispenser& m_nameDispenser;
+};
+
+}
+}
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index 0bc20f2e..ab544388 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -53,7 +53,7 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
SemVerVersion recommendedVersion{string(VersionString)};
if (!recommendedVersion.isPrerelease())
errorString +=
- "Consider adding \"pragma solidity ^" +
+ " Consider adding \"pragma solidity ^" +
to_string(recommendedVersion.major()) +
string(".") +
to_string(recommendedVersion.minor()) +
@@ -76,7 +76,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
{
solAssert(m_sourceUnit, "");
vector<string> literals(_pragma.literals().begin() + 1, _pragma.literals().end());
- if (literals.size() == 0)
+ if (literals.empty())
m_errorReporter.syntaxError(
_pragma.location(),
"Experimental feature name is missing."
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index bc040623..39ea494d 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -2123,7 +2123,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
auto& annotation = _memberAccess.annotation();
- if (possibleMembers.size() == 0)
+ if (possibleMembers.empty())
{
if (initialMemberCount == 0)
{
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index cadc5f28..4b282d85 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -325,17 +325,19 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
+ make_pair("kind", _node.isConstructor() ? "constructor" : (_node.isFallback() ? "fallback" : "function")),
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
make_pair("superFunction", idOrNull(_node.annotation().superFunction)),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("parameters", toJson(_node.parameterList())),
- make_pair("isConstructor", _node.isConstructor()),
make_pair("returnParameters", toJson(*_node.returnParameterList())),
make_pair("modifiers", toJson(_node.modifiers())),
make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json::nullValue),
make_pair("implemented", _node.isImplemented()),
make_pair("scope", idOrNull(_node.scope()))
};
+ if (m_legacy)
+ attributes.emplace_back("isConstructor", _node.isConstructor());
setJsonNode(_node, "FunctionDefinition", std::move(attributes));
return false;
}
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index e45fc81d..195b2e2d 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -841,13 +841,8 @@ TypePointer RationalNumberType::forLiteral(Literal const& _literal)
TypePointer compatibleBytesType;
if (_literal.isHexNumber())
{
- size_t digitCount = count_if(
- _literal.value().begin() + 2, // skip "0x"
- _literal.value().end(),
- [](unsigned char _c) -> bool { return isxdigit(_c); }
- );
- // require even number of digits
- if (!(digitCount & 1))
+ size_t const digitCount = _literal.valueWithoutUnderscores().length() - 2;
+ if (digitCount % 2 == 0 && (digitCount / 2) <= 32)
compatibleBytesType = make_shared<FixedBytesType>(digitCount / 2);
}
@@ -861,8 +856,7 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
rational value;
try
{
- ASTString valueString = _literal.value();
- boost::erase_all(valueString, "_");// Remove underscore separators
+ ASTString valueString = _literal.valueWithoutUnderscores();
auto expPoint = find(valueString.begin(), valueString.end(), 'e');
if (expPoint == valueString.end())
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index e26bc13a..3a0fccfb 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -965,7 +965,7 @@ void ContractCompiler::popScopedVariables(ASTNode const* _node)
unsigned stackDiff = m_context.stackHeight() - blockHeight;
CompilerUtils(m_context).popStackSlots(stackDiff);
m_scopeStackHeight[m_modifierDepth].erase(_node);
- if (m_scopeStackHeight[m_modifierDepth].size() == 0)
+ if (m_scopeStackHeight[m_modifierDepth].empty())
m_scopeStackHeight.erase(m_modifierDepth);
}
diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp
index 19785817..a7973852 100644
--- a/libsolidity/formal/SMTChecker.cpp
+++ b/libsolidity/formal/SMTChecker.cpp
@@ -894,7 +894,7 @@ void SMTChecker::pushPathCondition(smt::Expression const& _e)
smt::Expression SMTChecker::currentPathConditions()
{
- if (m_pathConditions.size() == 0)
+ if (m_pathConditions.empty())
return smt::Expression(true);
return m_pathConditions.back();
}
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index f34bbffe..54cdc1c6 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -26,7 +26,7 @@
#include <boost/algorithm/string.hpp>
-#include <ctype.h>
+#include <cctype>
#include <algorithm>
using namespace std;
@@ -97,7 +97,7 @@ assembly::Statement Parser::parseStatement()
fatalParserError("Only one default case allowed.");
else if (m_scanner->currentToken() == Token::Case)
fatalParserError("Case not allowed after default case.");
- if (_switch.cases.size() == 0)
+ if (_switch.cases.empty())
fatalParserError("Switch statement without any cases.");
_switch.location.end = _switch.cases.back().body.location.end;
return _switch;
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index d1001c80..1f58245f 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -780,7 +780,7 @@ CompilerStack::Contract const& CompilerStack::contract(string const& _contractNa
// To provide a measure of backward-compatibility, if a contract is not located by its
// fully-qualified name, a lookup will be attempted purely on the contract's name to see
// if anything will satisfy.
- if (_contractName.find(":") == string::npos)
+ if (_contractName.find(':') == string::npos)
{
for (auto const& contractEntry: m_contracts)
{
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 2305da13..8300e8db 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -509,7 +509,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
bool const compilationSuccess = m_compilerStack.state() == CompilerStack::State::CompilationSuccessful;
/// Inconsistent state - stop here to receive error reports from users
- if (!compilationSuccess && (errors.size() == 0))
+ if (!compilationSuccess && errors.empty())
return formatFatalError("InternalCompilerError", "No error reported, but compilation failed.");
Json::Value output = Json::objectValue;
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 1228b833..ca9a9b57 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -20,7 +20,7 @@
* Solidity parser.
*/
-#include <ctype.h>
+#include <cctype>
#include <vector>
#include <libevmasm/SourceLocation.h>
#include <libsolidity/parsing/Parser.h>
@@ -554,7 +554,7 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
if (m_scanner->currentToken() != Token::Identifier)
fatalParserError(string("Expected identifier after ','"));
}
- if (members.size() == 0)
+ if (members.empty())
parserError({"enum with no members is not allowed."});
nodeFactory.markEndPosition();
@@ -1554,6 +1554,9 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<TupleExpression>(components, isArray);
break;
}
+ case Token::IllegalHex:
+ fatalParserError("Expected even number of hex-nibbles within double-quotes.");
+ break;
default:
if (Token::isElementaryTypeName(token))
{
diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp
index 9a7f85cb..87d7c535 100644
--- a/libsolidity/parsing/Scanner.cpp
+++ b/libsolidity/parsing/Scanner.cpp
@@ -612,7 +612,7 @@ void Scanner::scanToken()
if (m_char == '"' || m_char == '\'')
token = scanHexString();
else
- token = Token::Illegal;
+ token = Token::IllegalHex;
}
}
else if (isDecimalDigit(m_char))
@@ -736,11 +736,11 @@ Token::Value Scanner::scanHexString()
{
char c = m_char;
if (!scanHexByte(c))
- return Token::Illegal;
+ return Token::IllegalHex;
addLiteralChar(c);
}
if (m_char != quote)
- return Token::Illegal;
+ return Token::IllegalHex;
literal.complete();
advance(); // consume quote
return Token::StringLiteral;
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 73c85482..8ecc850a 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -261,6 +261,8 @@ namespace solidity
\
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
+ /* Illegal hex token */ \
+ T(IllegalHex, "ILLEGAL_HEX", 0) \
\
/* Scanner-internal use only. */ \
T(Whitespace, NULL, 0)
diff --git a/test/cmdlineErrorReports/too_long_line.sol.ref b/test/cmdlineErrorReports/too_long_line.sol.ref
index 7cad93ee..55cd1935 100644
--- a/test/cmdlineErrorReports/too_long_line.sol.ref
+++ b/test/cmdlineErrorReports/too_long_line.sol.ref
@@ -1,4 +1,3 @@
-
too_long_line.sol:1:1: Warning: Source file does not specify required compiler version!
contract C {
^ (Relevant source part starts here and spans across multiple lines).
diff --git a/test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref b/test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref
index f2ea427a..9a5ebfba 100644
--- a/test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref
+++ b/test/cmdlineErrorReports/too_long_line_both_sides_short.sol.ref
@@ -1,4 +1,3 @@
-
too_long_line_both_sides_short.sol:1:1: Warning: Source file does not specify required compiler version!
contract C {
^ (Relevant source part starts here and spans across multiple lines).
diff --git a/test/cmdlineErrorReports/too_long_line_edge_in.sol.ref b/test/cmdlineErrorReports/too_long_line_edge_in.sol.ref
index b6699933..ad3b7805 100644
--- a/test/cmdlineErrorReports/too_long_line_edge_in.sol.ref
+++ b/test/cmdlineErrorReports/too_long_line_edge_in.sol.ref
@@ -1,4 +1,3 @@
-
too_long_line_edge_in.sol:1:1: Warning: Source file does not specify required compiler version!
contract C {
^ (Relevant source part starts here and spans across multiple lines).
diff --git a/test/cmdlineErrorReports/too_long_line_edge_out.sol.ref b/test/cmdlineErrorReports/too_long_line_edge_out.sol.ref
index 76df589a..d8495c11 100644
--- a/test/cmdlineErrorReports/too_long_line_edge_out.sol.ref
+++ b/test/cmdlineErrorReports/too_long_line_edge_out.sol.ref
@@ -1,4 +1,3 @@
-
too_long_line_edge_out.sol:1:1: Warning: Source file does not specify required compiler version!
contract C {
^ (Relevant source part starts here and spans across multiple lines).
diff --git a/test/cmdlineErrorReports/too_long_line_left_short.sol.ref b/test/cmdlineErrorReports/too_long_line_left_short.sol.ref
index efaa559d..00b6be5c 100644
--- a/test/cmdlineErrorReports/too_long_line_left_short.sol.ref
+++ b/test/cmdlineErrorReports/too_long_line_left_short.sol.ref
@@ -1,4 +1,3 @@
-
too_long_line_left_short.sol:1:1: Warning: Source file does not specify required compiler version!
contract C {
^ (Relevant source part starts here and spans across multiple lines).
diff --git a/test/cmdlineErrorReports/too_long_line_right_short.sol.ref b/test/cmdlineErrorReports/too_long_line_right_short.sol.ref
index 2b0c6d8c..88072d95 100644
--- a/test/cmdlineErrorReports/too_long_line_right_short.sol.ref
+++ b/test/cmdlineErrorReports/too_long_line_right_short.sol.ref
@@ -1,4 +1,3 @@
-
too_long_line_right_short.sol:1:1: Warning: Source file does not specify required compiler version!
contract C {
^ (Relevant source part starts here and spans across multiple lines).
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index d7b95e8a..71866bce 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -123,7 +123,8 @@ test_solc_file_input_failures() {
exitCode=$?
set -e
- stderr=`sed 's/.*This is a pre-release compiler version, please do not use it in production.*$//' $stderr_path`
+ sed -i -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
+ sed -i -e 's/ \?Consider adding "pragma .*$//' "$stderr_path"
if [[ $exitCode -eq 0 ]]; then
printError "Incorrect exit code. Expected failure (non-zero) but got success (0)."
@@ -141,12 +142,12 @@ test_solc_file_input_failures() {
exit 1
fi
- if [[ "$stderr" != "${stderr_expected}" ]]; then
+ if [[ "$(cat $stderr_path)" != "${stderr_expected}" ]]; then
printError "Incorrect output on stderr received. Expected:"
echo -e "${stderr_expected}"
printError "But got:"
- echo $stderr
+ cat $stderr_path
rm -f $stdout_path $stderr_path
exit 1
fi
diff --git a/test/libdevcore/IterateReplacing.cpp b/test/libdevcore/IterateReplacing.cpp
new file mode 100644
index 00000000..08cd1e22
--- /dev/null
+++ b/test/libdevcore/IterateReplacing.cpp
@@ -0,0 +1,97 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Unit tests for the iterateReplacing function
+ */
+
+#include <libdevcore/CommonData.h>
+
+#include <test/Options.h>
+
+using namespace std;
+
+namespace dev
+{
+namespace test
+{
+
+BOOST_AUTO_TEST_SUITE(IterateReplacing)
+
+BOOST_AUTO_TEST_CASE(no_replacement)
+{
+ vector<string> v{"abc", "def", "ghi"};
+ function<boost::optional<vector<string>>(string&)> f = [](string&) -> boost::optional<vector<string>> { return {}; };
+ iterateReplacing(v, f);
+ vector<string> expectation{"abc", "def", "ghi"};
+ BOOST_CHECK(v == expectation);
+}
+
+BOOST_AUTO_TEST_CASE(empty_input)
+{
+ vector<string> v;
+ function<boost::optional<vector<string>>(string&)> f = [](string&) -> boost::optional<vector<string>> { return {}; };
+ iterateReplacing(v, f);
+ vector<string> expectation;
+ BOOST_CHECK(v == expectation);
+}
+
+BOOST_AUTO_TEST_CASE(delete_some)
+{
+ vector<string> v{"abc", "def", "ghi"};
+ function<boost::optional<vector<string>>(string&)> f = [](string& _s) -> boost::optional<vector<string>> {
+ if (_s == "def")
+ return vector<string>();
+ else
+ return {};
+ };
+ iterateReplacing(v, f);
+ vector<string> expectation{"abc", "ghi"};
+ BOOST_CHECK(v == expectation);
+}
+
+BOOST_AUTO_TEST_CASE(inject_some_start)
+{
+ vector<string> v{"abc", "def", "ghi"};
+ function<boost::optional<vector<string>>(string&)> f = [](string& _s) -> boost::optional<vector<string>> {
+ if (_s == "abc")
+ return vector<string>{"x", "y"};
+ else
+ return {};
+ };
+ iterateReplacing(v, f);
+ vector<string> expectation{"x", "y", "def", "ghi"};
+ BOOST_CHECK(v == expectation);
+}
+
+BOOST_AUTO_TEST_CASE(inject_some_end)
+{
+ vector<string> v{"abc", "def", "ghi"};
+ function<boost::optional<vector<string>>(string&)> f = [](string& _s) -> boost::optional<vector<string>> {
+ if (_s == "ghi")
+ return vector<string>{"x", "y"};
+ else
+ return {};
+ };
+ iterateReplacing(v, f);
+ vector<string> expectation{"abc", "def", "x", "y"};
+ BOOST_CHECK(v == expectation);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+}
+}
diff --git a/test/libjulia/ExpressionBreaker.cpp b/test/libjulia/ExpressionBreaker.cpp
new file mode 100644
index 00000000..de8d2251
--- /dev/null
+++ b/test/libjulia/ExpressionBreaker.cpp
@@ -0,0 +1,156 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * Unit tests for the expression breaker.
+ */
+
+#include <test/libjulia/Common.h>
+
+#include <libjulia/optimiser/ExpressionBreaker.h>
+#include <libjulia/optimiser/NameCollector.h>
+
+#include <libsolidity/inlineasm/AsmPrinter.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include <boost/range/adaptors.hpp>
+#include <boost/algorithm/string/join.hpp>
+
+using namespace std;
+using namespace dev;
+using namespace dev::julia;
+using namespace dev::julia::test;
+using namespace dev::solidity;
+
+
+#define CHECK(_original, _expectation)\
+do\
+{\
+ auto result = parse(_original, false);\
+ NameDispenser nameDispenser;\
+ nameDispenser.m_usedNames = NameCollector(*result.first).names();\
+ ExpressionBreaker{nameDispenser}(*result.first);\
+ BOOST_CHECK_EQUAL(assembly::AsmPrinter{}(*result.first), format(_expectation, false));\
+}\
+while(false)
+
+BOOST_AUTO_TEST_SUITE(YulExpressionBreaker)
+
+BOOST_AUTO_TEST_CASE(smoke_test)
+{
+ CHECK("{ }", "{ }");
+}
+
+BOOST_AUTO_TEST_CASE(trivial)
+{
+ CHECK(
+ "{ mstore(add(calldataload(2), mload(3)), 8) }",
+ "{ let _1 := mload(3) let _2 := calldataload(2) let _3 := add(_2, _1) mstore(_3, 8) }"
+ );
+}
+
+BOOST_AUTO_TEST_CASE(control_flow)
+{
+ string input = R"({
+ let x := calldataload(0)
+ if mul(add(x, 2), 3) {
+ for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } {
+ let b := mul(add(a, 2), 4)
+ sstore(b, mul(b, 2))
+ }
+ }
+ })";
+ string expectation = R"({
+ let x := calldataload(0)
+ let _1 := add(x, 2)
+ let _2 := mul(_1, 3)
+ if _2
+ {
+ for { let a := 2 } lt(a, mload(a))
+ {
+ let _3 := mul(a, 2)
+ a := add(a, _3)
+ }
+ {
+ let _4 := add(a, 2)
+ let b := mul(_4, 4)
+ let _5 := mul(b, 2)
+ sstore(b, _5)
+ }
+ }
+ })";
+ CHECK(input, expectation);
+}
+
+BOOST_AUTO_TEST_CASE(switch_)
+{
+ string input = R"({
+ let x := 8
+ switch add(2, calldataload(0))
+ case 0 { sstore(0, mload(2)) }
+ default { mstore(0, mload(3)) }
+ x := add(mload(3), 4)
+ })";
+ string expectation = R"({
+ let x := 8
+ let _1 := calldataload(0)
+ let _2 := add(2, _1)
+ switch _2
+ case 0 {
+ let _3 := mload(2)
+ sstore(0, _3)
+ }
+ default {
+ let _4 := mload(3)
+ mstore(0, _4)
+ }
+ let _5 := mload(3)
+ x := add(_5, 4)
+ })";
+
+ CHECK(input, expectation);
+}
+
+BOOST_AUTO_TEST_CASE(inside_function)
+{
+ string input = R"({
+ let x := mul(f(0, mload(7)), 3)
+ function f(a, b) -> c {
+ c := mul(a, mload(add(b, c)))
+ }
+ sstore(x, f(mload(2), mload(2)))
+ })";
+ string expectation = R"({
+ let _1 := mload(7)
+ let _2 := f(0, _1)
+ let x := mul(_2, 3)
+ function f(a, b) -> c
+ {
+ let _3 := add(b, c)
+ let _4 := mload(_3)
+ c := mul(a, _4)
+ }
+ let _5 := mload(2)
+ let _6 := mload(2)
+ let _7 := f(_6, _5)
+ sstore(x, _7)
+ })";
+
+ CHECK(input, expectation);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json
index 42ad33e5..0f30e8e8 100644
--- a/test/libsolidity/ASTJSON/address_payable.json
+++ b/test/libsolidity/ASTJSON/address_payable.json
@@ -463,7 +463,7 @@
"documentation" : null,
"id" : 36,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/address_payable_legacy.json b/test/libsolidity/ASTJSON/address_payable_legacy.json
index 11a634c3..dd8a5582 100644
--- a/test/libsolidity/ASTJSON/address_payable_legacy.json
+++ b/test/libsolidity/ASTJSON/address_payable_legacy.json
@@ -93,6 +93,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/constructor.json b/test/libsolidity/ASTJSON/constructor.json
new file mode 100644
index 00000000..b0bc4201
--- /dev/null
+++ b/test/libsolidity/ASTJSON/constructor.json
@@ -0,0 +1,70 @@
+{
+ "absolutePath" : "a",
+ "exportedSymbols" :
+ {
+ "C" :
+ [
+ 5
+ ]
+ },
+ "id" : 6,
+ "nodeType" : "SourceUnit",
+ "nodes" :
+ [
+ {
+ "baseContracts" : [],
+ "contractDependencies" : [],
+ "contractKind" : "contract",
+ "documentation" : null,
+ "fullyImplemented" : true,
+ "id" : 5,
+ "linearizedBaseContracts" :
+ [
+ 5
+ ],
+ "name" : "C",
+ "nodeType" : "ContractDefinition",
+ "nodes" :
+ [
+ {
+ "body" :
+ {
+ "id" : 3,
+ "nodeType" : "Block",
+ "src" : "35:4:1",
+ "statements" : []
+ },
+ "documentation" : null,
+ "id" : 4,
+ "implemented" : true,
+ "kind" : "constructor",
+ "modifiers" : [],
+ "name" : "",
+ "nodeType" : "FunctionDefinition",
+ "parameters" :
+ {
+ "id" : 1,
+ "nodeType" : "ParameterList",
+ "parameters" : [],
+ "src" : "25:2:1"
+ },
+ "returnParameters" :
+ {
+ "id" : 2,
+ "nodeType" : "ParameterList",
+ "parameters" : [],
+ "src" : "35:0:1"
+ },
+ "scope" : 5,
+ "src" : "14:25:1",
+ "stateMutability" : "nonpayable",
+ "superFunction" : null,
+ "visibility" : "public"
+ }
+ ],
+ "scope" : 6,
+ "src" : "0:41:1"
+ }
+ ],
+ "src" : "0:42:1"
+}
diff --git a/test/libsolidity/ASTJSON/constructor.sol b/test/libsolidity/ASTJSON/constructor.sol
new file mode 100644
index 00000000..79d04eb5
--- /dev/null
+++ b/test/libsolidity/ASTJSON/constructor.sol
@@ -0,0 +1,4 @@
+contract C {
+ constructor() public {
+ }
+}
diff --git a/test/libsolidity/ASTJSON/constructor_legacy.json b/test/libsolidity/ASTJSON/constructor_legacy.json
new file mode 100644
index 00000000..0617073e
--- /dev/null
+++ b/test/libsolidity/ASTJSON/constructor_legacy.json
@@ -0,0 +1,110 @@
+{
+ "attributes" :
+ {
+ "absolutePath" : "a",
+ "exportedSymbols" :
+ {
+ "C" :
+ [
+ 5
+ ]
+ }
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "baseContracts" :
+ [
+ null
+ ],
+ "contractDependencies" :
+ [
+ null
+ ],
+ "contractKind" : "contract",
+ "documentation" : null,
+ "fullyImplemented" : true,
+ "linearizedBaseContracts" :
+ [
+ 5
+ ],
+ "name" : "C",
+ "scope" : 6
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "documentation" : null,
+ "implemented" : true,
+ "isConstructor" : true,
+ "kind" : "constructor",
+ "modifiers" :
+ [
+ null
+ ],
+ "name" : "",
+ "scope" : 5,
+ "stateMutability" : "nonpayable",
+ "superFunction" : null,
+ "visibility" : "public"
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "parameters" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 1,
+ "name" : "ParameterList",
+ "src" : "25:2:1"
+ },
+ {
+ "attributes" :
+ {
+ "parameters" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 2,
+ "name" : "ParameterList",
+ "src" : "35:0:1"
+ },
+ {
+ "attributes" :
+ {
+ "statements" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 3,
+ "name" : "Block",
+ "src" : "35:4:1"
+ }
+ ],
+ "id" : 4,
+ "name" : "FunctionDefinition",
+ "src" : "14:25:1"
+ }
+ ],
+ "id" : 5,
+ "name" : "ContractDefinition",
+ "src" : "0:41:1"
+ }
+ ],
+ "id" : 6,
+ "name" : "SourceUnit",
+ "src" : "0:42:1"
+}
diff --git a/test/libsolidity/ASTJSON/documentation.json b/test/libsolidity/ASTJSON/documentation.json
index 403d4e72..ce1e0b57 100644
--- a/test/libsolidity/ASTJSON/documentation.json
+++ b/test/libsolidity/ASTJSON/documentation.json
@@ -147,7 +147,7 @@
"documentation" : "Some comment on fn.",
"id" : 14,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "fn",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/documentation_legacy.json b/test/libsolidity/ASTJSON/documentation_legacy.json
index 5a890e50..0277902f 100644
--- a/test/libsolidity/ASTJSON/documentation_legacy.json
+++ b/test/libsolidity/ASTJSON/documentation_legacy.json
@@ -108,6 +108,7 @@
"documentation" : "Some comment on fn.",
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/fallback.json b/test/libsolidity/ASTJSON/fallback.json
new file mode 100644
index 00000000..a9c85b2f
--- /dev/null
+++ b/test/libsolidity/ASTJSON/fallback.json
@@ -0,0 +1,70 @@
+{
+ "absolutePath" : "a",
+ "exportedSymbols" :
+ {
+ "C" :
+ [
+ 5
+ ]
+ },
+ "id" : 6,
+ "nodeType" : "SourceUnit",
+ "nodes" :
+ [
+ {
+ "baseContracts" : [],
+ "contractDependencies" : [],
+ "contractKind" : "contract",
+ "documentation" : null,
+ "fullyImplemented" : true,
+ "id" : 5,
+ "linearizedBaseContracts" :
+ [
+ 5
+ ],
+ "name" : "C",
+ "nodeType" : "ContractDefinition",
+ "nodes" :
+ [
+ {
+ "body" :
+ {
+ "id" : 3,
+ "nodeType" : "Block",
+ "src" : "43:5:1",
+ "statements" : []
+ },
+ "documentation" : null,
+ "id" : 4,
+ "implemented" : true,
+ "kind" : "fallback",
+ "modifiers" : [],
+ "name" : "",
+ "nodeType" : "FunctionDefinition",
+ "parameters" :
+ {
+ "id" : 1,
+ "nodeType" : "ParameterList",
+ "parameters" : [],
+ "src" : "23:2:1"
+ },
+ "returnParameters" :
+ {
+ "id" : 2,
+ "nodeType" : "ParameterList",
+ "parameters" : [],
+ "src" : "43:0:1"
+ },
+ "scope" : 5,
+ "src" : "15:33:1",
+ "stateMutability" : "payable",
+ "superFunction" : null,
+ "visibility" : "external"
+ }
+ ],
+ "scope" : 6,
+ "src" : "0:50:1"
+ }
+ ],
+ "src" : "0:51:1"
+}
diff --git a/test/libsolidity/ASTJSON/fallback.sol b/test/libsolidity/ASTJSON/fallback.sol
new file mode 100644
index 00000000..4e318892
--- /dev/null
+++ b/test/libsolidity/ASTJSON/fallback.sol
@@ -0,0 +1,4 @@
+contract C {
+ function() external payable {
+ }
+}
diff --git a/test/libsolidity/ASTJSON/fallback_legacy.json b/test/libsolidity/ASTJSON/fallback_legacy.json
new file mode 100644
index 00000000..0aca3128
--- /dev/null
+++ b/test/libsolidity/ASTJSON/fallback_legacy.json
@@ -0,0 +1,110 @@
+{
+ "attributes" :
+ {
+ "absolutePath" : "a",
+ "exportedSymbols" :
+ {
+ "C" :
+ [
+ 5
+ ]
+ }
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "baseContracts" :
+ [
+ null
+ ],
+ "contractDependencies" :
+ [
+ null
+ ],
+ "contractKind" : "contract",
+ "documentation" : null,
+ "fullyImplemented" : true,
+ "linearizedBaseContracts" :
+ [
+ 5
+ ],
+ "name" : "C",
+ "scope" : 6
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "documentation" : null,
+ "implemented" : true,
+ "isConstructor" : false,
+ "kind" : "fallback",
+ "modifiers" :
+ [
+ null
+ ],
+ "name" : "",
+ "scope" : 5,
+ "stateMutability" : "payable",
+ "superFunction" : null,
+ "visibility" : "external"
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "parameters" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 1,
+ "name" : "ParameterList",
+ "src" : "23:2:1"
+ },
+ {
+ "attributes" :
+ {
+ "parameters" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 2,
+ "name" : "ParameterList",
+ "src" : "43:0:1"
+ },
+ {
+ "attributes" :
+ {
+ "statements" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 3,
+ "name" : "Block",
+ "src" : "43:5:1"
+ }
+ ],
+ "id" : 4,
+ "name" : "FunctionDefinition",
+ "src" : "15:33:1"
+ }
+ ],
+ "id" : 5,
+ "name" : "ContractDefinition",
+ "src" : "0:50:1"
+ }
+ ],
+ "id" : 6,
+ "name" : "SourceUnit",
+ "src" : "0:51:1"
+}
diff --git a/test/libsolidity/ASTJSON/fallback_payable.json b/test/libsolidity/ASTJSON/fallback_payable.json
new file mode 100644
index 00000000..9d56f74b
--- /dev/null
+++ b/test/libsolidity/ASTJSON/fallback_payable.json
@@ -0,0 +1,70 @@
+{
+ "absolutePath" : "a",
+ "exportedSymbols" :
+ {
+ "C" :
+ [
+ 5
+ ]
+ },
+ "id" : 6,
+ "nodeType" : "SourceUnit",
+ "nodes" :
+ [
+ {
+ "baseContracts" : [],
+ "contractDependencies" : [],
+ "contractKind" : "contract",
+ "documentation" : null,
+ "fullyImplemented" : true,
+ "id" : 5,
+ "linearizedBaseContracts" :
+ [
+ 5
+ ],
+ "name" : "C",
+ "nodeType" : "ContractDefinition",
+ "nodes" :
+ [
+ {
+ "body" :
+ {
+ "id" : 3,
+ "nodeType" : "Block",
+ "src" : "34:2:1",
+ "statements" : []
+ },
+ "documentation" : null,
+ "id" : 4,
+ "implemented" : true,
+ "kind" : "fallback",
+ "modifiers" : [],
+ "name" : "",
+ "nodeType" : "FunctionDefinition",
+ "parameters" :
+ {
+ "id" : 1,
+ "nodeType" : "ParameterList",
+ "parameters" : [],
+ "src" : "22:2:1"
+ },
+ "returnParameters" :
+ {
+ "id" : 2,
+ "nodeType" : "ParameterList",
+ "parameters" : [],
+ "src" : "34:0:1"
+ },
+ "scope" : 5,
+ "src" : "14:22:1",
+ "stateMutability" : "nonpayable",
+ "superFunction" : null,
+ "visibility" : "external"
+ }
+ ],
+ "scope" : 6,
+ "src" : "0:38:1"
+ }
+ ],
+ "src" : "0:39:1"
+}
diff --git a/test/libsolidity/ASTJSON/fallback_payable.sol b/test/libsolidity/ASTJSON/fallback_payable.sol
new file mode 100644
index 00000000..21db99ec
--- /dev/null
+++ b/test/libsolidity/ASTJSON/fallback_payable.sol
@@ -0,0 +1,3 @@
+contract C {
+ function() external {}
+}
diff --git a/test/libsolidity/ASTJSON/fallback_payable_legacy.json b/test/libsolidity/ASTJSON/fallback_payable_legacy.json
new file mode 100644
index 00000000..7320f574
--- /dev/null
+++ b/test/libsolidity/ASTJSON/fallback_payable_legacy.json
@@ -0,0 +1,110 @@
+{
+ "attributes" :
+ {
+ "absolutePath" : "a",
+ "exportedSymbols" :
+ {
+ "C" :
+ [
+ 5
+ ]
+ }
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "baseContracts" :
+ [
+ null
+ ],
+ "contractDependencies" :
+ [
+ null
+ ],
+ "contractKind" : "contract",
+ "documentation" : null,
+ "fullyImplemented" : true,
+ "linearizedBaseContracts" :
+ [
+ 5
+ ],
+ "name" : "C",
+ "scope" : 6
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "documentation" : null,
+ "implemented" : true,
+ "isConstructor" : false,
+ "kind" : "fallback",
+ "modifiers" :
+ [
+ null
+ ],
+ "name" : "",
+ "scope" : 5,
+ "stateMutability" : "nonpayable",
+ "superFunction" : null,
+ "visibility" : "external"
+ },
+ "children" :
+ [
+ {
+ "attributes" :
+ {
+ "parameters" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 1,
+ "name" : "ParameterList",
+ "src" : "22:2:1"
+ },
+ {
+ "attributes" :
+ {
+ "parameters" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 2,
+ "name" : "ParameterList",
+ "src" : "34:0:1"
+ },
+ {
+ "attributes" :
+ {
+ "statements" :
+ [
+ null
+ ]
+ },
+ "children" : [],
+ "id" : 3,
+ "name" : "Block",
+ "src" : "34:2:1"
+ }
+ ],
+ "id" : 4,
+ "name" : "FunctionDefinition",
+ "src" : "14:22:1"
+ }
+ ],
+ "id" : 5,
+ "name" : "ContractDefinition",
+ "src" : "0:38:1"
+ }
+ ],
+ "id" : 6,
+ "name" : "SourceUnit",
+ "src" : "0:39:1"
+}
diff --git a/test/libsolidity/ASTJSON/function_type.json b/test/libsolidity/ASTJSON/function_type.json
index 5dbc5b80..b78d8446 100644
--- a/test/libsolidity/ASTJSON/function_type.json
+++ b/test/libsolidity/ASTJSON/function_type.json
@@ -37,7 +37,7 @@
"documentation" : null,
"id" : 16,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/function_type_legacy.json b/test/libsolidity/ASTJSON/function_type_legacy.json
index af0c42dd..72ceec81 100644
--- a/test/libsolidity/ASTJSON/function_type_legacy.json
+++ b/test/libsolidity/ASTJSON/function_type_legacy.json
@@ -41,6 +41,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json
index fe3e73d2..c6d40af2 100644
--- a/test/libsolidity/ASTJSON/long_type_name_binary_operation.json
+++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation.json
@@ -142,7 +142,7 @@
"documentation" : null,
"id" : 10,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json b/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json
index d78d01ff..b5333286 100644
--- a/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json
+++ b/test/libsolidity/ASTJSON/long_type_name_binary_operation_legacy.json
@@ -41,6 +41,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier.json b/test/libsolidity/ASTJSON/long_type_name_identifier.json
index 0579967c..505d260c 100644
--- a/test/libsolidity/ASTJSON/long_type_name_identifier.json
+++ b/test/libsolidity/ASTJSON/long_type_name_identifier.json
@@ -148,7 +148,7 @@
"documentation" : null,
"id" : 13,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json
index a96ccef3..d3bcda56 100644
--- a/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json
+++ b/test/libsolidity/ASTJSON/long_type_name_identifier_legacy.json
@@ -83,6 +83,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/modifier_definition.json b/test/libsolidity/ASTJSON/modifier_definition.json
index 95554f03..66359453 100644
--- a/test/libsolidity/ASTJSON/modifier_definition.json
+++ b/test/libsolidity/ASTJSON/modifier_definition.json
@@ -97,7 +97,7 @@
"documentation" : null,
"id" : 13,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
{
diff --git a/test/libsolidity/ASTJSON/modifier_definition_legacy.json b/test/libsolidity/ASTJSON/modifier_definition_legacy.json
index e1e797ba..5186912c 100644
--- a/test/libsolidity/ASTJSON/modifier_definition_legacy.json
+++ b/test/libsolidity/ASTJSON/modifier_definition_legacy.json
@@ -105,6 +105,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"name" : "F",
"scope" : 14,
"stateMutability" : "nonpayable",
diff --git a/test/libsolidity/ASTJSON/modifier_invocation.json b/test/libsolidity/ASTJSON/modifier_invocation.json
index 95554f03..66359453 100644
--- a/test/libsolidity/ASTJSON/modifier_invocation.json
+++ b/test/libsolidity/ASTJSON/modifier_invocation.json
@@ -97,7 +97,7 @@
"documentation" : null,
"id" : 13,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
{
diff --git a/test/libsolidity/ASTJSON/modifier_invocation_legacy.json b/test/libsolidity/ASTJSON/modifier_invocation_legacy.json
index e1e797ba..5186912c 100644
--- a/test/libsolidity/ASTJSON/modifier_invocation_legacy.json
+++ b/test/libsolidity/ASTJSON/modifier_invocation_legacy.json
@@ -105,6 +105,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"name" : "F",
"scope" : 14,
"stateMutability" : "nonpayable",
diff --git a/test/libsolidity/ASTJSON/non_utf8.json b/test/libsolidity/ASTJSON/non_utf8.json
index 307259e9..1852bd38 100644
--- a/test/libsolidity/ASTJSON/non_utf8.json
+++ b/test/libsolidity/ASTJSON/non_utf8.json
@@ -89,7 +89,7 @@
"documentation" : null,
"id" : 7,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/non_utf8_legacy.json b/test/libsolidity/ASTJSON/non_utf8_legacy.json
index b1f847f7..df105096 100644
--- a/test/libsolidity/ASTJSON/non_utf8_legacy.json
+++ b/test/libsolidity/ASTJSON/non_utf8_legacy.json
@@ -41,6 +41,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/short_type_name.json b/test/libsolidity/ASTJSON/short_type_name.json
index 502c1e31..acb46157 100644
--- a/test/libsolidity/ASTJSON/short_type_name.json
+++ b/test/libsolidity/ASTJSON/short_type_name.json
@@ -93,7 +93,7 @@
"documentation" : null,
"id" : 9,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/short_type_name_legacy.json b/test/libsolidity/ASTJSON/short_type_name_legacy.json
index 761bcd3b..1f9b1968 100644
--- a/test/libsolidity/ASTJSON/short_type_name_legacy.json
+++ b/test/libsolidity/ASTJSON/short_type_name_legacy.json
@@ -41,6 +41,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/short_type_name_ref.json b/test/libsolidity/ASTJSON/short_type_name_ref.json
index b0c3ad97..b6b7bca5 100644
--- a/test/libsolidity/ASTJSON/short_type_name_ref.json
+++ b/test/libsolidity/ASTJSON/short_type_name_ref.json
@@ -105,7 +105,7 @@
"documentation" : null,
"id" : 10,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json
index d426a384..420b0f60 100644
--- a/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json
+++ b/test/libsolidity/ASTJSON/short_type_name_ref_legacy.json
@@ -41,6 +41,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSON/source_location.json b/test/libsolidity/ASTJSON/source_location.json
index 8d8acb0f..f0ed216d 100644
--- a/test/libsolidity/ASTJSON/source_location.json
+++ b/test/libsolidity/ASTJSON/source_location.json
@@ -127,7 +127,7 @@
"documentation" : null,
"id" : 10,
"implemented" : true,
- "isConstructor" : false,
+ "kind" : "function",
"modifiers" : [],
"name" : "f",
"nodeType" : "FunctionDefinition",
diff --git a/test/libsolidity/ASTJSON/source_location_legacy.json b/test/libsolidity/ASTJSON/source_location_legacy.json
index 327cd6da..a65979d6 100644
--- a/test/libsolidity/ASTJSON/source_location_legacy.json
+++ b/test/libsolidity/ASTJSON/source_location_legacy.json
@@ -41,6 +41,7 @@
"documentation" : null,
"implemented" : true,
"isConstructor" : false,
+ "kind" : "function",
"modifiers" :
[
null
diff --git a/test/libsolidity/ASTJSONTest.cpp b/test/libsolidity/ASTJSONTest.cpp
index 05839c1f..be482d99 100644
--- a/test/libsolidity/ASTJSONTest.cpp
+++ b/test/libsolidity/ASTJSONTest.cpp
@@ -22,7 +22,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/throw_exception.hpp>
-#include <cctype>
#include <fstream>
#include <memory>
#include <stdexcept>
diff --git a/test/libsolidity/LibSolc.cpp b/test/libsolidity/LibSolc.cpp
index 61e5ebba..94fed7e8 100644
--- a/test/libsolidity/LibSolc.cpp
+++ b/test/libsolidity/LibSolc.cpp
@@ -52,7 +52,7 @@ Json::Value compileMulti(string const& _input, bool _callback)
{
string output(
_callback ?
- compileJSONCallback(_input.c_str(), dev::test::Options::get().optimize, NULL) :
+ compileJSONCallback(_input.c_str(), dev::test::Options::get().optimize, nullptr) :
compileJSONMulti(_input.c_str(), dev::test::Options::get().optimize)
);
Json::Value ret;
@@ -62,7 +62,7 @@ Json::Value compileMulti(string const& _input, bool _callback)
Json::Value compile(string const& _input)
{
- string output(compileStandard(_input.c_str(), NULL));
+ string output(compileStandard(_input.c_str(), nullptr));
Json::Value ret;
BOOST_REQUIRE(jsonParseStrict(output, ret));
return ret;
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index f65c8b27..7a496e64 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -4519,6 +4519,31 @@ BOOST_AUTO_TEST_CASE(library_call_protection)
ABI_CHECK(callContractFunction("pu()"), encodeArgs(2));
}
+
+BOOST_AUTO_TEST_CASE(library_staticcall_delegatecall)
+{
+ char const* sourceCode = R"(
+ library Lib {
+ function x() public view returns (uint) {
+ return 1;
+ }
+ }
+ contract Test {
+ uint t;
+ function f() public returns (uint) {
+ t = 2;
+ return this.g();
+ }
+ function g() public view returns (uint) {
+ return Lib.x();
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "Lib");
+ compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
+}
+
BOOST_AUTO_TEST_CASE(store_bytes)
{
// this test just checks that the copy loop does not mess up the stack
diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp
index 93db236b..6965d886 100644
--- a/test/libsolidity/SolidityScanner.cpp
+++ b/test/libsolidity/SolidityScanner.cpp
@@ -471,6 +471,8 @@ BOOST_AUTO_TEST_CASE(invalid_short_unicode_string_escape)
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
}
+// HEX STRING LITERAL
+
BOOST_AUTO_TEST_CASE(valid_hex_literal)
{
Scanner scanner(CharStream("{ hex\"00112233FF\""));
@@ -483,30 +485,32 @@ BOOST_AUTO_TEST_CASE(invalid_short_hex_literal)
{
Scanner scanner(CharStream("{ hex\"00112233F\""));
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
- BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex);
}
BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_space)
{
Scanner scanner(CharStream("{ hex\"00112233FF \""));
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
- BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex);
}
BOOST_AUTO_TEST_CASE(invalid_hex_literal_with_wrong_quotes)
{
Scanner scanner(CharStream("{ hex\"00112233FF'"));
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
- BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex);
}
BOOST_AUTO_TEST_CASE(invalid_hex_literal_nonhex_string)
{
Scanner scanner(CharStream("{ hex\"hello\""));
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
- BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
+ BOOST_CHECK_EQUAL(scanner.next(), Token::IllegalHex);
}
+// COMMENTS
+
BOOST_AUTO_TEST_CASE(invalid_multiline_comment_close)
{
// This used to parse as "comment", "identifier"
diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp
index 1de42300..91d1681f 100644
--- a/test/libsolidity/SyntaxTest.cpp
+++ b/test/libsolidity/SyntaxTest.cpp
@@ -20,7 +20,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/throw_exception.hpp>
-#include <cctype>
#include <fstream>
#include <memory>
#include <stdexcept>
diff --git a/test/libsolidity/syntaxTests/types/rational_number_huge.sol b/test/libsolidity/syntaxTests/types/rational_number_huge.sol
new file mode 100644
index 00000000..378de201
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/rational_number_huge.sol
@@ -0,0 +1,10 @@
+contract C {
+ function f(uint y) public pure {
+ // fits FixedBytes with exactly 32-bytes
+ y = 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000; // FixedBytes (32)
+
+ // fits exactly into FixedBytes (32), ensures underscored literals won't hurt
+ y = 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff_00000000;
+ }
+}
+// ----
diff --git a/test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol b/test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol
new file mode 100644
index 00000000..08e50656
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/rational_number_huge_fail.sol
@@ -0,0 +1,8 @@
+contract C {
+ function f(uint y) public pure {
+ // one byte too long for storing in Fixedbytes (would require 33 bytes)
+ y = 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000001;
+ }
+}
+// ----
+// TypeError: (142-209): Type int_const 1852...(71 digits omitted)...7281 is not implicitly convertible to expected type uint256.
diff --git a/test/tools/fuzzer.cpp b/test/tools/fuzzer.cpp
index ce4b721f..f7b42b25 100644
--- a/test/tools/fuzzer.cpp
+++ b/test/tools/fuzzer.cpp
@@ -86,7 +86,7 @@ void testConstantOptimizer()
void runCompiler(string input)
{
- string outputString(compileStandard(input.c_str(), NULL));
+ string outputString(compileStandard(input.c_str(), nullptr));
Json::Value output;
if (!jsonParseStrict(outputString, output))
{