mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #3950 from ethereum/develop
Merge develop into release for 0.4.23
This commit is contained in:
commit
124ca40dc5
@ -159,7 +159,8 @@ cache:
|
|||||||
install:
|
install:
|
||||||
- test $SOLC_INSTALL_DEPS_TRAVIS != On || (scripts/install_deps.sh)
|
- test $SOLC_INSTALL_DEPS_TRAVIS != On || (scripts/install_deps.sh)
|
||||||
- test "$TRAVIS_OS_NAME" != "linux" || (scripts/install_cmake.sh)
|
- test "$TRAVIS_OS_NAME" != "linux" || (scripts/install_cmake.sh)
|
||||||
# - if [ "$TRAVIS_BRANCH" != release -a -z "$TRAVIS_TAG" ]; then SOLC_TESTS=Off; fi
|
# Disable tests unless run on the release branch, on tags or with daily cron
|
||||||
|
#- if [ "$TRAVIS_BRANCH" != release -a -z "$TRAVIS_TAG" -a "$TRAVIS_EVENT_TYPE" != cron ]; then SOLC_TESTS=Off; fi
|
||||||
- SOLC_TESTS=Off
|
- SOLC_TESTS=Off
|
||||||
- if [ "$TRAVIS_BRANCH" = release -o -n "$TRAVIS_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
|
- if [ "$TRAVIS_BRANCH" = release -o -n "$TRAVIS_TAG" ]; then echo -n > prerelease.txt; else date -u +"nightly.%Y.%-m.%-d" > prerelease.txt; fi
|
||||||
- echo -n "$TRAVIS_COMMIT" > commit_hash.txt
|
- echo -n "$TRAVIS_COMMIT" > commit_hash.txt
|
||||||
|
@ -8,7 +8,7 @@ include(EthPolicy)
|
|||||||
eth_policy()
|
eth_policy()
|
||||||
|
|
||||||
# project name and version should be set after cmake_policy CMP0048
|
# project name and version should be set after cmake_policy CMP0048
|
||||||
set(PROJECT_VERSION "0.4.22")
|
set(PROJECT_VERSION "0.4.23")
|
||||||
project(solidity VERSION ${PROJECT_VERSION})
|
project(solidity VERSION ${PROJECT_VERSION})
|
||||||
|
|
||||||
option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF)
|
option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF)
|
||||||
|
289
CODING_STYLE.md
289
CODING_STYLE.md
@ -1,35 +1,24 @@
|
|||||||
0. Formatting
|
## 0. Formatting
|
||||||
|
|
||||||
GOLDEN RULE: Follow the style of the existing code when you make changes.
|
**GOLDEN RULE**: Follow the style of the existing code when you make changes.
|
||||||
|
|
||||||
a. Use tabs for leading indentation
|
1. Use tabs for leading indentation:
|
||||||
- tab stops are every 4 characters (only relevant for line length).
|
- tab stops are every 4 characters (only relevant for line length).
|
||||||
- One indentation level -> exactly one byte (i.e. a tab character) in the source file.
|
- one indentation level -> exactly one byte (i.e. a tab character) in the source file.
|
||||||
b. Line widths:
|
2. Line widths:
|
||||||
- Lines should be at most 99 characters wide to make diff views readable and reduce merge conflicts.
|
- Lines should be at most 99 characters wide to make diff views readable and reduce merge conflicts.
|
||||||
- Lines of comments should be formatted according to ease of viewing, but simplicity is to be preferred over beauty.
|
- Lines of comments should be formatted according to ease of viewing, but simplicity is to be preferred over beauty.
|
||||||
c. Single-statement blocks should not have braces, unless required for clarity.
|
3. Single-statement blocks should not have braces, unless required for clarity.
|
||||||
d. Never place condition bodies on same line as condition.
|
4. Never place condition bodies on same line as condition.
|
||||||
e. Space between keyword and opening parenthesis, but not following opening parenthesis or before final parenthesis.
|
5. Space between keyword and opening parenthesis, but not following opening parenthesis or before final parenthesis.
|
||||||
f. No spaces for unary operators, `->` or `.`.
|
6. No spaces for unary operators, `->` or `.`.
|
||||||
g. No space before ':' but one after it, except in the ternary operator: one on both sides.
|
7. No space before `:` but one after it, except in the ternary operator: one on both sides.
|
||||||
h. Add spaces around all other operators.
|
8. Add spaces around all other operators.
|
||||||
i. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
|
9. Braces, when used, always have their own lines and are at same indentation level as "parent" scope.
|
||||||
j. If lines are broken, a list of elements enclosed with parentheses (of any kind) and separated by a
|
10. If lines are broken, a list of elements enclosed with parentheses (of any kind) and separated by a separator (of any kind) are formatted such that there is exactly one element per line, followed by the separator, the opening parenthesis is on the first line, followed by a line break and the closing parenthesis is on a line of its own unindented). See example below.
|
||||||
separator (of any kind) are formatted such that there is exactly one element per line, followed by
|
|
||||||
the separator, the opening parenthesis is on the first line, followed by a line break and the closing
|
|
||||||
parenthesis is on a line of its own (unindented). See example below.
|
|
||||||
|
|
||||||
(WRONG)
|
Yes:
|
||||||
if( a==b[ i ] ) { printf ("Hello\n"); }
|
```cpp
|
||||||
foo->bar(someLongVariableName,
|
|
||||||
anotherLongVariableName,
|
|
||||||
anotherLongVariableName,
|
|
||||||
anotherLongVariableName,
|
|
||||||
anotherLongVariableName);
|
|
||||||
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;
|
|
||||||
|
|
||||||
(RIGHT)
|
|
||||||
if (a == b[i])
|
if (a == b[i])
|
||||||
printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'.
|
printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'.
|
||||||
foo->bar(
|
foo->bar(
|
||||||
@ -44,99 +33,92 @@ cout <<
|
|||||||
"text that talks about this and that and contains the words " <<
|
"text that talks about this and that and contains the words " <<
|
||||||
"\"lorem\" and \"ipsum\"" <<
|
"\"lorem\" and \"ipsum\"" <<
|
||||||
endl;
|
endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
No:
|
||||||
|
```cpp
|
||||||
|
if( a==b[ i ] ) { printf ("Hello\n"); }
|
||||||
|
foo->bar(someLongVariableName,
|
||||||
|
anotherLongVariableName,
|
||||||
|
anotherLongVariableName,
|
||||||
|
anotherLongVariableName,
|
||||||
|
anotherLongVariableName);
|
||||||
|
cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1. Namespaces
|
||||||
|
|
||||||
1. Namespaces;
|
1. No `using namespace` declarations in header files.
|
||||||
|
2. All symbols should be declared in a namespace except for final applications.
|
||||||
|
3. Use anonymous namespaces for helpers whose scope is a cpp file only.
|
||||||
|
4. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
|
||||||
|
|
||||||
a. No "using namespace" declarations in header files.
|
Yes:
|
||||||
b. All symbols should be declared in a namespace except for final applications.
|
```cpp
|
||||||
c. Use anonymous namespaces for helpers whose scope is a cpp file only.
|
#include <cassert>
|
||||||
d. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore.
|
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
|
||||||
|
```
|
||||||
|
|
||||||
(WRONG)
|
No:
|
||||||
|
```cpp
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
tuple<float, float> meanAndSigma(vector<float> const& _v);
|
tuple<float, float> meanAndSigma(vector<float> const& _v);
|
||||||
|
```
|
||||||
|
|
||||||
(CORRECT)
|
## 2. Preprocessor
|
||||||
#include <cassert>
|
|
||||||
std::tuple<float, float> meanAndSigma(std::vector<float> const& _v);
|
|
||||||
|
|
||||||
|
1. File comment is always at top, and includes:
|
||||||
|
- Copyright
|
||||||
|
- License (e.g. see COPYING)
|
||||||
|
2. Never use `#ifdef`/`#define`/`#endif` file guards. Prefer `#pragma` once as first line below file comment.
|
||||||
|
3. Prefer static const variable to value macros.
|
||||||
|
4. Prefer inline constexpr functions to function macros.
|
||||||
|
5. Split complex macro on multiple lines with `\`.
|
||||||
|
|
||||||
|
## 3. Capitalization
|
||||||
|
|
||||||
2. Preprocessor;
|
**GOLDEN RULE**: Preprocessor: `ALL_CAPS`; C++: `camelCase`.
|
||||||
|
|
||||||
a. File comment is always at top, and includes:
|
1. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions.
|
||||||
- Copyright.
|
2. The following entities' first alpha is upper case:
|
||||||
- License (e.g. see COPYING).
|
- Type names
|
||||||
b. Never use #ifdef/#define/#endif file guards. Prefer #pragma once as first line below file comment.
|
- Template parameters
|
||||||
c. Prefer static const variable to value macros.
|
- Enum members
|
||||||
d. Prefer inline constexpr functions to function macros.
|
|
||||||
e. Split complex macro on multiple lines with '\'.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
3. Capitalization;
|
|
||||||
|
|
||||||
GOLDEN RULE: Preprocessor: ALL_CAPS; C++: camelCase.
|
|
||||||
|
|
||||||
a. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions.
|
|
||||||
b. The following entities' first alpha is upper case:
|
|
||||||
- Type names.
|
|
||||||
- Template parameters.
|
|
||||||
- Enum members.
|
|
||||||
- static const variables that form an external API.
|
- static const variables that form an external API.
|
||||||
c. All preprocessor symbols (macros, macro arguments) in full uppercase with underscore word separation.
|
3. All preprocessor symbols (macros, macro arguments) in full uppercase with underscore word separation.
|
||||||
|
|
||||||
|
|
||||||
All other entities' first alpha is lower case.
|
All other entities' first alpha is lower case.
|
||||||
|
|
||||||
|
## 4. Variable prefixes
|
||||||
|
|
||||||
|
1. Leading underscore "_" to parameter names:
|
||||||
4. Variable prefixes:
|
|
||||||
|
|
||||||
a. Leading underscore "_" to parameter names.
|
|
||||||
- Exception: "o_parameterName" when it is used exclusively for output. See 6(f).
|
- Exception: "o_parameterName" when it is used exclusively for output. See 6(f).
|
||||||
- Exception: "io_parameterName" when it is used for both input and output. See 6(f).
|
- Exception: "io_parameterName" when it is used for both input and output. See 6(f).
|
||||||
b. Leading "g_" to global (non-const) variables.
|
2. Leading "g_" to global (non-const) variables.
|
||||||
c. Leading "s_" to static (non-const, non-global) variables.
|
3. Leading "s_" to static (non-const, non-global) variables.
|
||||||
|
|
||||||
|
## 5. Assertions
|
||||||
|
|
||||||
|
Use `solAssert` and `solUnimplementedAssert` generously to check assumptions that span across different parts of the code base, for example before dereferencing a pointer.
|
||||||
|
|
||||||
5. Assertions:
|
## 6. Declarations
|
||||||
|
|
||||||
- use `solAssert` and `solUnimplementedAssert` generously to check assumptions
|
1. {Typename} + {qualifiers} + {name}.
|
||||||
that span across different parts of the code base, for example before dereferencing
|
2. Only one per line.
|
||||||
a pointer.
|
3. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)).
|
||||||
|
4. Favour declarations close to use; don't habitually declare at top of scope ala C.
|
||||||
|
5. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move.
|
||||||
|
6. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments.
|
||||||
|
7. Use parameters of pointer type only if ``nullptr`` is a valid argument, use references otherwise. Often, ``boost::optional`` is better suited than a raw pointer.
|
||||||
|
8. Never use a macro where adequate non-preprocessor C++ can be written.
|
||||||
|
9. Only use ``auto`` if the type is very long and rather irrelevant.
|
||||||
|
10. Do not pass bools: prefer enumerations instead.
|
||||||
|
11. Prefer enum class to straight enum.
|
||||||
|
12. Always initialize POD variables, even if their value is overwritten later.
|
||||||
|
|
||||||
|
Yes:
|
||||||
6. Declarations:
|
```cpp
|
||||||
|
|
||||||
a. {Typename} + {qualifiers} + {name}.
|
|
||||||
b. Only one per line.
|
|
||||||
c. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)).
|
|
||||||
d. Favour declarations close to use; don't habitually declare at top of scope ala C.
|
|
||||||
e. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move.
|
|
||||||
f. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments.
|
|
||||||
g. Use parameters of pointer type only if ``nullptr`` is a valid argument, use references otherwise. Often, ``boost::optional`` is better suited than a raw pointer.
|
|
||||||
h. Never use a macro where adequate non-preprocessor C++ can be written.
|
|
||||||
i. Only use ``auto`` if the type is very long and rather irrelevant.
|
|
||||||
j. Do not pass bools: prefer enumerations instead.
|
|
||||||
k. Prefer enum class to straight enum.
|
|
||||||
l. Always initialize POD variables, even if their value is overwritten later.
|
|
||||||
|
|
||||||
|
|
||||||
(WRONG)
|
|
||||||
const double d = 0;
|
|
||||||
int i, j;
|
|
||||||
char *s;
|
|
||||||
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
|
|
||||||
Derived* x(dynamic_cast<Derived*>(base));
|
|
||||||
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
|
|
||||||
|
|
||||||
|
|
||||||
(CORRECT)
|
|
||||||
enum class Accuracy
|
enum class Accuracy
|
||||||
{
|
{
|
||||||
Approximate,
|
Approximate,
|
||||||
@ -154,78 +136,78 @@ char* s;
|
|||||||
MeanAndSigma ms meanAndSigma(std::vector<float> const& _v, Accuracy _a);
|
MeanAndSigma ms meanAndSigma(std::vector<float> const& _v, Accuracy _a);
|
||||||
Derived* x = dynamic_cast<Derived*>(base);
|
Derived* x = dynamic_cast<Derived*>(base);
|
||||||
for (auto i = x->begin(); i != x->end(); ++i) {}
|
for (auto i = x->begin(); i != x->end(); ++i) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
No:
|
||||||
|
```cp
|
||||||
|
const double d = 0;
|
||||||
|
int i, j;
|
||||||
|
char *s;
|
||||||
|
float meanAndSigma(std::vector<float> _v, float* _sigma, bool _approximate);
|
||||||
|
Derived* x(dynamic_cast<Derived*>(base));
|
||||||
|
for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); ++l) {}
|
||||||
|
```
|
||||||
|
|
||||||
7. Structs & classes
|
## 7. Structs & classes
|
||||||
|
|
||||||
a. Structs to be used when all members public and no virtual functions.
|
1. Structs to be used when all members public and no virtual functions:
|
||||||
- In this case, members should be named naturally and not prefixed with 'm_'
|
- In this case, members should be named naturally and not prefixed with `m_`.
|
||||||
b. Classes to be used in all other circumstances.
|
2. Classes to be used in all other circumstances.
|
||||||
|
|
||||||
|
## 8. Members
|
||||||
|
|
||||||
|
1. One member per line only.
|
||||||
8. Members:
|
2. Private, non-static, non-const fields prefixed with `m_`.
|
||||||
|
3. Avoid public fields, except in structs.
|
||||||
a. One member per line only.
|
4. Use override, final and const as much as possible.
|
||||||
b. Private, non-static, non-const fields prefixed with m_.
|
5. No implementations with the class declaration, except:
|
||||||
c. Avoid public fields, except in structs.
|
|
||||||
d. Use override, final and const as much as possible.
|
|
||||||
e. No implementations with the class declaration, except:
|
|
||||||
- template or force-inline method (though prefer implementation at bottom of header file).
|
- template or force-inline method (though prefer implementation at bottom of header file).
|
||||||
- one-line implementation (in which case include it in same line as declaration).
|
- one-line implementation (in which case include it in same line as declaration).
|
||||||
f. For a property 'foo'
|
6. For a property `foo`
|
||||||
- Member: m_foo;
|
- Member: `m_foo`
|
||||||
- Getter: foo() [ also: for booleans, isFoo() ];
|
- Getter: `foo()` [ also: for booleans, `isFoo()` ]
|
||||||
- Setter: setFoo();
|
- Setter: `setFoo()`
|
||||||
|
|
||||||
|
## 9. Naming
|
||||||
|
|
||||||
|
1. Avoid unpronouncable names.
|
||||||
9. Naming
|
2. Names should be shortened only if they are extremely common, but shortening should be generally avoided
|
||||||
|
3. Avoid prefixes of initials (e.g. do not use `IMyInterface`, `CMyImplementation`)
|
||||||
a. Avoid unpronouncable names
|
4. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments:
|
||||||
b. Names should be shortened only if they are extremely common, but shortening should be generally avoided
|
- A dictionary and thesaurus are your friends;
|
||||||
c. Avoid prefixes of initials (e.g. do not use IMyInterface, CMyImplementation)
|
- Spell correctly;
|
||||||
c. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments.
|
- Think carefully about the class's purpose;
|
||||||
- A dictionary and thesaurus are your friends.
|
- Imagine it as an isolated component to try to decontextualise it when considering its name;
|
||||||
- Spell correctly.
|
|
||||||
- Think carefully about the class's purpose.
|
|
||||||
- Imagine it as an isolated component to try to decontextualise it when considering its name.
|
|
||||||
- Don't be trapped into naming it (purely) in terms of its implementation.
|
- Don't be trapped into naming it (purely) in terms of its implementation.
|
||||||
|
|
||||||
|
## 10. Type definitions
|
||||||
|
|
||||||
|
1. Prefer `using` to `typedef`. e.g. `using ints = std::vector<int>;` rather than typedef `std::vector<int> ints;`
|
||||||
|
2. Generally avoid shortening a standard form that already includes all important information:
|
||||||
|
- e.g. stick to `shared_ptr<X>` rather than shortening to `ptr<X>`.
|
||||||
|
3. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently:
|
||||||
|
- e.g. `using Guard = std::lock_guard<std::mutex>;` ///< Guard is used throughout the codebase since it is clear in meaning and used commonly.
|
||||||
|
4. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
|
||||||
|
5. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time.
|
||||||
|
|
||||||
10. Type-definitions
|
## 11. Commenting
|
||||||
|
|
||||||
a. Prefer 'using' to 'typedef'. e.g. using ints = std::vector<int>; rather than typedef std::vector<int> ints;
|
1. Comments should be doxygen-compilable, using @notation rather than \notation.
|
||||||
b. Generally avoid shortening a standard form that already includes all important information:
|
2. Document the interface, not the implementation:
|
||||||
- e.g. stick to shared_ptr<X> rather than shortening to ptr<X>.
|
- Documentation should be able to remain completely unchanged, even if the method is reimplemented;
|
||||||
c. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently.
|
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports);
|
||||||
- e.g. using Guard = std::lock_guard<std::mutex>; ///< Guard is used throughout the codebase since it is clear in meaning and used commonly.
|
- Be careful to scrutinise documentation that extends only to intended purpose and usage;
|
||||||
d. In general expressions should be roughly as important/semantically meaningful as the space they occupy.
|
|
||||||
e. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
11. Commenting
|
|
||||||
|
|
||||||
a. Comments should be doxygen-compilable, using @notation rather than \notation.
|
|
||||||
b. Document the interface, not the implementation.
|
|
||||||
- Documentation should be able to remain completely unchanged, even if the method is reimplemented.
|
|
||||||
- Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports).
|
|
||||||
- Be careful to scrutinise documentation that extends only to intended purpose and usage.
|
|
||||||
- Reject documentation that is simply an English transaction of the implementation.
|
- Reject documentation that is simply an English transaction of the implementation.
|
||||||
c. Avoid in-code comments. Instead, try to extract blocks of functionality into functions. This often already eliminates the need for an in-code comment.
|
3. Avoid in-code comments. Instead, try to extract blocks of functionality into functions. This often already eliminates the need for an in-code comment.
|
||||||
|
|
||||||
|
## 12. Include Headers
|
||||||
|
|
||||||
12. Include Headers
|
1. Includes should go in increasing order of generality (`libsolidity` -> `libevmasm` -> `libdevcore` -> `boost` -> `STL`).
|
||||||
|
2. The corresponding `.h` file should be the first include in the respective `.cpp` file.
|
||||||
Includes should go in increasing order of generality (libsolidity -> libevmasm -> libdevcore -> boost -> STL).
|
3. Insert empty lines between blocks of include files.
|
||||||
The corresponding .h file should be the first include in the respective .cpp file.
|
|
||||||
Insert empty lines between blocks of include files.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
```cpp
|
||||||
```
|
|
||||||
#include <libsolidity/codegen/ExpressionCompiler.h>
|
#include <libsolidity/codegen/ExpressionCompiler.h>
|
||||||
|
|
||||||
#include <libsolidity/ast/AST.h>
|
#include <libsolidity/ast/AST.h>
|
||||||
@ -245,18 +227,17 @@ Example:
|
|||||||
#include <numeric>
|
#include <numeric>
|
||||||
```
|
```
|
||||||
|
|
||||||
See http://stackoverflow.com/questions/614302/c-header-order/614333#614333 for the reason: this makes it easier to find missing includes in header files.
|
See [this issue](http://stackoverflow.com/questions/614302/c-header-order/614333#614333 "C header order") for the reason: this makes it easier to find missing includes in header files.
|
||||||
|
|
||||||
|
## 13. Recommended reading
|
||||||
|
|
||||||
13. Recommended reading
|
- Herb Sutter and Bjarne Stroustrup:
|
||||||
|
- [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
|
||||||
|
|
||||||
Herb Sutter and Bjarne Stroustrup
|
- Herb Sutter and Andrei Alexandrescu:
|
||||||
- "C++ Core Guidelines" (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
|
|
||||||
|
|
||||||
Herb Sutter and Andrei Alexandrescu
|
|
||||||
- "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices"
|
- "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices"
|
||||||
|
|
||||||
Scott Meyers
|
- Scott Meyers:
|
||||||
- "Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)"
|
- "Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)"
|
||||||
- "More Effective C++: 35 New Ways to Improve Your Programs and Designs"
|
- "More Effective C++: 35 New Ways to Improve Your Programs and Designs"
|
||||||
- "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14"
|
- "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14"
|
||||||
|
14
Changelog.md
14
Changelog.md
@ -1,3 +1,16 @@
|
|||||||
|
### 0.4.23 (2018-04-19)
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* Build system: Support Ubuntu Bionic.
|
||||||
|
* SMTChecker: Integration with CVC4 SMT solver
|
||||||
|
* Syntax Checker: Warn about functions named "constructor".
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Type Checker: Improve error message for failed function overload resolution.
|
||||||
|
* Type Checker: Do not complain about new-style constructor and fallback function to have the same name.
|
||||||
|
* Type Checker: Detect multiple constructor declarations in the new syntax and old syntax.
|
||||||
|
* Type Checker: Explicit conversion of ``bytesXX`` to ``contract`` is properly disallowed.
|
||||||
|
|
||||||
### 0.4.22 (2018-04-16)
|
### 0.4.22 (2018-04-16)
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
@ -25,7 +38,6 @@ Features:
|
|||||||
* Syntax Tests: Add source locations to syntax test expectations.
|
* Syntax Tests: Add source locations to syntax test expectations.
|
||||||
* Type Checker: Improve documentation and warnings for accessing contract members inherited from ``address``.
|
* Type Checker: Improve documentation and warnings for accessing contract members inherited from ``address``.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* Code Generator: Allow ``block.blockhash`` without being called.
|
* Code Generator: Allow ``block.blockhash`` without being called.
|
||||||
* Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor.
|
* Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor.
|
||||||
|
@ -14,6 +14,6 @@ Solidity is still under development. So please do not hesitate and open an [issu
|
|||||||
See the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source) for build instructions.
|
See the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source) for build instructions.
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
Please see our contribution guidelines in [the Solidity documentation](https://solidity.readthedocs.io/en/latest/contributing.html).
|
Please see our [contribution guidelines](https://solidity.readthedocs.io/en/latest/contributing.html) in the Solidity documentation.
|
||||||
|
|
||||||
Any contributions are welcome!
|
Any contributions are welcome!
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
Checklist for making a release:
|
Checklist for making a release:
|
||||||
|
|
||||||
- [ ] Check that all "nextrelease" issues and pull requests are merged to ``develop``.
|
- [ ] Ensure that a Github project exists for the release.
|
||||||
- [ ] Create a commit in ``develop`` that updates the ``Changelog`` to include a release date (run the tests locally to update the bug list).
|
- [ ] Check that all issues and pull requests from the Github project to be released are merged to ``develop``.
|
||||||
|
- [ ] Create a commit in ``develop`` that updates the ``Changelog`` to include a release date (run ``./scripts/tests.sh`` to update the bug list). Sort the changelog entries alphabetically and correct any errors you notice.
|
||||||
- [ ] Create a pull request and wait for the tests, merge it.
|
- [ ] Create a pull request and wait for the tests, merge it.
|
||||||
- [ ] Create a pull request from ``develop`` to ``release``, wait for the tests, then merge it.
|
- [ ] Create a pull request from ``develop`` to ``release``, wait for the tests, then merge it.
|
||||||
- [ ] Make a final check that there are no platform-dependency issues in the ``solc-test-bytecode`` repository.
|
- [ ] Make a final check that there are no platform-dependency issues in the ``solc-test-bytecode`` repository.
|
||||||
@ -9,7 +10,7 @@ Checklist for making a release:
|
|||||||
- [ ] Thank voluntary contributors in the Github release page (use ``git shortlog -s -n -e origin/release..origin/develop``).
|
- [ ] Thank voluntary contributors in the Github release page (use ``git shortlog -s -n -e origin/release..origin/develop``).
|
||||||
- [ ] Wait for the CI runs on the tag itself (they should push artefacts onto the Github release page).
|
- [ ] 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).
|
- [ ] 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).
|
- [ ] Check that the Docker release was pushed to Docker Hub (this still seems to have problems, run ``./scripts/docker_deploy_manual.sh release``).
|
||||||
- [ ] Update the homebrew realease in https://github.com/ethereum/homebrew-ethereum/blob/master/solidity.rb (version and hash)
|
- [ ] Update the homebrew realease in https://github.com/ethereum/homebrew-ethereum/blob/master/solidity.rb (version and hash)
|
||||||
- [ ] Update the default version on readthedocs.
|
- [ ] Update the default version on readthedocs.
|
||||||
- [ ] Make a release of ``solc-js``: Increment the version number, create a pull request for that, merge it after tests succeeded.
|
- [ ] Make a release of ``solc-js``: Increment the version number, create a pull request for that, merge it after tests succeeded.
|
||||||
|
@ -43,27 +43,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
|
|||||||
# TODO - Track down what breaks if we do NOT do this.
|
# TODO - Track down what breaks if we do NOT do this.
|
||||||
add_compile_options(-Wno-unknown-pragmas)
|
add_compile_options(-Wno-unknown-pragmas)
|
||||||
|
|
||||||
# To get the code building on FreeBSD and Arch Linux we seem to need the following
|
|
||||||
# warning suppression to work around some issues in Boost headers.
|
|
||||||
#
|
|
||||||
# See the following reports:
|
|
||||||
# https://github.com/ethereum/webthree-umbrella/issues/384
|
|
||||||
# https://github.com/ethereum/webthree-helpers/pull/170
|
|
||||||
#
|
|
||||||
# The issue manifest as warnings-as-errors like the following:
|
|
||||||
#
|
|
||||||
# /usr/local/include/boost/multiprecision/cpp_int.hpp:181:4: error:
|
|
||||||
# right operand of shift expression '(1u << 63u)' is >= than the precision of the left operand
|
|
||||||
#
|
|
||||||
# -fpermissive is a pretty nasty way to address this. It is described as follows:
|
|
||||||
#
|
|
||||||
# Downgrade some diagnostics about nonconformant code from errors to warnings.
|
|
||||||
# Thus, using -fpermissive will allow some nonconforming code to compile.
|
|
||||||
#
|
|
||||||
# NB: Have to use this form for the setting, so that it only applies to C++ builds.
|
|
||||||
# Applying -fpermissive to a C command-line (ie. secp256k1) gives a build error.
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
|
|
||||||
|
|
||||||
# Configuration-specific compiler settings.
|
# Configuration-specific compiler settings.
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
|
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG")
|
||||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
|
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
|
||||||
@ -82,18 +61,6 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA
|
|||||||
|
|
||||||
# Additional Clang-specific compiler settings.
|
# Additional Clang-specific compiler settings.
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
|
|
||||||
# A couple of extra warnings suppressions which we seemingly
|
|
||||||
# need when building with Clang.
|
|
||||||
#
|
|
||||||
# TODO - Nail down exactly where these warnings are manifesting and
|
|
||||||
# try to suppress them in a more localized way. Notes in this file
|
|
||||||
# indicate that the first is needed for sepc256k1 and that the
|
|
||||||
# second is needed for the (clog, cwarn) macros. These will need
|
|
||||||
# testing on at least OS X and Ubuntu.
|
|
||||||
add_compile_options(-Wno-unused-function)
|
|
||||||
add_compile_options(-Wno-dangling-else)
|
|
||||||
|
|
||||||
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
|
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
|
||||||
# Set stack size to 16MB - by default Apple's clang defines a stack size of 8MB, some tests require more.
|
# Set stack size to 16MB - by default Apple's clang defines a stack size of 8MB, some tests require more.
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size -Wl,0x1000000")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size -Wl,0x1000000")
|
||||||
|
4
cmake/FindCVC4.cmake
Normal file
4
cmake/FindCVC4.cmake
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h)
|
||||||
|
find_library(CVC4_LIBRARY NAMES cvc4 )
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR)
|
3
cmake/FindGMP.cmake
Normal file
3
cmake/FindGMP.cmake
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
find_library(GMP_LIBRARY NAMES gmp )
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(GMP DEFAULT_MSG GMP_LIBRARY)
|
@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "OneOfTwoConstructorsSkipped",
|
||||||
|
"summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.",
|
||||||
|
"description": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored. There will be a compiler warning about the old-style constructor, so contracts only using new-style constructors are fine.",
|
||||||
|
"introduced": "0.4.22",
|
||||||
|
"fixed": "0.4.23",
|
||||||
|
"severity": "very low"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ZeroFunctionSelector",
|
"name": "ZeroFunctionSelector",
|
||||||
"summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.",
|
"summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.",
|
||||||
|
@ -423,9 +423,15 @@
|
|||||||
"released": "2018-03-07"
|
"released": "2018-03-07"
|
||||||
},
|
},
|
||||||
"0.4.22": {
|
"0.4.22": {
|
||||||
"bugs": [],
|
"bugs": [
|
||||||
|
"OneOfTwoConstructorsSkipped"
|
||||||
|
],
|
||||||
"released": "2018-04-16"
|
"released": "2018-04-16"
|
||||||
},
|
},
|
||||||
|
"0.4.23": {
|
||||||
|
"bugs": [],
|
||||||
|
"released": "2018-04-19"
|
||||||
|
},
|
||||||
"0.4.3": {
|
"0.4.3": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
"ZeroFunctionSelector",
|
"ZeroFunctionSelector",
|
||||||
|
@ -225,9 +225,6 @@ Minor Details
|
|||||||
=============
|
=============
|
||||||
|
|
||||||
- In ``for (var i = 0; i < arrayName.length; i++) { ... }``, the type of ``i`` will be ``uint8``, because this is the smallest type that is required to hold the value ``0``. If the array has more than 255 elements, the loop will not terminate.
|
- In ``for (var i = 0; i < arrayName.length; i++) { ... }``, the type of ``i`` will be ``uint8``, because this is the smallest type that is required to hold the value ``0``. If the array has more than 255 elements, the loop will not terminate.
|
||||||
- The ``constant`` keyword for functions is currently not enforced by the compiler.
|
|
||||||
Furthermore, it is not enforced by the EVM, so a contract function that "claims"
|
|
||||||
to be constant might still cause changes to the state.
|
|
||||||
- Types that do not occupy the full 32 bytes might contain "dirty higher order bits".
|
- Types that do not occupy the full 32 bytes might contain "dirty higher order bits".
|
||||||
This is especially important if you access ``msg.data`` - it poses a malleability risk:
|
This is especially important if you access ``msg.data`` - it poses a malleability risk:
|
||||||
You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument
|
You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument
|
||||||
@ -239,6 +236,22 @@ Minor Details
|
|||||||
Recommendations
|
Recommendations
|
||||||
***************
|
***************
|
||||||
|
|
||||||
|
Take Warnings Seriously
|
||||||
|
=======================
|
||||||
|
|
||||||
|
If the compiler warns you about something, you should better change it.
|
||||||
|
Even if you do not think that this particular warning has security
|
||||||
|
implications, there might be another issue buried beneath it.
|
||||||
|
Any compiler warning we issue can be silenced by slight changes to the
|
||||||
|
code.
|
||||||
|
|
||||||
|
Also try to enable the "0.5.0" safety features as early as possible
|
||||||
|
by adding ``pragma experimental "v0.5.0";``. Note that in this case,
|
||||||
|
the word ``experimental`` does not mean that the safety features are in any
|
||||||
|
way risky, it is just a way to enable some features that are
|
||||||
|
not yet part of the latest version of Solidity due to backwards
|
||||||
|
compatibility.
|
||||||
|
|
||||||
Restrict the Amount of Ether
|
Restrict the Amount of Ether
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
(JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 7) && (JSONCPP_VERSION_PATCH == 7),
|
||||||
|
"Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.7.7."
|
||||||
|
);
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -6,10 +6,25 @@ find_package(Z3 QUIET)
|
|||||||
if (${Z3_FOUND})
|
if (${Z3_FOUND})
|
||||||
include_directories(${Z3_INCLUDE_DIR})
|
include_directories(${Z3_INCLUDE_DIR})
|
||||||
add_definitions(-DHAVE_Z3)
|
add_definitions(-DHAVE_Z3)
|
||||||
message("Z3 SMT solver found. This enables optional SMT checking.")
|
message("Z3 SMT solver found. This enables optional SMT checking with Z3.")
|
||||||
|
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
|
||||||
else()
|
else()
|
||||||
message("Z3 SMT solver NOT found. Optional SMT checking will not be available. Please install Z3 if it is desired.")
|
|
||||||
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp")
|
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp")
|
||||||
|
find_package(GMP QUIET)
|
||||||
|
find_package(CVC4 QUIET)
|
||||||
|
if (${CVC4_FOUND})
|
||||||
|
if (${GMP_FOUND})
|
||||||
|
include_directories(${CVC4_INCLUDE_DIR})
|
||||||
|
add_definitions(-DHAVE_CVC4)
|
||||||
|
message("CVC4 SMT solver and GMP found. This enables optional SMT checking with CVC4.")
|
||||||
|
else()
|
||||||
|
message("CVC4 SMT solver found but its dependency GMP was NOT found. Optional SMT checking with CVC4 will not be available. Please install GMP if it is desired.")
|
||||||
|
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message("No SMT solver found (Z3 or CVC4). Optional SMT checking will not be available. Please install Z3 or CVC4 if it is desired.")
|
||||||
|
list(REMOVE_ITEM sources "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(solidity ${sources} ${headers})
|
add_library(solidity ${sources} ${headers})
|
||||||
@ -18,3 +33,8 @@ target_link_libraries(solidity PUBLIC evmasm devcore)
|
|||||||
if (${Z3_FOUND})
|
if (${Z3_FOUND})
|
||||||
target_link_libraries(solidity PUBLIC ${Z3_LIBRARY})
|
target_link_libraries(solidity PUBLIC ${Z3_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (${CVC4_FOUND} AND ${GMP_FOUND})
|
||||||
|
target_link_libraries(solidity PUBLIC ${CVC4_LIBRARY})
|
||||||
|
target_link_libraries(solidity PUBLIC ${GMP_LIBRARY})
|
||||||
|
endif()
|
||||||
|
@ -239,6 +239,11 @@ bool SyntaxChecker::visit(FunctionDefinition const& _function)
|
|||||||
else
|
else
|
||||||
m_errorReporter.warning(_function.location(), "Modifiers of functions without implementation are ignored." );
|
m_errorReporter.warning(_function.location(), "Modifiers of functions without implementation are ignored." );
|
||||||
}
|
}
|
||||||
|
if (_function.name() == "constructor")
|
||||||
|
m_errorReporter.warning(_function.location(),
|
||||||
|
"This function is named \"constructor\" but is not the constructor of the contract. "
|
||||||
|
"If you intend this to be a constructor, use \"constructor(...) { ... }\" without the \"function\" keyword to define it."
|
||||||
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,20 +109,11 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
m_errorReporter.typeError(function->location(), "Constructor must be public or internal.");
|
m_errorReporter.typeError(function->location(), "Constructor must be public or internal.");
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDefinition const* fallbackFunction = nullptr;
|
|
||||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||||
{
|
|
||||||
if (function->isFallback())
|
if (function->isFallback())
|
||||||
{
|
{
|
||||||
if (fallbackFunction)
|
|
||||||
{
|
|
||||||
m_errorReporter.declarationError(function->location(), "Only one fallback function is allowed.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fallbackFunction = function;
|
|
||||||
if (_contract.isLibrary())
|
if (_contract.isLibrary())
|
||||||
m_errorReporter.typeError(fallbackFunction->location(), "Libraries cannot have fallback functions.");
|
m_errorReporter.typeError(function->location(), "Libraries cannot have fallback functions.");
|
||||||
if (function->stateMutability() != StateMutability::NonPayable && function->stateMutability() != StateMutability::Payable)
|
if (function->stateMutability() != StateMutability::NonPayable && function->stateMutability() != StateMutability::Payable)
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
function->location(),
|
function->location(),
|
||||||
@ -130,17 +121,15 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
stateMutabilityToString(function->stateMutability()) +
|
stateMutabilityToString(function->stateMutability()) +
|
||||||
"\"."
|
"\"."
|
||||||
);
|
);
|
||||||
if (!fallbackFunction->parameters().empty())
|
if (!function->parameters().empty())
|
||||||
m_errorReporter.typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
|
m_errorReporter.typeError(function->parameterList().location(), "Fallback function cannot take parameters.");
|
||||||
if (!fallbackFunction->returnParameters().empty())
|
if (!function->returnParameters().empty())
|
||||||
m_errorReporter.typeError(fallbackFunction->returnParameterList()->location(), "Fallback function cannot return values.");
|
m_errorReporter.typeError(function->returnParameterList()->location(), "Fallback function cannot return values.");
|
||||||
if (
|
if (
|
||||||
_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050) &&
|
_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050) &&
|
||||||
fallbackFunction->visibility() != FunctionDefinition::Visibility::External
|
function->visibility() != FunctionDefinition::Visibility::External
|
||||||
)
|
)
|
||||||
m_errorReporter.typeError(fallbackFunction->location(), "Fallback function must be defined as \"external\".");
|
m_errorReporter.typeError(function->location(), "Fallback function must be defined as \"external\".");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& n: _contract.subNodes())
|
for (auto const& n: _contract.subNodes())
|
||||||
@ -172,24 +161,33 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
|
|||||||
/// Checks that two functions with the same name defined in this contract have different
|
/// Checks that two functions with the same name defined in this contract have different
|
||||||
/// argument types and that there is at most one constructor.
|
/// argument types and that there is at most one constructor.
|
||||||
map<string, vector<FunctionDefinition const*>> functions;
|
map<string, vector<FunctionDefinition const*>> functions;
|
||||||
|
FunctionDefinition const* constructor = nullptr;
|
||||||
|
FunctionDefinition const* fallback = nullptr;
|
||||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||||
functions[function->name()].push_back(function);
|
if (function->isConstructor())
|
||||||
|
|
||||||
// Constructor
|
|
||||||
if (functions[_contract.name()].size() > 1)
|
|
||||||
{
|
{
|
||||||
SecondarySourceLocation ssl;
|
if (constructor)
|
||||||
auto it = ++functions[_contract.name()].begin();
|
|
||||||
for (; it != functions[_contract.name()].end(); ++it)
|
|
||||||
ssl.append("Another declaration is here:", (*it)->location());
|
|
||||||
|
|
||||||
string msg = "More than one constructor defined.";
|
|
||||||
ssl.limitSize(msg);
|
|
||||||
m_errorReporter.declarationError(
|
m_errorReporter.declarationError(
|
||||||
functions[_contract.name()].front()->location(),
|
function->location(),
|
||||||
ssl,
|
SecondarySourceLocation().append("Another declaration is here:", constructor->location()),
|
||||||
msg
|
"More than one constructor defined."
|
||||||
);
|
);
|
||||||
|
constructor = function;
|
||||||
|
}
|
||||||
|
else if (function->isFallback())
|
||||||
|
{
|
||||||
|
if (fallback)
|
||||||
|
m_errorReporter.declarationError(
|
||||||
|
function->location(),
|
||||||
|
SecondarySourceLocation().append("Another declaration is here:", fallback->location()),
|
||||||
|
"Only one fallback function is allowed."
|
||||||
|
);
|
||||||
|
fallback = function;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solAssert(!function->name().empty(), "");
|
||||||
|
functions[function->name()].push_back(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
findDuplicateDefinitions(functions, "Function with same name and arguments defined twice.");
|
findDuplicateDefinitions(functions, "Function with same name and arguments defined twice.");
|
||||||
@ -1906,7 +1904,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
|||||||
// Retrieve the types of the arguments if this is used to call a function.
|
// Retrieve the types of the arguments if this is used to call a function.
|
||||||
auto const& argumentTypes = _memberAccess.annotation().argumentTypes;
|
auto const& argumentTypes = _memberAccess.annotation().argumentTypes;
|
||||||
MemberList::MemberMap possibleMembers = exprType->members(m_scope).membersByName(memberName);
|
MemberList::MemberMap possibleMembers = exprType->members(m_scope).membersByName(memberName);
|
||||||
if (possibleMembers.size() > 1 && argumentTypes)
|
size_t const initialMemberCount = possibleMembers.size();
|
||||||
|
if (initialMemberCount > 1 && argumentTypes)
|
||||||
{
|
{
|
||||||
// do overload resolution
|
// do overload resolution
|
||||||
for (auto it = possibleMembers.begin(); it != possibleMembers.end();)
|
for (auto it = possibleMembers.begin(); it != possibleMembers.end();)
|
||||||
@ -1920,6 +1919,9 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
|||||||
}
|
}
|
||||||
if (possibleMembers.size() == 0)
|
if (possibleMembers.size() == 0)
|
||||||
{
|
{
|
||||||
|
if (initialMemberCount == 0)
|
||||||
|
{
|
||||||
|
// Try to see if the member was removed because it is only available for storage types.
|
||||||
auto storageType = ReferenceType::copyForLocationIfReference(
|
auto storageType = ReferenceType::copyForLocationIfReference(
|
||||||
DataLocation::Storage,
|
DataLocation::Storage,
|
||||||
exprType
|
exprType
|
||||||
@ -1931,6 +1933,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
|||||||
exprType->toString() +
|
exprType->toString() +
|
||||||
" outside of storage."
|
" outside of storage."
|
||||||
);
|
);
|
||||||
|
}
|
||||||
m_errorReporter.fatalTypeError(
|
m_errorReporter.fatalTypeError(
|
||||||
_memberAccess.location(),
|
_memberAccess.location(),
|
||||||
"Member \"" + memberName + "\" not found or not visible "
|
"Member \"" + memberName + "\" not found or not visible "
|
||||||
|
@ -1299,7 +1299,6 @@ bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
{
|
{
|
||||||
return _convertTo.category() == Category::Integer ||
|
return _convertTo.category() == Category::Integer ||
|
||||||
_convertTo.category() == Category::FixedPoint ||
|
_convertTo.category() == Category::FixedPoint ||
|
||||||
_convertTo.category() == Category::Contract ||
|
|
||||||
_convertTo.category() == category();
|
_convertTo.category() == category();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
200
libsolidity/formal/CVC4Interface.cpp
Normal file
200
libsolidity/formal/CVC4Interface.cpp
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libsolidity/formal/CVC4Interface.h>
|
||||||
|
|
||||||
|
#include <libsolidity/interface/Exceptions.h>
|
||||||
|
|
||||||
|
#include <libdevcore/CommonIO.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace dev;
|
||||||
|
using namespace dev::solidity::smt;
|
||||||
|
|
||||||
|
CVC4Interface::CVC4Interface():
|
||||||
|
m_solver(&m_context)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVC4Interface::reset()
|
||||||
|
{
|
||||||
|
m_constants.clear();
|
||||||
|
m_functions.clear();
|
||||||
|
m_solver.reset();
|
||||||
|
m_solver.setOption("produce-models", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVC4Interface::push()
|
||||||
|
{
|
||||||
|
m_solver.push();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVC4Interface::pop()
|
||||||
|
{
|
||||||
|
m_solver.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression CVC4Interface::newFunction(string _name, Sort _domain, Sort _codomain)
|
||||||
|
{
|
||||||
|
CVC4::Type fType = m_context.mkFunctionType(cvc4Sort(_domain), cvc4Sort(_codomain));
|
||||||
|
m_functions.insert({_name, m_context.mkVar(_name.c_str(), fType)});
|
||||||
|
return SolverInterface::newFunction(move(_name), _domain, _codomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression CVC4Interface::newInteger(string _name)
|
||||||
|
{
|
||||||
|
m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.integerType())});
|
||||||
|
return SolverInterface::newInteger(move(_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression CVC4Interface::newBool(string _name)
|
||||||
|
{
|
||||||
|
m_constants.insert({_name, m_context.mkVar(_name.c_str(), m_context.booleanType())});
|
||||||
|
return SolverInterface::newBool(std::move(_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVC4Interface::addAssertion(Expression const& _expr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_solver.assertFormula(toCVC4Expr(_expr));
|
||||||
|
}
|
||||||
|
catch (CVC4::TypeCheckingException const&)
|
||||||
|
{
|
||||||
|
solAssert(false, "");
|
||||||
|
}
|
||||||
|
catch (CVC4::LogicException const&)
|
||||||
|
{
|
||||||
|
solAssert(false, "");
|
||||||
|
}
|
||||||
|
catch (CVC4::UnsafeInterruptException const&)
|
||||||
|
{
|
||||||
|
solAssert(false, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const& _expressionsToEvaluate)
|
||||||
|
{
|
||||||
|
CheckResult result;
|
||||||
|
vector<string> values;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (m_solver.checkSat().isSat())
|
||||||
|
{
|
||||||
|
case CVC4::Result::SAT:
|
||||||
|
result = CheckResult::SATISFIABLE;
|
||||||
|
break;
|
||||||
|
case CVC4::Result::UNSAT:
|
||||||
|
result = CheckResult::UNSATISFIABLE;
|
||||||
|
break;
|
||||||
|
case CVC4::Result::SAT_UNKNOWN:
|
||||||
|
result = CheckResult::UNKNOWN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
solAssert(false, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != CheckResult::UNSATISFIABLE && !_expressionsToEvaluate.empty())
|
||||||
|
{
|
||||||
|
for (Expression const& e: _expressionsToEvaluate)
|
||||||
|
values.push_back(toString(m_solver.getValue(toCVC4Expr(e))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CVC4::Exception & e)
|
||||||
|
{
|
||||||
|
result = CheckResult::ERROR;
|
||||||
|
values.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_pair(result, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
|
||||||
|
{
|
||||||
|
if (_expr.arguments.empty() && m_constants.count(_expr.name))
|
||||||
|
return m_constants.at(_expr.name);
|
||||||
|
vector<CVC4::Expr> arguments;
|
||||||
|
for (auto const& arg: _expr.arguments)
|
||||||
|
arguments.push_back(toCVC4Expr(arg));
|
||||||
|
|
||||||
|
string const& n = _expr.name;
|
||||||
|
if (m_functions.count(n))
|
||||||
|
return m_context.mkExpr(CVC4::kind::APPLY_UF, m_functions[n], arguments);
|
||||||
|
else if (m_constants.count(n))
|
||||||
|
{
|
||||||
|
solAssert(arguments.empty(), "");
|
||||||
|
return m_constants.at(n);
|
||||||
|
}
|
||||||
|
else if (arguments.empty())
|
||||||
|
{
|
||||||
|
if (n == "true")
|
||||||
|
return m_context.mkConst(true);
|
||||||
|
else if (n == "false")
|
||||||
|
return m_context.mkConst(false);
|
||||||
|
else
|
||||||
|
// We assume it is an integer...
|
||||||
|
return m_context.mkConst(CVC4::Rational(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
solAssert(_expr.hasCorrectArity(), "");
|
||||||
|
if (n == "ite")
|
||||||
|
return arguments[0].iteExpr(arguments[1], arguments[2]);
|
||||||
|
else if (n == "not")
|
||||||
|
return arguments[0].notExpr();
|
||||||
|
else if (n == "and")
|
||||||
|
return arguments[0].andExpr(arguments[1]);
|
||||||
|
else if (n == "or")
|
||||||
|
return arguments[0].orExpr(arguments[1]);
|
||||||
|
else if (n == "=")
|
||||||
|
return m_context.mkExpr(CVC4::kind::EQUAL, arguments[0], arguments[1]);
|
||||||
|
else if (n == "<")
|
||||||
|
return m_context.mkExpr(CVC4::kind::LT, arguments[0], arguments[1]);
|
||||||
|
else if (n == "<=")
|
||||||
|
return m_context.mkExpr(CVC4::kind::LEQ, arguments[0], arguments[1]);
|
||||||
|
else if (n == ">")
|
||||||
|
return m_context.mkExpr(CVC4::kind::GT, arguments[0], arguments[1]);
|
||||||
|
else if (n == ">=")
|
||||||
|
return m_context.mkExpr(CVC4::kind::GEQ, arguments[0], arguments[1]);
|
||||||
|
else if (n == "+")
|
||||||
|
return m_context.mkExpr(CVC4::kind::PLUS, arguments[0], arguments[1]);
|
||||||
|
else if (n == "-")
|
||||||
|
return m_context.mkExpr(CVC4::kind::MINUS, arguments[0], arguments[1]);
|
||||||
|
else if (n == "*")
|
||||||
|
return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]);
|
||||||
|
else if (n == "/")
|
||||||
|
return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]);
|
||||||
|
// Cannot reach here.
|
||||||
|
solAssert(false, "");
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
CVC4::Type CVC4Interface::cvc4Sort(Sort _sort)
|
||||||
|
{
|
||||||
|
switch (_sort)
|
||||||
|
{
|
||||||
|
case Sort::Bool:
|
||||||
|
return m_context.booleanType();
|
||||||
|
case Sort::Int:
|
||||||
|
return m_context.integerType();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
solAssert(false, "");
|
||||||
|
// Cannot be reached.
|
||||||
|
return m_context.integerType();
|
||||||
|
}
|
62
libsolidity/formal/CVC4Interface.h
Normal file
62
libsolidity/formal/CVC4Interface.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libsolidity/formal/SolverInterface.h>
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
#include <cvc4/cvc4.h>
|
||||||
|
|
||||||
|
namespace dev
|
||||||
|
{
|
||||||
|
namespace solidity
|
||||||
|
{
|
||||||
|
namespace smt
|
||||||
|
{
|
||||||
|
|
||||||
|
class CVC4Interface: public SolverInterface, public boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CVC4Interface();
|
||||||
|
|
||||||
|
void reset() override;
|
||||||
|
|
||||||
|
void push() override;
|
||||||
|
void pop() override;
|
||||||
|
|
||||||
|
Expression newFunction(std::string _name, Sort _domain, Sort _codomain) override;
|
||||||
|
Expression newInteger(std::string _name) override;
|
||||||
|
Expression newBool(std::string _name) override;
|
||||||
|
|
||||||
|
void addAssertion(Expression const& _expr) override;
|
||||||
|
std::pair<CheckResult, std::vector<std::string>> check(std::vector<Expression> const& _expressionsToEvaluate) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CVC4::Expr toCVC4Expr(Expression const& _expr);
|
||||||
|
CVC4::Type cvc4Sort(smt::Sort _sort);
|
||||||
|
|
||||||
|
CVC4::ExprManager m_context;
|
||||||
|
CVC4::SmtEngine m_solver;
|
||||||
|
std::map<std::string, CVC4::Expr> m_constants;
|
||||||
|
std::map<std::string, CVC4::Expr> m_functions;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
#include <libsolidity/formal/Z3Interface.h>
|
#include <libsolidity/formal/Z3Interface.h>
|
||||||
|
#elif HAVE_CVC4
|
||||||
|
#include <libsolidity/formal/CVC4Interface.h>
|
||||||
#else
|
#else
|
||||||
#include <libsolidity/formal/SMTLib2Interface.h>
|
#include <libsolidity/formal/SMTLib2Interface.h>
|
||||||
#endif
|
#endif
|
||||||
@ -39,6 +41,8 @@ using namespace dev::solidity;
|
|||||||
SMTChecker::SMTChecker(ErrorReporter& _errorReporter, ReadCallback::Callback const& _readFileCallback):
|
SMTChecker::SMTChecker(ErrorReporter& _errorReporter, ReadCallback::Callback const& _readFileCallback):
|
||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
m_interface(make_shared<smt::Z3Interface>()),
|
m_interface(make_shared<smt::Z3Interface>()),
|
||||||
|
#elif HAVE_CVC4
|
||||||
|
m_interface(make_shared<smt::CVC4Interface>()),
|
||||||
#else
|
#else
|
||||||
m_interface(make_shared<smt::SMTLib2Interface>(_readFileCallback)),
|
m_interface(make_shared<smt::SMTLib2Interface>(_readFileCallback)),
|
||||||
#endif
|
#endif
|
||||||
@ -464,7 +468,7 @@ void SMTChecker::compareOperation(BinaryOperation const& _op)
|
|||||||
}
|
}
|
||||||
else // Bool
|
else // Bool
|
||||||
{
|
{
|
||||||
solAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "");
|
solUnimplementedAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "Operation not yet supported");
|
||||||
value = make_shared<smt::Expression>(
|
value = make_shared<smt::Expression>(
|
||||||
op == Token::Equal ? (left == right) :
|
op == Token::Equal ? (left == right) :
|
||||||
op == Token::NotEqual ? (left != right) :
|
op == Token::NotEqual ? (left != right) :
|
||||||
@ -835,7 +839,7 @@ void SMTChecker::createExpr(Expression const& _e)
|
|||||||
m_expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e)));
|
m_expressions.emplace(&_e, m_interface->newBool(uniqueSymbol(_e)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
solAssert(false, "Type not implemented.");
|
solUnimplementedAssert(false, "Type not implemented.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,26 @@ public:
|
|||||||
Expression& operator=(Expression const&) = default;
|
Expression& operator=(Expression const&) = default;
|
||||||
Expression& operator=(Expression&&) = default;
|
Expression& operator=(Expression&&) = default;
|
||||||
|
|
||||||
|
bool hasCorrectArity() const
|
||||||
|
{
|
||||||
|
static std::map<std::string, unsigned> const operatorsArity{
|
||||||
|
{"ite", 3},
|
||||||
|
{"not", 1},
|
||||||
|
{"and", 2},
|
||||||
|
{"or", 2},
|
||||||
|
{"=", 2},
|
||||||
|
{"<", 2},
|
||||||
|
{"<=", 2},
|
||||||
|
{">", 2},
|
||||||
|
{">=", 2},
|
||||||
|
{"+", 2},
|
||||||
|
{"-", 2},
|
||||||
|
{"*", 2},
|
||||||
|
{"/", 2}
|
||||||
|
};
|
||||||
|
return operatorsArity.count(name) && operatorsArity.at(name) == arguments.size();
|
||||||
|
}
|
||||||
|
|
||||||
static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue)
|
static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue)
|
||||||
{
|
{
|
||||||
solAssert(_trueValue.sort == _falseValue.sort, "");
|
solAssert(_trueValue.sort == _falseValue.sort, "");
|
||||||
|
@ -116,21 +116,6 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
|
|||||||
for (auto const& arg: _expr.arguments)
|
for (auto const& arg: _expr.arguments)
|
||||||
arguments.push_back(toZ3Expr(arg));
|
arguments.push_back(toZ3Expr(arg));
|
||||||
|
|
||||||
static map<string, unsigned> arity{
|
|
||||||
{"ite", 3},
|
|
||||||
{"not", 1},
|
|
||||||
{"and", 2},
|
|
||||||
{"or", 2},
|
|
||||||
{"=", 2},
|
|
||||||
{"<", 2},
|
|
||||||
{"<=", 2},
|
|
||||||
{">", 2},
|
|
||||||
{">=", 2},
|
|
||||||
{"+", 2},
|
|
||||||
{"-", 2},
|
|
||||||
{"*", 2},
|
|
||||||
{"/", 2}
|
|
||||||
};
|
|
||||||
string const& n = _expr.name;
|
string const& n = _expr.name;
|
||||||
if (m_functions.count(n))
|
if (m_functions.count(n))
|
||||||
return m_functions.at(n)(arguments);
|
return m_functions.at(n)(arguments);
|
||||||
@ -150,7 +135,7 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
|
|||||||
return m_context.int_val(n.c_str());
|
return m_context.int_val(n.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
solAssert(arity.count(n) && arity.at(n) == arguments.size(), "");
|
solAssert(_expr.hasCorrectArity(), "");
|
||||||
if (n == "ite")
|
if (n == "ite")
|
||||||
return z3::ite(arguments[0], arguments[1], arguments[2]);
|
return z3::ite(arguments[0], arguments[1], arguments[2]);
|
||||||
else if (n == "not")
|
else if (n == "not")
|
||||||
|
@ -51,9 +51,6 @@ private:
|
|||||||
z3::expr toZ3Expr(Expression const& _expr);
|
z3::expr toZ3Expr(Expression const& _expr);
|
||||||
z3::sort z3Sort(smt::Sort _sort);
|
z3::sort z3Sort(smt::Sort _sort);
|
||||||
|
|
||||||
std::string checkSatAndGetValuesCommand(std::vector<Expression> const& _expressionsToEvaluate);
|
|
||||||
std::vector<std::string> parseValues(std::string::const_iterator _start, std::string::const_iterator _end);
|
|
||||||
|
|
||||||
z3::context m_context;
|
z3::context m_context;
|
||||||
z3::solver m_solver;
|
z3::solver m_solver;
|
||||||
std::map<std::string, z3::expr> m_constants;
|
std::map<std::string, z3::expr> m_constants;
|
||||||
|
@ -268,43 +268,39 @@ case $(uname -s) in
|
|||||||
install_z3=""
|
install_z3=""
|
||||||
case $(lsb_release -cs) in
|
case $(lsb_release -cs) in
|
||||||
trusty|qiana|rebecca|rafaela|rosa)
|
trusty|qiana|rebecca|rafaela|rosa)
|
||||||
#trusty
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Trusty Tahr (14.04)."
|
echo "Installing solidity dependencies on Ubuntu Trusty Tahr (14.04)."
|
||||||
echo "Or, you may also be running Linux Mint Qiana / Rebecca / Rafaela / Rosa (base: Ubuntu Trusty Tahr (14.04).)"
|
echo "Or, you may also be running Linux Mint Qiana / Rebecca / Rafaela / Rosa (base: Ubuntu Trusty Tahr (14.04).)"
|
||||||
;;
|
;;
|
||||||
utopic)
|
utopic)
|
||||||
#utopic
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Utopic Unicorn (14.10)."
|
echo "Installing solidity dependencies on Ubuntu Utopic Unicorn (14.10)."
|
||||||
;;
|
;;
|
||||||
vivid)
|
vivid)
|
||||||
#vivid
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Vivid Vervet (15.04)."
|
echo "Installing solidity dependencies on Ubuntu Vivid Vervet (15.04)."
|
||||||
;;
|
;;
|
||||||
wily)
|
wily)
|
||||||
#wily
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Wily Werewolf (15.10)."
|
echo "Installing solidity dependencies on Ubuntu Wily Werewolf (15.10)."
|
||||||
;;
|
;;
|
||||||
xenial|sarah|serena|sonya|sylvia)
|
xenial|sarah|serena|sonya|sylvia)
|
||||||
#xenial
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Xenial Xerus (16.04)."
|
echo "Installing solidity dependencies on Ubuntu Xenial Xerus (16.04)."
|
||||||
echo "Or, you may also be running Linux Mint Sarah / Serena / Sonya / Sylvia (base: Ubuntu Xenial Xerus (16.04).)"
|
echo "Or, you may also be running Linux Mint Sarah / Serena / Sonya / Sylvia (base: Ubuntu Xenial Xerus (16.04).)"
|
||||||
install_z3="libz3-dev"
|
install_z3="libz3-dev"
|
||||||
;;
|
;;
|
||||||
yakkety)
|
yakkety)
|
||||||
#yakkety
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Yakkety Yak (16.10)."
|
echo "Installing solidity dependencies on Ubuntu Yakkety Yak (16.10)."
|
||||||
install_z3="libz3-dev"
|
install_z3="libz3-dev"
|
||||||
;;
|
;;
|
||||||
zesty)
|
zesty)
|
||||||
#zesty
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Zesty (17.04)."
|
echo "Installing solidity dependencies on Ubuntu Zesty (17.04)."
|
||||||
install_z3="libz3-dev"
|
install_z3="libz3-dev"
|
||||||
;;
|
;;
|
||||||
artful)
|
artful)
|
||||||
#artful
|
|
||||||
echo "Installing solidity dependencies on Ubuntu Artful (17.10)."
|
echo "Installing solidity dependencies on Ubuntu Artful (17.10)."
|
||||||
install_z3="libz3-dev"
|
install_z3="libz3-dev"
|
||||||
;;
|
;;
|
||||||
|
bionic)
|
||||||
|
echo "Installing solidity dependencies on Ubuntu Bionic (18.04)."
|
||||||
|
install_z3="libz3-dev"
|
||||||
|
;;
|
||||||
betsy)
|
betsy)
|
||||||
#do not try anything for betsy.
|
#do not try anything for betsy.
|
||||||
echo "Linux Mint Betsy is not supported at the moment as it runs off of Debian."
|
echo "Linux Mint Betsy is not supported at the moment as it runs off of Debian."
|
||||||
@ -319,7 +315,7 @@ case $(uname -s) in
|
|||||||
echo "ERROR - Unknown or unsupported Ubuntu version (" $(lsb_release -cs) ")"
|
echo "ERROR - Unknown or unsupported Ubuntu version (" $(lsb_release -cs) ")"
|
||||||
echo "ERROR - This might not work, but we are trying anyway."
|
echo "ERROR - This might not work, but we are trying anyway."
|
||||||
echo "Please drop us a message at https://gitter.im/ethereum/solidity-dev."
|
echo "Please drop us a message at https://gitter.im/ethereum/solidity-dev."
|
||||||
echo "We only support Trusty, Utopic, Vivid, Wily, Xenial, Yakkety, Zesty and Artful."
|
echo "We only support Trusty, Utopic, Vivid, Wily, Xenial, Yakkety, Zesty, Artful and Bionic."
|
||||||
install_z3="libz3-dev"
|
install_z3="libz3-dev"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -54,7 +54,7 @@ keyid=703F83D0
|
|||||||
email=builds@ethereum.org
|
email=builds@ethereum.org
|
||||||
packagename=solc
|
packagename=solc
|
||||||
|
|
||||||
for distribution in trusty vivid xenial zesty artful
|
for distribution in trusty vivid xenial zesty artful bionic
|
||||||
do
|
do
|
||||||
cd /tmp/
|
cd /tmp/
|
||||||
rm -rf $distribution
|
rm -rf $distribution
|
||||||
|
@ -42,13 +42,21 @@ else
|
|||||||
log_directory=""
|
log_directory=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Running commandline tests..."
|
function printError() { echo "$(tput setaf 1)$1$(tput sgr0)"; }
|
||||||
|
function printTask() { echo "$(tput bold)$(tput setaf 2)$1$(tput sgr0)"; }
|
||||||
|
|
||||||
|
|
||||||
|
printTask "Running commandline tests..."
|
||||||
"$REPO_ROOT/test/cmdlineTests.sh" &
|
"$REPO_ROOT/test/cmdlineTests.sh" &
|
||||||
CMDLINE_PID=$!
|
CMDLINE_PID=$!
|
||||||
# Only run in parallel if this is run on CI infrastructure
|
# Only run in parallel if this is run on CI infrastructure
|
||||||
if [ -z "$CI" ]
|
if [ -z "$CI" ]
|
||||||
then
|
then
|
||||||
wait $CMDLINE_PID
|
if ! wait $CMDLINE_PID
|
||||||
|
then
|
||||||
|
printError "Commandline tests FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function download_eth()
|
function download_eth()
|
||||||
@ -112,7 +120,7 @@ for optimize in "" "--optimize"
|
|||||||
do
|
do
|
||||||
for vm in $EVM_VERSIONS
|
for vm in $EVM_VERSIONS
|
||||||
do
|
do
|
||||||
echo "--> Running tests using "$optimize" --evm-version "$vm"..."
|
printTask "--> Running tests using "$optimize" --evm-version "$vm"..."
|
||||||
log=""
|
log=""
|
||||||
if [ -n "$log_directory" ]
|
if [ -n "$log_directory" ]
|
||||||
then
|
then
|
||||||
@ -127,7 +135,11 @@ do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
wait $CMDLINE_PID
|
if ! wait $CMDLINE_PID
|
||||||
|
then
|
||||||
|
printError "Commandline tests FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
pkill "$ETH_PID" || true
|
pkill "$ETH_PID" || true
|
||||||
sleep 4
|
sleep 4
|
||||||
|
@ -35,9 +35,9 @@ for v in versions:
|
|||||||
continue
|
continue
|
||||||
versions[v]['bugs'] += [bug['name']]
|
versions[v]['bugs'] += [bug['name']]
|
||||||
|
|
||||||
with open(path + '/../docs/bugs_by_version.json', 'r+') as bugs_by_version:
|
|
||||||
old_contents = bugs_by_version.read()
|
|
||||||
new_contents = json.dumps(versions, sort_keys=True, indent=4)
|
new_contents = json.dumps(versions, sort_keys=True, indent=4)
|
||||||
bugs_by_version.seek(0)
|
with open(path + '/../docs/bugs_by_version.json', 'r') as bugs_by_version:
|
||||||
|
old_contents = bugs_by_version.read()
|
||||||
|
with open(path + '/../docs/bugs_by_version.json', 'w') as bugs_by_version:
|
||||||
bugs_by_version.write(new_contents)
|
bugs_by_version.write(new_contents)
|
||||||
sys.exit(old_contents != new_contents)
|
sys.exit(old_contents != new_contents)
|
@ -47,13 +47,6 @@ function test_truffle
|
|||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
npm install
|
npm install
|
||||||
find . -name soljson.js -exec cp "$SOLJSON" {} \;
|
find . -name soljson.js -exec cp "$SOLJSON" {} \;
|
||||||
if [ "$name" == "Zeppelin" ]; then
|
|
||||||
# Fix some things that look like bugs (only seemed to fail on Node 6 and not Node 8)
|
|
||||||
# FIXME: report upstream or to web3.js?
|
|
||||||
sed -i -e 's/let token = await ERC827TokenMock.new();//;' test/token/ERC827/ERC827Token.js
|
|
||||||
sed -i -e 's/CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0)/CappedCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, this.token.address)/' test/crowdsale/CappedCrowdsale.test.js
|
|
||||||
sed -i -e 's/RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, { from: owner })/RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, this.token.address, { from: owner })/' test/crowdsale/RefundableCrowdsale.test.js
|
|
||||||
fi
|
|
||||||
if [ "$name" == "Gnosis" ]; then
|
if [ "$name" == "Gnosis" ]; then
|
||||||
# Replace fixed-version pragmas in Gnosis (part of Consensys best practice)
|
# Replace fixed-version pragmas in Gnosis (part of Consensys best practice)
|
||||||
find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity 0/pragma solidity ^0/'
|
find contracts test -name '*.sol' -type f -print0 | xargs -0 sed -i -e 's/pragma solidity 0/pragma solidity ^0/'
|
||||||
|
@ -243,16 +243,6 @@ BOOST_AUTO_TEST_CASE(assignment_to_struct)
|
|||||||
CHECK_SUCCESS(text);
|
CHECK_SUCCESS(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(returns_in_constructor)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract test {
|
|
||||||
function test() public returns (uint a) { }
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Non-empty \"returns\" directive for constructor.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(forward_function_reference)
|
BOOST_AUTO_TEST_CASE(forward_function_reference)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -869,26 +859,6 @@ BOOST_AUTO_TEST_CASE(complex_inheritance)
|
|||||||
CHECK_SUCCESS(text);
|
CHECK_SUCCESS(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(constructor_visibility)
|
|
||||||
{
|
|
||||||
// The constructor of a base class should not be visible in the derived class
|
|
||||||
char const* text = R"(
|
|
||||||
contract A { function A() public { } }
|
|
||||||
contract B is A { function f() public { A x = A(0); } }
|
|
||||||
)";
|
|
||||||
CHECK_SUCCESS(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(overriding_constructor)
|
|
||||||
{
|
|
||||||
// It is fine to "override" constructor of a base class since it is invisible
|
|
||||||
char const* text = R"(
|
|
||||||
contract A { function A() public { } }
|
|
||||||
contract B is A { function A() public returns (uint8 r) {} }
|
|
||||||
)";
|
|
||||||
CHECK_SUCCESS(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments)
|
BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -907,35 +877,6 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments_override)
|
|||||||
CHECK_SUCCESS(text);
|
CHECK_SUCCESS(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(new_constructor_syntax)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract A { constructor() public {} }
|
|
||||||
)";
|
|
||||||
CHECK_SUCCESS_NO_WARNINGS(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(old_constructor_syntax)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract A { function A() public {} }
|
|
||||||
)";
|
|
||||||
CHECK_WARNING(
|
|
||||||
text,
|
|
||||||
"Defining constructors as functions with the same name as the contract is deprecated."
|
|
||||||
);
|
|
||||||
|
|
||||||
text = R"(
|
|
||||||
pragma experimental "v0.5.0";
|
|
||||||
contract A { function A() public {} }
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(
|
|
||||||
text,
|
|
||||||
SyntaxError,
|
|
||||||
"Functions are not allowed to have the same name as the contract."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion)
|
BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -1199,7 +1140,6 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, (vector<string>{
|
CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, (vector<string>{
|
||||||
"Function with same name and arguments defined twice.",
|
|
||||||
"Only one fallback function is"
|
"Only one fallback function is"
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -2588,17 +2528,6 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types)
|
|||||||
CHECK_ERROR(sourceCode, TypeError, "Overriding function return types differ");
|
CHECK_ERROR(sourceCode, TypeError, "Overriding function return types differ");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(multiple_constructors)
|
|
||||||
{
|
|
||||||
char const* sourceCode = R"(
|
|
||||||
contract test {
|
|
||||||
function test(uint a) public { }
|
|
||||||
function test() public {}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(sourceCode, DeclarationError, "More than one constructor defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(equal_overload)
|
BOOST_AUTO_TEST_CASE(equal_overload)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
@ -3064,21 +2993,6 @@ BOOST_AUTO_TEST_CASE(literal_strings)
|
|||||||
CHECK_SUCCESS(text);
|
CHECK_SUCCESS(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract Test {
|
|
||||||
struct S { uint8 a; mapping(uint => uint) b; uint8 c; }
|
|
||||||
S s;
|
|
||||||
function f() public {
|
|
||||||
S memory x;
|
|
||||||
x.b[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Member \"b\" is not available in struct Test.S memory outside of storage.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
|
BOOST_AUTO_TEST_CASE(string_bytes_conversion)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -3122,19 +3036,6 @@ BOOST_AUTO_TEST_CASE(library_having_variables)
|
|||||||
CHECK_ERROR(text, TypeError, "Library cannot have non-constant state variables");
|
CHECK_ERROR(text, TypeError, "Library cannot have non-constant state variables");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(library_constructor)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
library Lib {
|
|
||||||
function Lib();
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR_ALLOW_MULTI(text, TypeError, (vector<std::string>{
|
|
||||||
"Constructor cannot be defined in libraries.",
|
|
||||||
"Constructor must be implemented if declared."
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(valid_library)
|
BOOST_AUTO_TEST_CASE(valid_library)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -5030,38 +4931,6 @@ BOOST_AUTO_TEST_CASE(unsatisfied_version)
|
|||||||
BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file requires different compiler version"));
|
BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file requires different compiler version"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(invalid_constructor_statemutability)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract test {
|
|
||||||
function test() constant {}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Constructor must be payable or non-payable");
|
|
||||||
text = R"(
|
|
||||||
contract test {
|
|
||||||
function test() view {}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Constructor must be payable or non-payable");
|
|
||||||
text = R"(
|
|
||||||
contract test {
|
|
||||||
function test() pure {}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Constructor must be payable or non-payable");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(external_constructor)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract test {
|
|
||||||
function test() external {}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Constructor must be public or internal.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
|
BOOST_AUTO_TEST_CASE(invalid_array_as_statement)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -5608,50 +5477,6 @@ BOOST_AUTO_TEST_CASE(assignment_to_constant)
|
|||||||
CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
|
CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable.");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(inconstructible_internal_constructor)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract C {
|
|
||||||
function C() internal {}
|
|
||||||
}
|
|
||||||
contract D {
|
|
||||||
function f() public { var x = new C(); }
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Contract with internal constructor cannot be created directly.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(inconstructible_internal_constructor_inverted)
|
|
||||||
{
|
|
||||||
// Previously, the type information for A was not yet available at the point of
|
|
||||||
// "new A".
|
|
||||||
char const* text = R"(
|
|
||||||
contract B {
|
|
||||||
A a;
|
|
||||||
function B() public {
|
|
||||||
a = new A(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contract A {
|
|
||||||
function A(address a) internal {}
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Contract with internal constructor cannot be created directly.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(constructible_internal_constructor)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract C {
|
|
||||||
function C() internal {}
|
|
||||||
}
|
|
||||||
contract D is C {
|
|
||||||
function D() public { }
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_SUCCESS(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(return_structs)
|
BOOST_AUTO_TEST_CASE(return_structs)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -5813,19 +5638,6 @@ BOOST_AUTO_TEST_CASE(interface)
|
|||||||
CHECK_SUCCESS(text);
|
CHECK_SUCCESS(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(interface_constructor)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
interface I {
|
|
||||||
function I();
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR_ALLOW_MULTI(text, TypeError, (std::vector<std::string>{
|
|
||||||
"Constructor cannot be defined in interfaces",
|
|
||||||
"Constructor must be implemented if declared.",
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(interface_functions)
|
BOOST_AUTO_TEST_CASE(interface_functions)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
@ -6907,16 +6719,6 @@ BOOST_AUTO_TEST_CASE(builtin_reject_value)
|
|||||||
CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup");
|
CHECK_ERROR(text, TypeError, "Member \"value\" not found or not visible after argument-dependent lookup");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(constructor_without_implementation)
|
|
||||||
{
|
|
||||||
char const* text = R"(
|
|
||||||
contract C {
|
|
||||||
function C();
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
CHECK_ERROR(text, TypeError, "Constructor must be implemented if declared.");
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(large_storage_array_fine)
|
BOOST_AUTO_TEST_CASE(large_storage_array_fine)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
contract C {
|
||||||
|
constructor() internal {}
|
||||||
|
}
|
||||||
|
contract D is C {
|
||||||
|
constructor() public { }
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
function C() internal {}
|
||||||
|
}
|
||||||
|
contract D is C {
|
||||||
|
function D() public {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (14-38): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (60-82): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
@ -0,0 +1 @@
|
|||||||
|
contract A { constructor() public {} }
|
@ -0,0 +1,3 @@
|
|||||||
|
contract A { function A() public {} }
|
||||||
|
// ----
|
||||||
|
// Warning: (13-35): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
@ -0,0 +1,4 @@
|
|||||||
|
pragma experimental "v0.5.0";
|
||||||
|
contract A { function A() public {} }
|
||||||
|
// ----
|
||||||
|
// SyntaxError: (43-65): Functions are not allowed to have the same name as the contract. If you intend this to be a constructor, use "constructor(...) { ... }" to define it.
|
@ -0,0 +1,13 @@
|
|||||||
|
contract test1 {
|
||||||
|
constructor() constant {}
|
||||||
|
}
|
||||||
|
contract test2 {
|
||||||
|
constructor() view {}
|
||||||
|
}
|
||||||
|
contract test3 {
|
||||||
|
constructor() pure {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (19-44): Constructor must be payable or non-payable, but is "view".
|
||||||
|
// TypeError: (66-87): Constructor must be payable or non-payable, but is "view".
|
||||||
|
// TypeError: (109-130): Constructor must be payable or non-payable, but is "pure".
|
@ -0,0 +1,16 @@
|
|||||||
|
contract test1 {
|
||||||
|
function test1() constant {}
|
||||||
|
}
|
||||||
|
contract test2 {
|
||||||
|
function test2() view {}
|
||||||
|
}
|
||||||
|
contract test3 {
|
||||||
|
function test3() pure {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (21-49): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (73-97): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (121-145): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (21-49): Constructor must be payable or non-payable, but is "view".
|
||||||
|
// TypeError: (73-97): Constructor must be payable or non-payable, but is "view".
|
||||||
|
// TypeError: (121-145): Constructor must be payable or non-payable, but is "pure".
|
@ -0,0 +1,12 @@
|
|||||||
|
// The constructor of a base class should not be visible in the derived class
|
||||||
|
contract A { constructor(string) public { } }
|
||||||
|
contract B is A {
|
||||||
|
function f() pure public {
|
||||||
|
A x = A(0); // convert from address
|
||||||
|
string memory y = "ab";
|
||||||
|
A(y); // call as a function is invalid
|
||||||
|
x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (243-247): Explicit type conversion not allowed from "string memory" to "contract A".
|
@ -0,0 +1,13 @@
|
|||||||
|
// The constructor of a base class should not be visible in the derived class
|
||||||
|
contract A { function A(string s) public { } }
|
||||||
|
contract B is A {
|
||||||
|
function f() pure public {
|
||||||
|
A x = A(0); // convert from address
|
||||||
|
string memory y = "ab";
|
||||||
|
A(y); // call as a function is invalid
|
||||||
|
x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (91-122): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (244-248): Explicit type conversion not allowed from "string memory" to "contract A".
|
@ -0,0 +1,5 @@
|
|||||||
|
contract C {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (14-28): Constructor must be implemented if declared.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract C {
|
||||||
|
function C();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (14-27): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (14-27): Constructor must be implemented if declared.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
constructor() external {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (17-42): Constructor must be public or internal.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function test() external {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (17-44): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (17-44): Constructor must be public or internal.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract C {
|
||||||
|
function constructor() public;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (17-47): This function is named "constructor" but is not the constructor of the contract. If you intend this to be a constructor, use "constructor(...) { ... }" without the "function" keyword to define it.
|
@ -0,0 +1,13 @@
|
|||||||
|
// Previously, the type information for A was not yet available at the point of
|
||||||
|
// "new A".
|
||||||
|
contract B {
|
||||||
|
A a;
|
||||||
|
constructor() public {
|
||||||
|
a = new A(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract A {
|
||||||
|
constructor(address a) internal {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (141-146): Contract with internal constructor cannot be created directly.
|
@ -0,0 +1,15 @@
|
|||||||
|
// Previously, the type information for A was not yet available at the point of
|
||||||
|
// "new A".
|
||||||
|
contract B {
|
||||||
|
A a;
|
||||||
|
function B() public {
|
||||||
|
a = new A(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract A {
|
||||||
|
function A(address a) internal {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (112-155): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (172-205): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (140-145): Contract with internal constructor cannot be created directly.
|
@ -0,0 +1,8 @@
|
|||||||
|
contract C {
|
||||||
|
constructor() internal {}
|
||||||
|
}
|
||||||
|
contract D {
|
||||||
|
function f() public { C c = new C(); c; }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (84-89): Contract with internal constructor cannot be created directly.
|
@ -0,0 +1,9 @@
|
|||||||
|
contract C {
|
||||||
|
function C() internal {}
|
||||||
|
}
|
||||||
|
contract D {
|
||||||
|
function f() public { C x = new C(); x; }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (14-38): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (83-88): Contract with internal constructor cannot be created directly.
|
@ -0,0 +1,7 @@
|
|||||||
|
interface I {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (15-29): Functions in interfaces should be declared external.
|
||||||
|
// TypeError: (15-29): Constructor cannot be defined in interfaces.
|
||||||
|
// TypeError: (15-29): Constructor must be implemented if declared.
|
@ -0,0 +1,8 @@
|
|||||||
|
interface I {
|
||||||
|
function I();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (15-28): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (15-28): Functions in interfaces should be declared external.
|
||||||
|
// TypeError: (15-28): Constructor cannot be defined in interfaces.
|
||||||
|
// TypeError: (15-28): Constructor must be implemented if declared.
|
@ -0,0 +1,6 @@
|
|||||||
|
library Lib {
|
||||||
|
constructor();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (15-29): Constructor cannot be defined in libraries.
|
||||||
|
// TypeError: (15-29): Constructor must be implemented if declared.
|
@ -0,0 +1,7 @@
|
|||||||
|
library Lib {
|
||||||
|
function Lib();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (15-30): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (15-30): Constructor cannot be defined in libraries.
|
||||||
|
// TypeError: (15-30): Constructor must be implemented if declared.
|
@ -0,0 +1,6 @@
|
|||||||
|
// It is fine to "override" constructor of a base class since it is invisible
|
||||||
|
contract A { function A() public { } }
|
||||||
|
contract B is A { function A() public pure returns (uint8) {} }
|
||||||
|
// ----
|
||||||
|
// Warning: (91-114): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (135-178): This declaration shadows an existing declaration.
|
@ -0,0 +1,5 @@
|
|||||||
|
contract test {
|
||||||
|
constructor() public returns (uint a) { }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (46-54): Non-empty "returns" directive for constructor.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
function test() public returns (uint a) { }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (17-60): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// TypeError: (48-56): Non-empty "returns" directive for constructor.
|
@ -0,0 +1,7 @@
|
|||||||
|
contract test {
|
||||||
|
function test(uint) public { }
|
||||||
|
constructor() public {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (17-47): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// DeclarationError: (49-72): More than one constructor defined.
|
@ -0,0 +1,6 @@
|
|||||||
|
contract test {
|
||||||
|
constructor(uint) public { }
|
||||||
|
constructor() public {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError: (47-70): More than one constructor defined.
|
@ -0,0 +1,8 @@
|
|||||||
|
contract test {
|
||||||
|
function test(uint a) public { }
|
||||||
|
function test() public {}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (17-49): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// Warning: (51-76): Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
|
||||||
|
// DeclarationError: (51-76): More than one constructor defined.
|
@ -0,0 +1,7 @@
|
|||||||
|
contract C {
|
||||||
|
function f(uint, uint) {}
|
||||||
|
function f(uint) {}
|
||||||
|
function g() { f(1, 2, 3); }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (80-81): No matching declaration found after argument-dependent lookup.
|
@ -0,0 +1,9 @@
|
|||||||
|
library L {
|
||||||
|
function f(uint, uint) {}
|
||||||
|
function f(uint) {}
|
||||||
|
}
|
||||||
|
contract C {
|
||||||
|
function g() { L.f(1, 2, 3); }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (94-97): Member "f" not found or not visible after argument-dependent lookup in type(library L)
|
@ -0,0 +1,10 @@
|
|||||||
|
contract Test {
|
||||||
|
struct S { uint8 a; mapping(uint => uint) b; uint8 c; }
|
||||||
|
S s;
|
||||||
|
function f() public {
|
||||||
|
S memory x;
|
||||||
|
x.b[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (118-121): Member "b" is not available in struct Test.S memory outside of storage.
|
@ -0,0 +1,8 @@
|
|||||||
|
contract Test {
|
||||||
|
function f() public pure {
|
||||||
|
uint[] memory x;
|
||||||
|
x.push(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (77-83): Member "push" is not available in uint256[] memory outside of storage.
|
7
test/libsolidity/syntaxTests/types/bytes_to_contract.sol
Normal file
7
test/libsolidity/syntaxTests/types/bytes_to_contract.sol
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
C(bytes20(0x1234));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (64-82): Explicit type conversion not allowed from "bytes20" to "contract C".
|
Loading…
Reference in New Issue
Block a user