diff options
99 files changed, 1388 insertions, 986 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 4514626b..aec8be18 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -179,6 +179,15 @@ jobs: name: Check spelling command: ~/.local/bin/codespell -S "*.enc,.git" -I ./scripts/codespell_whitelist.txt + test_trailing_whitespace: + docker: + - image: buildpack-deps:artful + steps: + - checkout + - run: + name: Check for trailing whitespace + command: ./scripts/detect_trailing_whitespace.sh + test_buglist: docker: - image: circleci/node @@ -263,6 +272,7 @@ workflows: build_all: jobs: - test_check_spelling: *build_on_tags + - test_trailing_whitespace: *build_on_tags - test_buglist: *build_on_tags - build_emscripten: *build_on_tags - test_emscripten_solcjs: diff --git a/.travis.yml b/.travis.yml index 8487deef..ef4f8b39 100644 --- a/.travis.yml +++ b/.travis.yml @@ -184,7 +184,7 @@ deploy: # Both the build and deploy steps for Emscripten are only run within the Ubuntu # configurations (not for macOS). That is controlled by conditionals within the bash # scripts because TravisCI doesn't provide much in the way of conditional logic. - + - provider: script script: test $SOLC_EMSCRIPTEN != On || (scripts/release_emscripten.sh) skip_cleanup: true diff --git a/CODING_STYLE.md b/CODING_STYLE.md index f36503d0..8101db0c 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -193,7 +193,7 @@ for (map<ComplexTypeOne, ComplexTypeTwo>::iterator i = l.begin(); i != l.end(); 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. + - 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. diff --git a/Changelog.md b/Changelog.md index c61d1007..8760b818 100644 --- a/Changelog.md +++ b/Changelog.md @@ -69,6 +69,7 @@ Breaking Changes: * Syntax Checker: Named return values in function types are an error. * Syntax Checker: Strictly require visibility specifier for functions. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Disallow unary ``+``. This was already the case in the experimental 0.5.0 mode. + * Syntax Checker: Disallow single statement variable declaration inside if/while/for bodies that are not blocks. * View Pure Checker: Strictly enfore state mutability. This was already the case in the experimental 0.5.0 mode. Language Features: @@ -113,6 +114,7 @@ Bugfixes: * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. * Type Checker: Dynamic types as key for public mappings return error instead of assertion fail. * Type System: Allow arbitrary exponents for literals with a mantissa of zero. + * Parser: Fix incorrect source location for nameless parameters. ### 0.4.24 (2018-05-16) @@ -39,7 +39,7 @@ contract HelloWorld { To get started with Solidity, you can use [Remix](https://remix.ethereum.org/), which is an browser-based IDE. Here are some example contracts: -1. [Voting](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#voting) +1. [Voting](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#voting) 2. [Blind Auction](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#blind-auction) 3. [Safe remote purchase](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#safe-remote-purchase) 4. [Micropayment Channel](https://solidity.readthedocs.io/en/v0.4.24/solidity-by-example.html#micropayment-channel) diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake index 9147a1b4..3fb6beb2 100644 --- a/cmake/scripts/buildinfo.cmake +++ b/cmake/scripts/buildinfo.cmake @@ -1,5 +1,5 @@ # generates BuildInfo.h -# +# # this module expects # ETH_SOURCE_DIR - main CMAKE_SOURCE_DIR # ETH_DST_DIR - main CMAKE_BINARY_DIR diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 560b6fa9..ab200036 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,565 +1,565 @@ { "0.1.0": { "bugs": [ - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-07-10" - }, + }, "0.1.1": { "bugs": [ - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-08-04" - }, + }, "0.1.2": { "bugs": [ - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-08-20" - }, + }, "0.1.3": { "bugs": [ - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-09-25" - }, + }, "0.1.4": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-09-30" - }, + }, "0.1.5": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-10-07" - }, + }, "0.1.6": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-10-16" - }, + }, "0.1.7": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-11-17" - }, + }, "0.2.0": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2015-12-02" - }, + }, "0.2.1": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2016-01-30" - }, + }, "0.2.2": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", - "ArrayAccessCleanHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", "AncientCompiler" - ], + ], "released": "2016-02-17" - }, + }, "0.3.0": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", - "CleanBytesHigherOrderBits", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits" - ], + ], "released": "2016-03-11" - }, + }, "0.3.1": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits" - ], + ], "released": "2016-03-31" - }, + }, "0.3.2": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", - "OptimizerClearStateOnCodePathJoin", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits" - ], + ], "released": "2016-04-18" - }, + }, "0.3.3": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" - ], + ], "released": "2016-05-27" - }, + }, "0.3.4": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" - ], + ], "released": "2016-05-31" - }, + }, "0.3.5": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", - "SendFailsForZeroEther", - "DynamicAllocationInfiniteLoop", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" - ], + ], "released": "2016-06-10" - }, + }, "0.3.6": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther" - ], + ], "released": "2016-08-10" - }, + }, "0.4.0": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", "LibrariesNotCallableFromPayableFunctions" - ], + ], "released": "2016-09-08" - }, + }, "0.4.1": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", - "OptimizerStaleKnowledgeAboutSHA3", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", "LibrariesNotCallableFromPayableFunctions" - ], + ], "released": "2016-09-09" - }, + }, "0.4.10": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2017-03-15" - }, + }, "0.4.11": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", "SkipEmptyStringLiteral" - ], + ], "released": "2017-05-03" - }, + }, "0.4.12": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", "ECRecoverMalformedInput" - ], + ], "released": "2017-07-03" - }, + }, "0.4.13": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", "ECRecoverMalformedInput" - ], + ], "released": "2017-07-06" - }, + }, "0.4.14": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", "DelegateCallReturnValue" - ], + ], "released": "2017-07-31" - }, + }, "0.4.15": { "bugs": [ - "NestedArrayFunctionCallDecoder", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" - ], + ], "released": "2017-08-08" - }, + }, "0.4.16": { "bugs": [ - "NestedArrayFunctionCallDecoder", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" - ], + ], "released": "2017-08-24" - }, + }, "0.4.17": { "bugs": [ - "EventStructWrongData", - "NestedArrayFunctionCallDecoder", + "EventStructWrongData", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" - ], + ], "released": "2017-09-21" - }, + }, "0.4.18": { "bugs": [ - "EventStructWrongData", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2017-10-18" - }, + }, "0.4.19": { "bugs": [ - "EventStructWrongData", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2017-11-30" - }, + }, "0.4.2": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", - "HighOrderByteCleanStorage", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3" - ], + ], "released": "2016-09-17" - }, + }, "0.4.20": { "bugs": [ - "EventStructWrongData", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2018-02-14" - }, + }, "0.4.21": { "bugs": [ - "EventStructWrongData", + "EventStructWrongData", "NestedArrayFunctionCallDecoder" - ], + ], "released": "2018-03-07" - }, + }, "0.4.22": { "bugs": [ - "EventStructWrongData", + "EventStructWrongData", "OneOfTwoConstructorsSkipped" - ], + ], "released": "2018-04-16" - }, + }, "0.4.23": { "bugs": [ "EventStructWrongData" - ], + ], "released": "2018-04-19" - }, + }, "0.4.24": { "bugs": [ "EventStructWrongData" - ], + ], "released": "2018-05-16" - }, + }, "0.4.3": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage" - ], + ], "released": "2016-10-25" - }, + }, "0.4.4": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" - ], + ], "released": "2016-10-31" - }, + }, "0.4.5": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", - "IdentityPrecompileReturnIgnored", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", "OptimizerStateKnowledgeNotResetForJumpdest" - ], + ], "released": "2016-11-21" - }, + }, "0.4.6": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", - "ConstantOptimizerSubtraction", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" - ], + ], "released": "2016-11-22" - }, + }, "0.4.7": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2016-12-15" - }, + }, "0.4.8": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2017-01-13" - }, + }, "0.4.9": { "bugs": [ - "NestedArrayFunctionCallDecoder", - "ZeroFunctionSelector", - "DelegateCallReturnValue", - "ECRecoverMalformedInput", - "SkipEmptyStringLiteral", + "NestedArrayFunctionCallDecoder", + "ZeroFunctionSelector", + "DelegateCallReturnValue", + "ECRecoverMalformedInput", + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" - ], + ], "released": "2017-01-31" } }
\ No newline at end of file diff --git a/docs/contracts.rst b/docs/contracts.rst index 669a374f..8fd1c89e 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -406,7 +406,8 @@ inheritable properties of contracts and may be overridden by derived contracts. /// The `return 7` statement assigns 7 to the return value but still /// executes the statement `locked = false` in the modifier. function f() public noReentrancy returns (uint) { - require(msg.sender.call("")); + (bool success,) = msg.sender.call(""); + require(success); return 7; } } @@ -645,7 +646,8 @@ Like any function, the fallback function can execute complex operations as long contract Caller { function callTest(Test test) public returns (bool) { - require(address(test).call(abi.encodeWithSignature("nonExistingFunction()"))); + (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); + require(success); // results in test.x becoming == 1. // If someone sends ether to that contract, diff --git a/docs/contributing.rst b/docs/contributing.rst index 160e73b3..8a83ca55 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -207,13 +207,13 @@ Next, build Solidity (or just the ``solfuzzer`` binary) with AFL as your compile At this stage you should be able to see a message similar to the following: :: - - Scanning dependencies of target solfuzzer - [ 98%] Building CXX object test/tools/CMakeFiles/solfuzzer.dir/fuzzer.cpp.o - afl-cc 2.52b by <lcamtuf@google.com> - afl-as 2.52b by <lcamtuf@google.com> + + Scanning dependencies of target solfuzzer + [ 98%] Building CXX object test/tools/CMakeFiles/solfuzzer.dir/fuzzer.cpp.o + afl-cc 2.52b by <lcamtuf@google.com> + afl-as 2.52b by <lcamtuf@google.com> [+] Instrumented 1949 locations (64-bit, non-hardened mode, ratio 100%). - [100%] Linking CXX executable solfuzzer + [100%] Linking CXX executable solfuzzer If the instrumentation messages did not appear, try switching the cmake flags pointing to AFL's clang binaries: @@ -228,7 +228,7 @@ Othwerise, upon execution the fuzzer will halt with an error saying binary is no :: - afl-fuzz 2.52b by <lcamtuf@google.com> + afl-fuzz 2.52b by <lcamtuf@google.com> ... (truncated messages) [*] Validating target binary... diff --git a/docs/grammar.txt b/docs/grammar.txt index 809fcffc..43ef07a9 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -131,7 +131,7 @@ HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]* -HexNumber = '0x' [0-9a-fA-F]+ +HexNumber = '0' [xX] [0-9a-fA-F]+ DecimalNumber = [0-9]+ ( '.' [0-9]* )? ( [eE] [0-9]+ )? TupleExpression = '(' ( Expression? ( ',' Expression? )* )? ')' diff --git a/docs/index.rst b/docs/index.rst index d59d476e..9f2844c7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -141,14 +141,14 @@ Solidity Tools * `ABI to solidity interface converter <https://gist.github.com/chriseth/8f533d133fa0c15b0d6eaf3ec502c82b>`_ A script for generating contract interfaces from the ABI of a smart contract. - -* `Securify <https://securify.ch/>`_ + +* `Securify <https://securify.ch/>`_ Fully automated online static analyzer for smart contracts, providing a security report based on vulnerability patterns. - + * `Sūrya <https://github.com/ConsenSys/surya/>`_ Utility tool for smart contract systems, offering a number of visual outputs and information about the contracts' structure. Also supports querying the function call graph. - -* `EVM Lab <https://github.com/ethereum/evmlab/>`_ + +* `EVM Lab <https://github.com/ethereum/evmlab/>`_ Rich tool package to interact with the EVM. Includes a VM, Etherchain API, and a trace-viewer with gas cost display. .. note:: diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 910f80cf..34806f4a 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -22,7 +22,7 @@ Remix `Access Remix online <https://remix.ethereum.org/>`_, you don't need to install anything. If you want to use it without connection to the Internet, go to -https://github.com/ethereum/browser-solidity/tree/gh-pages and download the .ZIP file as +https://github.com/ethereum/remix-live/tree/gh-pages and download the ``.zip`` file as explained on that page. Further options on this page detail installing commandline Solidity compiler software @@ -35,7 +35,7 @@ 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 all options further down this page. Our :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>`_. @@ -92,7 +92,7 @@ If you want to use the cutting edge developer version: sudo add-apt-repository ppa:ethereum/ethereum-dev sudo apt-get update sudo apt-get install solc - + We are also releasing a `snap package <https://snapcraft.io/>`_, which is installable in all the `supported Linux distros <https://snapcraft.io/docs/core/install>`_. To install the latest stable version of solc: .. code-block:: bash @@ -123,13 +123,13 @@ We will re-add the pre-built bottles soon. brew tap ethereum/ethereum brew install solidity -If you need a specific version of Solidity you can install a +If you need a specific version of Solidity you can install a Homebrew formula directly from Github. -View +View `solidity.rb commits on Github <https://github.com/ethereum/homebrew-ethereum/commits/master/solidity.rb>`_. -Follow the history links until you have a raw file link of a +Follow the history links until you have a raw file link of a specific commit of ``solidity.rb``. Install it using ``brew``: @@ -272,7 +272,7 @@ Building Solidity is quite similar on Linux, macOS and other Unices: or even easier: .. code-block:: bash - + #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh @@ -302,7 +302,7 @@ If you are interested what CMake options are available run ``cmake .. -LH``. SMT Solvers ----------- -Solidity can be built against SMT solvers and will do so by default if +Solidity can be built against SMT solvers and will do so by default if they are found in the system. Each solver can be disabled by a `cmake` option. *Note: In some cases, this can also be a potential workaround for build failures.* @@ -313,7 +313,7 @@ Inside the build folder you can disable them, since they are enabled by default: .. code-block:: bash # disables only Z3 SMT Solver. - cmake .. -DUSE_Z3=OFF + cmake .. -DUSE_Z3=OFF # disables only CVC4 SMT Solver. cmake .. -DUSE_CVC4=OFF diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 5cbb6cff..c1a1669a 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -96,43 +96,44 @@ filesystem, it can also map to resources discovered via e.g. ipfs, http or git. Use in Actual Compilers ----------------------- -When the compiler is invoked, it is not only possible to specify how to -discover the first element of a path, but it is possible to specify path prefix -remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to -``/usr/local/dapp-bin/library`` and the compiler will read the files from there. -If multiple remappings can be applied, the one with the longest key is tried first. -An empty prefix is not allowed. Furthermore, these remappings can depend on the context, -which allows you to configure packages to import e.g. different versions of a library -of the same name. +When invoking the compiler, you can specify how to discover the first element +of a path, and also path prefix remappings. For +example you can setup a remapping so that everything imported from the virtual +directory ``github.com/ethereum/dapp-bin/library`` would actually be read from +your local directory ``/usr/local/dapp-bin/library``. +If multiple remappings apply, the one with the longest key is tried first. +An empty prefix is not allowed. The remappings can depend on a context, +which allows you to configure packages to import e.g., different versions of a +library of the same name. **solc**: -For solc (the commandline compiler), these remappings are provided as +For solc (the commandline compiler), you provide these path remappings as ``context:prefix=target`` arguments, where both the ``context:`` and the -``=target`` parts are optional (where target defaults to prefix in that +``=target`` parts are optional (``target`` defaults to ``prefix`` in this case). All remapping values that are regular files are compiled (including -their dependencies). This mechanism is completely backwards-compatible (as long -as no filename contains = or :) and thus not a breaking change. All imports -in files in or below the directory ``context`` that import a file that -starts with ``prefix`` are redirected by replacing ``prefix`` by ``target``. +their dependencies). -So as an example, if you clone -``github.com/ethereum/dapp-bin/`` locally to ``/usr/local/dapp-bin``, you can use -the following in your source file: +This mechanism is backwards-compatible (as long +as no filename contains ``=`` or ``:``) and thus not a breaking change. All +files in or below the ``context`` directory that import a file that starts with +``prefix`` are redirected by replacing ``prefix`` by ``target``. + +For example, if you clone ``github.com/ethereum/dapp-bin/`` locally to +``/usr/local/dapp-bin``, you can use the following in your source file: :: import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; -and then run the compiler as +Then run the compiler: .. code-block:: bash solc github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ source.sol -As a more complex example, suppose you rely on some module that uses a -very old version of dapp-bin. That old version of dapp-bin is checked -out at ``/usr/local/dapp-bin_old``, then you can use +As a more complex example, suppose you rely on a module that uses an old +version of dapp-bin that you checked out to ``/usr/local/dapp-bin_old``, then you can run: .. code-block:: bash @@ -140,28 +141,29 @@ out at ``/usr/local/dapp-bin_old``, then you can use module2:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin_old/ \ source.sol -so that all imports in ``module2`` point to the old version but imports -in ``module1`` get the new version. +This means that all imports in ``module2`` point to the old version but imports +in ``module1`` point to the new version. + +.. note:: -Note that solc only allows you to include files from certain directories: -They have to be in the directory (or subdirectory) of one of the explicitly -specified source files or in the directory (or subdirectory) of a remapping -target. If you want to allow direct absolute includes, just add the -remapping ``/=/``. + ``solc`` only allows you to include files from certain directories. They have + to be in the directory (or subdirectory) of one of the explicitly specified + source files or in the directory (or subdirectory) of a remapping target. If + you want to allow direct absolute includes, add the remapping ``/=/``. If there are multiple remappings that lead to a valid file, the remapping with the longest common prefix is chosen. **Remix**: -`Remix <https://remix.ethereum.org/>`_ -provides an automatic remapping for github and will also automatically retrieve -the file over the network: -You can import the iterable mapping by e.g. -``import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;``. +`Remix <https://remix.ethereum.org/>`_ provides an automatic remapping for +GitHub and automatically retrieves the file over the network. You can import +the iterable mapping as above, e.g. -Other source code providers may be added in the future. +:: + import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; +Remix may add other source code providers in the future. .. index:: ! comment, natspec diff --git a/docs/make.bat b/docs/make.bat index de2bccf7..bc06e706 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,242 +1,242 @@ -@ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
- set SPHINXBUILD=sphinx-build
-)
-set BUILDDIR=_build
-set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
-set I18NSPHINXOPTS=%SPHINXOPTS% .
-if NOT "%PAPER%" == "" (
- set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
- set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
-)
-
-if "%1" == "" goto help
-
-if "%1" == "help" (
- :help
- echo.Please use `make ^<target^>` where ^<target^> is one of
- echo. html to make standalone HTML files
- echo. dirhtml to make HTML files named index.html in directories
- echo. singlehtml to make a single large HTML file
- echo. pickle to make pickle files
- echo. json to make JSON files
- echo. htmlhelp to make HTML files and a HTML help project
- echo. qthelp to make HTML files and a qthelp project
- echo. devhelp to make HTML files and a Devhelp project
- echo. epub to make an epub
- echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
- echo. text to make text files
- echo. man to make manual pages
- echo. texinfo to make Texinfo files
- echo. gettext to make PO message catalogs
- echo. changes to make an overview over all changed/added/deprecated items
- echo. xml to make Docutils-native XML files
- echo. pseudoxml to make pseudoxml-XML files for display purposes
- echo. linkcheck to check all external links for integrity
- echo. doctest to run all doctests embedded in the documentation if enabled
- goto end
-)
-
-if "%1" == "clean" (
- for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
- del /q /s %BUILDDIR%\*
- goto end
-)
-
-
-%SPHINXBUILD% 2> nul
-if errorlevel 9009 (
- echo.
- echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
- echo.installed, then set the SPHINXBUILD environment variable to point
- echo.to the full path of the 'sphinx-build' executable. Alternatively you
- echo.may add the Sphinx directory to PATH.
- echo.
- echo.If you don't have Sphinx installed, grab it from
- echo.http://sphinx-doc.org/
- exit /b 1
-)
-
-if "%1" == "html" (
- %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/html.
- goto end
-)
-
-if "%1" == "dirhtml" (
- %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
- goto end
-)
-
-if "%1" == "singlehtml" (
- %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
- goto end
-)
-
-if "%1" == "pickle" (
- %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished; now you can process the pickle files.
- goto end
-)
-
-if "%1" == "json" (
- %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished; now you can process the JSON files.
- goto end
-)
-
-if "%1" == "htmlhelp" (
- %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished; now you can run HTML Help Workshop with the ^
-.hhp project file in %BUILDDIR%/htmlhelp.
- goto end
-)
-
-if "%1" == "qthelp" (
- %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished; now you can run "qcollectiongenerator" with the ^
-.qhcp project file in %BUILDDIR%/qthelp, like this:
- echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Solidity.qhcp
- echo.To view the help file:
- echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Solidity.ghc
- goto end
-)
-
-if "%1" == "devhelp" (
- %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished.
- goto end
-)
-
-if "%1" == "epub" (
- %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The epub file is in %BUILDDIR%/epub.
- goto end
-)
-
-if "%1" == "latex" (
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
- goto end
-)
-
-if "%1" == "latexpdf" (
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
- cd %BUILDDIR%/latex
- make all-pdf
- cd %BUILDDIR%/..
- echo.
- echo.Build finished; the PDF files are in %BUILDDIR%/latex.
- goto end
-)
-
-if "%1" == "latexpdfja" (
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
- cd %BUILDDIR%/latex
- make all-pdf-ja
- cd %BUILDDIR%/..
- echo.
- echo.Build finished; the PDF files are in %BUILDDIR%/latex.
- goto end
-)
-
-if "%1" == "text" (
- %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The text files are in %BUILDDIR%/text.
- goto end
-)
-
-if "%1" == "man" (
- %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The manual pages are in %BUILDDIR%/man.
- goto end
-)
-
-if "%1" == "texinfo" (
- %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
- goto end
-)
-
-if "%1" == "gettext" (
- %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
- goto end
-)
-
-if "%1" == "changes" (
- %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
- if errorlevel 1 exit /b 1
- echo.
- echo.The overview file is in %BUILDDIR%/changes.
- goto end
-)
-
-if "%1" == "linkcheck" (
- %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
- if errorlevel 1 exit /b 1
- echo.
- echo.Link check complete; look for any errors in the above output ^
-or in %BUILDDIR%/linkcheck/output.txt.
- goto end
-)
-
-if "%1" == "doctest" (
- %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
- if errorlevel 1 exit /b 1
- echo.
- echo.Testing of doctests in the sources finished, look at the ^
-results in %BUILDDIR%/doctest/output.txt.
- goto end
-)
-
-if "%1" == "xml" (
- %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The XML files are in %BUILDDIR%/xml.
- goto end
-)
-
-if "%1" == "pseudoxml" (
- %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
- if errorlevel 1 exit /b 1
- echo.
- echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
- goto end
-)
-
-:end
+@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Solidity.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Solidity.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/metadata.rst b/docs/metadata.rst index 5e37219e..059faad2 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -131,7 +131,7 @@ user interface for the contract. Furthermore, Mist can use the userdoc to display a confirmation message to the user whenever they interact with the contract. -Additional information about Ethereum Natural Specification (NatSpec) can be found `here <https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format>`_. +Additional information about Ethereum Natural Specification (NatSpec) can be found `here <https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format>`_. Usage for Source Code Verification ================================== diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 066a31ea..3bcd9566 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -86,7 +86,8 @@ as it uses ``call`` which forwards all remaining gas by default: mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { - if (msg.sender.call.value(shares[msg.sender])("")) + (bool success,) = msg.sender.call.value(shares[msg.sender])(""); + if (success) shares[msg.sender] = 0; } } diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 28c9e6ab..55911dc6 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -191,8 +191,8 @@ For more information, see the section on :ref:`address`. must align in order for the called contract to correctly access the storage variables of the calling contract by name. This is of course not the case if storage pointers are passed as function arguments as in the case for the high-level libraries. - - + + .. note:: The use of ``callcode`` is discouraged and will be removed in the future. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index b286e1a3..0a64d840 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -83,6 +83,8 @@ Input Description [ "bzzr://56ab...", "ipfs://Qma...", + // If files are used, their directories should be added to the command line via + // `--allow-paths <path>`. "file:///tmp/path/to/file.sol" ] }, diff --git a/libdevcore/Exceptions.cpp b/libdevcore/Exceptions.cpp index 97f03f6e..cff5abf4 100644 --- a/libdevcore/Exceptions.cpp +++ b/libdevcore/Exceptions.cpp @@ -25,7 +25,7 @@ char const* Exception::what() const noexcept // Return the comment if available. if (string const* cmt = comment()) return cmt->data(); - + // Fallback to base what(). // Boost accepts nullptr, but the C++ standard doesn't // and crashes on some platforms. diff --git a/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp b/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp index dae591df..2568e17d 100644 --- a/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp +++ b/libdevcore/boost_multiprecision_number_compare_bug_workaround.hpp @@ -1,8 +1,8 @@ -// This is a copy of boost/multiprecision/detail/number_compare.hpp from boost 1.59 to replace buggy version from 1.58. +// This is a copy of boost/multiprecision/detail/number_compare.hpp from boost 1.59 to replace buggy version from 1.58. #ifdef BOOST_MP_COMPARE_HPP -#error This bug workaround header must be included before original boost/multiprecision/detail/number_compare.hpp +#error This bug workaround header must be included before original boost/multiprecision/detail/number_compare.hpp #endif /////////////////////////////////////////////////////////////////////////////// @@ -150,11 +150,11 @@ template <class B, expression_template_option ET> struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {}; template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4> -struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> > +struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {}; template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET> -struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> > +struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> > : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {}; template <class Backend, expression_template_option ExpressionTemplates> @@ -196,7 +196,7 @@ inline bool operator == (const number<Backend, ExpressionTemplates>& a, const nu return eval_eq(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_eq; @@ -204,7 +204,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_eq; @@ -212,7 +212,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -222,7 +222,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_eq(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -232,7 +232,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_eq(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_eq; @@ -250,7 +250,7 @@ inline bool operator != (const number<Backend, ExpressionTemplates>& a, const nu return !eval_eq(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_eq; @@ -258,7 +258,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_eq; @@ -266,7 +266,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -276,7 +276,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_eq(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -286,7 +286,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_eq(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_eq; @@ -304,7 +304,7 @@ inline bool operator < (const number<Backend, ExpressionTemplates>& a, const num return eval_lt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_lt; @@ -312,7 +312,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_gt; @@ -320,7 +320,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -330,7 +330,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_gt(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -340,7 +340,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return eval_lt(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_lt; @@ -358,7 +358,7 @@ inline bool operator > (const number<Backend, ExpressionTemplates>& a, const num return eval_gt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_gt; @@ -366,7 +366,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_lt; @@ -374,7 +374,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -384,7 +384,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return a > t; } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -394,7 +394,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return t > b; } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_gt; @@ -412,7 +412,7 @@ inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const nu return !eval_gt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_gt; @@ -420,7 +420,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_lt; @@ -428,7 +428,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -440,7 +440,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_lt(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -450,7 +450,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_gt(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_gt; @@ -468,7 +468,7 @@ inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const nu return !eval_lt(a.backend(), b.backend()); } template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { using default_ops::eval_lt; @@ -476,7 +476,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b)); } template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates> -inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { using default_ops::eval_gt; @@ -484,7 +484,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, Expre return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a)); } template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -494,7 +494,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_gt(t.backend(), result_type::canonical_value(a)); } template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic> -inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type +inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type; @@ -504,7 +504,7 @@ inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expr return !eval_lt(t.backend(), result_type::canonical_value(b)); } template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b> -inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type +inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { using default_ops::eval_lt; diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index f33de7b7..8750b47b 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -332,7 +332,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) case Location::Memory: return "\"memory\""; case Location::Storage: return "\"storage\""; case Location::CallData: return "\"calldata\""; - case Location::Default: return "none"; + case Location::Unspecified: return "none"; } return {}; }; @@ -368,12 +368,12 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) // Find correct data location. if (_variable.isEventParameter()) { - solAssert(varLoc == Location::Default, ""); + solAssert(varLoc == Location::Unspecified, ""); typeLoc = DataLocation::Memory; } else if (_variable.isStateVariable()) { - solAssert(varLoc == Location::Default, ""); + solAssert(varLoc == Location::Unspecified, ""); typeLoc = _variable.isConstant() ? DataLocation::Memory : DataLocation::Storage; } else if ( @@ -394,7 +394,7 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable) case Location::CallData: typeLoc = DataLocation::CallData; break; - case Location::Default: + case Location::Unspecified: solAssert(!_variable.hasReferenceOrMappingType(), "Data location not properly set."); } diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index ac4fa72b..0bc20f2e 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -138,9 +138,25 @@ void SyntaxChecker::endVisit(ModifierDefinition const& _modifier) m_placeholderFound = false; } -bool SyntaxChecker::visit(WhileStatement const&) +void SyntaxChecker::checkSingleStatementVariableDeclaration(ASTNode const& _statement) +{ + auto varDecl = dynamic_cast<VariableDeclarationStatement const*>(&_statement); + if (varDecl) + m_errorReporter.syntaxError(_statement.location(), "Variable declarations can only be used inside blocks."); +} + +bool SyntaxChecker::visit(IfStatement const& _ifStatement) +{ + checkSingleStatementVariableDeclaration(_ifStatement.trueStatement()); + if (Statement const* _statement = _ifStatement.falseStatement()) + checkSingleStatementVariableDeclaration(*_statement); + return true; +} + +bool SyntaxChecker::visit(WhileStatement const& _whileStatement) { m_inLoopDepth++; + checkSingleStatementVariableDeclaration(_whileStatement.body()); return true; } @@ -149,9 +165,10 @@ void SyntaxChecker::endVisit(WhileStatement const&) m_inLoopDepth--; } -bool SyntaxChecker::visit(ForStatement const&) +bool SyntaxChecker::visit(ForStatement const& _forStatement) { m_inLoopDepth++; + checkSingleStatementVariableDeclaration(_forStatement.body()); return true; } diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index 897df676..f5716bf9 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -52,6 +52,12 @@ private: virtual bool visit(ModifierDefinition const& _modifier) override; virtual void endVisit(ModifierDefinition const& _modifier) override; + /// Reports an error if _statement is a VariableDeclarationStatement. + /// Used by if/while/for to check for single statement variable declarations + /// without a block. + void checkSingleStatementVariableDeclaration(ASTNode const& _statement); + + virtual bool visit(IfStatement const& _ifStatement) override; virtual bool visit(WhileStatement const& _whileStatement) override; virtual void endVisit(WhileStatement const& _whileStatement) override; virtual bool visit(ForStatement const& _forStatement) override; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8b941fca..a2b72896 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -525,7 +525,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment) ); } -TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2) +TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2) { vector<ASTPointer<Expression const>> arguments = _functionCall.arguments(); if (arguments.size() != 2) @@ -544,10 +544,8 @@ TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall co " to bytes memory requested." ); - TypePointer returnType = make_shared<TupleType>(); - if (arguments.size() < 2) - return returnType; + return {}; // The following is a rather syntactic restriction, but we check it here anyway: // The second argument has to be a tuple expression containing type names. @@ -558,10 +556,10 @@ TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall co arguments[1]->location(), "The second argument to \"abi.decode\" has to be a tuple of types." ); - return returnType; + return {}; } - vector<TypePointer> components; + TypePointers components; for (auto const& typeArgument: tupleExpression->components()) { solAssert(typeArgument, ""); @@ -591,7 +589,7 @@ TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall co components.push_back(make_shared<TupleType>()); } } - return make_shared<TupleType>(components); + return components; } void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance) @@ -1215,7 +1213,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) if (ref->dataStoredIn(DataLocation::Storage)) { string errorText{"Uninitialized storage pointer."}; - if (varDecl.referenceLocation() == VariableDeclaration::Location::Default) + if (varDecl.referenceLocation() == VariableDeclaration::Location::Unspecified) errorText += " Did you mean '<type> memory " + varDecl.name() + "'?"; solAssert(m_scope, ""); m_errorReporter.declarationError(varDecl.location(), errorText); @@ -1780,15 +1778,6 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) if (functionType->kind() == FunctionType::Kind::BareStaticCall && !m_evmVersion.hasStaticCall()) m_errorReporter.typeError(_functionCall.location(), "\"staticcall\" is not supported by the VM version."); - auto returnTypes = - allowDynamicTypes ? - functionType->returnParameterTypes() : - functionType->returnParameterTypesWithoutDynamicTypes(); - if (returnTypes.size() == 1) - _functionCall.annotation().type = returnTypes.front(); - else - _functionCall.annotation().type = make_shared<TupleType>(returnTypes); - if (auto functionName = dynamic_cast<Identifier const*>(&_functionCall.expression())) { if (functionName->name() == "sha3" && functionType->kind() == FunctionType::Kind::KECCAK256) @@ -1824,8 +1813,14 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) bool const abiEncoderV2 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2); + // Will be assigned to .type at the end (turning multi-elements into a tuple). + TypePointers returnTypes = + allowDynamicTypes ? + functionType->returnParameterTypes() : + functionType->returnParameterTypesWithoutDynamicTypes(); + if (functionType->kind() == FunctionType::Kind::ABIDecode) - _functionCall.annotation().type = typeCheckABIDecodeAndRetrieveReturnType(_functionCall, abiEncoderV2); + returnTypes = typeCheckABIDecodeAndRetrieveReturnType(_functionCall, abiEncoderV2); else if (functionType->takesArbitraryParameters() && arguments.size() < parameterTypes.size()) { solAssert(_functionCall.annotation().kind == FunctionCallKind::FunctionCall, ""); @@ -1983,6 +1978,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) } } + if (returnTypes.size() == 1) + _functionCall.annotation().type = returnTypes.front(); + else + _functionCall.annotation().type = make_shared<TupleType>(returnTypes); + return false; } diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 4be0d1e4..8d25a88e 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -92,9 +92,9 @@ private: void checkExpressionAssignment(Type const& _type, Expression const& _expression); /// Performs type checks for ``abi.decode(bytes memory, (...))`` and returns the - /// return type (which is basically the second argument) if successful. It returns - /// the empty tuple type or error. - TypePointer typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2); + /// vector of return types (which is basically the second argument) if successful. It returns + /// the empty vector on error. + TypePointers typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2); virtual void endVisit(InheritanceSpecifier const& _inheritance) override; virtual void endVisit(UsingForDirective const& _usingFor) override; diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 635ab024..8e7a81a6 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -517,7 +517,7 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c using Location = VariableDeclaration::Location; if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter()) - return set<Location>{ Location::Default }; + return set<Location>{ Location::Unspecified }; else if (isStateVariable() && isConstant()) return set<Location>{ Location::Memory }; else if (isExternalCallableParameter()) @@ -546,7 +546,7 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c } else // Struct members etc. - return set<Location>{ Location::Default }; + return set<Location>{ Location::Unspecified }; } TypePointer VariableDeclaration::type() const diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index b953211d..a5cd277d 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -655,7 +655,7 @@ private: class VariableDeclaration: public Declaration { public: - enum Location { Default, Storage, Memory, CallData }; + enum Location { Unspecified, Storage, Memory, CallData }; VariableDeclaration( SourceLocation const& _sourceLocation, @@ -666,7 +666,7 @@ public: bool _isStateVar = false, bool _isIndexed = false, bool _isConstant = false, - Location _referenceLocation = Location::Default + Location _referenceLocation = Location::Unspecified ): Declaration(_sourceLocation, _name, _visibility), m_typeName(_type), diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 72b20b3b..beab356c 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -739,7 +739,7 @@ string ASTJsonConverter::location(VariableDeclaration::Location _location) { switch (_location) { - case VariableDeclaration::Location::Default: + case VariableDeclaration::Location::Unspecified: return "default"; case VariableDeclaration::Location::Storage: return "storage"; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index e1e8403c..a6867dcb 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -617,11 +617,11 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons if (isAddress()) return { {"balance", make_shared<IntegerType>(256)}, - {"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, - {"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, - {"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareDelegateCall, false)}, + {"call", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, + {"callcode", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, + {"delegatecall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false)}, {"send", make_shared<FunctionType>(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send)}, - {"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}, + {"staticcall", make_shared<FunctionType>(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}, {"transfer", make_shared<FunctionType>(strings{"uint"}, strings(), FunctionType::Kind::Transfer)} }; else @@ -2492,7 +2492,14 @@ TypePointers FunctionType::returnParameterTypesWithoutDynamicTypes() const { TypePointers returnParameterTypes = m_returnParameterTypes; - if (m_kind == Kind::External || m_kind == Kind::DelegateCall) + if ( + m_kind == Kind::External || + m_kind == Kind::DelegateCall || + m_kind == Kind::BareCall || + m_kind == Kind::BareCallCode || + m_kind == Kind::BareDelegateCall || + m_kind == Kind::BareStaticCall + ) for (auto& param: returnParameterTypes) if (param->isDynamicallySized() && !param->dataStoredIn(DataLocation::Storage)) param = make_shared<InaccessibleDynamicType>(); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index fbb1879a..4cc4ba53 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -281,19 +281,19 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) if (_tuple.isInlineArray()) { ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); - + solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); m_context << max(u256(32u), arrayType.memorySize()); utils().allocateMemory(); m_context << Instruction::DUP1; - + for (auto const& component: _tuple.components()) { component->accept(*this); utils().convertType(*component->annotation().type, *arrayType.baseType(), true); - utils().storeInMemoryDynamic(*arrayType.baseType(), true); + utils().storeInMemoryDynamic(*arrayType.baseType(), true); } - + m_context << Instruction::POP; } else @@ -1074,7 +1074,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) { arguments.front()->accept(*this); TypePointer firstArgType = arguments.front()->annotation().type; - TypePointers const& targetTypes = dynamic_cast<TupleType const&>(*_functionCall.annotation().type).components(); + TypePointers targetTypes; + if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type.get())) + targetTypes = targetTupleType->components(); + else + targetTypes = TypePointers{_functionCall.annotation().type}; if ( *firstArgType == ArrayType(DataLocation::CallData) || *firstArgType == ArrayType(DataLocation::CallData, true) @@ -1569,7 +1573,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) { CompilerContext::LocationSetter locationSetter(m_context, _literal); TypePointer type = _literal.annotation().type; - + switch (type->category()) { case Type::Category::RationalNumber: @@ -1827,33 +1831,34 @@ void ExpressionCompiler::appendExternalFunctionCall( auto funKind = _functionType.kind(); solAssert(funKind != FunctionType::Kind::BareStaticCall || m_context.evmVersion().hasStaticCall(), ""); - - bool returnSuccessCondition = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall; + + bool returnSuccessConditionAndReturndata = funKind == FunctionType::Kind::BareCall || funKind == FunctionType::Kind::BareCallCode || funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::BareStaticCall; bool isCallCode = funKind == FunctionType::Kind::BareCallCode; bool isDelegateCall = funKind == FunctionType::Kind::BareDelegateCall || funKind == FunctionType::Kind::DelegateCall; bool useStaticCall = funKind == FunctionType::Kind::BareStaticCall || (_functionType.stateMutability() <= StateMutability::View && m_context.evmVersion().hasStaticCall()); bool haveReturndatacopy = m_context.evmVersion().supportsReturndata(); unsigned retSize = 0; - TypePointers returnTypes; - if (returnSuccessCondition) - retSize = 0; // return value actually is success condition - else if (haveReturndatacopy) - returnTypes = _functionType.returnParameterTypes(); - else - returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes(); - bool dynamicReturnSize = false; - for (auto const& retType: returnTypes) - if (retType->isDynamicallyEncoded()) - { - solAssert(haveReturndatacopy, ""); - dynamicReturnSize = true; - retSize = 0; - break; - } + TypePointers returnTypes; + if (!returnSuccessConditionAndReturndata) + { + if (haveReturndatacopy) + returnTypes = _functionType.returnParameterTypes(); else - retSize += retType->calldataEncodedSize(); + returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes(); + + for (auto const& retType: returnTypes) + if (retType->isDynamicallyEncoded()) + { + solAssert(haveReturndatacopy, ""); + dynamicReturnSize = true; + retSize = 0; + break; + } + else + retSize += retType->calldataEncodedSize(); + } // Evaluate arguments. TypePointers argumentTypes; @@ -1997,7 +2002,7 @@ void ExpressionCompiler::appendExternalFunctionCall( (_functionType.gasSet() ? 1 : 0) + (!_functionType.isBareCall() ? 1 : 0); - if (returnSuccessCondition) + if (returnSuccessConditionAndReturndata) m_context << swapInstruction(remainsSize); else { @@ -2008,9 +2013,31 @@ void ExpressionCompiler::appendExternalFunctionCall( utils().popStackSlots(remainsSize); - if (returnSuccessCondition) + if (returnSuccessConditionAndReturndata) { - // already there + // success condition is already there + // The return parameter types can be empty, when this function is used as + // an internal helper function e.g. for ``send`` and ``transfer``. In that + // case we're only interested in the success condition, not the return data. + if (!_functionType.returnParameterTypes().empty()) + { + if (haveReturndatacopy) + { + m_context << Instruction::RETURNDATASIZE; + m_context.appendInlineAssembly(R"({ + switch v case 0 { + v := 0x60 + } default { + v := mload(0x40) + mstore(0x40, add(v, and(add(returndatasize(), 0x3f), not(0x1f)))) + mstore(v, returndatasize()) + returndatacopy(add(v, 0x20), 0, returndatasize()) + } + })", {"v"}); + } + else + utils().pushZeroPointer(); + } } else if (funKind == FunctionType::Kind::RIPEMD160) { diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 0bee2a91..c9c26f57 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -564,7 +564,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( bool isIndexed = false; bool isDeclaredConst = false; Declaration::Visibility visibility(Declaration::Visibility::Default); - VariableDeclaration::Location location = VariableDeclaration::Location::Default; + VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified; ASTPointer<ASTString> identifier; while (true) @@ -572,6 +572,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( Token::Value token = m_scanner->currentToken(); if (_options.isStateVariable && Token::isVariableVisibilitySpecifier(token)) { + nodeFactory.markEndPosition(); if (visibility != Declaration::Visibility::Default) { parserError(string( @@ -592,7 +593,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( isDeclaredConst = true; else if (_options.allowLocationSpecifier && Token::isLocationSpecifier(token)) { - if (location != VariableDeclaration::Location::Default) + if (location != VariableDeclaration::Location::Unspecified) parserError(string("Location already specified.")); else if (!type) parserError(string("Location specifier needs explicit type name.")); @@ -616,21 +617,21 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration( } else break; + nodeFactory.markEndPosition(); m_scanner->next(); } } - nodeFactory.markEndPosition(); if (_options.allowEmptyName && m_scanner->currentToken() != Token::Identifier) { identifier = make_shared<ASTString>(""); solAssert(!_options.allowVar, ""); // allowEmptyName && allowVar makes no sense - if (type) - nodeFactory.setEndPositionFromNode(type); - // if type is null this has already caused an error } else + { + nodeFactory.markEndPosition(); identifier = expectIdentifierToken(); + } ASTPointer<Expression> value; if (_options.allowInitialValue) { diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp index 5ce74316..27acb7d4 100644 --- a/libsolidity/parsing/Token.cpp +++ b/libsolidity/parsing/Token.cpp @@ -63,7 +63,7 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con { solAssert(_second == 0, "There should not be a second size argument to type " + string(Token::toString(_baseType)) + "."); solAssert( - _first <= 256 && _first % 8 == 0, + _first <= 256 && _first % 8 == 0, "No elementary type " + string(Token::toString(_baseType)) + to_string(_first) + "." ); } @@ -165,7 +165,7 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s else return make_tuple(Token::FixedMxN, m, n); } - } + } } return make_tuple(Token::Identifier, 0, 0); } diff --git a/scripts/detect_trailing_whitespace.sh b/scripts/detect_trailing_whitespace.sh new file mode 100755 index 00000000..1a136a10 --- /dev/null +++ b/scripts/detect_trailing_whitespace.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +REPO_ROOT="$(dirname "$0")"/.. + +( +cd $REPO_ROOT +WHITESPACE=$(git grep -n -I -E "^.*[[:space:]]+$" | grep -v "test/libsolidity/ASTJSON\|test/compilationTests/zeppelin/LICENSE") + +if [[ "$WHITESPACE" != "" ]] +then + echo "Error: Trailing whitespace found:" >&2 + echo "$WHITESPACE" >&2 + exit 1 +fi +) diff --git a/scripts/isolate_tests.py b/scripts/isolate_tests.py index de2a4438..06e9f9ea 100755 --- a/scripts/isolate_tests.py +++ b/scripts/isolate_tests.py @@ -79,7 +79,7 @@ if __name__ == '__main__': if isfile(path): extract_and_write(path, path) - else: + else: for root, subdirs, files in os.walk(path): if '_build' in subdirs: subdirs.remove('_build') diff --git a/scripts/release.bat b/scripts/release.bat index 6415a040..b15b49b7 100644 --- a/scripts/release.bat +++ b/scripts/release.bat @@ -32,11 +32,9 @@ set VERSION=%2 IF "%VERSION%"=="2015" ( set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.CRT\msvc*.dll" ) ELSE ( - IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.14.26405\x86\Microsoft.VC141.CRT\" ( - set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\14.14.26405\x86\Microsoft.VC141.CRT\msvc*.dll" - ) ELSE ( - set "DLLS=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\14.14.26405\x86\Microsoft.VC141.CRT\msvc*.dll" - ) + set "DLLS=MSVC_DLLS_NOT_FOUND" + FOR /d %%d IN ("C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Redist\MSVC\*" + "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\*") DO set "DLLS=%%d\x86\Microsoft.VC141.CRT\msvc*.dll" ) 7z a solidity-windows.zip ^ diff --git a/scripts/release_ppa.sh b/scripts/release_ppa.sh index ae565a02..1cfbf716 100755 --- a/scripts/release_ppa.sh +++ b/scripts/release_ppa.sh @@ -22,7 +22,7 @@ ## method = ftp ## incoming = ~ethereum/ethereum-dev ## login = anonymous -## +## ## [ethereum] ## fqdn = ppa.launchpad.net ## method = ftp diff --git a/scripts/update_bugs_by_version.py b/scripts/update_bugs_by_version.py index 68ccd72a..655ffe23 100755 --- a/scripts/update_bugs_by_version.py +++ b/scripts/update_bugs_by_version.py @@ -35,7 +35,7 @@ for v in versions: continue versions[v]['bugs'] += [bug['name']] -new_contents = json.dumps(versions, sort_keys=True, indent=4) +new_contents = json.dumps(versions, sort_keys=True, indent=4, separators=(',', ': ')) 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: diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index c9acb99a..6f8a8ac1 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -172,12 +172,12 @@ done ) printTask "Compiling all examples from the documentation..." -TMPDIR=$(mktemp -d) +SOLTMPDIR=$(mktemp -d) ( set -e cd "$REPO_ROOT" REPO_ROOT=$(pwd) # make it absolute - cd "$TMPDIR" + cd "$SOLTMPDIR" "$REPO_ROOT"/scripts/isolate_tests.py "$REPO_ROOT"/docs/ docs for f in *.sol do @@ -199,10 +199,10 @@ TMPDIR=$(mktemp -d) then opts="$opts -w" fi - compileFull $opts "$TMPDIR/$f" + compileFull $opts "$SOLTMPDIR/$f" done ) -rm -rf "$TMPDIR" +rm -rf "$SOLTMPDIR" echo "Done." printTask "Testing library checksum..." @@ -213,17 +213,17 @@ printTask "Testing long library names..." echo '' | "$SOLC" - --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname:0x90f20564390eAe531E810af625A22f51385Cd222 >/dev/null printTask "Testing overwriting files..." -TMPDIR=$(mktemp -d) +SOLTMPDIR=$(mktemp -d) ( set -e # First time it works - echo 'contract C {} ' | "$SOLC" - --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null + echo 'contract C {} ' | "$SOLC" - --bin -o "$SOLTMPDIR/non-existing-stuff-to-create" 2>/dev/null # Second time it fails - ! echo 'contract C {} ' | "$SOLC" - --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null + ! echo 'contract C {} ' | "$SOLC" - --bin -o "$SOLTMPDIR/non-existing-stuff-to-create" 2>/dev/null # Unless we force - echo 'contract C {} ' | "$SOLC" - --overwrite --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null + echo 'contract C {} ' | "$SOLC" - --overwrite --bin -o "$SOLTMPDIR/non-existing-stuff-to-create" 2>/dev/null ) -rm -rf "$TMPDIR" +rm -rf "$SOLTMPDIR" printTask "Testing assemble, yul, strict-assembly..." echo '{}' | "$SOLC" - --assemble &>/dev/null @@ -231,7 +231,7 @@ echo '{}' | "$SOLC" - --yul &>/dev/null echo '{}' | "$SOLC" - --strict-assembly &>/dev/null printTask "Testing standard input..." -TMPDIR=$(mktemp -d) +SOLTMPDIR=$(mktemp -d) ( set +e output=$("$SOLC" --bin 2>&1) @@ -256,12 +256,12 @@ TMPDIR=$(mktemp -d) ) printTask "Testing soljson via the fuzzer..." -TMPDIR=$(mktemp -d) +SOLTMPDIR=$(mktemp -d) ( set -e cd "$REPO_ROOT" REPO_ROOT=$(pwd) # make it absolute - cd "$TMPDIR" + cd "$SOLTMPDIR" "$REPO_ROOT"/scripts/isolate_tests.py "$REPO_ROOT"/test/ "$REPO_ROOT"/scripts/isolate_tests.py "$REPO_ROOT"/docs/ docs for f in *.sol @@ -283,5 +283,5 @@ TMPDIR=$(mktemp -d) set -e done ) -rm -rf "$TMPDIR" +rm -rf "$SOLTMPDIR" echo "Commandline tests successful." diff --git a/test/compilationTests/MultiSigWallet/MultiSigWallet.sol b/test/compilationTests/MultiSigWallet/MultiSigWallet.sol index 35f6208b..dc6e98e4 100644 --- a/test/compilationTests/MultiSigWallet/MultiSigWallet.sol +++ b/test/compilationTests/MultiSigWallet/MultiSigWallet.sol @@ -226,13 +226,11 @@ contract MultiSigWallet { { if (isConfirmed(transactionId)) { Transaction storage tx = transactions[transactionId]; - tx.executed = true; - if (tx.destination.call.value(tx.value)(tx.data)) + (tx.executed,) = tx.destination.call.value(tx.value)(tx.data); + if (tx.executed) emit Execution(transactionId); - else { + else emit ExecutionFailure(transactionId); - tx.executed = false; - } } } diff --git a/test/compilationTests/MultiSigWallet/MultiSigWalletWithDailyLimit.sol b/test/compilationTests/MultiSigWallet/MultiSigWalletWithDailyLimit.sol index 69e94fd5..df2a1400 100644 --- a/test/compilationTests/MultiSigWallet/MultiSigWalletWithDailyLimit.sol +++ b/test/compilationTests/MultiSigWallet/MultiSigWalletWithDailyLimit.sol @@ -45,14 +45,13 @@ contract MultiSigWalletWithDailyLimit is MultiSigWallet { Transaction storage tx = transactions[transactionId]; bool confirmed = isConfirmed(transactionId); if (confirmed || tx.data.length == 0 && isUnderLimit(tx.value)) { - tx.executed = true; if (!confirmed) spentToday += tx.value; - if (tx.destination.call.value(tx.value)(tx.data)) + (tx.executed,) = tx.destination.call.value(tx.value)(tx.data); + if (tx.executed) emit Execution(transactionId); else { emit ExecutionFailure(transactionId); - tx.executed = false; if (!confirmed) spentToday -= tx.value; } diff --git a/test/compilationTests/milestonetracker/MilestoneTracker.sol b/test/compilationTests/milestonetracker/MilestoneTracker.sol index 856fb1a5..41fa7404 100644 --- a/test/compilationTests/milestonetracker/MilestoneTracker.sol +++ b/test/compilationTests/milestonetracker/MilestoneTracker.sol @@ -360,8 +360,8 @@ contract MilestoneTracker { // Recheck again to not pay twice if (milestone.status == MilestoneStatus.AuthorizedForPayment) revert(); milestone.status = MilestoneStatus.AuthorizedForPayment; - if (!milestone.paymentSource.call.value(0)(milestone.payData)) - revert(); + (bool success,) = milestone.paymentSource.call.value(0)(milestone.payData); + require(success); emit ProposalStatusChanged(_idMilestone, milestone.status); } } diff --git a/test/compilationTests/zeppelin/MultisigWallet.sol b/test/compilationTests/zeppelin/MultisigWallet.sol index 9aac5c53..abad0a01 100644 --- a/test/compilationTests/zeppelin/MultisigWallet.sol +++ b/test/compilationTests/zeppelin/MultisigWallet.sol @@ -60,9 +60,8 @@ contract MultisigWallet is Multisig, Shareable, DayLimit { if (underLimit(_value)) { emit SingleTransact(msg.sender, _value, _to, _data); // yes - just execute the call. - if (!_to.call.value(_value)(_data)) { - revert(); - } + (bool success,) = _to.call.value(_value)(_data); + require(success); return 0; } // determine our operation hash. @@ -82,9 +81,8 @@ contract MultisigWallet is Multisig, Shareable, DayLimit { */ function confirm(bytes32 _h) onlymanyowners(_h) public returns (bool) { if (txs[_h].to != address(0)) { - if (!txs[_h].to.call.value(txs[_h].value)(txs[_h].data)) { - revert(); - } + (bool success,) = txs[_h].to.call.value(txs[_h].value)(txs[_h].data); + require(success); emit MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data); delete txs[_h]; return true; diff --git a/test/libdevcore/UTF8.cpp b/test/libdevcore/UTF8.cpp index 6de4570f..daf47bb0 100644 --- a/test/libdevcore/UTF8.cpp +++ b/test/libdevcore/UTF8.cpp @@ -148,7 +148,7 @@ hélló Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ -ἐ ἑ ἒ ἓ ἔ ἕ +ἐ ἑ ἒ ἓ ἔ ἕ ₠ ₡ ₢ ₣ ₤ ₥ @@ -164,9 +164,9 @@ hélló ␀ ␁ ␂ ␃ ␄ ␅ -⑀ ⑁ ⑂ ⑃ ⑄ +⑀ ⑁ ⑂ ⑃ ⑄ -① ② ③ ④ ⑤ +① ② ③ ④ ⑤ ╘ ╙ ╚ ╛ ╜ ╝ @@ -200,7 +200,7 @@ hélló שּׁ שּׂ אַ אָ אּ -ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ +ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ ﺵ ﺶ ﺷ ﺸ diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index f058458d..85582ece 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -3586,7 +3586,8 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws) char const* sourceCode = R"YY( contract A { function f() public returns (bool) { - return address(this).call(""); + (bool success,) = address(this).call(""); + return success; } } )YY"; @@ -3598,7 +3599,9 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws) char const* sourceCode = R"YY( contract A { function f() public returns (bool) { - return address(this).staticcall(""); + (bool success, bytes memory data) = address(this).staticcall(""); + assert(data.length == 0); + return success; } } )YY"; @@ -4408,7 +4411,8 @@ BOOST_AUTO_TEST_CASE(generic_delegatecall) function doSend(address rec) public payable { bytes4 signature = bytes4(bytes32(keccak256("receive(uint256)"))); - if (rec.delegatecall(abi.encodeWithSelector(signature, 23))) {} + (bool success,) = rec.delegatecall(abi.encodeWithSelector(signature, 23)); + success; } } )**"; @@ -4445,19 +4449,19 @@ BOOST_AUTO_TEST_CASE(generic_staticcall) function assertFunction(uint256 p) public view returns (uint256) { assert(x == p); return x; } } contract C { - function f(address a) public view returns (bool) + function f(address a) public view returns (bool, bytes memory) { return a.staticcall(abi.encodeWithSignature("pureFunction(uint256)", 23)); } - function g(address a) public view returns (bool) + function g(address a) public view returns (bool, bytes memory) { return a.staticcall(abi.encodeWithSignature("viewFunction(uint256)", 23)); } - function h(address a) public view returns (bool) + function h(address a) public view returns (bool, bytes memory) { return a.staticcall(abi.encodeWithSignature("nonpayableFunction(uint256)", 23)); } - function i(address a, uint256 v) public view returns (bool) + function i(address a, uint256 v) public view returns (bool, bytes memory) { return a.staticcall(abi.encodeWithSignature("assertFunction(uint256)", v)); } @@ -4466,11 +4470,11 @@ BOOST_AUTO_TEST_CASE(generic_staticcall) compileAndRun(sourceCode, 0, "A"); u160 const c_addressA = m_contractAddress; compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f(address)", c_addressA), encodeArgs(true)); - ABI_CHECK(callContractFunction("g(address)", c_addressA), encodeArgs(true)); - ABI_CHECK(callContractFunction("h(address)", c_addressA), encodeArgs(false)); - ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 42), encodeArgs(true)); - ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 23), encodeArgs(false)); + ABI_CHECK(callContractFunction("f(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23)); + ABI_CHECK(callContractFunction("g(address)", c_addressA), encodeArgs(true, 0x40, 0x20, 23 + 42)); + ABI_CHECK(callContractFunction("h(address)", c_addressA), encodeArgs(false, 0x40, 0x00)); + ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 42), encodeArgs(true, 0x40, 0x20, 42)); + ABI_CHECK(callContractFunction("i(address,uint256)", c_addressA, 23), encodeArgs(false, 0x40, 0x00)); } } @@ -4570,7 +4574,7 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes) contract sender { constructor() public { rec = new receiver(); } function() external { savedData = msg.data; } - function forward() public returns (bool) { !address(rec).call(savedData); return true; } + function forward() public returns (bool) { address(rec).call(savedData); return true; } function clear() public returns (bool) { delete savedData; return true; } function val() public returns (uint) { return rec.received(); } receiver rec; @@ -4599,18 +4603,21 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length) receiver rec; constructor() public { rec = new receiver(); } function viaCalldata() public returns (uint) { - require(address(rec).call(msg.data)); + (bool success,) = address(rec).call(msg.data); + require(success); return rec.calledLength(); } function viaMemory() public returns (uint) { bytes memory x = msg.data; - require(address(rec).call(x)); + (bool success,) = address(rec).call(x); + require(success); return rec.calledLength(); } bytes s; function viaStorage() public returns (uint) { s = msg.data; - require(address(rec).call(s)); + (bool success,) = address(rec).call(s); + require(success); return rec.calledLength(); } } @@ -10336,7 +10343,8 @@ BOOST_AUTO_TEST_CASE(mutex) // NOTE: It is very bad practice to write this function this way. // Please refer to the documentation of how to do this properly. if (amount > shares) revert(); - if (!msg.sender.call.value(amount)("")) revert(); + (bool success,) = msg.sender.call.value(amount)(""); + require(success); shares -= amount; return shares; } @@ -10344,7 +10352,8 @@ BOOST_AUTO_TEST_CASE(mutex) // NOTE: It is very bad practice to write this function this way. // Please refer to the documentation of how to do this properly. if (amount > shares) revert(); - if (!msg.sender.call.value(amount)("")) revert(); + (bool success,) = msg.sender.call.value(amount)(""); + require(success); shares -= amount; return shares; } @@ -12475,10 +12484,12 @@ BOOST_AUTO_TEST_CASE(bare_call_invalid_address) contract C { /// Calling into non-existant account is successful (creates the account) function f() external returns (bool) { - return address(0x4242).call(""); + (bool success,) = address(0x4242).call(""); + return success; } function h() external returns (bool) { - return address(0x4242).delegatecall(""); + (bool success,) = address(0x4242).delegatecall(""); + return success; } } )YY"; @@ -12490,50 +12501,217 @@ BOOST_AUTO_TEST_CASE(bare_call_invalid_address) { char const* sourceCode = R"YY( contract C { - function f() external returns (bool) { + function f() external returns (bool, bytes memory) { return address(0x4242).staticcall(""); } } )YY"; compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), 0x40, 0x00)); + } +} + +BOOST_AUTO_TEST_CASE(bare_call_return_data) +{ + if (dev::test::Options::get().evmVersion().supportsReturndata()) + { + vector<string> calltypes = {"call", "delegatecall"}; + if (dev::test::Options::get().evmVersion().hasStaticCall()) + calltypes.emplace_back("staticcall"); + for (string const& calltype: calltypes) + { + string sourceCode = R"DELIMITER( + contract A { + constructor() public { + } + function return_bool() public pure returns(bool) { + return true; + } + function return_int32() public pure returns(int32) { + return -32; + } + function return_uint32() public pure returns(uint32) { + return 0x3232; + } + function return_int256() public pure returns(int256) { + return -256; + } + function return_uint256() public pure returns(uint256) { + return 0x256256; + } + function return_bytes4() public pure returns(bytes4) { + return 0xabcd0012; + } + function return_multi() public pure returns(bool, uint32, bytes4) { + return (false, 0x3232, 0xabcd0012); + } + function return_bytes() public pure returns(bytes memory b) { + b = new bytes(2); + b[0] = 0x42; + b[1] = 0x21; + } + } + contract C { + A addr; + constructor() public { + addr = new A(); + } + function f(string memory signature) public returns (bool, bytes memory) { + return address(addr).)DELIMITER" + calltype + R"DELIMITER((abi.encodeWithSignature(signature)); + } + function check_bool() external returns (bool) { + (bool success, bytes memory data) = f("return_bool()"); + assert(success); + bool a = abi.decode(data, (bool)); + assert(a); + return true; + } + function check_int32() external returns (bool) { + (bool success, bytes memory data) = f("return_int32()"); + assert(success); + int32 a = abi.decode(data, (int32)); + assert(a == -32); + return true; + } + function check_uint32() external returns (bool) { + (bool success, bytes memory data) = f("return_uint32()"); + assert(success); + uint32 a = abi.decode(data, (uint32)); + assert(a == 0x3232); + return true; + } + function check_int256() external returns (bool) { + (bool success, bytes memory data) = f("return_int256()"); + assert(success); + int256 a = abi.decode(data, (int256)); + assert(a == -256); + return true; + } + function check_uint256() external returns (bool) { + (bool success, bytes memory data) = f("return_uint256()"); + assert(success); + uint256 a = abi.decode(data, (uint256)); + assert(a == 0x256256); + return true; + } + function check_bytes4() external returns (bool) { + (bool success, bytes memory data) = f("return_bytes4()"); + assert(success); + bytes4 a = abi.decode(data, (bytes4)); + assert(a == 0xabcd0012); + return true; + } + function check_multi() external returns (bool) { + (bool success, bytes memory data) = f("return_multi()"); + assert(success); + (bool a, uint32 b, bytes4 c) = abi.decode(data, (bool, uint32, bytes4)); + assert(a == false && b == 0x3232 && c == 0xabcd0012); + return true; + } + function check_bytes() external returns (bool) { + (bool success, bytes memory data) = f("return_bytes()"); + assert(success); + (bytes memory d) = abi.decode(data, (bytes)); + assert(d.length == 2 && d[0] == 0x42 && d[1] == 0x21); + return true; + } + } + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bool()"))), encodeArgs(true, 0x40, 0x20, true)); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_int32()"))), encodeArgs(true, 0x40, 0x20, u256(-32))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_uint32()"))), encodeArgs(true, 0x40, 0x20, u256(0x3232))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_int256()"))), encodeArgs(true, 0x40, 0x20, u256(-256))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_uint256()"))), encodeArgs(true, 0x40, 0x20, u256(0x256256))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bytes4()"))), encodeArgs(true, 0x40, 0x20, u256(0xabcd0012) << (28*8))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_multi()"))), encodeArgs(true, 0x40, 0x60, false, u256(0x3232), u256(0xabcd0012) << (28*8))); + ABI_CHECK(callContractFunction("f(string)", encodeDyn(string("return_bytes()"))), encodeArgs(true, 0x40, 0x60, 0x20, 0x02, encode(bytes{0x42,0x21}, false))); + ABI_CHECK(callContractFunction("check_bool()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_int32()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_uint32()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_int256()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_uint256()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_bytes4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_multi()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("check_bytes()"), encodeArgs(true)); + } } } BOOST_AUTO_TEST_CASE(delegatecall_return_value) { - char const* sourceCode = R"DELIMITER( - contract C { - uint value; - function set(uint _value) external { - value = _value; - } - function get() external view returns (uint) { - return value; - } - function get_delegated() external returns (bool) { - return address(this).delegatecall(abi.encodeWithSignature("get()")); - } - function assert0() external view { - assert(value == 0); + if (dev::test::Options::get().evmVersion().supportsReturndata()) + { + char const* sourceCode = R"DELIMITER( + contract C { + uint value; + function set(uint _value) external { + value = _value; + } + function get() external view returns (uint) { + return value; + } + function get_delegated() external returns (bool, bytes memory) { + return address(this).delegatecall(abi.encodeWithSignature("get()")); + } + function assert0() external view { + assert(value == 0); + } + function assert0_delegated() external returns (bool, bytes memory) { + return address(this).delegatecall(abi.encodeWithSignature("assert0()")); + } } - function assert0_delegated() external returns (bool) { - return address(this).delegatecall(abi.encodeWithSignature("assert0()")); + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1), 0x40, 0x00)); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1), 0x40, 0x20, 0x00)); + ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0), 0x40, 0x00)); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1), 0x40, 0x20, 1)); + ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0), 0x40, 0x00)); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1), 0x40, 0x20, 42)); + } + else + { + char const* sourceCode = R"DELIMITER( + contract C { + uint value; + function set(uint _value) external { + value = _value; + } + function get() external view returns (uint) { + return value; + } + function get_delegated() external returns (bool) { + (bool success,) = address(this).delegatecall(abi.encodeWithSignature("get()")); + return success; + } + function assert0() external view { + assert(value == 0); + } + function assert0_delegated() external returns (bool) { + (bool success,) = address(this).delegatecall(abi.encodeWithSignature("assert0()")); + return success; + } } - } - )DELIMITER"; - compileAndRun(sourceCode, 0, "C"); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); - ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); - ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); - ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + )DELIMITER"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("set(uint256)", u256(1)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + ABI_CHECK(callContractFunction("set(uint256)", u256(42)), encodeArgs()); + ABI_CHECK(callContractFunction("get()"), encodeArgs(u256(42))); + ABI_CHECK(callContractFunction("assert0_delegated()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("get_delegated()"), encodeArgs(u256(1))); + } } BOOST_AUTO_TEST_CASE(function_types_sig) @@ -13302,7 +13480,8 @@ BOOST_AUTO_TEST_CASE(abi_encode_call) uint[] memory b = new uint[](2); b[0] = 6; b[1] = 7; - require(address(this).call(abi.encodeWithSignature("c(uint256,uint256[])", a, b))); + (bool success,) = address(this).call(abi.encodeWithSignature("c(uint256,uint256[])", a, b)); + require(success); return x; } } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 387505a5..af8465fc 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -438,7 +438,8 @@ BOOST_AUTO_TEST_CASE(address_staticcall) char const* sourceCode = R"( contract C { function f() public view returns(bool) { - return address(0x4242).staticcall(""); + (bool success,) = address(0x4242).staticcall(""); + return success; } } )"; @@ -464,6 +465,58 @@ BOOST_AUTO_TEST_CASE(address_staticcall_value) } } +BOOST_AUTO_TEST_CASE(address_call_full_return_type) +{ + char const* sourceCode = R"( + contract C { + function f() public { + (bool success, bytes memory m) = address(0x4242).call(""); + success; m; + } + } + )"; + + if (dev::test::Options::get().evmVersion().supportsReturndata()) + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + else + CHECK_ERROR(sourceCode, TypeError, "Type inaccessible dynamic type is not implicitly convertible to expected type bytes memory."); +} + +BOOST_AUTO_TEST_CASE(address_delegatecall_full_return_type) +{ + char const* sourceCode = R"( + contract C { + function f() public { + (bool success, bytes memory m) = address(0x4242).delegatecall(""); + success; m; + } + } + )"; + + if (dev::test::Options::get().evmVersion().supportsReturndata()) + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + else + CHECK_ERROR(sourceCode, TypeError, "Type inaccessible dynamic type is not implicitly convertible to expected type bytes memory."); +} + + +BOOST_AUTO_TEST_CASE(address_staticcall_full_return_type) +{ + if (dev::test::Options::get().evmVersion().hasStaticCall()) + { + char const* sourceCode = R"( + contract C { + function f() public view { + (bool success, bytes memory m) = address(0x4242).staticcall(""); + success; m; + } + } + )"; + + CHECK_SUCCESS_NO_WARNINGS(sourceCode); + } +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index b97df972..d77050cb 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -647,7 +647,7 @@ BOOST_AUTO_TEST_CASE(dev_documenting_no_paramname) contract test { /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter - /// @param + /// @param function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; @@ -675,7 +675,7 @@ BOOST_AUTO_TEST_CASE(dev_documenting_no_param_description) contract test { /// @dev Multiplies a number by 7 and adds second parameter /// @param a Documentation for the first parameter - /// @param second + /// @param second function mul(uint a, uint second) public returns (uint d) { return a * 7 + second; } } )"; diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index d993b92e..b7ea1efc 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -103,7 +103,8 @@ BOOST_AUTO_TEST_CASE(address_staticcall) string text = R"( contract C { function i() view public returns (bool) { - return address(0x4242).staticcall(""); + (bool success,) = address(0x4242).staticcall(""); + return success; } } )"; diff --git a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol index 7e8c4501..52a8b3d7 100644 --- a/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/mappingReturn/unnamed_err.sol @@ -2,4 +2,4 @@ contract C { function f() internal pure returns (mapping(uint=>uint) storage) {} } // ---- -// TypeError: (53-72): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (53-80): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol index 5fde497c..cad9b8e8 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/assembly_err.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// TypeError: (87-88): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (87-96): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol index a0047782..42342979 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/modifier_err.sol @@ -18,5 +18,5 @@ contract C { } } // ---- -// TypeError: (249-250): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. -// TypeError: (367-368): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (249-258): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. +// TypeError: (367-376): This variable is of storage pointer type and might be returned without assignment and could be used uninitialized. Assign the variable (potentially from itself) to fix this error. diff --git a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol index e1ea6989..b80849ce 100644 --- a/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol +++ b/test/libsolidity/syntaxTests/dataLocations/data_location_in_function_type_fail.sol @@ -5,5 +5,5 @@ library L { } // ---- -// TypeError: (66-72): Data location must be "memory" for parameter in function, but "calldata" was given. -// TypeError: (159-165): Data location must be "memory" for parameter in function, but "storage" was given. +// TypeError: (66-81): Data location must be "memory" for parameter in function, but "calldata" was given. +// TypeError: (159-173): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol index d914fa5b..d30bde3f 100644 --- a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_memory.sol @@ -2,4 +2,4 @@ contract test { function f(bytes memory) external; } // ---- -// TypeError: (31-36): Data location must be "calldata" for parameter in external function, but "memory" was given. +// TypeError: (31-43): Data location must be "calldata" for parameter in external function, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol index adb7e52e..7dc5ba6d 100644 --- a/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol +++ b/test/libsolidity/syntaxTests/dataLocations/externalFunction/function_argument_location_specifier_test_external_storage.sol @@ -2,4 +2,4 @@ contract test { function f(bytes storage) external; } // ---- -// TypeError: (31-36): Data location must be "calldata" for parameter in external function, but "storage" was given. +// TypeError: (31-44): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol b/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol index 71756ebb..bc14aa1f 100644 --- a/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol +++ b/test/libsolidity/syntaxTests/dataLocations/function_argument_location_specifier_test_non_reference_type.sol @@ -2,4 +2,4 @@ contract test { function f(bytes4 memory) public; } // ---- -// TypeError: (31-37): Data location can only be specified for array, struct or mapping types, but "memory" was given. +// TypeError: (31-44): Data location can only be specified for array, struct or mapping types, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol index 771f1525..da3abff4 100644 --- a/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol +++ b/test/libsolidity/syntaxTests/dataLocations/internalFunction/function_argument_location_specifier_test_internal_calldata.sol @@ -2,4 +2,4 @@ contract test { function f(bytes calldata) internal; } // ---- -// TypeError: (31-36): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given. +// TypeError: (31-45): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol index 9a6b8b7c..2de0082a 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol @@ -2,4 +2,4 @@ library test { function f(bytes memory) external; } // ---- -// TypeError: (30-35): Data location must be "storage" or "calldata" for parameter in external function, but "memory" was given. +// TypeError: (30-42): Data location must be "storage" or "calldata" for parameter in external function, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol index 99b89dfc..c4b81f98 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryInternalFunction/function_argument_location_specifier_test_internal_calldata.sol @@ -2,4 +2,4 @@ library test { function f(bytes calldata) internal pure {} } // ---- -// TypeError: (30-35): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given. +// TypeError: (30-44): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol index efc92cf3..3aba870f 100644 --- a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_calldata.sol @@ -2,4 +2,4 @@ contract test { function f(bytes calldata) public; } // ---- -// TypeError: (31-36): Data location must be "memory" for parameter in function, but "calldata" was given. +// TypeError: (31-45): Data location must be "memory" for parameter in function, but "calldata" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol index b954ea78..1c033a69 100644 --- a/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol +++ b/test/libsolidity/syntaxTests/dataLocations/publicFunction/function_argument_location_specifier_test_public_storage.sol @@ -2,4 +2,4 @@ contract test { function f(bytes storage) public; } // ---- -// TypeError: (31-36): Data location must be "memory" for parameter in function, but "storage" was given. +// TypeError: (31-44): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol index aaf6028a..3f729a6a 100644 --- a/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_array_indexed_v2.sol @@ -4,4 +4,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (59-65): Indexed reference types cannot yet be used with ABIEncoderV2. +// TypeError: (59-73): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol index ffae5b9c..f05b884e 100644 --- a/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_nested_array_indexed_v2.sol @@ -4,4 +4,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (59-67): Indexed reference types cannot yet be used with ABIEncoderV2. +// TypeError: (59-75): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol index 69ee5017..7332cb3b 100644 --- a/test/libsolidity/syntaxTests/events/event_struct_indexed.sol +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed.sol @@ -3,4 +3,4 @@ contract c { event E(S indexed); } // ---- -// TypeError: (51-52): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. +// TypeError: (51-60): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol index a8e0837f..a1d8cf04 100644 --- a/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol +++ b/test/libsolidity/syntaxTests/events/event_struct_indexed_v2.sol @@ -5,4 +5,4 @@ contract c { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (85-86): Indexed reference types cannot yet be used with ABIEncoderV2. +// TypeError: (85-94): Indexed reference types cannot yet be used with ABIEncoderV2. diff --git a/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol index e8134539..92ec4eb7 100644 --- a/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol +++ b/test/libsolidity/syntaxTests/globalFunctions/call_with_wrong_arg_count.sol @@ -1,13 +1,17 @@ contract C { function f() public { - require(address(this).call()); - require(address(this).call(bytes4(0x12345678))); - require(address(this).call(uint(1))); - require(address(this).call(uint(1), uint(2))); + (bool success,) = address(this).call(); + require(success); + (success,) = address(this).call(bytes4(0x12345678)); + require(success); + (success,) = address(this).call(uint(1)); + require(success); + (success,) = address(this).call(uint(1), uint(2)); + require(success); } } // ---- -// TypeError: (55-75): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. -// TypeError: (113-131): Invalid type for argument in function call. Invalid implicit conversion from bytes4 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. -// TypeError: (170-177): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. -// TypeError: (197-233): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (65-85): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (153-171): Invalid type for argument in function call. Invalid implicit conversion from bytes4 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (240-247): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (297-333): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol index 2b424d53..655d5f4c 100644 --- a/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol +++ b/test/libsolidity/syntaxTests/globalFunctions/callcode_with_wrong_arg_count.sol @@ -1,11 +1,14 @@ contract C { function f() public { - require(address(this).callcode()); - require(address(this).callcode(uint(1))); - require(address(this).callcode(uint(1), uint(2))); + (bool success,) = address(this).callcode(); + require(success); + (success,) = address(this).callcode(uint(1)); + require(success); + (success,) = address(this).callcode(uint(1), uint(2)); + require(success); } } // ---- -// TypeError: (55-79): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. -// TypeError: (121-128): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. -// TypeError: (148-188): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (65-89): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (161-168): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (218-258): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol b/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol index be0347de..fa524b99 100644 --- a/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol +++ b/test/libsolidity/syntaxTests/globalFunctions/delegatecall_with_wrong_arg_count.sol @@ -1,11 +1,14 @@ contract C { function f() public { - require(address(this).delegatecall()); - require(address(this).delegatecall(uint(1))); - require(address(this).delegatecall(uint(1), uint(2))); + (bool success,) = address(this).delegatecall(); + require(success); + (success,) = address(this).delegatecall(uint(1)); + require(success); + (success,) = address(this).delegatecall(uint(1), uint(2)); + require(success); } } // ---- -// TypeError: (55-83): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. -// TypeError: (129-136): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. -// TypeError: (156-200): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (65-93): Wrong argument count for function call: 0 arguments given but expected 1. This function requires a single bytes argument. Use "" as argument to provide empty calldata. +// TypeError: (169-176): Invalid type for argument in function call. Invalid implicit conversion from uint256 to bytes memory requested. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. +// TypeError: (226-270): Wrong argument count for function call: 2 arguments given but expected 1. This function requires a single bytes argument. If all your arguments are value types, you can use abi.encode(...) to properly generate it. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol index 9fd09dd7..73b608ae 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/041_functions_with_stucts_of_non_external_types_in_interface.sol @@ -6,4 +6,4 @@ contract C { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (103-104): Internal or recursive type is not allowed for public or external functions. +// TypeError: (103-111): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol index 435a02ef..607a4a68 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/042_functions_with_stucts_of_non_external_types_in_interface_2.sol @@ -6,4 +6,4 @@ contract C { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (105-106): Internal or recursive type is not allowed for public or external functions. +// TypeError: (105-113): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol index b9dc7c2e..da73d8dd 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/043_functions_with_stucts_of_non_external_types_in_interface_nested.sol @@ -7,4 +7,4 @@ contract C { } // ---- // Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. -// TypeError: (132-133): Internal or recursive type is not allowed for public or external functions. +// TypeError: (132-140): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol index 221e5fa4..b9a64c2a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/045_returning_multi_dimensional_arrays.sol @@ -2,4 +2,4 @@ contract C { function f() public pure returns (string[][] memory) {} } // ---- -// TypeError: (51-61): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. +// TypeError: (51-68): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol index 75423bc9..ccee6093 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/046_returning_multi_dimensional_static_arrays.sol @@ -2,4 +2,4 @@ contract C { function f() public pure returns (uint[][2] memory) {} } // ---- -// TypeError: (51-60): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. +// TypeError: (51-67): This type is only supported in the new experimental ABI encoder. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol index 9c42bc8f..b63d2a55 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/413_address_methods.sol @@ -2,11 +2,11 @@ contract C { function f() public { address addr; uint balance = addr.balance; - bool callRet = addr.call(""); - bool delegatecallRet = addr.delegatecall(""); + (bool callSuc,) = addr.call(""); + (bool delegatecallSuc,) = addr.delegatecall(""); bool sendRet = addr.send(1); addr.transfer(1); - balance; callRet; delegatecallRet; sendRet; + balance; callSuc; delegatecallSuc; sendRet; } } // ---- diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_empty.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_empty.sol new file mode 100644 index 00000000..9972f01d --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_empty.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure { + abi.decode("abc", ()); + } +} +// ---- +// Warning: (52-73): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_single_return.sol b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_single_return.sol new file mode 100644 index 00000000..654b7873 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abidecode/abi_decode_single_return.sol @@ -0,0 +1,5 @@ +contract C { + function f() public pure returns (bool) { + return abi.decode("abc", (uint)) == 2; + } +} diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol index c97f588e..6e0b6db4 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol @@ -1,13 +1,13 @@ contract C { function f() public pure { - bool a = address(this).call(abi.encode(address(this).delegatecall, super)); - bool b = address(this).delegatecall(abi.encode(log0, tx, mulmod)); - a; b; + (bool a,) = address(this).call(abi.encode(address(this).delegatecall, super)); + (a,) = address(this).delegatecall(abi.encode(log0, tx, mulmod)); + a; } } // ---- -// TypeError: (91-117): This type cannot be encoded. -// TypeError: (119-124): This type cannot be encoded. -// TypeError: (183-187): This type cannot be encoded. -// TypeError: (189-191): This type cannot be encoded. -// TypeError: (193-199): This type cannot be encoded. +// TypeError: (94-120): This type cannot be encoded. +// TypeError: (122-127): This type cannot be encoded. +// TypeError: (184-188): This type cannot be encoded. +// TypeError: (190-192): This type cannot be encoded. +// TypeError: (194-200): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol index 89d1ddd9..c8f9185c 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (91-92): Internal or recursive type is not allowed for public or external functions. +// TypeError: (91-99): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol index 1c31e180..a8b7ac75 100644 --- a/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol +++ b/test/libsolidity/syntaxTests/structs/recursion/return_recursive_structs2.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (94-95): Internal or recursive type is not allowed for public or external functions. +// TypeError: (94-102): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol index 02beefec..2b5e6b05 100644 --- a/test/libsolidity/syntaxTests/types/mapping/argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/argument_external.sol @@ -3,4 +3,4 @@ contract C { } } // ---- -// TypeError: (28-49): Data location must be "calldata" for parameter in external function, but "storage" was given. +// TypeError: (28-57): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol index 3939cf26..32f11fe9 100644 --- a/test/libsolidity/syntaxTests/types/mapping/argument_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/argument_public.sol @@ -3,4 +3,4 @@ contract C { } } // ---- -// TypeError: (28-49): Data location must be "memory" for parameter in function, but "storage" was given. +// TypeError: (28-57): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol index ef0046d4..0863653c 100644 --- a/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_external.sol @@ -3,4 +3,4 @@ contract C { } } // ---- -// TypeError: (28-51): Data location must be "calldata" for parameter in external function, but "storage" was given. +// TypeError: (28-59): Data location must be "calldata" for parameter in external function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol index fb3f25a4..99c83d8a 100644 --- a/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/array_argument_public.sol @@ -3,4 +3,4 @@ contract C { } } // ---- -// TypeError: (28-51): Data location must be "memory" for parameter in function, but "storage" was given. +// TypeError: (28-59): Data location must be "memory" for parameter in function, but "storage" was given. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol index 349a4f97..34f95701 100644 --- a/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_argument_external.sol @@ -3,5 +3,5 @@ contract C { } } // ---- -// TypeError: (37-56): Data location must be "memory" for parameter in function, but "storage" was given. -// TypeError: (37-56): Internal type cannot be used for external function type. +// TypeError: (37-64): Data location must be "memory" for parameter in function, but "storage" was given. +// TypeError: (37-64): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol index 108d9861..aed9b387 100644 --- a/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/function_type_return_external.sol @@ -3,5 +3,5 @@ contract C { } } // ---- -// TypeError: (57-76): Data location must be "memory" for return parameter in function, but "storage" was given. -// TypeError: (57-76): Internal type cannot be used for external function type. +// TypeError: (57-84): Data location must be "memory" for return parameter in function, but "storage" was given. +// TypeError: (57-84): Internal type cannot be used for external function type. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol index e78c6930..1098008d 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_external.sol @@ -3,4 +3,4 @@ library L { } } // ---- -// TypeError: (27-48): Type is required to live outside storage. +// TypeError: (27-56): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol index 56393b68..dedd4f68 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_argument_public.sol @@ -3,4 +3,4 @@ library L { } } // ---- -// TypeError: (27-48): Type is required to live outside storage. +// TypeError: (27-56): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol index f5691675..da5a911b 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_external.sol @@ -3,4 +3,4 @@ library L { } } // ---- -// TypeError: (27-50): Type is required to live outside storage. +// TypeError: (27-58): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol index bb06d4bc..adb62203 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_array_argument_public.sol @@ -3,4 +3,4 @@ library L { } } // ---- -// TypeError: (27-50): Type is required to live outside storage. +// TypeError: (27-58): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol index a3bb1c32..1e756819 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_external.sol @@ -7,4 +7,4 @@ library L // ---- // TypeError: (27-58): Type is required to live outside storage. // TypeError: (60-91): Type is required to live outside storage. -// TypeError: (123-144): Type is required to live outside storage. +// TypeError: (123-152): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol index ac52d677..357751a0 100644 --- a/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/library_return_public.sol @@ -7,4 +7,4 @@ library L // ---- // TypeError: (27-58): Type is required to live outside storage. // TypeError: (60-91): Type is required to live outside storage. -// TypeError: (121-142): Type is required to live outside storage. +// TypeError: (121-150): Type is required to live outside storage. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol index 9b96fd3a..0c29ebd8 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_array_data_location_function_param_external.sol @@ -2,5 +2,5 @@ contract c { function f1(mapping(uint => uint)[] calldata) pure external {} } // ---- -// TypeError: (29-52): Type is required to live outside storage. -// TypeError: (29-52): Internal or recursive type is not allowed for public or external functions. +// TypeError: (29-61): Type is required to live outside storage. +// TypeError: (29-61): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol index adcfee2a..c050f8e9 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_external.sol @@ -2,5 +2,5 @@ contract c { function f1(mapping(uint => uint) calldata) pure external returns (mapping(uint => uint) memory) {} } // ---- -// TypeError: (29-50): Type is required to live outside storage. -// TypeError: (29-50): Internal or recursive type is not allowed for public or external functions. +// TypeError: (29-59): Type is required to live outside storage. +// TypeError: (29-59): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol index e98c1fe8..b63868b8 100644 --- a/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol +++ b/test/libsolidity/syntaxTests/types/mapping/mapping_data_location_function_param_public.sol @@ -2,5 +2,5 @@ contract c { function f3(mapping(uint => uint) memory) view public {} } // ---- -// TypeError: (29-50): Type is required to live outside storage. -// TypeError: (29-50): Internal or recursive type is not allowed for public or external functions. +// TypeError: (29-57): Type is required to live outside storage. +// TypeError: (29-57): Internal or recursive type is not allowed for public or external functions. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/do_while.sol b/test/libsolidity/syntaxTests/variableDeclaration/do_while.sol new file mode 100644 index 00000000..8fc48b33 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/do_while.sol @@ -0,0 +1,12 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + do + uint y; + while (x > 0); + } +} +// ---- +// SyntaxError: (81-87): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/else.sol b/test/libsolidity/syntaxTests/variableDeclaration/else.sol new file mode 100644 index 00000000..914e0c0c --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/else.sol @@ -0,0 +1,13 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + if (x > 0) + {uint y;} + else + uint z; + } +} +// ---- +// SyntaxError: (109-115): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/for.sol b/test/libsolidity/syntaxTests/variableDeclaration/for.sol new file mode 100644 index 00000000..bc137f93 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/for.sol @@ -0,0 +1,11 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + for (uint i = 0; i < x; ++i) + uint y; + } +} +// ---- +// SyntaxError: (107-113): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/if.sol b/test/libsolidity/syntaxTests/variableDeclaration/if.sol new file mode 100644 index 00000000..75ab2026 --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/if.sol @@ -0,0 +1,11 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + if (x > 0) + uint y; + } +} +// ---- +// SyntaxError: (89-95): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/variableDeclaration/while.sol b/test/libsolidity/syntaxTests/variableDeclaration/while.sol new file mode 100644 index 00000000..2997d80c --- /dev/null +++ b/test/libsolidity/syntaxTests/variableDeclaration/while.sol @@ -0,0 +1,11 @@ +pragma solidity >0.4.24; + +contract C +{ + function f(uint x) public pure { + while (x > 0) + uint y; + } +} +// ---- +// SyntaxError: (92-98): Variable declarations can only be used inside blocks. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol index 2cb185c9..2503a319 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions.sol @@ -3,8 +3,10 @@ contract C { address(this).transfer(1); require(address(this).send(2)); selfdestruct(address(this)); - require(address(this).delegatecall("")); - require(address(this).call("")); + (bool success,) = address(this).delegatecall(""); + require(success); + (success,) = address(this).call(""); + require(success); } function g() pure public { bytes32 x = keccak256("abc"); diff --git a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol index 9b00fd6d..f951feb4 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_functions_view_fail.sol @@ -9,15 +9,17 @@ contract C { selfdestruct(address(this)); } function i() view public { - require(address(this).delegatecall("")); + (bool success,) = address(this).delegatecall(""); + require(success); } function j() view public { - require(address(this).call("")); + (bool success,) = address(this).call(""); + require(success); } } // ---- // TypeError: (52-77): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. // TypeError: (132-153): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. // TypeError: (201-228): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError: (283-313): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. -// TypeError: (369-391): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (293-323): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. +// TypeError: (414-436): Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. |