diff options
13 files changed, 139 insertions, 27 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst index b9179b27..470d775e 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1210,6 +1210,8 @@ Abstract contracts are useful in the same way that defining methods in an interf .. index:: ! contract;interface, ! interface contract +.. _interfaces: + ********** Interfaces ********** diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 34806f4a..3332a83b 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -35,13 +35,15 @@ npm / Node.js ============= Use `npm` for a convenient and portable way to install `solcjs`, a Solidity compiler. The -`solcjs` program has fewer features than all options further down this page. Our +`solcjs` program has fewer features than the ways to access the compiler described +further down this page. The :ref:`commandline-compiler` documentation assumes you are using -the full-featured compiler, `solc`. So if you install `solcjs` from `npm` then you will -stop reading the documentation here and then continue to `solc-js <https://github.com/ethereum/solc-js>`_. +the full-featured compiler, `solc`. The usage of `solcjs` is documented inside its own +`repository <https://github.com/ethereum/solc-js>`_. Note: The solc-js project is derived from the C++ -`solc` by using Emscripten. `solc-js` can be used in JavaScript projects directly (such as Remix). +`solc` by using Emscripten which means that both use the same compiler source code. +`solc-js` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. .. code-block:: bash @@ -50,7 +52,7 @@ Please refer to the solc-js repository for instructions. .. note:: - The commandline is named `solcjs`. + The commandline executable is named `solcjs`. The comandline options of `solcjs` are not compatible with `solc` and tools (such as `geth`) expecting the behaviour of `solc` will not work with `solcjs`. @@ -76,7 +78,8 @@ Binary Packages Binary packages of Solidity are available at `solidity/releases <https://github.com/ethereum/solidity/releases>`_. -We also have PPAs for Ubuntu. For the latest stable version. +We also have PPAs for Ubuntu, you can get the latest stable +version using the following commands: .. code-block:: bash @@ -84,7 +87,7 @@ We also have PPAs for Ubuntu. For the latest stable version. sudo apt-get update sudo apt-get install solc -If you want to use the cutting edge developer version: +The nightly version can be installed using these commands: .. code-block:: bash @@ -99,7 +102,8 @@ We are also releasing a `snap package <https://snapcraft.io/>`_, which is instal sudo snap install solc -Or if you want to help testing the unstable solc with the most recent changes from the development branch: +If you want to help testing the latest development version of Solidity +with the most recent changes, please use the following: .. code-block:: bash @@ -111,10 +115,9 @@ Arch Linux also has packages, albeit limited to the latest development version: pacman -S solidity -Homebrew is missing pre-built bottles at the time of writing, -following a Jenkins to TravisCI migration, but Homebrew -should still work just fine as a means to build-from-source. -We will re-add the pre-built bottles soon. +We distribute the Solidity compiler through Homebrow +as a build-from-source version. Pre-built bottles are +currently not supported. .. code-block:: bash @@ -166,7 +169,6 @@ you should fork Solidity and add your personal fork as a second remote: .. code-block:: bash - cd solidity git remote add personal git@github.com:[username]/solidity.git Solidity has git submodules. Ensure they are properly loaded: @@ -240,9 +242,8 @@ in Visual Studio 2017 Build Tools or Visual Studio 2017: External Dependencies --------------------- -We now have a "one button" script which installs all required external dependencies -on macOS, Windows and on numerous Linux distros. This used to be a multi-step -manual process, but is now a one-liner: +We have a helper script which installs all required external dependencies +on macOS, Windows and on numerous Linux distros. .. code-block:: bash @@ -261,6 +262,8 @@ Command-Line Build **Be sure to install External Dependencies (see above) before build.** Solidity project uses CMake to configure the build. +You might want to install ccache to speed up repeated builds. +CMake will pick it up automatically. Building Solidity is quite similar on Linux, macOS and other Unices: .. code-block:: bash @@ -276,7 +279,7 @@ or even easier: #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh -And even for Windows: +And for Windows: .. code-block:: bash @@ -329,7 +332,7 @@ The Solidity version string contains four parts: - the version number - pre-release tag, usually set to ``develop.YYYY.MM.DD`` or ``nightly.YYYY.MM.DD`` - commit in the format of ``commit.GITHASH`` -- platform has arbitrary number of items, containing details about the platform and compiler +- platform, which has an arbitrary number of items, containing details about the platform and compiler If there are local modifications, the commit will be postfixed with ``.mod``. diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index c1a1669a..b88e7e45 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -56,18 +56,27 @@ At a global level, you can use import statements of the following form: This statement imports all global symbols from "filename" (and symbols imported there) into the current global scope (different than in ES6 but backwards-compatible for Solidity). +This simple form is not recommended for use, because it pollutes the namespace in an +unpredictable way: If you add new top-level items inside "filename", they will automatically +appear in all files that import like this from "filename". It is better to import specific +symbols explicitly. + +The following example creates a new global symbol ``symbolName`` whose members are all +the global symbols from ``"filename"``. :: import * as symbolName from "filename"; -...creates a new global symbol ``symbolName`` whose members are all the global symbols from ``"filename"``. +If there is a naming collision, you can also rename symbols while importing. +This code +creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from inside ``"filename"``, respectively. :: import {symbol1 as alias, symbol2} from "filename"; -...creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from ``"filename"``, respectively. + Another syntax is not part of ES6, but probably convenient: @@ -93,6 +102,11 @@ It depends on the compiler (see below) how to actually resolve the paths. In general, the directory hierarchy does not need to strictly map onto your local filesystem, it can also map to resources discovered via e.g. ipfs, http or git. +.. note:: + Always use relative imports like ``import "./filename.sol";`` and avoid + using ``..`` in path specifiers. In the latter case, it is probably better to use + global paths and set up remappings as explained below. + Use in Actual Compilers ----------------------- @@ -181,6 +195,11 @@ Single-line comments (``//``) and multi-line comments (``/*...*/``) are possible multi-line comment. */ +.. note:: + A single-line comment is terminated by any unicode line terminator + (LF, VF, FF, CR, NEL, LS or PS) in utf8 encoding. The terminator is still part of + the source code after the comment, so if it is not an ascii symbol + (these are NEL, LS and PS), it will lead to a parser error. Additionally, there is another type of comment called a natspec comment, for which the documentation is not yet written. They are written with a diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index ae349055..1b4a6c55 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -11,6 +11,11 @@ Each contract can contain declarations of :ref:`structure-state-variables`, :ref :ref:`structure-function-modifiers`, :ref:`structure-events`, :ref:`structure-struct-types` and :ref:`structure-enum-types`. Furthermore, contracts can inherit from other contracts. +There are also special kinds of contracts called :ref:`libraries<libraries>` and :ref:`interfaces<interfaces>`. + +The section about :ref:`contracts<contracts>` contains more details than this section, +which serves to provide a quick overview. + .. _structure-state-variables: State Variables @@ -49,7 +54,7 @@ Functions are the executable units of code within a contract. } :ref:`function-calls` can happen internally or externally -and have different levels of visibility (:ref:`visibility-and-getters`) +and have different levels of :ref:`visibility<visibility-and-getters>` towards other contracts. .. _structure-function-modifiers: @@ -58,7 +63,7 @@ Function Modifiers ================== Function modifiers can be used to amend the semantics of functions in a declarative way -(see :ref:`modifiers` in contracts section). +(see :ref:`modifiers` in the contracts section). :: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 13294476..3056561b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1733,8 +1733,23 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) DataLocation dataLoc = DataLocation::Memory; if (auto argRefType = dynamic_cast<ReferenceType const*>(argType.get())) dataLoc = argRefType->location(); - resultType = ReferenceType::copyForLocationIfReference(dataLoc, resultType); - if (!argType->isExplicitlyConvertibleTo(*resultType)) + if (auto type = dynamic_cast<ReferenceType const*>(resultType.get())) + resultType = type->copyForLocation(dataLoc, type->isPointer()); + if (argType->isExplicitlyConvertibleTo(*resultType)) + { + if (auto argArrayType = dynamic_cast<ArrayType const*>(argType.get())) + { + auto resultArrayType = dynamic_cast<ArrayType const*>(resultType.get()); + solAssert(!!resultArrayType, ""); + solAssert( + argArrayType->location() != DataLocation::Storage || + ((resultArrayType->isPointer() || (argArrayType->isByteArray() && resultArrayType->isByteArray())) && + resultArrayType->location() == DataLocation::Storage), + "Invalid explicit conversion to storage type." + ); + } + } + else { if (resultType->category() == Type::Category::Contract && argType->category() == Type::Category::Address) { diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py index 06e9f9ea..8a9aa0a7 100755 --- a/scripts/isolate_tests.py +++ b/scripts/isolate_tests.py @@ -56,9 +56,10 @@ def extract_docs_cases(path): if re.search(r'^ [ ]*(pragma solidity|contract |library |interface )', test, re.MULTILINE) ] -def write_cases(tests): +def write_cases(f, tests): + cleaned_filename = f.replace(".","_").replace("-","_").replace(" ","_").lower() for test in tests: - open('test_%s.sol' % hashlib.sha256(test).hexdigest(), 'wb').write(test) + open('test_%s_%s.sol' % (hashlib.sha256(test).hexdigest(), cleaned_filename), 'wb').write(test) def extract_and_write(f, path): @@ -69,7 +70,7 @@ def extract_and_write(f, path): cases = [open(path, 'r').read()] else: cases = extract_test_cases(path) - write_cases(cases) + write_cases(f, cases) if __name__ == '__main__': path = sys.argv[1] diff --git a/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol new file mode 100644 index 00000000..78c40e53 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_bytes_array.sol @@ -0,0 +1,9 @@ +contract C { + bytes a; + bytes b; + function f() public view { + bytes storage c = a; + bytes memory d = b; + d = bytes(c); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol new file mode 100644 index 00000000..f7e96f35 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/allowed_conversion_to_string.sol @@ -0,0 +1,9 @@ +contract C { + string a; + string b; + function f() public view { + string storage c = a; + string memory d = b; + d = string(c); + } +} diff --git a/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol b/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol new file mode 100644 index 00000000..458adda6 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/explicit_conversion_from_storage_array_ref.sol @@ -0,0 +1,10 @@ +contract C { + int[10] x; + function f() public view { + int[](x); + int(x); + } +} +// ---- +// TypeError: (55-63): Explicit type conversion not allowed from "int256[10] storage ref" to "int256[] storage pointer". +// TypeError: (67-73): Explicit type conversion not allowed from "int256[10] storage ref" to "int256". diff --git a/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol b/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol new file mode 100644 index 00000000..31e298d0 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/implicit_conversion_from_storage_array_ref.sol @@ -0,0 +1,7 @@ +contract C { + int[10] x; + int[] y; + function f() public { + y = x; + } +} diff --git a/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol new file mode 100644 index 00000000..3aa59612 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer1.sol @@ -0,0 +1,10 @@ +contract C { + uint[] a; + uint[] b; + function f() public view { + uint[] storage c = a; + uint[] storage d = b; + d = uint[](c); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol new file mode 100644 index 00000000..060c9707 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/not_allowed_conversion_to_int_array_pointer2.sol @@ -0,0 +1,10 @@ +contract C { + uint[] a; + uint[] b; + function f() public view { + uint[] storage c = a; + uint[] memory d = b; + d = uint[](c); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol b/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol new file mode 100644 index 00000000..a441b540 --- /dev/null +++ b/test/libsolidity/syntaxTests/dataLocations/memory_storage_data_location.sol @@ -0,0 +1,12 @@ +contract C { + int[] x; + function f() public { + int[] storage a = x; + int[] memory b; + a = b; + a = int[](b); + } +} +// ---- +// TypeError: (93-94): Type int256[] memory is not implicitly convertible to expected type int256[] storage pointer. +// TypeError: (102-110): Type int256[] memory is not implicitly convertible to expected type int256[] storage pointer. |