aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md5
-rw-r--r--docs/abi-spec.rst2
-rw-r--r--docs/contracts.rst19
-rw-r--r--docs/grammar.txt7
-rw-r--r--docs/miscellaneous.rst5
-rw-r--r--docs/types.rst2
-rw-r--r--docs/utils/SolidityLexer.py4
-rw-r--r--libdevcore/Common.h3
-rw-r--r--libdevcore/CommonData.h3
-rw-r--r--libdevcore/FixedHash.h4
-rw-r--r--libevmasm/Assembly.cpp7
-rw-r--r--libevmasm/AssemblyItem.cpp12
-rw-r--r--libevmasm/BlockDeduplicator.h2
-rw-r--r--libevmasm/CommonSubexpressionEliminator.cpp1
-rw-r--r--libevmasm/CommonSubexpressionEliminator.h4
-rw-r--r--libevmasm/ConstantOptimiser.cpp10
-rw-r--r--libevmasm/ConstantOptimiser.h24
-rw-r--r--libevmasm/PathGasMeter.h2
-rw-r--r--liblll/CodeFragment.h4
-rw-r--r--liblll/CompilerState.cpp2
-rw-r--r--liblll/CompilerState.h2
-rw-r--r--libsolidity/analysis/TypeChecker.cpp13
-rw-r--r--libsolidity/ast/AST.cpp1
-rw-r--r--libsolidity/ast/AST.h5
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp47
-rw-r--r--libsolidity/ast/ASTJsonConverter.h20
-rw-r--r--libsolidity/ast/ASTPrinter.cpp12
-rw-r--r--libsolidity/ast/ASTPrinter.h4
-rw-r--r--libsolidity/ast/ASTVisitor.h4
-rw-r--r--libsolidity/ast/AST_accept.h12
-rw-r--r--libsolidity/ast/Types.cpp11
-rw-r--r--libsolidity/ast/Types.h1
-rw-r--r--libsolidity/codegen/ABIFunctions.h2
-rw-r--r--libsolidity/codegen/ArrayUtils.h2
-rw-r--r--libsolidity/codegen/Compiler.h6
-rw-r--r--libsolidity/codegen/CompilerContext.h4
-rw-r--r--libsolidity/codegen/CompilerUtils.h2
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp2
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp2
-rw-r--r--libsolidity/codegen/ExpressionCompiler.h2
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp4
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp21
-rw-r--r--libsolidity/inlineasm/AsmParser.h4
-rw-r--r--libsolidity/inlineasm/AsmPrinter.cpp2
-rw-r--r--libsolidity/inlineasm/AsmPrinter.h2
-rw-r--r--libsolidity/inlineasm/AsmScope.cpp2
-rw-r--r--libsolidity/inlineasm/AsmScope.h2
-rw-r--r--libsolidity/interface/ABI.cpp4
-rw-r--r--libsolidity/interface/CompilerStack.cpp55
-rw-r--r--libsolidity/interface/CompilerStack.h21
-rw-r--r--libsolidity/interface/ErrorReporter.h2
-rw-r--r--libsolidity/interface/StandardCompiler.cpp4
-rw-r--r--libsolidity/interface/StandardCompiler.h2
-rw-r--r--libsolidity/parsing/Parser.cpp7
-rw-r--r--libsolidity/parsing/Parser.h2
-rw-r--r--libsolidity/parsing/ParserBase.h2
-rw-r--r--libsolidity/parsing/Scanner.h10
-rw-r--r--libsolidity/parsing/Token.h4
-rw-r--r--solc/CommandLineInterface.cpp38
-rw-r--r--solc/CommandLineInterface.h2
-rw-r--r--test/Metadata.cpp1
-rw-r--r--test/RPCSession.h2
-rw-r--r--test/libevmasm/Optimiser.cpp1
-rw-r--r--test/libjulia/Parser.cpp8
-rw-r--r--test/libsolidity/InlineAssembly.cpp8
-rw-r--r--test/libsolidity/JSONCompiler.cpp2
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp58
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp66
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp4
-rw-r--r--test/libsolidity/SolidityParser.cpp5
-rw-r--r--test/libsolidity/StandardCompiler.cpp2
71 files changed, 385 insertions, 238 deletions
diff --git a/Changelog.md b/Changelog.md
index 7d026862..efcea03f 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -3,6 +3,7 @@
Features:
* ABI JSON: Include new field ``statemutability`` with values ``view``, ``nonpayable`` and ``payable``.
* Parser: Display previous visibility specifier in error if multiple are found.
+ * Parser: Introduce ``view`` keyword on functions (``constant`` remains an alias for ``view``).
* Syntax Checker: Support ``pragma experimental <feature>;`` to turn on experimental features.
* Static Analyzer: Warn about large storage structures.
* Metadata: Store experimental flag in metadata CBOR.
@@ -10,8 +11,12 @@ Features:
* Type Checker: Warn about shifting a literal.
Bugfixes:
+ * Assembly Parser: Be more strict about number literals.
* Parser: Enforce commas between array and tuple elements.
* Parser: Limit maximum recursion depth.
+ * Type Checker: Crash fix related to ``using``.
+ * Type Checker: Disallow constructors in libraries.
+ * Type Checker: Reject the creation of interface contracts using the ``new`` statement.
### 0.4.15 (2017-08-08)
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index a9110a0a..159bd6c7 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -293,7 +293,7 @@ The JSON format for a contract's interface is given by an array of function and/
* `name`: the name of the parameter;
* `type`: the canonical type of the parameter.
- `outputs`: an array of objects similar to `inputs`, can be omitted if function doesn't return anything;
-- `constant`: `true` if function is :ref:`specified to not modify blockchain state <constant-functions>`);
+- `constant`: `true` if function is :ref:`specified to not modify blockchain state <view-functions>`);
- `payable`: `true` if function accepts ether, defaults to `false`;
- `statemutability`: a string with one of the following values: `view` (same as `constant` above), `nonpayable` and `payable` (same as `payable` above).
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 7b972e17..0f1a882c 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -461,29 +461,32 @@ value types and strings.
}
-.. _constant-functions:
+.. _view-functions:
-******************
-Constant Functions
-******************
+**************
+View Functions
+**************
-Functions can be declared constant in which case they promise not to modify the state.
+Functions can be declared ``view`` in which case they promise not to modify the state.
::
pragma solidity ^0.4.0;
contract C {
- function f(uint a, uint b) constant returns (uint) {
+ function f(uint a, uint b) view returns (uint) {
return a * (b + 42);
}
}
.. note::
- Getter methods are marked constant.
+ ``constant`` is an alias to ``view``.
+
+.. note::
+ Getter methods are marked ``view``.
.. warning::
- The compiler does not enforce yet that a constant method is not modifying state.
+ The compiler does not enforce yet that a ``view`` method is not modifying state.
.. index:: ! fallback function, function;fallback
diff --git a/docs/grammar.txt b/docs/grammar.txt
index a9838ccb..36ba36f0 100644
--- a/docs/grammar.txt
+++ b/docs/grammar.txt
@@ -16,7 +16,7 @@ ContractPart = StateVariableDeclaration | UsingForDeclaration
InheritanceSpecifier = UserDefinedTypeName ( '(' Expression ( ',' Expression )* ')' )?
-StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' )? Identifier ('=' Expression)? ';'
+StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' | 'constant' )? Identifier ('=' Expression)? ';'
UsingForDeclaration = 'using' Identifier 'for' ('*' | TypeName) ';'
StructDefinition = 'struct' Identifier '{'
( VariableDeclaration ';' (VariableDeclaration ';')* )? '}'
@@ -25,7 +25,7 @@ ModifierDefinition = 'modifier' Identifier ParameterList? Block
ModifierInvocation = Identifier ( '(' ExpressionList? ')' )?
FunctionDefinition = 'function' Identifier? ParameterList
- ( ModifierInvocation | 'constant' | 'payable' | 'external' | 'public' | 'internal' | 'private' )*
+ ( ModifierInvocation | StateMutability | 'external' | 'public' | 'internal' | 'private' )*
( 'returns' ParameterList )? ( ';' | Block )
EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';'
@@ -50,9 +50,10 @@ UserDefinedTypeName = Identifier ( '.' Identifier )*
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
ArrayTypeName = TypeName '[' Expression? ']'
-FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant' | 'payable' )*
+FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | StateMutability )*
( 'returns' TypeNameList )?
StorageLocation = 'memory' | 'storage'
+StateMutability = 'constant' | 'view' | 'payable'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 199182d3..7889fff2 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -505,11 +505,12 @@ Function Visibility Specifiers
Modifiers
=========
+- ``view`` for functions: Disallow modification of state - this is not enforced yet.
+- ``payable`` for functions: Allows them to receive Ether together with a call.
- ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot.
-- ``constant`` for functions: Disallows modification of state - this is not enforced yet.
+- ``constant`` for functions: Same as ``view``.
- ``anonymous`` for events: Does not store event signature as topic.
- ``indexed`` for event parameters: Stores the parameter as topic.
-- ``payable`` for functions: Allows them to receive Ether together with a call.
Reserved Keywords
=================
diff --git a/docs/types.rst b/docs/types.rst
index abf8bb17..9c1c73c6 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -337,7 +337,7 @@ be passed via and returned from external function calls.
Function types are notated as follows::
- function (<parameter types>) {internal|external} [constant] [payable] [returns (<return types>)]
+ function (<parameter types>) {internal|external} [constant|view|payable] [returns (<return types>)]
In contrast to the parameter types, the return types cannot be empty - if the
function type should not return anything, the whole ``returns (<return types>)``
diff --git a/docs/utils/SolidityLexer.py b/docs/utils/SolidityLexer.py
index ef55c6a2..a828146f 100644
--- a/docs/utils/SolidityLexer.py
+++ b/docs/utils/SolidityLexer.py
@@ -57,7 +57,7 @@ class SolidityLexer(RegexLexer):
(r'(anonymous|as|assembly|break|constant|continue|do|delete|else|external|for|hex|if|'
r'indexed|internal|import|is|mapping|memory|new|payable|public|pragma|'
r'private|return|returns|storage|super|this|throw|using|while)\b', Keyword, 'slashstartsregex'),
- (r'(var|function|event|modifier|struct|enum|contract|library)\b', Keyword.Declaration, 'slashstartsregex'),
+ (r'(var|function|event|modifier|struct|enum|contract|library|interface)\b', Keyword.Declaration, 'slashstartsregex'),
(r'(bytes|string|address|uint|int|bool|byte|' +
'|'.join(
['uint%d' % (i + 8) for i in range(0, 256, 8)] +
@@ -71,7 +71,7 @@ class SolidityLexer(RegexLexer):
r'null|of|pure|relocatable|static|switch|try|type|typeof|view)\b', Keyword.Reserved),
(r'(true|false)\b', Keyword.Constant),
(r'(block|msg|tx|now|suicide|selfdestruct|addmod|mulmod|sha3|keccak256|log[0-4]|'
- r'sha256|ecrecover|ripemd160|assert|revert)', Name.Builtin),
+ r'sha256|ecrecover|ripemd160|assert|revert|require)', Name.Builtin),
(r'[$a-zA-Z_][a-zA-Z0-9_]*', Name.Other),
(r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float),
(r'0x[0-9a-fA-F]+', Number.Hex),
diff --git a/libdevcore/Common.h b/libdevcore/Common.h
index c5b09a80..9d6dd408 100644
--- a/libdevcore/Common.h
+++ b/libdevcore/Common.h
@@ -44,7 +44,6 @@
#include <unordered_set>
#include <functional>
#include <string>
-#include <chrono>
#if defined(__GNUC__)
#pragma warning(push)
@@ -158,7 +157,7 @@ template <> inline u256 exp10<0>()
class ScopeGuard
{
public:
- ScopeGuard(std::function<void(void)> _f): m_f(_f) {}
+ explicit ScopeGuard(std::function<void(void)> _f): m_f(_f) {}
~ScopeGuard() { m_f(); }
private:
diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h
index 6f40d7be..0321011e 100644
--- a/libdevcore/CommonData.h
+++ b/libdevcore/CommonData.h
@@ -184,7 +184,8 @@ template <class T>
inline std::vector<T> operator+(std::vector<T> const& _a, std::vector<T> const& _b)
{
std::vector<T> ret(_a);
- return ret += _b;
+ ret += _b;
+ return ret;
}
template <class T, class V>
diff --git a/libdevcore/FixedHash.h b/libdevcore/FixedHash.h
index 5b1c7acf..141e9ffd 100644
--- a/libdevcore/FixedHash.h
+++ b/libdevcore/FixedHash.h
@@ -27,6 +27,7 @@
#include <cstdint>
#include <algorithm>
#include <boost/functional/hash.hpp>
+#include <boost/io/ios_state.hpp>
#include "CommonData.h"
namespace dev
@@ -59,7 +60,7 @@ public:
enum ConstructFromHashType { AlignLeft, AlignRight, FailIfDifferent };
/// Construct an empty hash.
- FixedHash() { m_data.fill(0); }
+ explicit FixedHash() { m_data.fill(0); }
/// Construct from another hash, filling with zeroes or cropping as necessary.
template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) { m_data.fill(0); unsigned c = std::min(M, N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _h[_t == AlignRight ? M - 1 - i : i]; }
@@ -224,6 +225,7 @@ template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& va
template <unsigned N>
inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
{
+ boost::io::ios_all_saver guard(_out);
_out << std::noshowbase << std::hex << std::setfill('0');
for (unsigned i = 0; i < N; ++i)
_out << std::setw(2) << (int)_h[i];
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index 42b923df..0a3bf6b8 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -233,7 +233,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
{
Json::Value root;
- Json::Value collection(Json::arrayValue);
+ Json::Value& collection = root[".code"] = Json::arrayValue;
for (AssemblyItem const& i: m_items)
{
switch (i.type())
@@ -289,11 +289,9 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
}
}
- root[".code"] = collection;
-
if (!m_data.empty() || !m_subs.empty())
{
- Json::Value data;
+ Json::Value& data = root[".data"] = Json::objectValue;
for (auto const& i: m_data)
if (u256(i.first) >= m_subs.size())
data[toStringInHex((u256)i.first)] = toHex(i.second);
@@ -304,7 +302,6 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
hexStr << hex << i;
data[hexStr.str()] = m_subs[i]->stream(_out, "", _sourceCodes, true);
}
- root[".data"] = data;
}
if (m_auxiliaryData.size() > 0)
diff --git a/libevmasm/AssemblyItem.cpp b/libevmasm/AssemblyItem.cpp
index 76104866..419a8c0b 100644
--- a/libevmasm/AssemblyItem.cpp
+++ b/libevmasm/AssemblyItem.cpp
@@ -219,10 +219,10 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << "\t" << _item.getJumpTypeAsString();
break;
case Push:
- _out << " PUSH " << hex << _item.data();
+ _out << " PUSH " << hex << _item.data() << dec;
break;
case PushString:
- _out << " PushString" << hex << (unsigned)_item.data();
+ _out << " PushString" << hex << (unsigned)_item.data() << dec;
break;
case PushTag:
{
@@ -237,19 +237,19 @@ ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item)
_out << " Tag " << _item.data();
break;
case PushData:
- _out << " PushData " << hex << (unsigned)_item.data();
+ _out << " PushData " << hex << (unsigned)_item.data() << dec;
break;
case PushSub:
- _out << " PushSub " << hex << size_t(_item.data());
+ _out << " PushSub " << hex << size_t(_item.data()) << dec;
break;
case PushSubSize:
- _out << " PushSubSize " << hex << size_t(_item.data());
+ _out << " PushSubSize " << hex << size_t(_item.data()) << dec;
break;
case PushProgramSize:
_out << " PushProgramSize";
break;
case PushLibraryAddress:
- _out << " PushLibraryAddress " << hex << h256(_item.data()).abridgedMiddle();
+ _out << " PushLibraryAddress " << hex << h256(_item.data()).abridgedMiddle() << dec;
break;
case UndefinedItem:
_out << " ???";
diff --git a/libevmasm/BlockDeduplicator.h b/libevmasm/BlockDeduplicator.h
index 797c2476..5640984b 100644
--- a/libevmasm/BlockDeduplicator.h
+++ b/libevmasm/BlockDeduplicator.h
@@ -45,7 +45,7 @@ using AssemblyItems = std::vector<AssemblyItem>;
class BlockDeduplicator
{
public:
- BlockDeduplicator(AssemblyItems& _items): m_items(_items) {}
+ explicit BlockDeduplicator(AssemblyItems& _items): m_items(_items) {}
/// @returns true if something was changed
bool deduplicate();
/// @returns the tags that were replaced.
diff --git a/libevmasm/CommonSubexpressionEliminator.cpp b/libevmasm/CommonSubexpressionEliminator.cpp
index 70324e7f..293cb02c 100644
--- a/libevmasm/CommonSubexpressionEliminator.cpp
+++ b/libevmasm/CommonSubexpressionEliminator.cpp
@@ -220,6 +220,7 @@ void CSECodeGenerator::addDependencies(Id _c)
if (m_neededBy.count(_c))
return; // we already computed the dependencies for _c
ExpressionClasses::Expression expr = m_expressionClasses.representative(_c);
+ assertThrow(expr.item, OptimizerException, "");
if (expr.item->type() == UndefinedItem)
BOOST_THROW_EXCEPTION(
// If this exception happens, we need to find a different way to generate the
diff --git a/libevmasm/CommonSubexpressionEliminator.h b/libevmasm/CommonSubexpressionEliminator.h
index 83fc9732..0b957a0e 100644
--- a/libevmasm/CommonSubexpressionEliminator.h
+++ b/libevmasm/CommonSubexpressionEliminator.h
@@ -61,7 +61,7 @@ public:
using Id = ExpressionClasses::Id;
using StoreOperation = KnownState::StoreOperation;
- CommonSubexpressionEliminator(KnownState const& _state): m_initialState(_state), m_state(_state) {}
+ explicit CommonSubexpressionEliminator(KnownState const& _state): m_initialState(_state), m_state(_state) {}
/// Feeds AssemblyItems into the eliminator and @returns the iterator pointing at the first
/// item that must be fed into a new instance of the eliminator.
@@ -147,7 +147,7 @@ private:
AssemblyItems m_generatedItems;
/// Current height of the stack relative to the start.
- int m_stackHeight;
+ int m_stackHeight = 0;
/// If (b, a) is in m_requests then b is needed to compute a.
std::multimap<Id, Id> m_neededBy;
/// Current content of the stack.
diff --git a/libevmasm/ConstantOptimiser.cpp b/libevmasm/ConstantOptimiser.cpp
index 2ecbfa7f..2efd2dc9 100644
--- a/libevmasm/ConstantOptimiser.cpp
+++ b/libevmasm/ConstantOptimiser.cpp
@@ -124,7 +124,7 @@ void ConstantOptimisationMethod::replaceConstants(
_items = std::move(replaced);
}
-bigint LiteralMethod::gasNeeded()
+bigint LiteralMethod::gasNeeded() const
{
return combineGas(
simpleRunGas({Instruction::PUSH1}),
@@ -139,7 +139,7 @@ CodeCopyMethod::CodeCopyMethod(Params const& _params, u256 const& _value):
{
}
-bigint CodeCopyMethod::gasNeeded()
+bigint CodeCopyMethod::gasNeeded() const
{
return combineGas(
// Run gas: we ignore memory increase costs
@@ -151,7 +151,7 @@ bigint CodeCopyMethod::gasNeeded()
);
}
-AssemblyItems CodeCopyMethod::execute(Assembly& _assembly)
+AssemblyItems CodeCopyMethod::execute(Assembly& _assembly) const
{
bytes data = toBigEndian(m_value);
AssemblyItems actualCopyRoutine = copyRoutine();
@@ -159,7 +159,7 @@ AssemblyItems CodeCopyMethod::execute(Assembly& _assembly)
return actualCopyRoutine;
}
-AssemblyItems const& CodeCopyMethod::copyRoutine() const
+AssemblyItems const& CodeCopyMethod::copyRoutine()
{
AssemblyItems static copyRoutine{
u256(0),
@@ -282,7 +282,7 @@ bool ComputeMethod::checkRepresentation(u256 const& _value, AssemblyItems const&
return stack.size() == 1 && stack.front() == _value;
}
-bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine)
+bigint ComputeMethod::gasNeeded(AssemblyItems const& _routine) const
{
size_t numExps = count(_routine.begin(), _routine.end(), Instruction::EXP);
return combineGas(
diff --git a/libevmasm/ConstantOptimiser.h b/libevmasm/ConstantOptimiser.h
index 85bdabac..82982e25 100644
--- a/libevmasm/ConstantOptimiser.h
+++ b/libevmasm/ConstantOptimiser.h
@@ -63,11 +63,11 @@ public:
explicit ConstantOptimisationMethod(Params const& _params, u256 const& _value):
m_params(_params), m_value(_value) {}
- virtual bigint gasNeeded() = 0;
+ virtual bigint gasNeeded() const = 0;
/// Executes the method, potentially appending to the assembly and returns a vector of
/// assembly items the constant should be relpaced with in one sweep.
/// If the vector is empty, the constants will not be deleted.
- virtual AssemblyItems execute(Assembly& _assembly) = 0;
+ virtual AssemblyItems execute(Assembly& _assembly) const = 0;
protected:
size_t dataSize() const { return std::max<size_t>(1, dev::bytesRequired(m_value)); }
@@ -84,7 +84,7 @@ protected:
bigint const& _runGas,
bigint const& _repeatedDataGas,
bigint const& _uniqueDataGas
- )
+ ) const
{
// _runGas is not multiplied by _multiplicity because the runs are "per opcode"
return m_params.runs * _runGas + m_params.multiplicity * _repeatedDataGas + _uniqueDataGas;
@@ -106,8 +106,8 @@ class LiteralMethod: public ConstantOptimisationMethod
public:
explicit LiteralMethod(Params const& _params, u256 const& _value):
ConstantOptimisationMethod(_params, _value) {}
- virtual bigint gasNeeded() override;
- virtual AssemblyItems execute(Assembly&) override { return AssemblyItems{}; }
+ virtual bigint gasNeeded() const override;
+ virtual AssemblyItems execute(Assembly&) const override { return AssemblyItems{}; }
};
/**
@@ -117,11 +117,11 @@ class CodeCopyMethod: public ConstantOptimisationMethod
{
public:
explicit CodeCopyMethod(Params const& _params, u256 const& _value);
- virtual bigint gasNeeded() override;
- virtual AssemblyItems execute(Assembly& _assembly) override;
+ virtual bigint gasNeeded() const override;
+ virtual AssemblyItems execute(Assembly& _assembly) const override;
protected:
- AssemblyItems const& copyRoutine() const;
+ static AssemblyItems const& copyRoutine();
};
/**
@@ -141,8 +141,8 @@ public:
);
}
- virtual bigint gasNeeded() override { return gasNeeded(m_routine); }
- virtual AssemblyItems execute(Assembly&) override
+ virtual bigint gasNeeded() const override { return gasNeeded(m_routine); }
+ virtual AssemblyItems execute(Assembly&) const override
{
return m_routine;
}
@@ -151,8 +151,8 @@ protected:
/// Tries to recursively find a way to compute @a _value.
AssemblyItems findRepresentation(u256 const& _value);
/// Recomputes the value from the calculated representation and checks for correctness.
- bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine);
- bigint gasNeeded(AssemblyItems const& _routine);
+ static bool checkRepresentation(u256 const& _value, AssemblyItems const& _routine);
+ bigint gasNeeded(AssemblyItems const& _routine) const;
/// Counter for the complexity of optimization, will stop when it reaches zero.
size_t m_maxSteps = 10000;
diff --git a/libevmasm/PathGasMeter.h b/libevmasm/PathGasMeter.h
index 0a0fe5d0..4826eac2 100644
--- a/libevmasm/PathGasMeter.h
+++ b/libevmasm/PathGasMeter.h
@@ -50,7 +50,7 @@ struct GasPath
class PathGasMeter
{
public:
- PathGasMeter(AssemblyItems const& _items);
+ explicit PathGasMeter(AssemblyItems const& _items);
GasMeter::GasConsumption estimateMax(size_t _startIndex, std::shared_ptr<KnownState> const& _state);
diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h
index 6622de3e..95d21563 100644
--- a/liblll/CodeFragment.h
+++ b/liblll/CodeFragment.h
@@ -50,8 +50,8 @@ public:
private:
void finalise(CompilerState const& _cs);
- template <class T> void error() const { BOOST_THROW_EXCEPTION(T() ); }
- template <class T> void error(std::string const& reason) const {
+ template <class T> static void error() { BOOST_THROW_EXCEPTION(T() ); }
+ template <class T> static void error(std::string const& reason) {
auto err = T();
err << errinfo_comment(reason);
BOOST_THROW_EXCEPTION(err);
diff --git a/liblll/CompilerState.cpp b/liblll/CompilerState.cpp
index 9701e16b..d53dec7e 100644
--- a/liblll/CompilerState.cpp
+++ b/liblll/CompilerState.cpp
@@ -30,7 +30,7 @@ CompilerState::CompilerState()
{
}
-CodeFragment const& CompilerState::getDef(std::string const& _s)
+CodeFragment const& CompilerState::getDef(std::string const& _s) const
{
if (defs.count(_s))
return defs.at(_s);
diff --git a/liblll/CompilerState.h b/liblll/CompilerState.h
index c29d3b7d..96a0246d 100644
--- a/liblll/CompilerState.h
+++ b/liblll/CompilerState.h
@@ -40,7 +40,7 @@ struct CompilerState
{
CompilerState();
- CodeFragment const& getDef(std::string const& _s);
+ CodeFragment const& getDef(std::string const& _s) const;
void populateStandard();
unsigned stackSize = 128;
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 0764bf67..99f3c64c 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -430,7 +430,11 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
m_errorReporter.typeError(_inheritance.location(), "Libraries cannot be inherited from.");
auto const& arguments = _inheritance.arguments();
- TypePointers parameterTypes = ContractType(*base).newExpressionType()->parameterTypes();
+ TypePointers parameterTypes;
+ if (base->contractKind() != ContractDefinition::ContractKind::Interface)
+ // Interfaces do not have constructors, so there are zero parameters.
+ parameterTypes = ContractType(*base).newExpressionType()->parameterTypes();
+
if (!arguments.empty() && parameterTypes.size() != arguments.size())
{
m_errorReporter.typeError(
@@ -463,7 +467,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
_usingFor.libraryName().annotation().referencedDeclaration
);
if (!library || !library->isLibrary())
- m_errorReporter.typeError(_usingFor.libraryName().location(), "Library name expected.");
+ m_errorReporter.fatalTypeError(_usingFor.libraryName().location(), "Library name expected.");
}
bool TypeChecker::visit(StructDefinition const& _struct)
@@ -546,6 +550,9 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (_function.isConstructor())
m_errorReporter.typeError(_function.location(), "Constructor cannot be defined in interfaces.");
}
+ else if (m_scope->contractKind() == ContractDefinition::ContractKind::Library)
+ if (_function.isConstructor())
+ m_errorReporter.typeError(_function.location(), "Constructor cannot be defined in libraries.");
if (_function.isImplemented())
_function.body().accept(*this);
else if (_function.isConstructor())
@@ -1551,6 +1558,8 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
if (!contract)
m_errorReporter.fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
+ if (contract->contractKind() == ContractDefinition::ContractKind::Interface)
+ m_errorReporter.fatalTypeError(_newExpression.location(), "Cannot instantiate an interface.");
if (!contract->annotation().unimplementedFunctions.empty())
m_errorReporter.typeError(
_newExpression.location(),
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index e173237e..605daf55 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -188,7 +188,6 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::inter
{
if (!m_interfaceFunctionList)
{
- set<string> functionsSeen;
set<string> signaturesSeen;
m_interfaceFunctionList.reset(new vector<pair<FixedHash<4>, FunctionTypePointer>>());
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 53a34d32..4592a190 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -836,11 +836,10 @@ private:
*/
class TypeName: public ASTNode
{
-public:
+protected:
explicit TypeName(SourceLocation const& _location): ASTNode(_location) {}
- virtual void accept(ASTVisitor& _visitor) override;
- virtual void accept(ASTConstVisitor& _visitor) const override;
+public:
virtual TypeNameAnnotation& annotation() const override;
};
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index 3f16db23..f1f6770e 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -15,8 +15,7 @@
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
- * @author Lefteris <lefteris@ethdev.com>
- * @date 2015
+ * @date 2017
* Converts the AST into json format
*/
@@ -81,28 +80,30 @@ void ASTJsonConverter::setJsonNode(
(_nodeType == "InlineAssembly") ||
(_nodeType == "Throw")
)
- {
- Json::Value children(Json::arrayValue);
- m_currentValue["children"] = children;
- }
+ m_currentValue["children"] = Json::arrayValue;
for (auto& e: _attributes)
{
- if (
- (!e.second.isNull()) &&
- (
- (e.second.isObject() && e.second.isMember("name")) ||
- (e.second.isArray() && e.second[0].isObject() && e.second[0].isMember("name")) ||
- (e.first == "declarations") // (in the case (_,x)= ... there's a nullpointer at [0]
- )
- )
+ if ((!e.second.isNull()) && (
+ (e.second.isObject() && e.second.isMember("name")) ||
+ (e.second.isArray() && e.second[0].isObject() && e.second[0].isMember("name")) ||
+ (e.first == "declarations") // (in the case (_,x)= ... there's a nullpointer at [0]
+ ))
{
if (e.second.isObject())
- m_currentValue["children"].append(std::move(e.second));
+ {
+ if (!m_currentValue["children"].isArray())
+ m_currentValue["children"] = Json::arrayValue;
+ appendMove(m_currentValue["children"], std::move(e.second));
+ }
if (e.second.isArray())
for (auto& child: e.second)
if (!child.isNull())
- m_currentValue["children"].append(std::move(child));
+ {
+ if (!m_currentValue["children"].isArray())
+ m_currentValue["children"] = Json::arrayValue;
+ appendMove(m_currentValue["children"], std::move(child));
+ }
}
else
{
@@ -147,7 +148,7 @@ Json::Value ASTJsonConverter::typePointerToJson(std::shared_ptr<std::vector<Type
{
Json::Value arguments(Json::arrayValue);
for (auto const& tp: *_tps)
- arguments.append(typePointerToJson(tp));
+ appendMove(arguments, typePointerToJson(tp));
return arguments;
}
else
@@ -186,7 +187,7 @@ void ASTJsonConverter::print(ostream& _stream, ASTNode const& _node)
_stream << toJson(_node);
}
-Json::Value ASTJsonConverter::toJson(ASTNode const& _node)
+Json::Value&& ASTJsonConverter::toJson(ASTNode const& _node)
{
_node.accept(*this);
return std::move(m_currentValue);
@@ -323,6 +324,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
+ // FIXME: remove with next breaking release
make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() == StateMutability::View),
make_pair("payable", _node.isPayable()),
make_pair("statemutability", stateMutabilityToString(_node.stateMutability())),
@@ -378,12 +380,6 @@ bool ASTJsonConverter::visit(ModifierInvocation const& _node)
return false;
}
-bool ASTJsonConverter::visit(TypeName const&)
-{
- solAssert(false, "AST node of abstract type used.");
- return false;
-}
-
bool ASTJsonConverter::visit(EventDefinition const& _node)
{
m_inEvent = true;
@@ -421,6 +417,7 @@ bool ASTJsonConverter::visit(FunctionTypeName const& _node)
make_pair("payable", _node.isPayable()),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("statemutability", stateMutabilityToString(_node.stateMutability())),
+ // FIXME: remove with next breaking release
make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() == StateMutability::View),
make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
@@ -547,7 +544,7 @@ bool ASTJsonConverter::visit(VariableDeclarationStatement const& _node)
{
Json::Value varDecs(Json::arrayValue);
for (auto const& v: _node.annotation().assignments)
- varDecs.append(idOrNull(v));
+ appendMove(varDecs, idOrNull(v));
setJsonNode(_node, "VariableDeclarationStatement", {
make_pair("assignments", std::move(varDecs)),
make_pair("declarations", toJson(_node.declarations())),
diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h
index 70e260db..60c660c1 100644
--- a/libsolidity/ast/ASTJsonConverter.h
+++ b/libsolidity/ast/ASTJsonConverter.h
@@ -49,13 +49,16 @@ public:
);
/// Output the json representation of the AST to _stream.
void print(std::ostream& _stream, ASTNode const& _node);
- Json::Value toJson(ASTNode const& _node);
+ Json::Value&& toJson(ASTNode const& _node);
template <class T>
Json::Value toJson(std::vector<ASTPointer<T>> const& _nodes)
{
Json::Value ret(Json::arrayValue);
for (auto const& n: _nodes)
- ret.append(n ? toJson(*n) : Json::nullValue);
+ if (n)
+ appendMove(ret, toJson(*n));
+ else
+ ret.append(Json::nullValue);
return ret;
}
bool visit(SourceUnit const& _node) override;
@@ -73,7 +76,6 @@ public:
bool visit(ModifierDefinition const& _node) override;
bool visit(ModifierInvocation const& _node) override;
bool visit(EventDefinition const& _node) override;
- bool visit(TypeName const& _node) override;
bool visit(ElementaryTypeName const& _node) override;
bool visit(UserDefinedTypeName const& _node) override;
bool visit(FunctionTypeName const& _node) override;
@@ -119,7 +121,7 @@ private:
);
std::string sourceLocationToString(SourceLocation const& _location) const;
std::string namePathToString(std::vector<ASTString> const& _namePath) const;
- Json::Value idOrNull(ASTNode const* _pt)
+ static Json::Value idOrNull(ASTNode const* _pt)
{
return _pt ? Json::Value(nodeId(*_pt)) : Json::nullValue;
}
@@ -134,12 +136,12 @@ private:
std::string literalTokenKind(Token::Value _token);
std::string type(Expression const& _expression);
std::string type(VariableDeclaration const& _varDecl);
- int nodeId(ASTNode const& _node)
+ static int nodeId(ASTNode const& _node)
{
return _node.id();
}
template<class Container>
- Json::Value getContainerIds(Container const& container)
+ static Json::Value getContainerIds(Container const& container)
{
Json::Value tmp(Json::arrayValue);
for (auto const& element: container)
@@ -155,6 +157,12 @@ private:
std::vector<std::pair<std::string, Json::Value>> &_attributes,
ExpressionAnnotation const& _annotation
);
+ static void appendMove(Json::Value& _array, Json::Value&& _value)
+ {
+ solAssert(_array.isArray(), "");
+ _array.append(std::move(_value));
+ }
+
bool m_legacy = false; ///< if true, use legacy format
bool m_inEvent = false; ///< whether we are currently inside an event or not
Json::Value m_currentValue;
diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp
index bcb5e3b9..392179ef 100644
--- a/libsolidity/ast/ASTPrinter.cpp
+++ b/libsolidity/ast/ASTPrinter.cpp
@@ -143,13 +143,6 @@ bool ASTPrinter::visit(EventDefinition const& _node)
return goDeeper();
}
-bool ASTPrinter::visit(TypeName const& _node)
-{
- writeLine("TypeName");
- printSourcePart(_node);
- return goDeeper();
-}
-
bool ASTPrinter::visit(ElementaryTypeName const& _node)
{
writeLine(string("ElementaryTypeName ") + _node.typeName().toString());
@@ -434,11 +427,6 @@ void ASTPrinter::endVisit(EventDefinition const&)
m_indentation--;
}
-void ASTPrinter::endVisit(TypeName const&)
-{
- m_indentation--;
-}
-
void ASTPrinter::endVisit(ElementaryTypeName const&)
{
m_indentation--;
diff --git a/libsolidity/ast/ASTPrinter.h b/libsolidity/ast/ASTPrinter.h
index 4a37f17f..d6897dfd 100644
--- a/libsolidity/ast/ASTPrinter.h
+++ b/libsolidity/ast/ASTPrinter.h
@@ -60,7 +60,6 @@ public:
bool visit(ModifierDefinition const& _node) override;
bool visit(ModifierInvocation const& _node) override;
bool visit(EventDefinition const& _node) override;
- bool visit(TypeName const& _node) override;
bool visit(ElementaryTypeName const& _node) override;
bool visit(UserDefinedTypeName const& _node) override;
bool visit(FunctionTypeName const& _node) override;
@@ -104,7 +103,6 @@ public:
void endVisit(ModifierDefinition const&) override;
void endVisit(ModifierInvocation const&) override;
void endVisit(EventDefinition const&) override;
- void endVisit(TypeName const&) override;
void endVisit(ElementaryTypeName const&) override;
void endVisit(UserDefinedTypeName const&) override;
void endVisit(FunctionTypeName const&) override;
@@ -146,7 +144,7 @@ private:
std::string m_source;
ASTNode const* m_ast;
GasEstimator::ASTGasConsumption m_gasCosts;
- std::ostream* m_ostream;
+ std::ostream* m_ostream = nullptr;
};
}
diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h
index 20be634b..b726d592 100644
--- a/libsolidity/ast/ASTVisitor.h
+++ b/libsolidity/ast/ASTVisitor.h
@@ -58,7 +58,6 @@ public:
virtual bool visit(ModifierDefinition& _node) { return visitNode(_node); }
virtual bool visit(ModifierInvocation& _node) { return visitNode(_node); }
virtual bool visit(EventDefinition& _node) { return visitNode(_node); }
- virtual bool visit(TypeName& _node) { return visitNode(_node); }
virtual bool visit(ElementaryTypeName& _node) { return visitNode(_node); }
virtual bool visit(UserDefinedTypeName& _node) { return visitNode(_node); }
virtual bool visit(FunctionTypeName& _node) { return visitNode(_node); }
@@ -104,7 +103,6 @@ public:
virtual void endVisit(ModifierDefinition& _node) { endVisitNode(_node); }
virtual void endVisit(ModifierInvocation& _node) { endVisitNode(_node); }
virtual void endVisit(EventDefinition& _node) { endVisitNode(_node); }
- virtual void endVisit(TypeName& _node) { endVisitNode(_node); }
virtual void endVisit(ElementaryTypeName& _node) { endVisitNode(_node); }
virtual void endVisit(UserDefinedTypeName& _node) { endVisitNode(_node); }
virtual void endVisit(FunctionTypeName& _node) { endVisitNode(_node); }
@@ -162,7 +160,6 @@ public:
virtual bool visit(ModifierDefinition const& _node) { return visitNode(_node); }
virtual bool visit(ModifierInvocation const& _node) { return visitNode(_node); }
virtual bool visit(EventDefinition const& _node) { return visitNode(_node); }
- virtual bool visit(TypeName const& _node) { return visitNode(_node); }
virtual bool visit(ElementaryTypeName const& _node) { return visitNode(_node); }
virtual bool visit(UserDefinedTypeName const& _node) { return visitNode(_node); }
virtual bool visit(FunctionTypeName const& _node) { return visitNode(_node); }
@@ -208,7 +205,6 @@ public:
virtual void endVisit(ModifierDefinition const& _node) { endVisitNode(_node); }
virtual void endVisit(ModifierInvocation const& _node) { endVisitNode(_node); }
virtual void endVisit(EventDefinition const& _node) { endVisitNode(_node); }
- virtual void endVisit(TypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(ElementaryTypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(UserDefinedTypeName const& _node) { endVisitNode(_node); }
virtual void endVisit(FunctionTypeName const& _node) { endVisitNode(_node); }
diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h
index 7c1c64b0..904d9ff6 100644
--- a/libsolidity/ast/AST_accept.h
+++ b/libsolidity/ast/AST_accept.h
@@ -291,18 +291,6 @@ void EventDefinition::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this);
}
-void TypeName::accept(ASTVisitor& _visitor)
-{
- _visitor.visit(*this);
- _visitor.endVisit(*this);
-}
-
-void TypeName::accept(ASTConstVisitor& _visitor) const
-{
- _visitor.visit(*this);
- _visitor.endVisit(*this);
-}
-
void ElementaryTypeName::accept(ASTVisitor& _visitor)
{
_visitor.visit(*this);
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index e6664895..5e61cdee 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -739,18 +739,18 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.category() == Category::Integer)
{
- auto targetType = dynamic_cast<IntegerType const*>(&_convertTo);
if (m_value == rational(0))
return true;
if (isFractional())
return false;
- int forSignBit = (targetType->isSigned() ? 1 : 0);
+ IntegerType const& targetType = dynamic_cast<IntegerType const&>(_convertTo);
+ int forSignBit = (targetType.isSigned() ? 1 : 0);
if (m_value > rational(0))
{
- if (m_value.numerator() <= (u256(-1) >> (256 - targetType->numBits() + forSignBit)))
+ if (m_value.numerator() <= (u256(-1) >> (256 - targetType.numBits() + forSignBit)))
return true;
}
- else if (targetType->isSigned() && -m_value.numerator() <= (u256(1) << (targetType->numBits() - forSignBit)))
+ else if (targetType.isSigned() && -m_value.numerator() <= (u256(1) << (targetType.numBits() - forSignBit)))
return true;
return false;
}
@@ -2140,6 +2140,8 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c
strings parameterNames;
StateMutability stateMutability = StateMutability::NonPayable;
+ solAssert(_contract.contractKind() != ContractDefinition::ContractKind::Interface, "");
+
if (constructor)
{
for (ASTPointer<VariableDeclaration> const& var: constructor->parameters())
@@ -2150,6 +2152,7 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c
if (constructor->isPayable())
stateMutability = StateMutability::Payable;
}
+
return make_shared<FunctionType>(
parameters,
TypePointers{make_shared<ContractType>(_contract)},
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 56546a82..ce2d3bf8 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -993,7 +993,6 @@ public:
return *m_declaration;
}
bool hasDeclaration() const { return !!m_declaration; }
- bool isConstant() const { return m_stateMutability == StateMutability::View; }
/// @returns true if the the result of this function only depends on its arguments
/// and it does not modify the state.
/// Currently, this will only return true for internal functions like keccak and ecrecover.
diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h
index 76f4b467..e43e2323 100644
--- a/libsolidity/codegen/ABIFunctions.h
+++ b/libsolidity/codegen/ABIFunctions.h
@@ -162,7 +162,7 @@ private:
std::string createFunction(std::string const& _name, std::function<std::string()> const& _creator);
/// @returns the size of the static part of the encoding of the given types.
- size_t headSize(TypePointers const& _targetTypes);
+ static size_t headSize(TypePointers const& _targetTypes);
/// Map from function name to code for a multi-use function.
std::map<std::string, std::string> m_requestedFunctions;
diff --git a/libsolidity/codegen/ArrayUtils.h b/libsolidity/codegen/ArrayUtils.h
index 806fbea7..f3ddc4ee 100644
--- a/libsolidity/codegen/ArrayUtils.h
+++ b/libsolidity/codegen/ArrayUtils.h
@@ -40,7 +40,7 @@ using TypePointer = std::shared_ptr<Type const>;
class ArrayUtils
{
public:
- ArrayUtils(CompilerContext& _context): m_context(_context) {}
+ explicit ArrayUtils(CompilerContext& _context): m_context(_context) {}
/// Copies an array to an array in storage. The arrays can be of different types only if
/// their storage representation is the same.
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index eef078c1..8c63ea9c 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -51,9 +51,9 @@ public:
ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
);
- eth::Assembly const& assembly() { return m_context.assembly(); }
- eth::LinkerObject assembledObject() { return m_context.assembledObject(); }
- eth::LinkerObject runtimeObject() { return m_context.assembledRuntimeObject(m_runtimeSub); }
+ eth::Assembly const& assembly() const { return m_context.assembly(); }
+ eth::LinkerObject assembledObject() const { return m_context.assembledObject(); }
+ eth::LinkerObject runtimeObject() const { return m_context.assembledRuntimeObject(m_runtimeSub); }
/// @arg _sourceCodes is the map of input files to source code strings
/// @arg _inJsonFromat shows whether the out should be in Json format
Json::Value streamAssembly(std::ostream& _stream, StringMap const& _sourceCodes = StringMap(), bool _inJsonFormat = false) const
diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h
index 583360ea..96cbf6c1 100644
--- a/libsolidity/codegen/CompilerContext.h
+++ b/libsolidity/codegen/CompilerContext.h
@@ -208,8 +208,8 @@ public:
return m_asm->stream(_stream, "", _sourceCodes, _inJsonFormat);
}
- eth::LinkerObject const& assembledObject() { return m_asm->assemble(); }
- eth::LinkerObject const& assembledRuntimeObject(size_t _subIndex) { return m_asm->sub(_subIndex).assemble(); }
+ eth::LinkerObject const& assembledObject() const { return m_asm->assemble(); }
+ eth::LinkerObject const& assembledRuntimeObject(size_t _subIndex) const { return m_asm->sub(_subIndex).assemble(); }
/**
* Helper class to pop the visited nodes stack when a scope closes
diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h
index 09427788..18b70250 100644
--- a/libsolidity/codegen/CompilerUtils.h
+++ b/libsolidity/codegen/CompilerUtils.h
@@ -33,7 +33,7 @@ class Type; // forward
class CompilerUtils
{
public:
- CompilerUtils(CompilerContext& _context): m_context(_context) {}
+ explicit CompilerUtils(CompilerContext& _context): m_context(_context) {}
/// Stores the initial value of the free-memory-pointer at its position;
void initialiseFreeMemoryPointer();
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 29a22fae..e53f1b94 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -45,7 +45,7 @@ using namespace dev::solidity;
class StackHeightChecker
{
public:
- StackHeightChecker(CompilerContext const& _context):
+ explicit StackHeightChecker(CompilerContext const& _context):
m_context(_context), stackHeight(m_context.stackHeight()) {}
void check() { solAssert(m_context.stackHeight() == stackHeight, std::string("I sense a disturbance in the stack: ") + std::to_string(m_context.stackHeight()) + " vs " + std::to_string(stackHeight)); }
private:
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 55d35c44..639bfc32 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -1811,7 +1811,7 @@ void ExpressionCompiler::setLValueToStorageItem(Expression const& _expression)
setLValue<StorageItem>(_expression, *_expression.annotation().type);
}
-bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _op)
+bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _op) const
{
if (Token::isCompareOp(_op) || Token::isShiftOp(_op))
return true;
diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h
index 3b8cf1c6..5f6c3d64 100644
--- a/libsolidity/codegen/ExpressionCompiler.h
+++ b/libsolidity/codegen/ExpressionCompiler.h
@@ -119,7 +119,7 @@ private:
/// @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);
+ bool cleanupNeededForOp(Type::Category _type, Token::Value _op) const;
/// @returns the CompilerUtils object containing the current context.
CompilerUtils utils();
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index 74743737..6d0c0255 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -52,7 +52,7 @@ using namespace dev::solidity::assembly;
class EthAssemblyAdapter: public julia::AbstractAssembly
{
public:
- EthAssemblyAdapter(eth::Assembly& _assembly):
+ explicit EthAssemblyAdapter(eth::Assembly& _assembly):
m_assembly(_assembly)
{
}
@@ -127,7 +127,7 @@ public:
}
private:
- LabelID assemblyTagToIdentifier(eth::AssemblyItem const& _tag) const
+ static LabelID assemblyTagToIdentifier(eth::AssemblyItem const& _tag)
{
u256 id = _tag.data();
solAssert(id <= std::numeric_limits<LabelID>::max(), "Tag id too large.");
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index 133f70b1..1dcc42b8 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -23,6 +23,9 @@
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/ErrorReporter.h>
+
+#include <boost/algorithm/string.hpp>
+
#include <ctype.h>
#include <algorithm>
@@ -297,6 +300,8 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
kind = LiteralKind::String;
break;
case Token::Number:
+ if (!isValidNumberLiteral(currentLiteral()))
+ fatalParserError("Invalid number literal.");
kind = LiteralKind::Number;
break;
case Token::TrueLiteral:
@@ -501,3 +506,19 @@ string Parser::expectAsmIdentifier()
expectToken(Token::Identifier);
return name;
}
+
+bool Parser::isValidNumberLiteral(string const& _literal)
+{
+ try
+ {
+ u256(_literal);
+ }
+ catch (...)
+ {
+ return false;
+ }
+ if (boost::starts_with(_literal, "0x"))
+ return true;
+ else
+ return _literal.find_first_not_of("0123456789") == string::npos;
+}
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index 45708afd..e46d1732 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -45,7 +45,7 @@ public:
protected:
/// Creates an inline assembly node with the given source location.
- template <class T> T createWithLocation(SourceLocation const& _loc = SourceLocation())
+ template <class T> T createWithLocation(SourceLocation const& _loc = SourceLocation()) const
{
T r;
r.location = _loc;
@@ -75,6 +75,8 @@ protected:
TypedName parseTypedName();
std::string expectAsmIdentifier();
+ static bool isValidNumberLiteral(std::string const& _literal);
+
private:
bool m_julia = false;
};
diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp
index 4f96a3e9..47ede91d 100644
--- a/libsolidity/inlineasm/AsmPrinter.cpp
+++ b/libsolidity/inlineasm/AsmPrinter.cpp
@@ -209,7 +209,7 @@ string AsmPrinter::operator()(Block const& _block)
return "{\n " + body + "\n}";
}
-string AsmPrinter::appendTypeName(std::string const& _type)
+string AsmPrinter::appendTypeName(std::string const& _type) const
{
if (m_julia)
return ":" + _type;
diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libsolidity/inlineasm/AsmPrinter.h
index f57dddc8..66520632 100644
--- a/libsolidity/inlineasm/AsmPrinter.h
+++ b/libsolidity/inlineasm/AsmPrinter.h
@@ -53,7 +53,7 @@ public:
std::string operator()(assembly::Block const& _block);
private:
- std::string appendTypeName(std::string const& _type);
+ std::string appendTypeName(std::string const& _type) const;
bool m_julia = false;
};
diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp
index 315d5953..64d5bd9a 100644
--- a/libsolidity/inlineasm/AsmScope.cpp
+++ b/libsolidity/inlineasm/AsmScope.cpp
@@ -70,7 +70,7 @@ Scope::Identifier* Scope::lookup(string const& _name)
return nullptr;
}
-bool Scope::exists(string const& _name)
+bool Scope::exists(string const& _name) const
{
if (identifiers.count(_name))
return true;
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index cc240565..447d6490 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -107,7 +107,7 @@ struct Scope
}
/// @returns true if the name exists in this scope or in super scopes (also searches
/// across function and assembly boundaries).
- bool exists(std::string const& _name);
+ bool exists(std::string const& _name) const;
/// @returns the number of variables directly registered inside the scope.
size_t numberOfVariables() const;
diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp
index 9fc2f4e8..6e8563f7 100644
--- a/libsolidity/interface/ABI.cpp
+++ b/libsolidity/interface/ABI.cpp
@@ -19,7 +19,6 @@
*/
#include <libsolidity/interface/ABI.h>
-#include <boost/range/irange.hpp>
#include <libsolidity/ast/AST.h>
using namespace std;
@@ -36,7 +35,8 @@ Json::Value ABI::generate(ContractDefinition const& _contractDef)
Json::Value method;
method["type"] = "function";
method["name"] = it.second->declaration().name();
- method["constant"] = it.second->isConstant();
+ // TODO: deprecate constant in a future release
+ method["constant"] = it.second->stateMutability() == StateMutability::View;
method["payable"] = it.second->isPayable();
method["statemutability"] = stateMutabilityToString(it.second->stateMutability());
method["inputs"] = formatTypeList(
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 70bebfa5..412d2fd3 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -49,8 +49,6 @@
#include <json/json.h>
#include <boost/algorithm/string.hpp>
-#include <boost/filesystem.hpp>
-
using namespace std;
using namespace dev;
@@ -406,39 +404,42 @@ Json::Value const& CompilerStack::contractABI(Contract const& _contract) const
return *_contract.abi;
}
-Json::Value const& CompilerStack::natspec(string const& _contractName, DocumentationType _type) const
+Json::Value const& CompilerStack::natspecUser(string const& _contractName) const
{
- return natspec(contract(_contractName), _type);
+ return natspecUser(contract(_contractName));
}
-Json::Value const& CompilerStack::natspec(Contract const& _contract, DocumentationType _type) const
+Json::Value const& CompilerStack::natspecUser(Contract const& _contract) const
{
if (m_stackState < AnalysisSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
solAssert(_contract.contract, "");
- std::unique_ptr<Json::Value const>* doc;
- // checks wheather we already have the documentation
- switch (_type)
- {
- case DocumentationType::NatspecUser:
- doc = &_contract.userDocumentation;
- // caches the result
- if (!*doc)
- doc->reset(new Json::Value(Natspec::userDocumentation(*_contract.contract)));
- break;
- case DocumentationType::NatspecDev:
- doc = &_contract.devDocumentation;
- // caches the result
- if (!*doc)
- doc->reset(new Json::Value(Natspec::devDocumentation(*_contract.contract)));
- break;
- default:
- solAssert(false, "Illegal documentation type.");
- }
+ // caches the result
+ if (!_contract.userDocumentation)
+ _contract.userDocumentation.reset(new Json::Value(Natspec::userDocumentation(*_contract.contract)));
+
+ return *_contract.userDocumentation;
+}
+
+Json::Value const& CompilerStack::natspecDev(string const& _contractName) const
+{
+ return natspecDev(contract(_contractName));
+}
+
+Json::Value const& CompilerStack::natspecDev(Contract const& _contract) const
+{
+ if (m_stackState < AnalysisSuccessful)
+ BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful."));
+
+ solAssert(_contract.contract, "");
+
+ // caches the result
+ if (!_contract.devDocumentation)
+ _contract.devDocumentation.reset(new Json::Value(Natspec::devDocumentation(*_contract.contract)));
- return *(*doc);
+ return *_contract.devDocumentation;
}
Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const
@@ -819,8 +820,8 @@ string CompilerStack::createMetadata(Contract const& _contract) const
meta["settings"]["libraries"][library.first] = "0x" + toHex(library.second.asBytes());
meta["output"]["abi"] = contractABI(_contract);
- meta["output"]["userdoc"] = natspec(_contract, DocumentationType::NatspecUser);
- meta["output"]["devdoc"] = natspec(_contract, DocumentationType::NatspecDev);
+ meta["output"]["userdoc"] = natspecUser(_contract);
+ meta["output"]["devdoc"] = natspecDev(_contract);
return jsonCompactPrint(meta);
}
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index d287f224..bb0f4126 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -63,12 +63,6 @@ class Natspec;
class Error;
class DeclarationContainer;
-enum class DocumentationType: uint8_t
-{
- NatspecUser = 1,
- NatspecDev
-};
-
/**
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
* It holds state and can be used to either step through the compilation stages (and abort e.g.
@@ -94,7 +88,7 @@ public:
m_errorReporter(m_errorList) {}
/// @returns the list of errors that occured during parsing and type checking.
- ErrorList const& errors() { return m_errorReporter.errors(); }
+ ErrorList const& errors() const { return m_errorReporter.errors(); }
/// @returns the current state.
State state() const { return m_stackState; }
@@ -203,11 +197,13 @@ public:
/// Prerequisite: Successful call to parse or compile.
Json::Value const& contractABI(std::string const& _contractName = "") const;
- /// @returns a JSON representing the contract's documentation.
+ /// @returns a JSON representing the contract's user documentation.
+ /// Prerequisite: Successful call to parse or compile.
+ Json::Value const& natspecUser(std::string const& _contractName) const;
+
+ /// @returns a JSON representing the contract's developer documentation.
/// Prerequisite: Successful call to parse or compile.
- /// @param type The type of the documentation to get.
- /// Can be one of 4 types defined at @c DocumentationType
- Json::Value const& natspec(std::string const& _contractName, DocumentationType _type) const;
+ Json::Value const& natspecDev(std::string const& _contractName) const;
/// @returns a JSON representing a map of method identifiers (hashes) to function names.
Json::Value methodIdentifiers(std::string const& _contractName) const;
@@ -274,7 +270,8 @@ private:
std::string createMetadata(Contract const& _contract) const;
std::string computeSourceMapping(eth::AssemblyItems const& _items) const;
Json::Value const& contractABI(Contract const&) const;
- Json::Value const& natspec(Contract const&, DocumentationType _type) const;
+ Json::Value const& natspecUser(Contract const&) const;
+ Json::Value const& natspecDev(Contract const&) const;
/// @returns the offset of the entry point of the given function into the list of assembly items
/// or zero if it is not found or does not exist.
diff --git a/libsolidity/interface/ErrorReporter.h b/libsolidity/interface/ErrorReporter.h
index 12f4e8df..241d6b43 100644
--- a/libsolidity/interface/ErrorReporter.h
+++ b/libsolidity/interface/ErrorReporter.h
@@ -36,7 +36,7 @@ class ErrorReporter
{
public:
- ErrorReporter(ErrorList& _errors):
+ explicit ErrorReporter(ErrorList& _errors):
m_errorList(_errors) { }
ErrorReporter& operator=(ErrorReporter const& _errorReporter);
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index dd135ce5..7a6f9989 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -394,8 +394,8 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
Json::Value contractData(Json::objectValue);
contractData["abi"] = m_compilerStack.contractABI(contractName);
contractData["metadata"] = m_compilerStack.metadata(contractName);
- contractData["userdoc"] = m_compilerStack.natspec(contractName, DocumentationType::NatspecUser);
- contractData["devdoc"] = m_compilerStack.natspec(contractName, DocumentationType::NatspecDev);
+ contractData["userdoc"] = m_compilerStack.natspecUser(contractName);
+ contractData["devdoc"] = m_compilerStack.natspecDev(contractName);
// EVM
Json::Value evmData(Json::objectValue);
diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h
index dfaf88cd..d9787a40 100644
--- a/libsolidity/interface/StandardCompiler.h
+++ b/libsolidity/interface/StandardCompiler.h
@@ -40,7 +40,7 @@ public:
/// Creates a new StandardCompiler.
/// @param _readFile callback to used to read files for import statements. Must return
/// and must not emit exceptions.
- StandardCompiler(ReadFile::Callback const& _readFile = ReadFile::Callback())
+ explicit StandardCompiler(ReadFile::Callback const& _readFile = ReadFile::Callback())
: m_compilerStack(_readFile), m_readFile(_readFile)
{
}
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index d3a6aa45..92a614e0 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -40,7 +40,7 @@ namespace solidity
class Parser::ASTNodeFactory
{
public:
- ASTNodeFactory(Parser const& _parser):
+ explicit ASTNodeFactory(Parser const& _parser):
m_parser(_parser), m_location(_parser.position(), -1, _parser.sourceName()) {}
ASTNodeFactory(Parser const& _parser, ASTPointer<ASTNode> const& _childNode):
m_parser(_parser), m_location(_childNode->location()) {}
@@ -69,7 +69,7 @@ private:
class Parser::RecursionGuard
{
public:
- RecursionGuard(Parser& _parser):
+ explicit RecursionGuard(Parser& _parser):
m_parser(_parser)
{
m_parser.increaseRecursionDepth();
@@ -337,7 +337,8 @@ StateMutability Parser::parseStateMutability(Token::Value _token)
StateMutability stateMutability(StateMutability::NonPayable);
if (_token == Token::Payable)
stateMutability = StateMutability::Payable;
- else if (_token == Token::Constant)
+ // FIXME: constant should be removed at the next breaking release
+ else if (_token == Token::View || _token == Token::Constant)
stateMutability = StateMutability::View;
else
solAssert(false, "Invalid state mutability specifier.");
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 5e6f3ef6..0f74880c 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -35,7 +35,7 @@ class Scanner;
class Parser: public ParserBase
{
public:
- Parser(ErrorReporter& _errorReporter): ParserBase(_errorReporter) {}
+ explicit Parser(ErrorReporter& _errorReporter): ParserBase(_errorReporter) {}
ASTPointer<SourceUnit> parse(std::shared_ptr<Scanner> const& _scanner);
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
index 5b03ab5e..48733fc1 100644
--- a/libsolidity/parsing/ParserBase.h
+++ b/libsolidity/parsing/ParserBase.h
@@ -36,7 +36,7 @@ class Scanner;
class ParserBase
{
public:
- ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {}
+ explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {}
std::shared_ptr<std::string const> const& sourceName() const;
diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h
index d6b48c6f..0adaa6fd 100644
--- a/libsolidity/parsing/Scanner.h
+++ b/libsolidity/parsing/Scanner.h
@@ -75,7 +75,7 @@ public:
int position() const { return m_position; }
bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); }
char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; }
- char advanceAndGet(size_t _chars=1);
+ char advanceAndGet(size_t _chars = 1);
char rollback(size_t _amount);
void reset() { m_position = 0; }
@@ -118,11 +118,11 @@ public:
///@name Information about the current token
/// @returns the current token
- Token::Value currentToken()
+ Token::Value currentToken() const
{
return m_currentToken.token;
}
- ElementaryTypeNameToken currentElementaryTypeNameToken()
+ ElementaryTypeNameToken currentElementaryTypeNameToken() const
{
unsigned firstSize;
unsigned secondSize;
@@ -219,8 +219,8 @@ private:
bool scanEscape();
/// Return the current source position.
- int sourcePos() { return m_source.position(); }
- bool isSourcePastEndOfInput() { return m_source.isPastEndOfInput(); }
+ int sourcePos() const { return m_source.position(); }
+ bool isSourcePastEndOfInput() const { return m_source.isPastEndOfInput(); }
TokenDesc m_skippedComment; // desc for current skipped comment
TokenDesc m_nextSkippedComment; // desc for next skiped comment
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index efbe5e9e..3bc52f1d 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -176,6 +176,7 @@ namespace solidity
K(Throw, "throw", 0) \
K(Using, "using", 0) \
K(Var, "var", 0) \
+ K(View, "view", 0) \
K(While, "while", 0) \
\
/* Ether subdenominations */ \
@@ -236,7 +237,6 @@ namespace solidity
K(Try, "try", 0) \
K(Type, "type", 0) \
K(TypeOf, "typeof", 0) \
- K(View, "view", 0) \
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
\
@@ -290,7 +290,7 @@ public:
static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; }
static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Internal; }
static bool isLocationSpecifier(Value op) { return op == Memory || op == Storage; }
- static bool isStateMutabilitySpecifier(Value op) { return op == Constant || op == Payable; }
+ static bool isStateMutabilitySpecifier(Value op) { return op == Constant || op == View || op == Payable; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; }
static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; }
static bool isReservedKeyword(Value op) { return (Abstract <= op && op <= TypeOf); }
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 740061a1..bfc53aef 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -316,31 +316,32 @@ void CommandLineInterface::handleABI(string const& _contract)
cout << "Contract JSON ABI " << endl << data << endl;
}
-void CommandLineInterface::handleNatspec(DocumentationType _type, string const& _contract)
+void CommandLineInterface::handleNatspec(bool _natspecDev, string const& _contract)
{
std::string argName;
std::string suffix;
std::string title;
- switch(_type)
+
+ if (_natspecDev)
{
- case DocumentationType::NatspecUser:
- argName = g_argNatspecUser;
- suffix = ".docuser";
- title = "User Documentation";
- break;
- case DocumentationType::NatspecDev:
argName = g_argNatspecDev;
suffix = ".docdev";
title = "Developer Documentation";
- break;
- default:
- // should never happen
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation _type"));
+ }
+ else
+ {
+ argName = g_argNatspecUser;
+ suffix = ".docuser";
+ title = "User Documentation";
}
if (m_args.count(argName))
{
- std::string output = dev::jsonPrettyPrint(m_compiler->natspec(_contract, _type));
+ std::string output = dev::jsonPrettyPrint(
+ _natspecDev ?
+ m_compiler->natspecDev(_contract) :
+ m_compiler->natspecUser(_contract)
+ );
if (m_args.count(g_argOutputDir))
createFile(m_compiler->filesystemFriendlyName(_contract) + suffix, output);
@@ -850,7 +851,7 @@ void CommandLineInterface::handleCombinedJSON()
output[g_strContracts] = Json::Value(Json::objectValue);
for (string const& contractName: contracts)
{
- Json::Value contractData(Json::objectValue);
+ Json::Value& contractData = output[g_strContracts][contractName] = Json::objectValue;
if (requests.count(g_strAbi))
contractData[g_strAbi] = dev::jsonCompactPrint(m_compiler->contractABI(contractName));
if (requests.count("metadata"))
@@ -881,10 +882,9 @@ void CommandLineInterface::handleCombinedJSON()
if (requests.count(g_strSignatureHashes))
contractData[g_strSignatureHashes] = m_compiler->methodIdentifiers(contractName);
if (requests.count(g_strNatspecDev))
- contractData[g_strNatspecDev] = dev::jsonCompactPrint(m_compiler->natspec(contractName, DocumentationType::NatspecDev));
+ contractData[g_strNatspecDev] = dev::jsonCompactPrint(m_compiler->natspecDev(contractName));
if (requests.count(g_strNatspecUser))
- contractData[g_strNatspecUser] = dev::jsonCompactPrint(m_compiler->natspec(contractName, DocumentationType::NatspecUser));
- output[g_strContracts][contractName] = contractData;
+ contractData[g_strNatspecUser] = dev::jsonCompactPrint(m_compiler->natspecUser(contractName));
}
bool needsSourceList = requests.count(g_strAst) || requests.count(g_strSrcMap) || requests.count(g_strSrcMapRuntime);
@@ -1170,8 +1170,8 @@ void CommandLineInterface::outputCompilationResults()
handleSignatureHashes(contract);
handleMetadata(contract);
handleABI(contract);
- handleNatspec(DocumentationType::NatspecDev, contract);
- handleNatspec(DocumentationType::NatspecUser, contract);
+ handleNatspec(true, contract);
+ handleNatspec(false, contract);
} // end of contracts iteration
if (m_args.count(g_argFormal))
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index 8a476ef5..bf9400e4 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -66,7 +66,7 @@ private:
void handleSignatureHashes(std::string const& _contract);
void handleMetadata(std::string const& _contract);
void handleABI(std::string const& _contract);
- void handleNatspec(DocumentationType _type, std::string const& _contract);
+ void handleNatspec(bool _natspecDev, std::string const& _contract);
void handleGasEstimation(std::string const& _contract);
void handleFormal();
diff --git a/test/Metadata.cpp b/test/Metadata.cpp
index 03f905b1..e4de0a6b 100644
--- a/test/Metadata.cpp
+++ b/test/Metadata.cpp
@@ -21,7 +21,6 @@
#include <string>
#include <iostream>
-#include <regex>
#include <libdevcore/JSON.h>
using namespace std;
diff --git a/test/RPCSession.h b/test/RPCSession.h
index f7fdd86e..558cb99f 100644
--- a/test/RPCSession.h
+++ b/test/RPCSession.h
@@ -124,7 +124,7 @@ public:
std::string const& accountCreateIfNotExists(size_t _id);
private:
- RPCSession(std::string const& _path);
+ explicit RPCSession(std::string const& _path);
inline std::string quote(std::string const& _arg) { return "\"" + _arg + "\""; }
/// Parse std::string replacing keywords to values
diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp
index 5aa81af5..6656f15b 100644
--- a/test/libevmasm/Optimiser.cpp
+++ b/test/libevmasm/Optimiser.cpp
@@ -29,7 +29,6 @@
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
-#include <chrono>
#include <string>
#include <tuple>
#include <memory>
diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp
index dd6f3d94..e1bf5a3a 100644
--- a/test/libjulia/Parser.cpp
+++ b/test/libjulia/Parser.cpp
@@ -214,6 +214,14 @@ BOOST_AUTO_TEST_CASE(invalid_types)
CHECK_ERROR("{ function f(a:invalid) {} }", TypeError, "\"invalid\" is not a valid type (user defined types are not yet supported).");
}
+BOOST_AUTO_TEST_CASE(number_literals)
+{
+ BOOST_CHECK(successParse("{ let x:u256 := 1:u256 }"));
+ CHECK_ERROR("{ let x:u256 := .1:u256 }", ParserError, "Invalid number literal.");
+ CHECK_ERROR("{ let x:u256 := 1e5:u256 }", ParserError, "Invalid number literal.");
+ CHECK_ERROR("{ let x:u256 := 67.235:u256 }", ParserError, "Invalid number literal.");
+}
+
BOOST_AUTO_TEST_CASE(builtin_types)
{
BOOST_CHECK(successParse("{ let x:bool := true:bool }"));
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index 4bf4eb48..8e1c304a 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -339,6 +339,14 @@ BOOST_AUTO_TEST_CASE(blocks)
BOOST_CHECK(successParse("{ let x := 7 { let y := 3 } { let z := 2 } }"));
}
+BOOST_AUTO_TEST_CASE(number_literals)
+{
+ BOOST_CHECK(successParse("{ let x := 1 }"));
+ CHECK_PARSE_ERROR("{ let x := .1 }", ParserError, "Invalid number literal.");
+ CHECK_PARSE_ERROR("{ let x := 1e5 }", ParserError, "Invalid number literal.");
+ CHECK_PARSE_ERROR("{ let x := 67.235 }", ParserError, "Invalid number literal.");
+}
+
BOOST_AUTO_TEST_CASE(function_definitions)
{
BOOST_CHECK(successParse("{ function f() { } function g(a) -> x { } }"));
diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index 536ba730..0fe7636c 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -20,8 +20,6 @@
*/
#include <string>
-#include <iostream>
-#include <regex>
#include <boost/test/unit_test.hpp>
#include <libdevcore/JSON.h>
#include <libsolidity/interface/Version.h>
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index 80b4b6ad..12fb1f9c 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -250,7 +250,63 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order)
checkInterface(sourceCode, interface);
}
-BOOST_AUTO_TEST_CASE(const_function)
+BOOST_AUTO_TEST_CASE(view_function)
+{
+ char const* sourceCode = R"(
+ contract test {
+ function foo(uint a, uint b) returns(uint d) { return a + b; }
+ function boo(uint32 a) view returns(uint b) { return a * 4; }
+ }
+ )";
+
+ char const* interface = R"([
+ {
+ "name": "foo",
+ "constant": false,
+ "payable" : false,
+ "statemutability": "nonpayable",
+ "type": "function",
+ "inputs": [
+ {
+ "name": "a",
+ "type": "uint256"
+ },
+ {
+ "name": "b",
+ "type": "uint256"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "d",
+ "type": "uint256"
+ }
+ ]
+ },
+ {
+ "name": "boo",
+ "constant": true,
+ "payable" : false,
+ "statemutability": "view",
+ "type": "function",
+ "inputs": [{
+ "name": "a",
+ "type": "uint32"
+ }],
+ "outputs": [
+ {
+ "name": "b",
+ "type": "uint256"
+ }
+ ]
+ }
+ ])";
+
+ checkInterface(sourceCode, interface);
+}
+
+// constant is an alias to view above
+BOOST_AUTO_TEST_CASE(constant_function)
{
char const* sourceCode = R"(
contract test {
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index fb2686fc..380978e8 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -1172,7 +1172,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_REQUIRE(function && function->hasDeclaration());
auto returnParams = function->returnParameterTypes();
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(false), "uint256");
- BOOST_CHECK(function->isConstant());
+ BOOST_CHECK(function->stateMutability() == StateMutability::View);
function = retrieveFunctionBySignature(*contract, "map(uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
@@ -1180,7 +1180,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_EQUAL(params.at(0)->canonicalName(false), "uint256");
returnParams = function->returnParameterTypes();
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(false), "bytes4");
- BOOST_CHECK(function->isConstant());
+ BOOST_CHECK(function->stateMutability() == StateMutability::View);
function = retrieveFunctionBySignature(*contract, "multiple_map(uint256,uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
@@ -1189,7 +1189,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
BOOST_CHECK_EQUAL(params.at(1)->canonicalName(false), "uint256");
returnParams = function->returnParameterTypes();
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(false), "bytes4");
- BOOST_CHECK(function->isConstant());
+ BOOST_CHECK(function->stateMutability() == StateMutability::View);
}
BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor)
@@ -3055,6 +3055,16 @@ BOOST_AUTO_TEST_CASE(library_having_variables)
CHECK_ERROR(text, TypeError, "Library cannot have non-constant state variables");
}
+BOOST_AUTO_TEST_CASE(library_constructor)
+{
+ char const* text = R"(
+ library Lib {
+ function Lib();
+ }
+ )";
+ CHECK_ERROR_ALLOW_MULTI(text, TypeError, "Constructor cannot be defined in libraries.");
+}
+
BOOST_AUTO_TEST_CASE(valid_library)
{
char const* text = R"(
@@ -6647,6 +6657,21 @@ BOOST_AUTO_TEST_CASE(library_function_without_implementation)
CHECK_ERROR(text, TypeError, "Internal library function must be implemented if declared.");
}
+BOOST_AUTO_TEST_CASE(using_for_with_non_library)
+{
+ // This tests a crash that was resolved by making the first error fatal.
+ char const* text = R"(
+ library L {
+ struct S { uint d; }
+ using S for S;
+ function f(S _s) internal {
+ _s.d = 1;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Library name expected.");
+}
+
BOOST_AUTO_TEST_CASE(experimental_pragma)
{
char const* text = R"(
@@ -6684,6 +6709,41 @@ BOOST_AUTO_TEST_CASE(experimental_pragma)
// CHECK_ERROR_ALLOW_MULTI(text, SyntaxError, "Duplicate experimental feature name.");
}
+BOOST_AUTO_TEST_CASE(reject_interface_creation)
+{
+ char const* text = R"(
+ interface I {}
+ contract C {
+ function f() {
+ new I();
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Cannot instantiate an interface.");
+}
+
+BOOST_AUTO_TEST_CASE(accept_library_creation)
+{
+ char const* text = R"(
+ library L {}
+ contract C {
+ function f() {
+ new L();
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
+BOOST_AUTO_TEST_CASE(reject_interface_constructors)
+{
+ char const* text = R"(
+ interface I {}
+ contract C is I(2) {}
+ )";
+ CHECK_ERROR(text, TypeError, "Wrong argument count for constructor call: 1 arguments given but expected 0.");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index be20a9f2..149221d5 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -51,9 +51,9 @@ public:
Json::Value generatedDocumentation;
if (_userDocumentation)
- generatedDocumentation = m_compilerStack.natspec("", DocumentationType::NatspecUser);
+ generatedDocumentation = m_compilerStack.natspecUser("");
else
- generatedDocumentation = m_compilerStack.natspec("", DocumentationType::NatspecDev);
+ generatedDocumentation = m_compilerStack.natspecDev("");
Json::Value expectedDocumentation;
m_reader.parse(_expectedDocumentationString, expectedDocumentation);
BOOST_CHECK_MESSAGE(
diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp
index 30dc80d9..8e84ead1 100644
--- a/test/libsolidity/SolidityParser.cpp
+++ b/test/libsolidity/SolidityParser.cpp
@@ -920,6 +920,11 @@ BOOST_AUTO_TEST_CASE(multiple_statemutability_specifiers)
CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\".");
text = R"(
contract c {
+ function f() constant view {}
+ })";
+ CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\".");
+ text = R"(
+ contract c {
function f() payable constant {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"payable\".");
diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp
index be13d46b..79848c36 100644
--- a/test/libsolidity/StandardCompiler.cpp
+++ b/test/libsolidity/StandardCompiler.cpp
@@ -20,8 +20,6 @@
*/
#include <string>
-#include <iostream>
-#include <regex>
#include <boost/test/unit_test.hpp>
#include <libsolidity/interface/StandardCompiler.h>
#include <libdevcore/JSON.h>