aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-08-14 22:33:39 +0800
committerGitHub <noreply@github.com>2018-08-14 22:33:39 +0800
commit414559bd0746424484d8fd1111cd9ee440eb5306 (patch)
tree3aa839acb6030afe3b63aaa44e8a1923691934a1
parentec7ccbdf866c108e96e3e9adeab60c3b00195f91 (diff)
parent8a06000a307e7f2a72f9bfdc114d84fab8ad2ebf (diff)
downloaddexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.tar
dexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.tar.gz
dexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.tar.bz2
dexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.tar.lz
dexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.tar.xz
dexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.tar.zst
dexon-solidity-414559bd0746424484d8fd1111cd9ee440eb5306.zip
Merge pull request #4788 from ethereum/noWarnDoc
Test that documentation does not contain any warnings.
-rw-r--r--docs/abi-spec.rst4
-rw-r--r--docs/assembly.rst18
-rw-r--r--docs/common-patterns.rst2
-rw-r--r--docs/contracts.rst61
-rw-r--r--docs/control-structures.rst44
-rw-r--r--docs/frequently-asked-questions.rst13
-rw-r--r--docs/layout-of-source-files.rst2
-rw-r--r--docs/solidity-by-example.rst10
-rw-r--r--docs/structure-of-a-contract.rst2
-rw-r--r--docs/style-guide.rst123
-rw-r--r--docs/types.rst41
-rwxr-xr-xscripts/isolate_tests.py49
-rwxr-xr-xtest/cmdlineTests.sh73
13 files changed, 262 insertions, 180 deletions
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index 69bbe5c3..bf9b8fb7 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -494,8 +494,8 @@ As an example, the code
contract Test {
struct S { uint a; uint[] b; T[] c; }
struct T { uint x; uint y; }
- function f(S memory s, T memory t, uint a) public { }
- function g() public returns (S memory s, T memory t, uint a) {}
+ function f(S memory s, T memory t, uint a) public;
+ function g() public returns (S memory s, T memory t, uint a);
}
would result in the JSON:
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 91ba076a..2cbad06f 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -82,7 +82,7 @@ you really know what you are doing.
library VectorSum {
// This function is less efficient because the optimizer currently fails to
// remove the bounds checks in array access.
- function sumSolidity(uint[] memory _data) public view returns (uint o_sum) {
+ function sumSolidity(uint[] memory _data) public pure returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i)
o_sum += _data[i];
}
@@ -90,7 +90,7 @@ you really know what you are doing.
// We know that we only access the array in bounds, so we can avoid the check.
// 0x20 needs to be added to an array because the first slot contains the
// array length.
- function sumAsm(uint[] memory _data) public view returns (uint o_sum) {
+ function sumAsm(uint[] memory _data) public pure returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i) {
assembly {
o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
@@ -99,7 +99,7 @@ you really know what you are doing.
}
// Same as above, but accomplish the entire code within inline assembly.
- function sumPureAsm(uint[] memory _data) public view returns (uint o_sum) {
+ function sumPureAsm(uint[] memory _data) public pure returns (uint o_sum) {
assembly {
// Load the length (first 32 bytes)
let len := mload(_data)
@@ -378,23 +378,13 @@ used ``x_slot`` and to retrieve the byte-offset you used ``x_offset``.
In assignments (see below), we can even use local Solidity variables to assign to.
-Functions external to inline assembly can also be accessed: The assembly will
-push their entry label (with virtual function resolution applied). The calling semantics
-in solidity are:
-
- - the caller pushes ``return label``, ``arg1``, ``arg2``, ..., ``argn``
- - the call returns with ``ret1``, ``ret2``, ..., ``retm``
-
-This feature is still a bit cumbersome to use, because the stack offset essentially
-changes during the call, and thus references to local variables will be wrong.
-
.. code::
pragma solidity ^0.4.11;
contract C {
uint b;
- function f(uint x) public returns (uint r) {
+ function f(uint x) public view returns (uint r) {
assembly {
r := mul(x, sload(b_slot)) // ignore the offset, we know it is zero
}
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst
index bc8286b2..6b061bf7 100644
--- a/docs/common-patterns.rst
+++ b/docs/common-patterns.rst
@@ -198,7 +198,7 @@ restrictions highly readable.
);
_;
if (msg.value > _amount)
- msg.sender.send(msg.value - _amount);
+ msg.sender.transfer(msg.value - _amount);
}
function forceOwnerChange(address _newOwner)
diff --git a/docs/contracts.rst b/docs/contracts.rst
index e9ac1af7..ca15d814 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -110,11 +110,11 @@ This means that cyclic creation dependencies are impossible.
function isTokenTransferOK(address currentOwner, address newOwner)
public
- view
+ pure
returns (bool ok)
{
// Check some arbitrary condition.
- return currentOwner != newOwner;
+ return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f;
}
}
@@ -137,16 +137,16 @@ Functions have to be specified as being ``external``,
For state variables, ``external`` is not possible.
``external``:
- External functions are part of the contract
- interface, which means they can be called from other contracts and
+ External functions are part of the contract interface,
+ which means they can be called from other contracts and
via transactions. An external function ``f`` cannot be called
internally (i.e. ``f()`` does not work, but ``this.f()`` works).
External functions are sometimes more efficient when
they receive large arrays of data.
``public``:
- Public functions are part of the contract
- interface and can be either called internally or via
+ Public functions are part of the contract interface
+ and can be either called internally or via
messages. For public state variables, an automatic getter
function (see below) is generated.
@@ -187,8 +187,6 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
::
- // This will not compile
-
pragma solidity ^0.4.0;
contract C {
@@ -200,6 +198,7 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
function compute(uint a, uint b) internal pure returns (uint) { return a + b; }
}
+ // This will not compile
contract D {
function readData() public {
C c = new C();
@@ -227,8 +226,8 @@ The compiler automatically creates getter functions for
all **public** state variables. For the contract given below, the compiler will
generate a function called ``data`` that does not take any
arguments and returns a ``uint``, the value of the state
-variable ``data``. The initialization of state variables can
-be done at declaration.
+variable ``data``. State variables can be initialized
+when they are declared.
::
@@ -240,8 +239,8 @@ be done at declaration.
contract Caller {
C c = new C();
- function f() public {
- uint local = c.data();
+ function f() public view returns (uint) {
+ return c.data();
}
}
@@ -256,9 +255,9 @@ it is evaluated as a state variable. If it is accessed externally
contract C {
uint public data;
- function x() public {
+ function x() public returns (uint) {
data = 3; // internal access
- uint val = this.data(); // external access
+ return this.data(); // external access
}
}
@@ -615,14 +614,13 @@ Like any function, the fallback function can execute complex operations as long
}
contract Caller {
- function callTest(Test test) public {
- address(test).call(abi.encodeWithSignature("nonExistingFunction()"));
+ function callTest(Test test) public returns (bool) {
+ require(address(test).call(abi.encodeWithSignature("nonExistingFunction()")));
// results in test.x becoming == 1.
// If someone sends ether to that contract,
- // the transaction will fail and reject the
- // Ether.
- address(test).send(2 ether);
+ // the transfer will fail, i.e. this returns false here.
+ return address(test).send(2 ether);
}
}
@@ -633,9 +631,11 @@ Like any function, the fallback function can execute complex operations as long
Function Overloading
====================
-A Contract can have multiple functions of the same name but with different arguments.
-This also applies to inherited functions. The following example shows overloading of the
-``f`` function in the scope of contract ``A``.
+A contract can have multiple functions of the same name but with different parameter
+types.
+This process is called "overloading" and also applies to inherited functions.
+The following example shows overloading of the function
+``f`` in the scope of contract ``A``.
::
@@ -643,11 +643,12 @@ This also applies to inherited functions. The following example shows overloadin
contract A {
function f(uint _in) public pure returns (uint out) {
- out = 1;
+ out = _in;
}
- function f(uint _in, bytes32 _key) public pure returns (uint out) {
- out = 2;
+ function f(uint _in, bool _really) public pure returns (uint out) {
+ if (_really)
+ out = _in;
}
}
@@ -656,9 +657,9 @@ externally visible functions differ by their Solidity types but not by their ext
::
- // This will not compile
pragma solidity ^0.4.16;
+ // This will not compile
contract A {
function f(B _in) public pure returns (B out) {
out = _in;
@@ -1037,10 +1038,12 @@ derived contracts need to specify all of them. This can be done in two ways::
constructor(uint _x) public { x = _x; }
}
+ // Either directly specify in the inheritance list...
contract Derived1 is Base(7) {
- constructor(uint _y) public {}
+ constructor() public {}
}
+ // or through a "modifier" of the derived constructor.
contract Derived2 is Base {
constructor(uint _y) Base(_y * _y) public {}
}
@@ -1079,12 +1082,11 @@ error "Linearization of inheritance graph impossible".
::
- // This will not compile
-
pragma solidity ^0.4.0;
contract X {}
contract A is X {}
+ // This will not compile
contract C is A, X {}
The reason for this is that ``C`` requests ``X`` to override ``A``
@@ -1342,6 +1344,7 @@ custom types without the overhead of external function calls:
BigInt.bigint memory x = BigInt.fromUint(7);
BigInt.bigint memory y = BigInt.fromUint(uint(-1));
BigInt.bigint memory z = x.add(y);
+ assert(z.limb(1) > 0);
}
}
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 9fd017db..def75132 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -23,8 +23,9 @@ something like::
pragma solidity ^0.4.16;
contract Simple {
- function taker(uint _a, uint _b) public pure {
- // do something with _a and _b.
+ uint sum;
+ function taker(uint _a, uint _b) public {
+ sum = _a + _b;
}
}
@@ -102,7 +103,7 @@ this nonsensical example::
pragma solidity ^0.4.16;
contract C {
- function g(uint a) public pure returns (uint ret) { return f(); }
+ function g(uint a) public pure returns (uint ret) { return a + f(); }
function f() internal pure returns (uint ret) { return g(7) + f(); }
}
@@ -158,8 +159,8 @@ throws an exception or goes out of gas.
.. warning::
Any interaction with another contract imposes a potential danger, especially
- if the source code of the contract is not known in advance. The current
- contract hands over control to the called contract and that may potentially
+ if the source code of the contract is not known in advance. The
+ current contract hands over control to the called contract and that may potentially
do just about anything. Even if the called contract inherits from a known parent contract,
the inheriting contract is only required to have a correct interface. The
implementation of the contract, however, can be completely arbitrary and thus,
@@ -184,14 +185,16 @@ parameters from the function declaration, but can be in arbitrary order.
pragma solidity ^0.4.0;
contract C {
- function f(uint key, uint value) public {
- // ...
+ mapping(uint => uint) data;
+
+ function f() public {
+ set({value: 2, key: 3});
}
- function g() public {
- // named arguments
- f({value: 2, key: 3});
+ function set(uint key, uint value) public {
+ data[key] = value;
}
+
}
Omitted Function Parameter Names
@@ -228,7 +231,7 @@ creation-dependencies are not possible.
pragma solidity >0.4.24;
contract D {
- uint x;
+ uint public x;
constructor(uint a) public payable {
x = a;
}
@@ -239,11 +242,13 @@ creation-dependencies are not possible.
function createD(uint arg) public {
D newD = new D(arg);
+ newD.x();
}
function createAndEndowD(uint arg, uint amount) public payable {
// Send ether along with the creation
D newD = (new D).value(amount)(arg);
+ newD.x();
}
}
@@ -287,12 +292,13 @@ These can then either be assigned to newly declared variables or to pre-existing
}
function g() public {
- // Variables declared with type and assigned from the returned tuple.
- (uint x, bool b, uint y) = f();
+ // Variables declared with type and assigned from the returned tuple,
+ // not all elements have to be specified (but the number must match).
+ (uint x, , uint y) = f();
// Common trick to swap values -- does not work for non-value storage types.
(x, y) = (y, x);
// Components can be left out (also for variable declarations).
- (data.length,,) = f(); // Sets the length to 7
+ (data.length, , ) = f(); // Sets the length to 7
}
}
@@ -338,11 +344,13 @@ the two variables have the same name but disjoint scopes.
contract C {
function minimalScoping() pure public {
{
- uint same2 = 0;
+ uint same;
+ same = 1;
}
{
- uint same2 = 0;
+ uint same;
+ same = 3;
}
}
}
@@ -354,6 +362,7 @@ In any case, you will get a warning about the outer variable being shadowed.
::
pragma solidity >0.4.24;
+ // This will report a warning
contract C {
function f() pure public returns (uint) {
uint x = 1;
@@ -372,9 +381,8 @@ In any case, you will get a warning about the outer variable being shadowed.
::
- // This will not compile
-
pragma solidity >0.4.24;
+ // This will not compile
contract C {
function f() pure public returns (uint) {
x = 2;
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 786c3341..b26ff527 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -62,7 +62,8 @@ Example::
contract C {
function f() public pure returns (uint8[5] memory) {
string[4] memory adaArr = ["This", "is", "an", "array"];
- return ([1, 2, 3, 4, 5]);
+ adaArr[0] = "That";
+ return [1, 2, 3, 4, 5];
}
}
@@ -186,9 +187,10 @@ If you do not want to throw, you can return a pair::
function checkCounter(uint index) public view {
(uint counter, bool error) = getCounter(index);
if (error) {
- // ...
+ // Handle the error
} else {
- // ...
+ // Do something with counter.
+ require(counter > 7, "Invalid counter value");
}
}
}
@@ -372,15 +374,14 @@ contract level) with ``arrayname.length = <some new length>;``. If you get the
::
- // This will not compile
-
pragma solidity ^0.4.18;
+ // This will not compile
contract C {
int8[] dynamicStorageArray;
int8[5] fixedStorageArray;
- function f() {
+ function f() public {
int8[] memory memArr; // Case 1
memArr.length++; // illegal
diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst
index 4bacd704..5cbb6cff 100644
--- a/docs/layout-of-source-files.rst
+++ b/docs/layout-of-source-files.rst
@@ -204,7 +204,7 @@ for the two input parameters and two returned values.
* @return s The calculated surface.
* @return p The calculated perimeter.
*/
- function rectangle(uint w, uint h) public returns (uint s, uint p) {
+ function rectangle(uint w, uint h) public pure returns (uint s, uint p) {
s = w * h;
p = 2 * (w + h);
}
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 3f054297..7d325746 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -467,22 +467,22 @@ high or low invalid bids.
uint refund;
for (uint i = 0; i < length; i++) {
- Bid storage bid = bids[msg.sender][i];
+ Bid storage bidToCheck = bids[msg.sender][i];
(uint value, bool fake, bytes32 secret) =
(_values[i], _fake[i], _secret[i]);
- if (bid.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
+ if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
// Bid was not actually revealed.
// Do not refund deposit.
continue;
}
- refund += bid.deposit;
- if (!fake && bid.deposit >= value) {
+ refund += bidToCheck.deposit;
+ if (!fake && bidToCheck.deposit >= value) {
if (placeBid(msg.sender, value))
refund -= value;
}
// Make it impossible for the sender to re-claim
// the same deposit.
- bid.blindedBid = bytes32(0);
+ bidToCheck.blindedBid = bytes32(0);
}
msg.sender.transfer(refund);
}
diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst
index 7a6317eb..ae349055 100644
--- a/docs/structure-of-a-contract.rst
+++ b/docs/structure-of-a-contract.rst
@@ -75,7 +75,7 @@ Function modifiers can be used to amend the semantics of functions in a declarat
_;
}
- function abort() public onlySeller { // Modifier usage
+ function abort() public view onlySeller { // Modifier usage
// ...
}
}
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index 53e126b4..d2de5287 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -52,31 +52,35 @@ Surround top level declarations in solidity source with two blank lines.
Yes::
+ pragma solidity ^0.4.0;
+
contract A {
- ...
+ // ...
}
contract B {
- ...
+ // ...
}
contract C {
- ...
+ // ...
}
No::
+ pragma solidity ^0.4.0;
+
contract A {
- ...
+ // ...
}
contract B {
- ...
+ // ...
}
contract C {
- ...
+ // ...
}
Within a contract surround function declarations with a single blank line.
@@ -85,30 +89,34 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu
Yes::
+ pragma solidity ^0.4.0;
+
contract A {
- function spam() public;
- function ham() public;
+ function spam() public pure;
+ function ham() public pure;
}
contract B is A {
- function spam() public {
- ...
+ function spam() public pure {
+ // ...
}
- function ham() public {
- ...
+ function ham() public pure {
+ // ...
}
}
No::
+ pragma solidity ^0.4.0;
+
contract A {
- function spam() public {
- ...
+ function spam() public pure {
+ // ...
}
- function ham() public {
- ...
+ function ham() public pure {
+ // ...
}
}
@@ -229,22 +237,24 @@ Import statements should always be placed at the top of the file.
Yes::
- import "./Owned.sol";
+ pragma solidity ^0.4.0;
+ import "./Owned.sol";
contract A {
- ...
+ // ...
}
-
contract B is Owned {
- ...
+ // ...
}
No::
+ pragma solidity ^0.4.0;
+
contract A {
- ...
+ // ...
}
@@ -252,7 +262,7 @@ No::
contract B is Owned {
- ...
+ // ...
}
Order of Functions
@@ -273,13 +283,15 @@ Within a grouping, place the ``view`` and ``pure`` functions last.
Yes::
+ pragma solidity ^0.4.0;
+
contract A {
constructor() public {
- ...
+ // ...
}
function() external {
- ...
+ // ...
}
// External functions
@@ -303,13 +315,15 @@ Yes::
No::
+ pragma solidity ^0.4.0;
+
contract A {
// External functions
// ...
function() external {
- ...
+ // ...
}
// Private functions
@@ -319,7 +333,7 @@ No::
// ...
constructor() public {
- ...
+ // ...
}
// Internal functions
@@ -397,6 +411,8 @@ should:
Yes::
+ pragma solidity ^0.4.0;
+
contract Coin {
struct Bank {
address owner;
@@ -406,6 +422,8 @@ Yes::
No::
+ pragma solidity ^0.4.0;
+
contract Coin
{
struct Bank {
@@ -705,7 +723,25 @@ manner as modifiers if the function declaration is long or hard to read.
Yes::
+ pragma solidity ^0.4.0;
+
+ // Base contracts just to make this compile
+ contract B {
+ constructor(uint) public {
+ }
+ }
+ contract C {
+ constructor(uint, uint) public {
+ }
+ }
+ contract D {
+ constructor(uint) public {
+ }
+ }
+
contract A is B, C, D {
+ uint x;
+
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
@@ -713,29 +749,50 @@ Yes::
public
{
// do something with param5
+ x = param5;
}
}
No::
+ pragma solidity ^0.4.0;
+
+ // Base contracts just to make this compile
+ contract B {
+ constructor(uint) public {
+ }
+ }
+ contract C {
+ constructor(uint, uint) public {
+ }
+ }
+ contract D {
+ constructor(uint) public {
+ }
+ }
+
contract A is B, C, D {
+ uint x;
+
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4)
public
{
- // do something with param5
+ x = param5;
}
}
- contract A is B, C, D {
+ contract X is B, C, D {
+ uint x;
+
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4)
public {
- // do something with param5
+ x = param5;
}
}
@@ -875,6 +932,8 @@ As shown in the example below, if the contract name is `Congress` and the librar
Yes::
+ pragma solidity ^0.4.0;
+
// Owned.sol
contract Owned {
address public owner;
@@ -897,11 +956,13 @@ Yes::
import "./Owned.sol";
contract Congress is Owned, TokenRecipient {
- ...
+ //...
}
No::
+ pragma solidity ^0.4.0;
+
// owned.sol
contract owned {
address public owner;
@@ -924,7 +985,7 @@ No::
import "./owned.sol";
contract Congress is owned, tokenRecipient {
- ...
+ //...
}
diff --git a/docs/types.rst b/docs/types.rst
index 7e222bc1..c216fd83 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -447,7 +447,7 @@ which returns the :ref:`ABI function selector <abi_function_selector>`::
pragma solidity ^0.4.16;
contract Selector {
- function f() public view returns (bytes4) {
+ function f() public pure returns (bytes4) {
return this.f.selector;
}
}
@@ -510,15 +510,15 @@ Another example that uses external function types::
contract Oracle {
struct Request {
bytes data;
- function(bytes memory) external callback;
+ function(uint) external callback;
}
Request[] requests;
event NewRequest(uint);
- function query(bytes memory data, function(bytes memory) external callback) public {
+ function query(bytes memory data, function(uint) external callback) public {
requests.push(Request(data, callback));
emit NewRequest(requests.length - 1);
}
- function reply(uint requestID, bytes memory response) public {
+ function reply(uint requestID, uint response) public {
// Here goes the check that the reply comes from a trusted source
requests[requestID].callback(response);
}
@@ -526,15 +526,16 @@ Another example that uses external function types::
contract OracleUser {
Oracle constant oracle = Oracle(0x1234567); // known contract
+ uint exchangeRate;
function buySomething() public {
oracle.query("USD", this.oracleResponse);
}
- function oracleResponse(bytes memory response) public {
+ function oracleResponse(uint response) public {
require(
msg.sender == address(oracle),
"Only oracle can call this."
);
- // Use the data
+ exchangeRate = response;
}
}
@@ -601,8 +602,8 @@ memory-stored reference type do not create a copy.
h(x); // calls h and creates an independent, temporary copy in memory
}
- function g(uint[] storage storageArray) internal {}
- function h(uint[] memory memoryArray) public {}
+ function g(uint[] storage) internal pure {}
+ function h(uint[] memory) public pure {}
}
Summary
@@ -659,8 +660,9 @@ Allocating Memory Arrays
^^^^^^^^^^^^^^^^^^^^^^^^
Creating arrays with variable length in memory can be done using the ``new`` keyword.
-As opposed to storage arrays, it is **not** possible to resize memory arrays by assigning to
-the ``.length`` member.
+As opposed to storage arrays, it is **not** possible to resize memory arrays (e.g. by assigning to
+the ``.length`` member). You either have to calculate the required size in advance
+or create a new memory array and copy every element.
::
@@ -670,7 +672,8 @@ the ``.length`` member.
function f(uint len) public pure {
uint[] memory a = new uint[](7);
bytes memory b = new bytes(len);
- // Here we have a.length == 7 and b.length == len
+ assert(a.length == 7);
+ assert(b.length == len);
a[6] = 8;
}
}
@@ -691,7 +694,7 @@ assigned to a variable right away.
function f() public pure {
g([uint(1), 2, 3]);
}
- function g(uint[3] memory _data) public pure {
+ function g(uint[3] memory) public pure {
// ...
}
}
@@ -706,10 +709,9 @@ possible:
::
- // This will not compile.
-
pragma solidity ^0.4.0;
+ // This will not compile.
contract C {
function f() public {
// The next line creates a type error because uint[3] memory
@@ -752,9 +754,12 @@ Members
uint[2**20] m_aLotOfIntegers;
// Note that the following is not a pair of dynamic arrays but a
// dynamic array of pairs (i.e. of fixed size arrays of length two).
+ // Because of that, T[] is always a dynamic array of T, even if T
+ // itself is an array.
bool[2][] m_pairsOfFlags;
- // newPairs is stored in memory - the default for function arguments
+ // newPairs is stored in memory - the only possibility
+ // for public function arguments
function setAllFlagPairs(bool[2][] memory newPairs) public {
// assignment to a storage array replaces the complete array
m_pairsOfFlags = newPairs;
@@ -797,6 +802,11 @@ Members
function createMemoryArray(uint size) public pure returns (bytes memory) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
+
+ // Inline arrays are always statically-sized and if you only
+ // use literals, you have to provide at least one type.
+ arrayOfPairs[0] = [uint(1), 2];
+
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
@@ -968,6 +978,7 @@ It is important to note that ``delete a`` really behaves like an assignment to `
// y is affected which is an alias to the storage object
// On the other hand: "delete y" is not valid, as assignments to local variables
// referencing storage objects can only be made from existing storage objects.
+ assert(y.length == 0);
}
}
diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py
index 1f913504..de2a4438 100755
--- a/scripts/isolate_tests.py
+++ b/scripts/isolate_tests.py
@@ -35,43 +35,26 @@ def extract_test_cases(path):
return tests
# Contract sources are indented by 4 spaces.
-# Look for `pragma solidity` and abort a line not indented properly.
-# If the comment `// This will not compile` is above the pragma,
-# the code is skipped.
+# Look for `pragma solidity`, `contract`, `library` or `interface`
+# and abort a line not indented properly.
def extract_docs_cases(path):
- # Note: this code works, because splitlines() removes empty new lines
- # and thus even if the empty new lines are missing indentation
- lines = open(path, 'rb').read().splitlines()
-
- ignore = False
inside = False
tests = []
- for l in lines:
- if inside:
- # Abort if indentation is missing
- m = re.search(r'^[^ ]+', l)
- if m:
- inside = False
- else:
- tests[-1] += l + '\n'
- else:
- m = re.search(r'^ // This will not compile', l)
- if m:
- ignore = True
-
- if ignore:
- # Abort if indentation is missing
- m = re.search(r'^[^ ]+', l)
- if m:
- ignore = False
- else:
- m = re.search(r'^ pragma solidity .*[0-9]+\.[0-9]+\.[0-9]+;$', l)
- if m:
- inside = True
- tests += [l]
-
- return tests
+ # Collect all snippets of indented blocks
+ for l in open(path, 'rb').read().splitlines():
+ if l != '':
+ if not inside and l.startswith(' '):
+ # start new test
+ tests += ['']
+ inside = l.startswith(' ')
+ if inside:
+ tests[-1] += l + '\n'
+ # Filter all tests that do not contain Solidity
+ return [
+ test for test in tests
+ if re.search(r'^ [ ]*(pragma solidity|contract |library |interface )', test, re.MULTILINE)
+ ]
def write_cases(tests):
for test in tests:
diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh
index a260da34..c9acb99a 100755
--- a/test/cmdlineTests.sh
+++ b/test/cmdlineTests.sh
@@ -43,18 +43,42 @@ function printError() { echo "$(tput setaf 1)$1$(tput sgr0)"; }
function compileFull()
{
+ local expected_exit_code=0
+ local expect_output=0
+ if [[ $1 = '-e' ]]
+ then
+ expected_exit_code=1
+ expect_output=1
+ shift;
+ fi
+ if [[ $1 = '-w' ]]
+ then
+ expect_output=1
+ shift;
+ fi
+
local files="$*"
- local output failed
+ local output
+
+ local stderr_path=$(mktemp)
set +e
- output=$( ("$SOLC" $FULLARGS $files) 2>&1 )
- failed=$?
+ "$SOLC" $FULLARGS $files >/dev/null 2>"$stderr_path"
+ local exit_code=$?
+ local errors=$(grep -v -E 'Warning: This is a pre-release compiler version|Warning: Experimental features are turned on|pragma experimental ABIEncoderV2|\^-------------------------------\^' < "$stderr_path")
set -e
+ rm "$stderr_path"
- if [ $failed -ne 0 ]
+ if [[ \
+ "$exit_code" -ne "$expected_exit_code" || \
+ ( $expect_output -eq 0 && -n "$errors" ) || \
+ ( $expect_output -ne 0 && -z "$errors" ) \
+ ]]
then
- printError "Compilation failed on:"
- echo "$output"
+ printError "Unexpected compilation result:"
+ printError "Expected failure: $expected_exit_code - Expected warning / error output: $expect_output"
+ printError "Was failure: $exit_code"
+ echo "$errors"
printError "While calling:"
echo "\"$SOLC\" $FULLARGS $files"
printError "Inside directory:"
@@ -63,22 +87,6 @@ function compileFull()
fi
}
-function compileWithoutWarning()
-{
- local files="$*"
- local output failed
-
- set +e
- output=$("$SOLC" $files 2>&1)
- failed=$?
- # Remove the pre-release warning from the compiler output
- output=$(echo "$output" | grep -v 'pre-release')
- echo "$output"
- set -e
-
- test -z "$output" -a "$failed" -eq 0
-}
-
printTask "Testing unknown options..."
(
set +e
@@ -157,7 +165,7 @@ do
then
echo " - $dir"
cd "$dir"
- compileFull *.sol */*.sol
+ compileFull -w *.sol */*.sol
cd ..
fi
done
@@ -173,8 +181,25 @@ TMPDIR=$(mktemp -d)
"$REPO_ROOT"/scripts/isolate_tests.py "$REPO_ROOT"/docs/ docs
for f in *.sol
do
+ # The contributors guide uses syntax tests, but we cannot
+ # really handle them here.
+ if grep -E 'DeclarationError:|// ----' "$f" >/dev/null
+ then
+ continue
+ fi
echo "$f"
- compileFull "$TMPDIR/$f"
+ opts=''
+ # We expect errors if explicitly stated, or if imports
+ # are used (in the style guide)
+ if grep -E "This will not compile|import \"" "$f" >/dev/null
+ then
+ opts="-e"
+ fi
+ if grep "This will report a warning" "$f" >/dev/null
+ then
+ opts="$opts -w"
+ fi
+ compileFull $opts "$TMPDIR/$f"
done
)
rm -rf "$TMPDIR"