aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md3
-rw-r--r--ReleaseChecklist.md3
-rw-r--r--cmake/EthCompilerSettings.cmake22
-rw-r--r--docs/abi-spec.rst2
-rw-r--r--docs/assembly.rst10
-rw-r--r--docs/contracts.rst2
-rw-r--r--docs/control-structures.rst2
-rw-r--r--docs/frequently-asked-questions.rst33
-rw-r--r--docs/layout-of-source-files.rst27
-rw-r--r--docs/types.rst4
-rw-r--r--liblll/CodeFragment.cpp28
-rw-r--r--liblll/Compiler.cpp10
-rw-r--r--libsolidity/analysis/StaticAnalyzer.cpp9
-rw-r--r--libsolidity/analysis/StaticAnalyzer.h6
-rw-r--r--libsolidity/ast/AST.h2
-rw-r--r--libsolidity/ast/Types.cpp101
-rw-r--r--libsolidity/ast/Types.h23
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp2
-rw-r--r--libsolidity/interface/CompilerStack.cpp24
-rw-r--r--libsolidity/interface/CompilerStack.h6
-rw-r--r--libsolidity/interface/Natspec.cpp17
-rw-r--r--libsolidity/interface/Natspec.h10
-rw-r--r--libsolidity/interface/StandardCompiler.cpp2
-rw-r--r--libsolidity/parsing/Parser.cpp2
-rw-r--r--libsolidity/parsing/Token.cpp10
-rw-r--r--solc/CMakeLists.txt2
-rw-r--r--solc/CommandLineInterface.cpp8
-rw-r--r--solc/CommandLineInterface.h2
-rw-r--r--test/contracts/LLL_ENS.cpp2
-rw-r--r--test/contracts/LLL_ERC20.cpp2
-rw-r--r--test/liblll/EndToEndTest.cpp50
-rw-r--r--test/libsolidity/GasMeter.cpp5
-rw-r--r--test/libsolidity/JSONCompiler.cpp15
-rw-r--r--test/libsolidity/Metadata.cpp5
-rw-r--r--test/libsolidity/SolidityABIJSON.cpp4
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp249
-rw-r--r--test/libsolidity/SolidityNatspecJSON.cpp4
37 files changed, 412 insertions, 296 deletions
diff --git a/Changelog.md b/Changelog.md
index e64a8fea..36186462 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,14 +1,17 @@
### 0.4.14 (unreleased)
Features:
+ * C API (``jsonCompiler``): Export the ``license`` method.
* Inline Assembly: Show useful error message if trying to access calldata variables.
* Inline Assembly: Support variable declaration without initial value (defaults to 0).
* Type Checker: Disallow value transfers to contracts without a payable fallback function.
* Type Checker: Include types in explicit conversion error message.
* Type Checker: Raise proper error for arrays too large for ABI encoding.
+ * Type checker: Warn if using ``this`` in a constructor.
Bugfixes:
* Type Checker: Fix invalid "specify storage keyword" warning for reference members of structs.
+ * Type Checker: Mark modifiers as internal.
### 0.4.13 (2017-07-06)
diff --git a/ReleaseChecklist.md b/ReleaseChecklist.md
index 76e3bfb1..b5df9fda 100644
--- a/ReleaseChecklist.md
+++ b/ReleaseChecklist.md
@@ -10,9 +10,10 @@ Checklist for making a release:
- [ ] Wait for the CI runs on the tag itself (they should push artefacts onto the Github release page).
- [ ] Run ``scripts/release_ppa.sh release`` to create the PPA release (you need the relevant openssl key).
- [ ] Check that the Docker release was pushed to Docker Hub (this still seems to have problems).
+ - [ ] Update the homebrew realease in https://github.com/ethereum/homebrew-ethereum/blob/master/solidity.rb (version and hash)
- [ ] Make a release of ``solc-js``: Increment the version number, create a pull request for that, merge it after tests succeeded.
- [ ] Run ``npm publish`` in the updated ``solc-js`` repository.
- [ ] Create a commit to increase the version number on ``develop`` in ``CMakeLists.txt`` and add a new skeleton changelog entry.
- [ ] Merge ``release`` back into ``develop``.
- [ ] Announce on Twitter and Reddit.
- - [ ] Lay back, wait for bug reports and repeat from step 1 :)
+ - [ ] Lean back, wait for bug reports and repeat from step 1 :)
diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake
index ea3b185a..4ce9d22d 100644
--- a/cmake/EthCompilerSettings.cmake
+++ b/cmake/EthCompilerSettings.cmake
@@ -160,10 +160,24 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
endif()
if (EMSCRIPTEN)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --memory-init-file 0 -O3 -s LINKABLE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s NO_EXIT_RUNTIME=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_DYNAMIC_EXECUTION=1")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_FILESYSTEM=1 -s AGGRESSIVE_VARIABLE_ELIMINATION=1")
+ # Do emit a separate memory initialiser file
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --memory-init-file 0")
+ # Leave only exported symbols as public and agressively remove others
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections -fvisibility=hidden")
+ # Optimisation level
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
+ # Re-enable exception catching (optimisations above -O1 disable it)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0")
+ # Remove any code related to exit (such as atexit)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_EXIT_RUNTIME=1")
+ # Remove any code related to filesystem access
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_FILESYSTEM=1")
+ # Remove variables even if it needs to be duplicated (can improve speed at the cost of size)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s AGGRESSIVE_VARIABLE_ELIMINATION=1")
+ # Allow memory growth, but disable some optimisations
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1")
+ # Disable eval()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_DYNAMIC_EXECUTION=1")
add_definitions(-DETH_EMSCRIPTEN=1)
endif()
endif()
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index 82c52159..2cf57427 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -316,6 +316,8 @@ For example,
::
+ pragma solidity ^0.4.0;
+
contract Test {
function Test(){ b = 0x12345678901234567890123456789012; }
event Event(uint indexed a, bytes32 b)
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 37222faf..4e665b7e 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -92,7 +92,7 @@ you really know what you are doing.
function sumAsm(uint[] _data) returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i) {
assembly {
- o_sum := mload(add(add(_data, 0x20), mul(i, 0x20)))
+ o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
}
}
}
@@ -490,7 +490,7 @@ is performed by replacing the variable's value on the stack by the new value.
.. code::
- assembly {
+ {
let v := 0 // functional-style assignment as part of variable declaration
let g := add(v, 2)
sload(10)
@@ -509,7 +509,7 @@ case called ``default``.
.. code::
- assembly {
+ {
let x := 0
switch calldataload(4)
case 0 {
@@ -538,7 +538,7 @@ The following example computes the sum of an area in memory.
.. code::
- assembly {
+ {
let x := 0
for { let i := 0 } lt(i, 0x100) { i := add(i, 0x20) } {
x := add(x, mload(i))
@@ -565,7 +565,7 @@ The following example implements the power function by square-and-multiply.
.. code::
- assembly {
+ {
function power(base, exponent) -> result {
switch exponent
case 0 { result := 1 }
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 3c9769ff..11e674d1 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -968,6 +968,8 @@ Interfaces are denoted by their own keyword:
::
+ pragma solidity ^0.4.11;
+
interface Token {
function transfer(address recipient, uint amount);
}
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 8d7c78a2..128e6fae 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -128,7 +128,6 @@ the gas can be specified with special options ``.value()`` and ``.gas()``, respe
function info() payable returns (uint ret) { return 42; }
}
-
contract Consumer {
InfoFeed feed;
function setFeed(address addr) { feed = InfoFeed(addr); }
@@ -231,7 +230,6 @@ creation-dependencies are not possible.
}
}
-
contract C {
D d = new D(4); // will be executed as part of C's constructor
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 03ee8388..73210991 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -116,6 +116,8 @@ array in the return statement. Pretty cool, huh?
Example::
+ pragma solidity ^0.4.0;
+
contract C {
function f() returns (uint8[5]) {
string[4] memory adaArr = ["This", "is", "an", "array"];
@@ -192,6 +194,8 @@ should be noted that you must declare them as static memory arrays.
Examples::
+ pragma solidity ^0.4.0;
+
contract C {
struct S {
uint a;
@@ -200,10 +204,9 @@ Examples::
S public x = S(1, 2);
string name = "Ada";
- string[4] memory adaArr = ["This", "is", "an", "array"];
+ string[4] adaArr = ["This", "is", "an", "array"];
}
-
contract D {
C c = new C();
}
@@ -243,6 +246,8 @@ which will be extended in the future. In addition, Arachnid has written `solidit
For now, if you want to modify a string (even when you only want to know its length),
you should always convert it to a ``bytes`` first::
+ pragma solidity ^0.4.0;
+
contract C {
string s;
@@ -288,6 +293,8 @@ situation.
If you do not want to throw, you can return a pair::
+ pragma solidity ^0.4.0;
+
contract C {
uint[] counters;
@@ -302,9 +309,9 @@ If you do not want to throw, you can return a pair::
function checkCounter(uint index) {
var (counter, error) = getCounter(index);
if (error) {
- ...
+ // ...
} else {
- ...
+ // ...
}
}
}
@@ -363,6 +370,8 @@ of variable it concerns:
Example::
+ pragma solidity ^0.4.0;
+
contract C {
uint[] data1;
uint[] data2;
@@ -375,7 +384,7 @@ Example::
append(data2);
}
- function append(uint[] storage d) {
+ function append(uint[] storage d) internal {
d.push(1);
}
}
@@ -393,6 +402,9 @@ A common mistake is to declare a local variable and assume that it will
be created in memory, although it will be created in storage::
/// THIS CONTRACT CONTAINS AN ERROR
+
+ pragma solidity ^0.4.0;
+
contract C {
uint someVariable;
uint[] data;
@@ -417,6 +429,8 @@ slot ``0``) is modified by ``x.push(2)``.
The correct way to do this is the following::
+ pragma solidity ^0.4.0;
+
contract C {
uint someVariable;
uint[] data;
@@ -533,11 +547,12 @@ In the case of a ``contract A`` calling a new instance of ``contract B``, parent
You will need to make sure that you have both contracts aware of each other's presence and that ``contract B`` has a ``payable`` constructor.
In this example::
+ pragma solidity ^0.4.0;
+
contract B {
function B() payable {}
}
-
contract A {
address child;
@@ -580,6 +595,8 @@ Can a contract pass an array (static size) or string or ``bytes`` (dynamic size)
Sure. Take care that if you cross the memory / storage boundary,
independent copies will be created::
+ pragma solidity ^0.4.0;
+
contract C {
uint[20] x;
@@ -588,11 +605,11 @@ independent copies will be created::
h(x);
}
- function g(uint[20] y) {
+ function g(uint[20] y) internal {
y[2] = 3;
}
- function h(uint[20] storage y) {
+ function h(uint[20] storage y) internal {
y[3] = 4;
}
}
diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst
index e4b403f6..f9d197b7 100644
--- a/docs/layout-of-source-files.rst
+++ b/docs/layout-of-source-files.rst
@@ -197,17 +197,16 @@ for the two input parameters and two returned values.
pragma solidity ^0.4.0;
- /** @title Shape calculator.*/
- contract shapeCalculator{
- /**@dev Calculates a rectangle's surface and perimeter.
- * @param w Width of the rectangle.
- * @param h Height of the rectangle.
- * @return s The calculated surface.
- * @return p The calculated perimeter.
- */
- function rectangle(uint w, uint h) returns (uint s, uint p) {
- s = w * h;
- p = 2 * (w + h);
- }
- }
-
+ /** @title Shape calculator. */
+ contract shapeCalculator {
+ /** @dev Calculates a rectangle's surface and perimeter.
+ * @param w Width of the rectangle.
+ * @param h Height of the rectangle.
+ * @return s The calculated surface.
+ * @return p The calculated perimeter.
+ */
+ function rectangle(uint w, uint h) returns (uint s, uint p) {
+ s = w * h;
+ p = 2 * (w + h);
+ }
+ }
diff --git a/docs/types.rst b/docs/types.rst
index b9ecd083..0dc436c9 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -543,7 +543,7 @@ So ``bytes`` should always be preferred over ``byte[]`` because it is cheaper.
that you are accessing the low-level bytes of the UTF-8 representation,
and not the individual characters!
-It is possible to mark arrays ``public`` and have Solidity create a getter.
+It is possible to mark arrays ``public`` and have Solidity create a :ref:`getter <visibility-and-getters>`.
The numeric index will become a required parameter for the getter.
.. index:: ! array;allocating, new
@@ -795,7 +795,7 @@ Because of this, mappings do not have a length or a concept of a key or value be
Mappings are only allowed for state variables (or as storage reference types
in internal functions).
-It is possible to mark mappings ``public`` and have Solidity create a getter.
+It is possible to mark mappings ``public`` and have Solidity create a :ref:`getter <visibility-and-getters>`.
The ``_KeyType`` will become a required parameter for the getter and it will
return ``_ValueType``.
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp
index f637dfb1..254f436f 100644
--- a/liblll/CodeFragment.cpp
+++ b/liblll/CodeFragment.cpp
@@ -203,7 +203,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (us == "INCLUDE")
{
if (_t.size() != 2)
- error<IncorrectParameterCount>();
+ error<IncorrectParameterCount>(us);
string fileName = firstAsString();
if (fileName.empty())
error<InvalidName>("Empty file name provided");
@@ -215,7 +215,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (us == "SET")
{
if (_t.size() != 3)
- error<IncorrectParameterCount>();
+ error<IncorrectParameterCount>(us);
int c = 0;
for (auto const& i: _t)
if (c++ == 2)
@@ -226,7 +226,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (us == "GET")
{
if (_t.size() != 2)
- error<IncorrectParameterCount>();
+ error<IncorrectParameterCount>(us);
m_asm.append((u256)varAddress(firstAsString()));
m_asm.append(Instruction::MLOAD);
}
@@ -237,7 +237,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
string n;
unsigned ii = 0;
if (_t.size() != 3 && _t.size() != 4)
- error<IncorrectParameterCount>();
+ error<IncorrectParameterCount>(us);
vector<string> args;
for (auto const& i: _t)
{
@@ -288,7 +288,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (us == "LIT")
{
if (_t.size() < 3)
- error<IncorrectParameterCount>();
+ error<IncorrectParameterCount>(us);
unsigned ii = 0;
CodeFragment pos;
bytes data;
@@ -303,7 +303,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
{
pos = CodeFragment(i, _s);
if (pos.m_asm.deposit() != 1)
- error<InvalidDeposit>();
+ error<InvalidDeposit>(us);
}
else if (i.tag() != 0)
{
@@ -384,10 +384,10 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else
code.push_back(CodeFragment(i, _s));
}
- auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(); };
- auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(); };
- auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error<IncorrectParameterCount>(); };
- auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_asm.deposit() != s) error<InvalidDeposit>(); };
+ auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(us); };
+ auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(us); };
+ auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error<IncorrectParameterCount>(us); };
+ auto requireDeposit = [&](unsigned i, int s) { if (code[i].m_asm.deposit() != s) error<InvalidDeposit>(us); };
if (_s.macros.count(make_pair(s, code.size())))
{
@@ -412,11 +412,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
else if (c_instructions.count(us))
{
auto it = c_instructions.find(us);
- int ea = instructionInfo(it->second).args;
- if (ea >= 0)
- requireSize(ea);
- else
- requireMinSize(-ea);
+ requireSize(instructionInfo(it->second).args);
for (unsigned i = code.size(); i; --i)
m_asm.append(code[i - 1].m_asm, 1);
@@ -475,7 +471,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
m_asm.append(code[1].m_asm, minDep);
m_asm << end.tag();
if (m_asm.deposit() != deposit)
- error<InvalidDeposit>();
+ error<InvalidDeposit>(us);
}
else if (us == "WHEN" || us == "UNLESS")
{
diff --git a/liblll/Compiler.cpp b/liblll/Compiler.cpp
index 05376cd5..4ec11ca9 100644
--- a/liblll/Compiler.cpp
+++ b/liblll/Compiler.cpp
@@ -34,7 +34,10 @@ bytes dev::eth::compileLLL(string const& _src, bool _opt, vector<string>* _error
{
CompilerState cs;
cs.populateStandard();
- bytes ret = CodeFragment::compile(_src, cs).assembly(cs).optimise(_opt).assemble().bytecode;
+ auto assembly = CodeFragment::compile(_src, cs).assembly(cs);
+ if (_opt)
+ assembly = assembly.optimise(true);
+ bytes ret = assembly.assemble().bytecode;
for (auto i: cs.treesToKill)
killBigints(i);
return ret;
@@ -70,7 +73,10 @@ std::string dev::eth::compileLLLToAsm(std::string const& _src, bool _opt, std::v
CompilerState cs;
cs.populateStandard();
stringstream ret;
- CodeFragment::compile(_src, cs).assembly(cs).optimise(_opt).stream(ret);
+ auto assembly = CodeFragment::compile(_src, cs).assembly(cs);
+ if (_opt)
+ assembly = assembly.optimise(true);
+ assembly.stream(ret);
for (auto i: cs.treesToKill)
killBigints(i);
return ret.str();
diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp
index b1b31163..46477e1e 100644
--- a/libsolidity/analysis/StaticAnalyzer.cpp
+++ b/libsolidity/analysis/StaticAnalyzer.cpp
@@ -38,12 +38,14 @@ bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit)
bool StaticAnalyzer::visit(ContractDefinition const& _contract)
{
m_library = _contract.isLibrary();
+ m_currentContract = &_contract;
return true;
}
void StaticAnalyzer::endVisit(ContractDefinition const&)
{
m_library = false;
+ m_currentContract = nullptr;
}
bool StaticAnalyzer::visit(FunctionDefinition const& _function)
@@ -54,6 +56,7 @@ bool StaticAnalyzer::visit(FunctionDefinition const& _function)
solAssert(!m_currentFunction, "");
solAssert(m_localVarUseCount.empty(), "");
m_nonPayablePublic = _function.isPublic() && !_function.isPayable();
+ m_constructor = _function.isConstructor();
return true;
}
@@ -61,6 +64,7 @@ void StaticAnalyzer::endVisit(FunctionDefinition const&)
{
m_currentFunction = nullptr;
m_nonPayablePublic = false;
+ m_constructor = false;
for (auto const& var: m_localVarUseCount)
if (var.second == 0)
m_errorReporter.warning(var.first->location(), "Unused local variable");
@@ -131,6 +135,11 @@ bool StaticAnalyzer::visit(MemberAccess const& _memberAccess)
"\"callcode\" has been deprecated in favour of \"delegatecall\"."
);
+ if (m_constructor && m_currentContract)
+ if (ContractType const* type = dynamic_cast<ContractType const*>(_memberAccess.expression().annotation().type.get()))
+ if (type->contractDefinition() == *m_currentContract)
+ m_errorReporter.warning(_memberAccess.location(), "\"this\" used in constructor.");
+
return true;
}
diff --git a/libsolidity/analysis/StaticAnalyzer.h b/libsolidity/analysis/StaticAnalyzer.h
index cd6913b5..21a487df 100644
--- a/libsolidity/analysis/StaticAnalyzer.h
+++ b/libsolidity/analysis/StaticAnalyzer.h
@@ -77,6 +77,12 @@ private:
std::map<VariableDeclaration const*, int> m_localVarUseCount;
FunctionDefinition const* m_currentFunction = nullptr;
+
+ /// Flag that indicates a constructor.
+ bool m_constructor = false;
+
+ /// Current contract.
+ ContractDefinition const* m_currentContract = nullptr;
};
}
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index cde14ea0..81ddc754 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -704,7 +704,7 @@ public:
ASTPointer<ParameterList> const& _parameters,
ASTPointer<Block> const& _body
):
- CallableDeclaration(_location, _name, Visibility::Default, _parameters),
+ CallableDeclaration(_location, _name, Visibility::Internal, _parameters),
Documented(_documentation),
m_body(_body)
{
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 76bfb1a8..bcfccc3e 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -196,9 +196,9 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
case Token::UInt:
return make_shared<IntegerType>(256, IntegerType::Modifier::Unsigned);
case Token::Fixed:
- return make_shared<FixedPointType>(128, 128, FixedPointType::Modifier::Signed);
+ return make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Signed);
case Token::UFixed:
- return make_shared<FixedPointType>(128, 128, FixedPointType::Modifier::Unsigned);
+ return make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Unsigned);
case Token::Byte:
return make_shared<FixedBytesType>(1);
case Token::Address:
@@ -352,12 +352,11 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedPoint)
{
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
- if (convertTo.integerBits() < m_bits || isAddress())
+
+ if (isAddress())
return false;
- else if (isSigned())
- return convertTo.isSigned();
else
- return !convertTo.isSigned() || convertTo.integerBits() > m_bits;
+ return maxValue() <= convertTo.maxIntegerValue() && minValue() >= convertTo.minIntegerValue();
}
else
return false;
@@ -487,22 +486,20 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons
return MemberList::MemberMap();
}
-FixedPointType::FixedPointType(int _integerBits, int _fractionalBits, FixedPointType::Modifier _modifier):
- m_integerBits(_integerBits), m_fractionalBits(_fractionalBits), m_modifier(_modifier)
+FixedPointType::FixedPointType(int _totalBits, int _fractionalDigits, FixedPointType::Modifier _modifier):
+ m_totalBits(_totalBits), m_fractionalDigits(_fractionalDigits), m_modifier(_modifier)
{
solAssert(
- m_integerBits + m_fractionalBits > 0 &&
- m_integerBits + m_fractionalBits <= 256 &&
- m_integerBits % 8 == 0 &&
- m_fractionalBits % 8 == 0,
+ 8 <= m_totalBits && m_totalBits <= 256 && m_totalBits % 8 == 0 &&
+ 0 <= m_fractionalDigits && m_fractionalDigits <= 80,
"Invalid bit number(s) for fixed type: " +
- dev::toString(_integerBits) + "x" + dev::toString(_fractionalBits)
- );
+ dev::toString(_totalBits) + "x" + dev::toString(_fractionalDigits)
+ );
}
string FixedPointType::identifier() const
{
- return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(integerBits()) + "x" + std::to_string(fractionalBits());
+ return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(m_totalBits) + "x" + std::to_string(m_fractionalDigits);
}
bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
@@ -510,12 +507,10 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (_convertTo.category() == category())
{
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
- if (convertTo.m_integerBits < m_integerBits || convertTo.m_fractionalBits < m_fractionalBits)
+ if (convertTo.numBits() < m_totalBits || convertTo.fractionalDigits() < m_fractionalDigits)
return false;
- else if (isSigned())
- return convertTo.isSigned();
else
- return !convertTo.isSigned() || (convertTo.m_integerBits > m_integerBits);
+ return convertTo.maxIntegerValue() >= maxIntegerValue() && convertTo.minIntegerValue() <= minIntegerValue();
}
return false;
}
@@ -549,13 +544,30 @@ bool FixedPointType::operator==(Type const& _other) const
if (_other.category() != category())
return false;
FixedPointType const& other = dynamic_cast<FixedPointType const&>(_other);
- return other.m_integerBits == m_integerBits && other.m_fractionalBits == m_fractionalBits && other.m_modifier == m_modifier;
+ return other.m_totalBits == m_totalBits && other.m_fractionalDigits == m_fractionalDigits && other.m_modifier == m_modifier;
}
string FixedPointType::toString(bool) const
{
string prefix = isSigned() ? "fixed" : "ufixed";
- return prefix + dev::toString(m_integerBits) + "x" + dev::toString(m_fractionalBits);
+ return prefix + dev::toString(m_totalBits) + "x" + dev::toString(m_fractionalDigits);
+}
+
+bigint FixedPointType::maxIntegerValue() const
+{
+ bigint maxValue = (bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))) - 1;
+ return maxValue / pow(bigint(10), m_fractionalDigits);
+}
+
+bigint FixedPointType::minIntegerValue() const
+{
+ if (isSigned())
+ {
+ bigint minValue = -(bigint(1) << (m_totalBits - (isSigned() ? 1 : 0)));
+ return minValue / pow(bigint(10), m_fractionalDigits);
+ }
+ else
+ return bigint(0);
}
TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
@@ -743,13 +755,9 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedPoint)
{
if (auto fixed = fixedPointType())
- {
- // We disallow implicit conversion if we would have to truncate (fixedPointType()
- // can return a type that requires truncation).
- rational value = m_value * (bigint(1) << fixed->fractionalBits());
- return value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo);
- }
- return false;
+ return fixed->isImplicitlyConvertibleTo(_convertTo);
+ else
+ return false;
}
else if (_convertTo.category() == Category::FixedBytes)
{
@@ -953,10 +961,9 @@ u256 RationalNumberType::literalValue(Literal const*) const
else
{
auto fixed = fixedPointType();
- solAssert(!!fixed, "");
- rational shifted = m_value * (bigint(1) << fixed->fractionalBits());
- // truncate
- shiftedValue = shifted.numerator() / shifted.denominator();
+ solAssert(fixed, "");
+ int fractionalDigits = fixed->fractionalDigits();
+ shiftedValue = (m_value.numerator() / m_value.denominator()) * pow(bigint(10), fractionalDigits);
}
// we ignore the literal and hope that the type was correctly determined
@@ -997,22 +1004,21 @@ shared_ptr<IntegerType const> RationalNumberType::integerType() const
shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
{
bool negative = (m_value < 0);
- unsigned fractionalBits = 0;
+ unsigned fractionalDigits = 0;
rational value = abs(m_value); // We care about the sign later.
rational maxValue = negative ?
rational(bigint(1) << 255, 1):
rational((bigint(1) << 256) - 1, 1);
- while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256)
+ while (value * 10 <= maxValue && value.denominator() != 1 && fractionalDigits < 80)
{
- value *= 0x100;
- fractionalBits += 8;
+ value *= 10;
+ fractionalDigits++;
}
if (value > maxValue)
return shared_ptr<FixedPointType const>();
- // u256(v) is the actual value that will be put on the stack
- // From here on, very similar to integerType()
+ // This means we round towards zero for positive and negative values.
bigint v = value.numerator() / value.denominator();
if (negative)
// modify value to satisfy bit requirements for negative numbers:
@@ -1022,26 +1028,11 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
if (v > u256(-1))
return shared_ptr<FixedPointType const>();
- unsigned totalBits = bytesRequired(v) * 8;
+ unsigned totalBits = max(bytesRequired(v), 1u) * 8;
solAssert(totalBits <= 256, "");
- unsigned integerBits = totalBits >= fractionalBits ? totalBits - fractionalBits : 0;
- // Special case: Numbers between -1 and 0 have their sign bit in the fractional part.
- if (negative && abs(m_value) < 1 && totalBits > fractionalBits)
- {
- fractionalBits += 8;
- integerBits = 0;
- }
-
- if (integerBits > 256 || fractionalBits > 256 || fractionalBits + integerBits > 256)
- return shared_ptr<FixedPointType const>();
- if (integerBits == 0 && fractionalBits == 0)
- {
- integerBits = 0;
- fractionalBits = 8;
- }
return make_shared<FixedPointType>(
- integerBits, fractionalBits,
+ totalBits, fractionalDigits,
negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned
);
}
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index c24cc11a..3d7dad16 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -342,7 +342,7 @@ public:
};
virtual Category category() const override { return Category::FixedPoint; }
- explicit FixedPointType(int _integerBits, int _fractionalBits, Modifier _modifier = Modifier::Unsigned);
+ explicit FixedPointType(int _totalBits, int _fractionalDigits, Modifier _modifier = Modifier::Unsigned);
virtual std::string identifier() const override;
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
@@ -352,8 +352,8 @@ public:
virtual bool operator==(Type const& _other) const override;
- virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : (m_integerBits + m_fractionalBits) / 8; }
- virtual unsigned storageBytes() const override { return (m_integerBits + m_fractionalBits) / 8; }
+ virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_totalBits / 8; }
+ virtual unsigned storageBytes() const override { return m_totalBits / 8; }
virtual bool isValueType() const override { return true; }
virtual std::string toString(bool _short) const override;
@@ -361,14 +361,21 @@ public:
virtual TypePointer encodingType() const override { return shared_from_this(); }
virtual TypePointer interfaceType(bool) const override { return shared_from_this(); }
- int numBits() const { return m_integerBits + m_fractionalBits; }
- int integerBits() const { return m_integerBits; }
- int fractionalBits() const { return m_fractionalBits; }
+ /// Number of bits used for this type in total.
+ int numBits() const { return m_totalBits; }
+ /// Number of decimal digits after the radix point.
+ int fractionalDigits() const { return m_fractionalDigits; }
bool isSigned() const { return m_modifier == Modifier::Signed; }
+ /// @returns the largest integer value this type con hold. Note that this is not the
+ /// largest value in general.
+ bigint maxIntegerValue() const;
+ /// @returns the smallest integer value this type can hold. Note hat this is not the
+ /// smallest value in general.
+ bigint minIntegerValue() const;
private:
- int m_integerBits;
- int m_fractionalBits;
+ int m_totalBits;
+ int m_fractionalDigits;
Modifier m_modifier;
};
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 7067ddd5..782aad9d 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -504,7 +504,7 @@ void CompilerUtils::convertType(
//shift all integer bits onto the left side of the fixed type
FixedPointType const& targetFixedPointType = dynamic_cast<FixedPointType const&>(_targetType);
if (auto typeOnStack = dynamic_cast<IntegerType const*>(&_typeOnStack))
- if (targetFixedPointType.integerBits() > typeOnStack->numBits())
+ if (targetFixedPointType.numBits() > typeOnStack->numBits())
cleanHigherOrderBits(*typeOnStack);
solUnimplemented("Not yet implemented - FixedPointType.");
}
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index e2507821..7a87875c 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -451,18 +451,20 @@ Json::Value const& CompilerStack::natspec(Contract const& _contract, Documentati
{
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:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Illegal documentation type."));
}
- // caches the result
- if (!*doc)
- doc->reset(new Json::Value(Natspec::documentation(*_contract.contract, _type)));
-
return *(*doc);
}
@@ -474,12 +476,12 @@ Json::Value CompilerStack::methodIdentifiers(string const& _contractName) const
return methodIdentifiers;
}
-string const& CompilerStack::onChainMetadata(string const& _contractName) const
+string const& CompilerStack::metadata(string const& _contractName) const
{
if (m_stackState != CompilationSuccessful)
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Compilation was not successful."));
- return contract(_contractName).onChainMetadata;
+ return contract(_contractName).metadata;
}
Scanner const& CompilerStack::scanner(string const& _sourceName) const
@@ -673,11 +675,11 @@ void CompilerStack::compileContract(
shared_ptr<Compiler> compiler = make_shared<Compiler>(m_optimize, m_optimizeRuns);
Contract& compiledContract = m_contracts.at(_contract.fullyQualifiedName());
- string onChainMetadata = createOnChainMetadata(compiledContract);
+ string metadata = createMetadata(compiledContract);
bytes cborEncodedMetadata =
- // CBOR-encoding of {"bzzr0": dev::swarmHash(onChainMetadata)}
+ // CBOR-encoding of {"bzzr0": dev::swarmHash(metadata)}
bytes{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} +
- dev::swarmHash(onChainMetadata).asBytes();
+ dev::swarmHash(metadata).asBytes();
solAssert(cborEncodedMetadata.size() <= 0xffff, "Metadata too large");
// 16-bit big endian length
cborEncodedMetadata += toCompactBigEndian(cborEncodedMetadata.size(), 2);
@@ -710,7 +712,7 @@ void CompilerStack::compileContract(
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Assembly exception for deployed bytecode"));
}
- compiledContract.onChainMetadata = onChainMetadata;
+ compiledContract.metadata = metadata;
_compiledContracts[compiledContract.contract] = &compiler->assembly();
try
@@ -771,7 +773,7 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co
return it->second;
}
-string CompilerStack::createOnChainMetadata(Contract const& _contract) const
+string CompilerStack::createMetadata(Contract const& _contract) const
{
Json::Value meta;
meta["version"] = 1;
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 03a1b806..6b8fb538 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -183,7 +183,7 @@ public:
/// @returns a JSON representing a map of method identifiers (hashes) to function names.
Json::Value methodIdentifiers(std::string const& _contractName) const;
- std::string const& onChainMetadata(std::string const& _contractName) const;
+ std::string const& metadata(std::string const& _contractName) const;
void useMetadataLiteralSources(bool _metadataLiteralSources) { m_metadataLiteralSources = _metadataLiteralSources; }
/// @returns a JSON representing the estimated gas usage for contract creation, internal and external functions
@@ -223,7 +223,7 @@ private:
eth::LinkerObject object;
eth::LinkerObject runtimeObject;
eth::LinkerObject cloneObject;
- std::string onChainMetadata; ///< The metadata json that will be hashed into the chain.
+ std::string metadata; ///< The metadata json that will be hashed into the chain.
mutable std::unique_ptr<Json::Value const> abi;
mutable std::unique_ptr<Json::Value const> userDocumentation;
mutable std::unique_ptr<Json::Value const> devDocumentation;
@@ -255,7 +255,7 @@ private:
/// does not exist.
ContractDefinition const& contractDefinition(std::string const& _contractName) const;
- std::string createOnChainMetadata(Contract const& _contract) const;
+ 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;
diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp
index 70486e23..7f7084ef 100644
--- a/libsolidity/interface/Natspec.cpp
+++ b/libsolidity/interface/Natspec.cpp
@@ -26,28 +26,11 @@
#include <libsolidity/interface/Natspec.h>
#include <boost/range/irange.hpp>
#include <libsolidity/ast/AST.h>
-#include <libsolidity/interface/CompilerStack.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
-Json::Value Natspec::documentation(
- ContractDefinition const& _contractDef,
- DocumentationType _type
-)
-{
- switch(_type)
- {
- case DocumentationType::NatspecUser:
- return userDocumentation(_contractDef);
- case DocumentationType::NatspecDev:
- return devDocumentation(_contractDef);
- }
-
- BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unknown documentation type"));
-}
-
Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
{
Json::Value doc;
diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h
index bec9acd2..9ac3efea 100644
--- a/libsolidity/interface/Natspec.h
+++ b/libsolidity/interface/Natspec.h
@@ -39,7 +39,6 @@ class ContractDefinition;
class Type;
using TypePointer = std::shared_ptr<Type const>;
struct DocTag;
-enum class DocumentationType: uint8_t;
enum class DocTagType: uint8_t
{
@@ -61,15 +60,6 @@ enum class CommentOwner
class Natspec
{
public:
- /// Get the given type of documentation
- /// @param _contractDef The contract definition
- /// @param _type The type of the documentation. Can be one of the
- /// types provided by @c DocumentationType
- /// @return A JSON representation of provided type
- static Json::Value documentation(
- ContractDefinition const& _contractDef,
- DocumentationType _type
- );
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
/// @return A JSON representation of the contract's user documentation
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index df1afdc5..82eeac3d 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -386,7 +386,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
// ABI, documentation and metadata
Json::Value contractData(Json::objectValue);
contractData["abi"] = m_compilerStack.contractABI(contractName);
- contractData["metadata"] = m_compilerStack.onChainMetadata(contractName);
+ contractData["metadata"] = m_compilerStack.metadata(contractName);
contractData["userdoc"] = m_compilerStack.natspec(contractName, DocumentationType::NatspecUser);
contractData["devdoc"] = m_compilerStack.natspec(contractName, DocumentationType::NatspecDev);
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index b0cf364e..b98991f3 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -87,7 +87,7 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
nodes.push_back(parseContractDefinition(token));
break;
default:
- fatalParserError(string("Expected import directive or contract definition."));
+ fatalParserError(string("Expected pragma, import directive or contract/interface/library definition."));
}
}
return nodeFactory.createNode<SourceUnit>(nodes);
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
index 66312f69..9cec0303 100644
--- a/libsolidity/parsing/Token.cpp
+++ b/libsolidity/parsing/Token.cpp
@@ -70,7 +70,7 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con
else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN)
{
solAssert(
- _first + _second <= 256 && _first % 8 == 0 && _second % 8 == 0,
+ _first >= 8 && _first <= 256 && _first % 8 == 0 && _second <= 80,
"No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
);
}
@@ -157,12 +157,8 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s
) {
int n = parseSize(positionX + 1, _literal.end());
if (
- 0 <= m && m <= 256 &&
- 8 <= n && n <= 256 &&
- m + n > 0 &&
- m + n <= 256 &&
- m % 8 == 0 &&
- n % 8 == 0
+ 8 <= m && m <= 256 && m % 8 == 0 &&
+ 0 <= n && n <= 80
) {
if (keyword == Token::UFixed)
return make_tuple(Token::UFixedMxN, m, n);
diff --git a/solc/CMakeLists.txt b/solc/CMakeLists.txt
index a5515d81..18e83e75 100644
--- a/solc/CMakeLists.txt
+++ b/solc/CMakeLists.txt
@@ -18,7 +18,7 @@ else()
endif()
if (EMSCRIPTEN)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='[\"_compileJSON\",\"_license\",\"_version\",\"_compileJSONMulti\",\"_compileJSONCallback\",\"_compileStandard\"]' -s RESERVED_FUNCTION_POINTERS=20")
add_executable(soljson jsonCompiler.cpp ${HEADERS})
eth_use(soljson REQUIRED Solidity::solidity)
else()
diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp
index 0222ccb0..db497d84 100644
--- a/solc/CommandLineInterface.cpp
+++ b/solc/CommandLineInterface.cpp
@@ -292,12 +292,12 @@ void CommandLineInterface::handleSignatureHashes(string const& _contract)
cout << "Function signatures: " << endl << out;
}
-void CommandLineInterface::handleOnChainMetadata(string const& _contract)
+void CommandLineInterface::handleMetadata(string const& _contract)
{
if (!m_args.count(g_argMetadata))
return;
- string data = m_compiler->onChainMetadata(_contract);
+ string data = m_compiler->metadata(_contract);
if (m_args.count(g_argOutputDir))
createFile(m_compiler->filesystemFriendlyName(_contract) + "_meta.json", data);
else
@@ -850,7 +850,7 @@ void CommandLineInterface::handleCombinedJSON()
if (requests.count(g_strAbi))
contractData[g_strAbi] = dev::jsonCompactPrint(m_compiler->contractABI(contractName));
if (requests.count("metadata"))
- contractData["metadata"] = m_compiler->onChainMetadata(contractName);
+ contractData["metadata"] = m_compiler->metadata(contractName);
if (requests.count(g_strBinary))
contractData[g_strBinary] = m_compiler->object(contractName).toHex();
if (requests.count(g_strBinaryRuntime))
@@ -1164,7 +1164,7 @@ void CommandLineInterface::outputCompilationResults()
handleBytecode(contract);
handleSignatureHashes(contract);
- handleOnChainMetadata(contract);
+ handleMetadata(contract);
handleABI(contract);
handleNatspec(DocumentationType::NatspecDev, contract);
handleNatspec(DocumentationType::NatspecUser, contract);
diff --git a/solc/CommandLineInterface.h b/solc/CommandLineInterface.h
index b482c20b..8a476ef5 100644
--- a/solc/CommandLineInterface.h
+++ b/solc/CommandLineInterface.h
@@ -64,7 +64,7 @@ private:
void handleOpcode(std::string const& _contract);
void handleBytecode(std::string const& _contract);
void handleSignatureHashes(std::string const& _contract);
- void handleOnChainMetadata(std::string const& _contract);
+ void handleMetadata(std::string const& _contract);
void handleABI(std::string const& _contract);
void handleNatspec(DocumentationType _type, std::string const& _contract);
void handleGasEstimation(std::string const& _contract);
diff --git a/test/contracts/LLL_ENS.cpp b/test/contracts/LLL_ENS.cpp
index 3df1546d..c5fe8a82 100644
--- a/test/contracts/LLL_ENS.cpp
+++ b/test/contracts/LLL_ENS.cpp
@@ -345,7 +345,7 @@ protected:
if (!s_compiledEns)
{
vector<string> errors;
- s_compiledEns.reset(new bytes(compileLLL(ensCode, false, &errors)));
+ s_compiledEns.reset(new bytes(compileLLL(ensCode, dev::test::Options::get().optimize, &errors)));
BOOST_REQUIRE(errors.empty());
}
sendMessage(*s_compiledEns, true);
diff --git a/test/contracts/LLL_ERC20.cpp b/test/contracts/LLL_ERC20.cpp
index 3ee1aa98..25665d64 100644
--- a/test/contracts/LLL_ERC20.cpp
+++ b/test/contracts/LLL_ERC20.cpp
@@ -396,7 +396,7 @@ protected:
if (!s_compiledErc20)
{
vector<string> errors;
- s_compiledErc20.reset(new bytes(compileLLL(erc20Code, false, &errors)));
+ s_compiledErc20.reset(new bytes(compileLLL(erc20Code, dev::test::Options::get().optimize, &errors)));
BOOST_REQUIRE(errors.empty());
}
sendMessage(*s_compiledErc20, true);
diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp
index 4e896fd0..9292d963 100644
--- a/test/liblll/EndToEndTest.cpp
+++ b/test/liblll/EndToEndTest.cpp
@@ -165,6 +165,56 @@ BOOST_AUTO_TEST_CASE(conditional_seq)
BOOST_CHECK(callFallback() == toBigEndian(u256(1)));
}
+BOOST_AUTO_TEST_CASE(conditional_nested_else)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (def 'input (calldataload 0x04))
+ ;; Calculates width in bytes of utf-8 characters.
+ (return
+ (if (< input 0x80) 1
+ (if (< input 0xE0) 2
+ (if (< input 0xF0) 3
+ (if (< input 0xF8) 4
+ (if (< input 0xFC) 5
+ 6))))))))
+
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2)));
+ BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3)));
+ BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4)));
+ BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5)));
+ BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6)));
+}
+
+BOOST_AUTO_TEST_CASE(conditional_nested_then)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (def 'input (calldataload 0x04))
+ ;; Calculates width in bytes of utf-8 characters.
+ (return
+ (if (>= input 0x80)
+ (if (>= input 0xE0)
+ (if (>= input 0xF0)
+ (if (>= input 0xF8)
+ (if (>= input 0xFC)
+ 6 5) 4) 3) 2) 1))))
+
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callContractFunction("test()", 0x00) == encodeArgs(u256(1)));
+ BOOST_CHECK(callContractFunction("test()", 0x80) == encodeArgs(u256(2)));
+ BOOST_CHECK(callContractFunction("test()", 0xe0) == encodeArgs(u256(3)));
+ BOOST_CHECK(callContractFunction("test()", 0xf0) == encodeArgs(u256(4)));
+ BOOST_CHECK(callContractFunction("test()", 0xf8) == encodeArgs(u256(5)));
+ BOOST_CHECK(callContractFunction("test()", 0xfc) == encodeArgs(u256(6)));
+}
+
BOOST_AUTO_TEST_CASE(exp_operator_const)
{
char const* sourceCode = R"(
diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp
index ef560b12..8b41e1db 100644
--- a/test/libsolidity/GasMeter.cpp
+++ b/test/libsolidity/GasMeter.cpp
@@ -47,8 +47,9 @@ public:
GasMeterTestFramework() { }
void compile(string const& _sourceCode)
{
- m_compiler.setSource("pragma solidity >= 0.0;" + _sourceCode);
- ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(), "Compiling contract failed");
+ m_compiler.reset(false);
+ m_compiler.addSource("", "pragma solidity >=0.0;\n" + _sourceCode);
+ ETH_TEST_REQUIRE_NO_THROW(m_compiler.compile(dev::test::Options::get().optimize), "Compiling contract failed");
AssemblyItems const* items = m_compiler.runtimeAssemblyItems("");
ASTNode const& sourceUnit = m_compiler.ast();
diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp
index aa690f0b..a6a7bc5b 100644
--- a/test/libsolidity/JSONCompiler.cpp
+++ b/test/libsolidity/JSONCompiler.cpp
@@ -24,6 +24,7 @@
#include <regex>
#include <boost/test/unit_test.hpp>
#include <libdevcore/JSON.h>
+#include <libsolidity/interface/Version.h>
#include "../Metadata.h"
#include "../TestHelper.h"
@@ -32,6 +33,8 @@ using namespace std;
extern "C"
{
+extern char const* version();
+extern char const* license();
extern char const* compileJSONMulti(char const* _input, bool _optimize);
}
@@ -57,6 +60,18 @@ Json::Value compile(string const& _input)
BOOST_AUTO_TEST_SUITE(JSONCompiler)
+BOOST_AUTO_TEST_CASE(read_version)
+{
+ string output(version());
+ BOOST_CHECK(output.find(VersionString) == 0);
+}
+
+BOOST_AUTO_TEST_CASE(read_license)
+{
+ string output(license());
+ BOOST_CHECK(output.find("GNU GENERAL PUBLIC LICENSE") != string::npos);
+}
+
BOOST_AUTO_TEST_CASE(basic_compilation)
{
char const* input = R"(
diff --git a/test/libsolidity/Metadata.cpp b/test/libsolidity/Metadata.cpp
index 60bb2e4e..ce1a7b18 100644
--- a/test/libsolidity/Metadata.cpp
+++ b/test/libsolidity/Metadata.cpp
@@ -43,9 +43,10 @@ BOOST_AUTO_TEST_CASE(metadata_stamp)
}
)";
CompilerStack compilerStack;
- BOOST_REQUIRE(compilerStack.compile(std::string(sourceCode)));
+ compilerStack.addSource("", std::string(sourceCode));
+ ETH_TEST_REQUIRE_NO_THROW(compilerStack.compile(dev::test::Options::get().optimize), "Compiling contract failed");
bytes const& bytecode = compilerStack.runtimeObject("test").bytecode;
- std::string const& metadata = compilerStack.onChainMetadata("test");
+ std::string const& metadata = compilerStack.metadata("test");
BOOST_CHECK(dev::test::isValidMetadata(metadata));
bytes hash = dev::swarmHash(metadata).asBytes();
BOOST_REQUIRE(hash.size() == 32);
diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp
index f87390e1..452a2662 100644
--- a/test/libsolidity/SolidityABIJSON.cpp
+++ b/test/libsolidity/SolidityABIJSON.cpp
@@ -42,7 +42,9 @@ public:
void checkInterface(std::string const& _code, std::string const& _expectedInterfaceString)
{
- ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze("pragma solidity >=0.0;\n" + _code), "Parsing contract failed");
+ m_compilerStack.reset(false);
+ m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code);
+ ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze(), "Parsing contract failed");
Json::Value generatedInterface = m_compilerStack.contractABI("");
Json::Value expectedInterface;
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index cb39101e..4b29243a 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -112,7 +112,14 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false,
)
{
if (error && !_allowMultipleErrors)
- BOOST_FAIL("Multiple errors found");
+ {
+ string message("Multiple errors found: ");
+ for (auto const& e: errorReporter.errors())
+ if (string const* description = boost::get_error_info<errinfo_comment>(*e))
+ message += *description + ", ";
+
+ BOOST_FAIL(message);
+ }
if (!error)
error = currentError;
}
@@ -2283,6 +2290,9 @@ BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName)
BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 30, 0)) == *make_shared<FixedBytesType>(30));
BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 31, 0)) == *make_shared<FixedBytesType>(31));
BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::BytesM, 32, 0)) == *make_shared<FixedBytesType>(32));
+
+ BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::Fixed, 0, 0)) == *make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Signed));
+ BOOST_CHECK(*Type::fromElementaryTypeName(ElementaryTypeNameToken(Token::UFixed, 0, 0)) == *make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Unsigned));
}
BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1)
@@ -4026,7 +4036,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_types_0x7_mxn)
fixed0x7 a = .3;
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, DeclarationError, "Identifier not found");
}
BOOST_AUTO_TEST_CASE(invalid_fixed_types_long_invalid_identifier)
@@ -4036,7 +4046,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_types_long_invalid_identifier)
fixed99999999999999999999999999999999999999x7 b = 9.5;
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, DeclarationError, "Identifier not found");
}
BOOST_AUTO_TEST_CASE(invalid_fixed_types_7x8_mxn)
@@ -4046,7 +4056,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_types_7x8_mxn)
fixed7x8 c = 3.12345678;
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, DeclarationError, "Identifier not found");
}
BOOST_AUTO_TEST_CASE(library_instances_cannot_be_used)
@@ -4060,7 +4070,7 @@ BOOST_AUTO_TEST_CASE(library_instances_cannot_be_used)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "Member \"l\" not found or not visible after argument-dependent lookup in library L");
}
BOOST_AUTO_TEST_CASE(invalid_fixed_type_long)
@@ -4072,7 +4082,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_type_long)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, DeclarationError, "Identifier not found");
}
BOOST_AUTO_TEST_CASE(fixed_type_int_conversion)
@@ -4080,8 +4090,8 @@ BOOST_AUTO_TEST_CASE(fixed_type_int_conversion)
char const* text = R"(
contract test {
function f() {
- uint128 a = 3;
- int128 b = 4;
+ uint64 a = 3;
+ int64 b = 4;
fixed c = b;
ufixed d = a;
c; d;
@@ -4130,7 +4140,7 @@ BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "Type fixed128x19 is not implicitly convertible to expected type int256");
}
BOOST_AUTO_TEST_CASE(rational_unary_operation)
@@ -4138,10 +4148,9 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation)
char const* text = R"(
contract test {
function f() {
- ufixed8x16 a = 3.25;
- fixed8x16 b = -3.25;
- a;
- b;
+ ufixed16x2 a = 3.25;
+ fixed16x2 b = -3.25;
+ a; b;
}
}
)";
@@ -4149,13 +4158,13 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation)
text = R"(
contract test {
function f() {
- ufixed8x16 a = +3.25;
- fixed8x16 b = -3.25;
+ ufixed16x2 a = +3.25;
+ fixed16x2 b = -3.25;
a; b;
}
}
)";
- CHECK_WARNING(text,"Use of unary + is deprecated");
+ CHECK_WARNING(text, "Use of unary + is deprecated");
text = R"(
contract test {
function f(uint x) {
@@ -4172,10 +4181,10 @@ BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert)
char const* text = R"(
contract A {
function f() {
- ufixed0x8 a = 0.5;
- ufixed0x56 b = 0.0000000000000006661338147750939242541790008544921875;
- fixed0x8 c = -0.5;
- fixed0x56 d = -0.0000000000000006661338147750939242541790008544921875;
+ ufixed16x2 a = 0.5;
+ ufixed256x52 b = 0.0000000000000006661338147750939242541790008544921875;
+ fixed16x2 c = -0.5;
+ fixed256x52 d = -0.0000000000000006661338147750939242541790008544921875;
a; b; c; d;
}
}
@@ -4188,12 +4197,12 @@ BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
char const* text = R"(
contract test {
function f() {
- ufixed248x8 a = 123456781234567979695948382928485849359686494864095409282048094275023098123.5;
- ufixed0x256 b = 0.920890746623327805482905058466021565416131529487595827354393978494366605267637829135688384325135165352082715782143655824815685807141335814463015972119819459298455224338812271036061391763384038070334798471324635050876128428143374549108557403087615966796875;
- ufixed0x256 c = 0.0000000000015198847363997979984922685411315294875958273543939784943666052676464653042434787697605517039455161817147718251801220885263595179331845639229818863564267318422845592626219390573301877339317935702714669975697814319204326238832436501979827880859375;
- fixed248x8 d = -123456781234567979695948382928485849359686494864095409282048094275023098123.5;
- fixed0x256 e = -0.93322335481643744342575580035176794825198893968114429702091846411734101080123092162893656820177312738451291806995868682861328125;
- fixed0x256 g = -0.00011788606643744342575580035176794825198893968114429702091846411734101080123092162893656820177312738451291806995868682861328125;
+ ufixed256x1 a = 123456781234567979695948382928485849359686494864095409282048094275023098123.5;
+ ufixed256x77 b = 0.920890746623327805482905058466021565416131529487595827354393978494366605267637;
+ ufixed224x78 c = 0.000000000001519884736399797998492268541131529487595827354393978494366605267646;
+ fixed256x1 d = -123456781234567979695948382928485849359686494864095409282048094275023098123.5;
+ fixed256x76 e = -0.93322335481643744342575580035176794825198893968114429702091846411734101080123;
+ fixed256x79 g = -0.0001178860664374434257558003517679482519889396811442970209184641173410108012309;
a; b; c; d; e; g;
}
}
@@ -4201,17 +4210,30 @@ BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
CHECK_SUCCESS(text);
}
+BOOST_AUTO_TEST_CASE(zero_handling)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed16x2 a = 0; a;
+ ufixed32x1 b = 0; b;
+ }
+ }
+ )";
+ CHECK_SUCCESS(text);
+}
+
BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size)
{
char const* text = R"(
contract test {
function f() {
ufixed a = 11/4;
- ufixed248x8 b = a;
+ ufixed248x8 b = a; b;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "Type ufixed128x19 is not implicitly convertible to expected type ufixed248x8");
}
BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_lost_data)
@@ -4219,11 +4241,11 @@ BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_lost_data)
char const* text = R"(
contract test {
function f() {
- ufixed0x256 a = 1/3;
+ ufixed256x1 a = 1/3; a;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type ufixed256x1");
}
BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions)
@@ -4231,10 +4253,9 @@ BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions)
char const* text = R"(
contract test {
function f() {
- ufixed0x256 a = ufixed0x256(1/3);
- ufixed0x248 b = ufixed0x248(1/3);
- ufixed0x8 c = ufixed0x8(1/3);
- a; b; c;
+ ufixed256x80 a = ufixed256x80(1/3); a;
+ ufixed248x80 b = ufixed248x80(1/3); b;
+ ufixed8x1 c = ufixed8x1(1/3); c;
}
}
)";
@@ -4246,23 +4267,35 @@ BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational)
char const* text = R"(
contract test {
function f() {
- uint[3.5] a;
+ uint[3.5] a; a;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal");
}
-BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_fixed_type)
+BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_signed_fixed_type)
{
char const* text = R"(
contract test {
function f() {
- uint[fixed(3.5)] a;
+ uint[fixed(3.5)] a; a;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal");
+}
+
+BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_unsigned_fixed_type)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ uint[ufixed(3.5)] a; a;
+ }
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal");
}
BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion)
@@ -4270,11 +4303,11 @@ BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion)
char const* text = R"(
contract test {
function f() {
- bytes32 c = 3.2;
+ bytes32 c = 3.2; c;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type bytes32");
}
BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
@@ -4283,18 +4316,18 @@ BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
contract test {
function f() {
fixed a = 3.25;
- bytes32 c = a;
+ bytes32 c = a; c;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "fixed128x19 is not implicitly convertible to expected type bytes32");
}
BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal)
{
char const* text = R"(
contract test {
- mapping(ufixed8x248 => string) fixedString;
+ mapping(ufixed8x1 => string) fixedString;
function f() {
fixedString[0.5] = "Half";
}
@@ -4334,7 +4367,7 @@ BOOST_AUTO_TEST_CASE(inline_array_rationals)
char const* text = R"(
contract test {
function f() {
- ufixed8x8[4] memory a = [3.5, 4.125, 2.5, 4.0];
+ ufixed128x3[4] memory a = [ufixed128x3(3.5), 4.125, 2.5, 4.0];
}
}
)";
@@ -4351,7 +4384,7 @@ BOOST_AUTO_TEST_CASE(rational_index_access)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "rational_const 1/2 is not implicitly convertible to expected type uint256");
}
BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression)
@@ -4359,12 +4392,12 @@ BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression)
char const* text = R"(
contract test {
function f() {
- ufixed8x8 a = 3.5 * 3;
- ufixed8x8 b = 4 - 2.5;
- ufixed8x8 c = 11 / 4;
- ufixed16x240 d = 599 + 0.21875;
- ufixed8x248 e = ufixed8x248(35.245 % 12.9);
- ufixed8x248 f = ufixed8x248(1.2 % 2);
+ ufixed64x8 a = 3.5 * 3;
+ ufixed64x8 b = 4 - 2.5;
+ ufixed64x8 c = 11 / 4;
+ ufixed240x5 d = 599 + 0.21875;
+ ufixed256x80 e = ufixed256x80(35.245 % 12.9);
+ ufixed256x80 f = ufixed256x80(1.2 % 2);
fixed g = 2 ** -2;
a; b; c; d; e; f; g;
}
@@ -4373,7 +4406,7 @@ BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression)
CHECK_SUCCESS(text);
}
-BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_decimal)
+BOOST_AUTO_TEST_CASE(rational_as_exponent_value_signed)
{
char const* text = R"(
contract test {
@@ -4382,10 +4415,10 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_decimal)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
-BOOST_AUTO_TEST_CASE(rational_as_exponent_value_pos_decimal)
+BOOST_AUTO_TEST_CASE(rational_as_exponent_value_unsigned)
{
char const* text = R"(
contract test {
@@ -4394,7 +4427,7 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value_pos_decimal)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(rational_as_exponent_half)
@@ -4402,11 +4435,11 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_half)
char const* text = R"(
contract test {
function f() {
- ufixed24x24 b = 2 ** (1/2);
+ 2 ** (1/2);
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_quarter)
@@ -4414,11 +4447,11 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_quarter)
char const* text = R"(
contract test {
function f() {
- fixed40x40 c = 42 ** (-1/4);
+ 42 ** (-1/4);
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_15)
@@ -4426,23 +4459,11 @@ BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_15)
char const* text = R"(
contract test {
function f() {
- ufixed a = 3 ** ufixed(1.5);
- }
- }
- )";
- BOOST_CHECK(!success(text));
-}
-
-BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_half)
-{
- char const* text = R"(
- contract test {
- function f() {
- ufixed b = 2 ** ufixed(1/2);
+ var a = 3 ** ufixed(1.5);
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg)
@@ -4450,23 +4471,11 @@ BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg)
char const* text = R"(
contract test {
function f() {
- fixed c = 42 ** fixed(-1/4);
- }
- }
- )";
- BOOST_CHECK(!success(text));
-}
-
-BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg_decimal)
-{
- char const* text = R"(
- contract test {
- function f() {
- fixed d = 16 ** fixed(-0.5);
+ var c = 42 ** fixed(-1/4);
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals)
@@ -4506,7 +4515,7 @@ BOOST_AUTO_TEST_CASE(var_handle_divided_integers)
}
}
)";
- CHECK_SUCCESS(text);
+ CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation)
@@ -4514,11 +4523,11 @@ BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = ~3.5;
+ ~fixed(3.5);
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "cannot be applied");
}
BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation)
@@ -4526,11 +4535,11 @@ BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = 1.5 | 3;
+ fixed(1.5) | 3;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation)
@@ -4538,11 +4547,11 @@ BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = 1.75 ^ 3;
+ fixed(1.75) ^ 3;
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation)
@@ -4550,25 +4559,11 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation)
char const* text = R"(
contract test {
function f() {
- fixed a = 1.75 & 3;
+ fixed(1.75) & 3;
}
}
)";
- BOOST_CHECK(!success(text));
-}
-
-BOOST_AUTO_TEST_CASE(zero_handling)
-{
- char const* text = R"(
- contract test {
- function f() {
- fixed8x8 a = 0;
- ufixed8x8 b = 0;
- a; b;
- }
- }
- )";
- CHECK_SUCCESS(text);
+ CHECK_ERROR(text, TypeError, "not compatible with types");
}
BOOST_AUTO_TEST_CASE(missing_bool_conversion)
@@ -4588,7 +4583,7 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction)
char const* text = R"(
contract test {
function f() {
- ufixed a = uint128(1) + ufixed(2);
+ ufixed a = uint64(1) + ufixed(2);
}
}
)";
@@ -4618,7 +4613,7 @@ BOOST_AUTO_TEST_CASE(one_divided_by_three_integer_conversion)
}
}
)";
- BOOST_CHECK(!success(text));
+ CHECK_ERROR(text, TypeError, "is not implicitly convertible to expected type uint256. Try converting to type ufixed256x77");
}
BOOST_AUTO_TEST_CASE(unused_return_value)
@@ -6359,6 +6354,34 @@ BOOST_AUTO_TEST_CASE(explicit_literal_to_storage_string)
CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed from \"literal_string \"abc\"\" to \"string storage pointer\"");
}
+BOOST_AUTO_TEST_CASE(modifiers_access_storage_pointer)
+{
+ char const* text = R"(
+ contract C {
+ struct S { }
+ modifier m(S storage x) {
+ x;
+ _;
+ }
+ }
+ )";
+ CHECK_SUCCESS_NO_WARNINGS(text);
+}
+
+BOOST_AUTO_TEST_CASE(using_this_in_constructor)
+{
+ char const* text = R"(
+ contract C {
+ function C() {
+ this.f();
+ }
+ function f() {
+ }
+ }
+ )";
+ CHECK_WARNING(text, "\"this\" used in constructor");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}
diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp
index 2a7376b9..aa343561 100644
--- a/test/libsolidity/SolidityNatspecJSON.cpp
+++ b/test/libsolidity/SolidityNatspecJSON.cpp
@@ -45,7 +45,9 @@ public:
bool _userDocumentation
)
{
- ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze("pragma solidity >=0.0;\n" + _code), "Parsing failed");
+ m_compilerStack.reset(false);
+ m_compilerStack.addSource("", "pragma solidity >=0.0;\n" + _code);
+ ETH_TEST_REQUIRE_NO_THROW(m_compilerStack.parseAndAnalyze(), "Parsing contract failed");
Json::Value generatedDocumentation;
if (_userDocumentation)