diff options
40 files changed, 193 insertions, 227 deletions
diff --git a/Changelog.md b/Changelog.md index 3e63108e..07b74ddc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,15 +16,18 @@ Breaking Changes: ``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. * General: Remove assembly instruction aliases ``sha3`` and ``suicide`` + * General: C99-style scoping rules are enforced now. This was already the case in the experimental 0.5.0 mode. * Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence. * Parser: Disallow trailing dots that are not followed by a number. * Type Checker: Disallow arithmetic operations for boolean variables. * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. + * Syntax Checker: Named return values in function types are an error. Language Features: * General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions. * General: Support ``pop()`` for storage arrays. + * General: Scoping rules now follow the C99-style. Compiler Features: * Type Checker: Show named argument in case of error. diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 856284db..2fb207c7 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -277,6 +277,106 @@ All together, the encoding is (newline after function selector and each 32-bytes 000000000000000000000000000000000000000000000000000000000000000d 48656c6c6f2c20776f726c642100000000000000000000000000000000000000 +Let us apply the same principle to encode the data for a function with a signature ``g(uint[][],string[])`` with values ``([[1, 2], [3]], ["one", "two", "three"])`` but start from the most atomic parts of the encoding: + +First we encode the length and data of the first embeded dynamic array ``[1, 2]`` of the first root array ``[[1, 2], [3]]``: + + - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first array, 2; the elements themselves are ``1`` and ``2``) + - ``0x0000000000000000000000000000000000000000000000000000000000000001`` (first element) + - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (second element) + +Then we encode the length and data of the second embeded dynamic array ``[3]`` of the first root array ``[[1, 2], [3]]``: + + - ``0x0000000000000000000000000000000000000000000000000000000000000001`` (number of elements in the second array, 1; the element is ``3``) + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (first element) + +Then we need to find the offsets ``a`` and ``b`` for their respective dynamic arrays ``[1, 2]`` and ``[3]``. To calculate the offsets we can take a look at the encoded data of the first root array ``[[1, 2], [3]]`` enumerating each line in the encoding: + +:: + + 0 - a - offset of [1, 2] + 1 - b - offset of [3] + 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] + 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 + 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 + 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] + 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 + +Offset ``a`` points to the start of the content of the array ``[1, 2]`` which is line 2 (64 bytes); thus ``a = 0x0000000000000000000000000000000000000000000000000000000000000040``. + +Offset ``b`` points to the start of the content of the array ``[3]`` which is line 5 (160 bytes); thus ``b = 0x00000000000000000000000000000000000000000000000000000000000000a0``. + + +Then we encode the embeded strings of the second root array: + + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"one"``) + - ``0x6f6e650000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"one"``) + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"two"``) + - ``0x74776f0000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"two"``) + - ``0x0000000000000000000000000000000000000000000000000000000000000005`` (number of characters in word ``"three"``) + - ``0x7468726565000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"three"``) + +In parallel to the first root array, since strings are dynamic elements we need to find their offsets ``c``, ``d`` and ``e``: + +:: + + 0 - c - offset for "one" + 1 - d - offset for "two" + 2 - e - offset for "three" + 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" + 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" + 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" + 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" + 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" + 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" + +Offset ``c`` points to the start of the content of the string ``"one"`` which is line 3 (96 bytes); thus ``c = 0x0000000000000000000000000000000000000000000000000000000000000060``. + +Offset ``d`` points to the start of the content of the string ``"two"`` which is line 5 (160 bytes); thus ``d = 0x00000000000000000000000000000000000000000000000000000000000000a0``. + +Offset ``e`` points to the start of the content of the string ``"three"`` which is line 7 (224 bytes); thus ``e = 0x00000000000000000000000000000000000000000000000000000000000000e0``. + + +Note that the encodings of the embeded elements of the root arrays are not dependent on each other and have the same encodings for a fuction with a signature ``g(string[],uint[][])``. + +Then we encode the length of the first root array: + + - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first root array, 2; the elements themselves are ``[1, 2]`` and ``[3]``) + +Then we encode the length of the second root array: + + - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of strings in the second root array, 3; the strings themselves are ``"one"``, ``"two"`` and ``"three"``) + +Finally we find the offsets ``f`` and ``g`` for their respective root dynamic arrays ``[[1, 2], [3]]`` and ``["one", "two", "three"]``, and assemble parts in the correct order: + +:: + + 0x2289b18c - function signature + 0 - f - offset of [[1, 2], [3]] + 1 - g - offset of ["one", "two", "three"] + 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]] + 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2] + 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3] + 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] + 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 + 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 + 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] + 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 + 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"] + 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one" + 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two" + 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three" + 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" + 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" + 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" + 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" + 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" + 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" + +Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` which is line 2 (64 bytes); thus ``f = 0x0000000000000000000000000000000000000000000000000000000000000040``. + +Offset ``g`` points to the start of the content of the array ``["one", "two", "three"]`` which is line 10 (320 bytes); thus ``g = 0x0000000000000000000000000000000000000000000000000000000000000140``. + Events ====== diff --git a/docs/contracts.rst b/docs/contracts.rst index 4dd185aa..5e7eab80 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1323,6 +1323,7 @@ custom types without the overhead of external function calls: if (carry > 0) { // too bad, we have to add a limb uint[] memory newLimbs = new uint[](r.limbs.length + 1); + uint i; for (i = 0; i < r.limbs.length; ++i) newLimbs[i] = r.limbs[i]; newLimbs[i] = carry; diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 7849d15a..cc1f7ca5 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -325,74 +325,7 @@ is ``false``. The default value for the ``uint`` or ``int`` types is ``0``. For element will be initialized to the default value corresponding to its type. Finally, for dynamically-sized arrays, ``bytes`` and ``string``, the default value is an empty array or string. -A variable declared anywhere within a function will be in scope for the *entire function*, regardless of where it is declared -(this will change soon, see below). -This happens because Solidity inherits its scoping rules from JavaScript. -This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block. -As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``: - -:: - - // This will not compile - - pragma solidity ^0.4.16; - - contract ScopingErrors { - function scoping() public { - uint i = 0; - - while (i++ < 1) { - uint same1 = 0; - } - - while (i++ < 2) { - uint same1 = 0;// Illegal, second declaration of same1 - } - } - - function minimalScoping() public { - { - uint same2 = 0; - } - - { - uint same2 = 0;// Illegal, second declaration of same2 - } - } - - function forLoopScoping() public { - for (uint same3 = 0; same3 < 1; same3++) { - } - - for (uint same3 = 0; same3 < 1; same3++) {// Illegal, second declaration of same3 - } - } - } - -In addition to this, if a variable is declared, it will be initialized at the beginning of the function to its default value. -As a result, the following code is legal, despite being poorly written: - -:: - - pragma solidity ^0.4.0; - - contract C { - function foo() public pure returns (uint) { - // baz is implicitly initialized as 0 - uint bar = 5; - if (true) { - bar += baz; - } else { - uint baz = 10;// never executes - } - return bar;// returns 5 - } - } - -Scoping starting from Version 0.5.0 ------------------------------------ - -Starting from version 0.5.0, Solidity will change to the more widespread scoping rules of C99 +Scoping in Solidity follows the widespread scoping rules of C99 (and many other languages): Variables are visible from the point right after their declaration until the end of a ``{ }``-block. As an exception to this rule, variables declared in the initialization part of a for-loop are only visible until the end of the for-loop. @@ -401,17 +334,12 @@ Variables and other items declared outside of a code block, for example function user-defined types, etc., do not change their scoping behaviour. This means you can use state variables before they are declared and call functions recursively. -These rules are already introduced now as an experimental feature. - As a consequence, the following examples will compile without warnings, since -the two variables have the same name but disjoint scopes. In non-0.5.0-mode, -they have the same scope (the function ``minimalScoping``) and thus it does -not compile there. +the two variables have the same name but disjoint scopes. :: - pragma solidity ^0.4.0; - pragma experimental "v0.5.0"; + pragma solidity >0.4.24; contract C { function minimalScoping() pure public { { @@ -430,8 +358,7 @@ In any case, you will get a warning about the outer variable being shadowed. :: - pragma solidity ^0.4.0; - pragma experimental "v0.5.0"; + pragma solidity >0.4.24; contract C { function f() pure public returns (uint) { uint x = 1; @@ -443,6 +370,24 @@ In any case, you will get a warning about the outer variable being shadowed. } } +.. warning:: + Before version 0.5.0 Solidity followed the same scoping rules as JavaScript, that is, a variable declared anywhere within a function would be in scope + for the entire function, regardless where it was declared. Note that this is a breaking change. The following example shows a code snippet that used + to compile but leads to an error starting from version 0.5.0. + + :: + + // This will not compile + + pragma solidity >0.4.24; + contract C { + function f() pure public returns (uint) { + x = 2; + uint x; + return x; + } + } + .. index:: ! exception, ! throw, ! assert, ! require, ! revert Error handling: Assert, Require, Revert and Exceptions diff --git a/libsolidity/analysis/DeclarationContainer.h b/libsolidity/analysis/DeclarationContainer.h index e4b3320a..a3e0bd0a 100644 --- a/libsolidity/analysis/DeclarationContainer.h +++ b/libsolidity/analysis/DeclarationContainer.h @@ -58,7 +58,7 @@ public: /// @returns whether declaration is valid, and if not also returns previous declaration. Declaration const* conflictingDeclaration(Declaration const& _declaration, ASTString const* _name = nullptr) const; - /// Activates a previously inactive (invisible) variable. To be used in C99 scpoing for + /// Activates a previously inactive (invisible) variable. To be used in C99 scoping for /// VariableDeclarationStatements. void activateVariable(ASTString const& _name); diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 0a356f04..b856544a 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -54,11 +54,10 @@ NameAndTypeResolver::NameAndTypeResolver( bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode const* _currentScope) { - bool useC99Scoping = _sourceUnit.annotation().experimentalFeatures.count(ExperimentalFeature::V050); // The helper registers all declarations in m_scopes as a side-effect of its construction. try { - DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, useC99Scoping, m_errorReporter, _currentScope); + DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, _currentScope); } catch (FatalError const&) { @@ -449,11 +448,9 @@ string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const DeclarationRegistrationHelper::DeclarationRegistrationHelper( map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes, ASTNode& _astRoot, - bool _useC99Scoping, ErrorReporter& _errorReporter, ASTNode const* _currentScope ): - m_useC99Scoping(_useC99Scoping), m_scopes(_scopes), m_currentScope(_currentScope), m_errorReporter(_errorReporter) @@ -629,29 +626,25 @@ void DeclarationRegistrationHelper::endVisit(ModifierDefinition&) bool DeclarationRegistrationHelper::visit(Block& _block) { _block.setScope(m_currentScope); - if (m_useC99Scoping) - enterNewSubScope(_block); + enterNewSubScope(_block); return true; } void DeclarationRegistrationHelper::endVisit(Block&) { - if (m_useC99Scoping) - closeCurrentScope(); + closeCurrentScope(); } bool DeclarationRegistrationHelper::visit(ForStatement& _for) { _for.setScope(m_currentScope); - if (m_useC99Scoping) - enterNewSubScope(_for); + enterNewSubScope(_for); return true; } void DeclarationRegistrationHelper::endVisit(ForStatement&) { - if (m_useC99Scoping) - closeCurrentScope(); + closeCurrentScope(); } void DeclarationRegistrationHelper::endVisit(VariableDeclarationStatement& _variableDeclarationStatement) @@ -716,9 +709,8 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio if (fun->isConstructor()) warnAboutShadowing = false; - // Register declaration as inactive if we are in block scope and C99 mode. + // Register declaration as inactive if we are in block scope. bool inactive = - m_useC99Scoping && (dynamic_cast<Block const*>(m_currentScope) || dynamic_cast<ForStatement const*>(m_currentScope)); registerDeclaration(*m_scopes[m_currentScope], _declaration, nullptr, nullptr, warnAboutShadowing, inactive, m_errorReporter); diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index 3d10fbd8..8178ee17 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -69,7 +69,7 @@ public: /// that create their own scope. /// @returns false in case of error. bool updateDeclaration(Declaration const& _declaration); - /// Activates a previously inactive (invisible) variable. To be used in C99 scpoing for + /// Activates a previously inactive (invisible) variable. To be used in C99 scoping for /// VariableDeclarationStatements. void activateVariable(std::string const& _name); @@ -142,7 +142,6 @@ public: DeclarationRegistrationHelper( std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes, ASTNode& _astRoot, - bool _useC99Scoping, ErrorReporter& _errorReporter, ASTNode const* _currentScope = nullptr ); @@ -190,7 +189,6 @@ private: /// @returns the canonical name of the current scope. std::string currentCanonicalName() const; - bool m_useC99Scoping = false; std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes; ASTNode const* m_currentScope = nullptr; VariableScope* m_currentFunction = nullptr; diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index a051d7f9..58b659f7 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -48,9 +48,7 @@ bool ReferencesResolver::visit(Block const& _block) if (!m_resolveInsideCode) return false; m_experimental050Mode = _block.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); - // C99-scoped variables - if (m_experimental050Mode) - m_resolver.setScope(&_block); + m_resolver.setScope(&_block); return true; } @@ -59,9 +57,7 @@ void ReferencesResolver::endVisit(Block const& _block) if (!m_resolveInsideCode) return; - // C99-scoped variables - if (m_experimental050Mode) - m_resolver.setScope(_block.scope()); + m_resolver.setScope(_block.scope()); } bool ReferencesResolver::visit(ForStatement const& _for) @@ -69,9 +65,7 @@ bool ReferencesResolver::visit(ForStatement const& _for) if (!m_resolveInsideCode) return false; m_experimental050Mode = _for.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050); - // C99-scoped variables - if (m_experimental050Mode) - m_resolver.setScope(&_for); + m_resolver.setScope(&_for); return true; } @@ -79,18 +73,16 @@ void ReferencesResolver::endVisit(ForStatement const& _for) { if (!m_resolveInsideCode) return; - if (m_experimental050Mode) - m_resolver.setScope(_for.scope()); + m_resolver.setScope(_for.scope()); } void ReferencesResolver::endVisit(VariableDeclarationStatement const& _varDeclStatement) { if (!m_resolveInsideCode) return; - if (m_experimental050Mode) - for (auto const& var: _varDeclStatement.declarations()) - if (var) - m_resolver.activateVariable(var->name()); + for (auto const& var: _varDeclStatement.declarations()) + if (var) + m_resolver.activateVariable(var->name()); } bool ReferencesResolver::visit(Identifier const& _identifier) @@ -99,9 +91,14 @@ bool ReferencesResolver::visit(Identifier const& _identifier) if (declarations.empty()) { string suggestions = m_resolver.similarNameSuggestions(_identifier.name()); - string errorMessage = - "Undeclared identifier." + - (suggestions.empty()? "": " Did you mean " + std::move(suggestions) + "?"); + string errorMessage = "Undeclared identifier."; + if (!suggestions.empty()) + { + if ("\"" + _identifier.name() + "\"" == suggestions) + errorMessage += " " + std::move(suggestions) + " is not (or not yet) visible at this point."; + else + errorMessage += " Did you mean " + std::move(suggestions) + "?"; + } declarationError(_identifier.location(), errorMessage); } else if (declarations.size() == 1) diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index f234dcaf..c408b393 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -255,7 +255,7 @@ bool SyntaxChecker::visit(FunctionTypeName const& _node) for (auto const& decl: _node.returnParameterTypeList()->parameters()) if (!decl->name().empty()) - m_errorReporter.warning(decl->location(), "Naming function type return parameters is deprecated."); + m_errorReporter.syntaxError(decl->location(), "Return parameters in function types may not be named."); return true; } diff --git a/test/compilationTests/corion/provider.sol b/test/compilationTests/corion/provider.sol index 5fa90fcd..dba1253d 100644 --- a/test/compilationTests/corion/provider.sol +++ b/test/compilationTests/corion/provider.sol @@ -536,8 +536,9 @@ contract provider is module, safeMath, announcementTypes { address provAddr; uint256 provHeight; bool interest = false; + uint256 a; var rate = clients[msg.sender].lastRate; - for ( uint256 a = (clients[msg.sender].paidUpTo + 1) ; a <= currentSchellingRound ; a++ ) { + for ( a = (clients[msg.sender].paidUpTo + 1) ; a <= currentSchellingRound ; a++ ) { if (globalFunds[a].reward > 0 && globalFunds[a].supply > 0) { provAddr = clients[msg.sender].providerAddress; provHeight = clients[msg.sender].providerHeight; @@ -585,8 +586,9 @@ contract provider is module, safeMath, announcementTypes { uint256 steps; uint256 currHeight = providers[addr].currentHeight; uint256 LTSID = providers[addr].data[currHeight].lastSupplyID; + uint256 a; var rate = providers[addr].data[currHeight].lastPaidRate; - for ( uint256 a = (providers[addr].data[currHeight].paidUpTo + 1) ; a <= currentSchellingRound ; a++ ) { + for ( a = (providers[addr].data[currHeight].paidUpTo + 1) ; a <= currentSchellingRound ; a++ ) { if (globalFunds[a].reward > 0 && globalFunds[a].supply > 0) { if ( providers[addr].data[currHeight].rateHistory[a].valid ) { rate = providers[addr].data[currHeight].rateHistory[a].value; diff --git a/test/compilationTests/stringutils/strings.sol b/test/compilationTests/stringutils/strings.sol index 771f7a53..939a777a 100644 --- a/test/compilationTests/stringutils/strings.sol +++ b/test/compilationTests/stringutils/strings.sol @@ -155,7 +155,8 @@ library strings { // Starting at ptr-31 means the LSB will be the byte we care about var ptr = self._ptr - 31; var end = ptr + self._len; - for (uint len = 0; ptr < end; len++) { + uint len; + for (len = 0; ptr < end; len++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { @@ -695,7 +696,7 @@ library strings { uint retptr; assembly { retptr := add(ret, 32) } - for(i = 0; i < parts.length; i++) { + for(uint i = 0; i < parts.length; i++) { memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index ec23f452..18c8c025 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -133,22 +133,6 @@ BOOST_AUTO_TEST_CASE(assignment_in_declaration) CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(use_before_declaration) -{ - string text = R"( - contract C { - function f() public pure { a = 3; uint a = 2; assert(a == 2); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f() public pure { assert(a == 0); uint a = 2; assert(a == 2); } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); -} - BOOST_AUTO_TEST_CASE(function_call_does_not_clear_local_vars) { string text = R"( diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 2a24a1e3..65473f0d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5011,7 +5011,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition) if (data.length != i) return 0x1000 + i; if (data[data.length - 1] != byte(i)) return i; } - for (i = 1; i < 40; i++) + for (uint8 i = 1; i < 40; i++) if (data[i - 1] != byte(i)) return 0x1000000 + i; return 0; } diff --git a/test/libsolidity/syntaxTests/double_variable_declaration.sol b/test/libsolidity/syntaxTests/double_variable_declaration.sol index 9ab87959..53c5c9be 100644 --- a/test/libsolidity/syntaxTests/double_variable_declaration.sol +++ b/test/libsolidity/syntaxTests/double_variable_declaration.sol @@ -1,8 +1,9 @@ contract test { function f() pure public { uint256 x; - if (true) { uint256 x; } + x = 1; + if (true) { uint256 x; x = 2; } } } // ---- -// DeclarationError: (71-80): Identifier already declared. +// Warning: (80-89): This declaration shadows an existing declaration. diff --git a/test/libsolidity/syntaxTests/double_variable_declaration_050.sol b/test/libsolidity/syntaxTests/double_variable_declaration_050.sol deleted file mode 100644 index 2f47e6dc..00000000 --- a/test/libsolidity/syntaxTests/double_variable_declaration_050.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - uint256 x; - if (true) { uint256 x; } - } -} -// ---- -// Warning: (101-110): This declaration shadows an existing declaration. -// Warning: (76-85): Unused local variable. -// Warning: (101-110): Unused local variable. diff --git a/test/libsolidity/syntaxTests/functionTypes/function_type_return_parameters_with_names.sol b/test/libsolidity/syntaxTests/functionTypes/function_type_return_parameters_with_names.sol new file mode 100644 index 00000000..12191530 --- /dev/null +++ b/test/libsolidity/syntaxTests/functionTypes/function_type_return_parameters_with_names.sol @@ -0,0 +1,5 @@ +contract C { + function(uint) returns (bool ret) f; +} +// ---- +// SyntaxError: (41-49): Return parameters in function types may not be named. diff --git a/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol b/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol deleted file mode 100644 index 67a74e54..00000000 --- a/test/libsolidity/syntaxTests/functionTypes/warn_function_type_return_parameters_with_names.sol +++ /dev/null @@ -1,5 +0,0 @@ -contract C { - function(uint) returns (bool ret) f; -} -// ---- -// Warning: (41-49): Naming function type return parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol index 00031924..76bb6fc0 100644 --- a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol +++ b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables.sol @@ -2,3 +2,5 @@ contract B { function f() mod(x) pure public { uint x = 7; } modifier mod(uint a) { if (a > 0) _; } } +// ---- +// DeclarationError: (34-35): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol b/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol deleted file mode 100644 index c19ccf2c..00000000 --- a/test/libsolidity/syntaxTests/modifiers/function_modifier_invocation_local_variables050.sol +++ /dev/null @@ -1,7 +0,0 @@ -pragma experimental "v0.5.0"; -contract B { - function f() mod(x) pure public { uint x = 7; } - modifier mod(uint a) { if (a > 0) _; } -} -// ---- -// DeclarationError: (64-65): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol index 3ba85f69..224d9614 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping.sol @@ -1,5 +1,3 @@ -pragma experimental "v0.5.0"; - contract C { function f() internal { { @@ -9,4 +7,4 @@ contract C { } } // ---- -// DeclarationError: (130-131): Undeclared identifier. +// DeclarationError: (99-100): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol index e21181de..242a1f39 100644 --- a/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol +++ b/test/libsolidity/syntaxTests/multiVariableDeclaration/multiVariableDeclarationScoping2.sol @@ -1,5 +1,3 @@ -pragma experimental "v0.5.0"; - contract C { function f() internal { { @@ -8,6 +6,6 @@ contract C { } } // ---- -// DeclarationError: (110-111): Undeclared identifier. Did you mean "a"? -// DeclarationError: (113-114): Undeclared identifier. Did you mean "b"? -// DeclarationError: (116-117): Undeclared identifier. Did you mean "c"? +// DeclarationError: (79-80): Undeclared identifier. "a" is not (or not yet) visible at this point. +// DeclarationError: (82-83): Undeclared identifier. "b" is not (or not yet) visible at this point. +// DeclarationError: (85-86): Undeclared identifier. "c" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol index 2a0cbde0..214ad60a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/137_external_visibility.sol @@ -3,4 +3,4 @@ contract c { function g() public { f(); } } // ---- -// DeclarationError: (68-69): Undeclared identifier. Did you mean "f"? +// DeclarationError: (68-69): Undeclared identifier. "f" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/448_no_unused_dec_after_use.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/448_no_unused_dec_after_use.sol deleted file mode 100644 index 3bfa9cb8..00000000 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/448_no_unused_dec_after_use.sol +++ /dev/null @@ -1,6 +0,0 @@ -contract C { - function f() pure public { - a = 7; - uint a; - } -} diff --git a/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol b/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol index 6f8040d6..7489aaf9 100644 --- a/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol +++ b/test/libsolidity/syntaxTests/parsing/conditional_with_assignment.sol @@ -1,11 +1,8 @@ contract A { - function f() { + function f() public pure { uint y = 1; - uint x = 3 < 0 ? x = 3 : 6; + uint x = 3 < 0 ? y = 3 : 6; true ? x = 3 : 4; } } // ---- -// Warning: (17-119): No visibility specified. Defaulting to "public". -// Warning: (40-46): Unused local variable. -// Warning: (17-119): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol b/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol index d3c84678..c7703b47 100644 --- a/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol +++ b/test/libsolidity/syntaxTests/parsing/function_type_in_struct.sol @@ -1,6 +1,6 @@ contract test { struct S { - function (uint x, uint y) internal returns (uint a) f; + function (uint x, uint y) internal returns (uint) f; function (uint, uint) external returns (uint) g; uint d; } @@ -8,4 +8,3 @@ contract test { // ---- // Warning: (49-55): Naming function type parameters is deprecated. // Warning: (57-63): Naming function type parameters is deprecated. -// Warning: (83-89): Naming function type return parameters is deprecated. diff --git a/test/libsolidity/syntaxTests/parsing/while_loop.sol b/test/libsolidity/syntaxTests/parsing/while_loop.sol index 129b52e1..dbb00a69 100644 --- a/test/libsolidity/syntaxTests/parsing/while_loop.sol +++ b/test/libsolidity/syntaxTests/parsing/while_loop.sol @@ -1,9 +1,7 @@ contract test { - function fun(uint256 a) { - while (true) { uint256 x = 1; break; continue; } x = 9; + function fun() public pure { + uint256 x; + while (true) { x = 1; break; continue; } x = 9; } } // ---- -// Warning: (20-115): No visibility specified. Defaulting to "public". -// Warning: (33-42): Unused function parameter. Remove or comment out the variable name to silence this warning. -// Warning: (20-115): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol index d90ec2d7..36bae6a8 100644 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope.sol @@ -5,4 +5,5 @@ contract test { } } // ---- -// DeclarationError: (77-83): Identifier already declared. +// Warning: (57-63): Unused local variable. +// Warning: (77-83): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol deleted file mode 100644 index 06bfe7be..00000000 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - { uint x; } - { uint x; } - } -} -// ---- -// Warning: (87-93): Unused local variable. -// Warning: (107-113): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol index 1a5ff2f9..0c03ec3e 100644 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol +++ b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation.sol @@ -5,4 +5,5 @@ contract test { } } // ---- -// DeclarationError: (75-81): Identifier already declared. +// Warning: (57-63): Unused local variable. +// Warning: (75-81): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol b/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol deleted file mode 100644 index 20ea0349..00000000 --- a/test/libsolidity/syntaxTests/scoping/double_variable_declaration_disjoint_scope_activation_050.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - { uint x; } - uint x; - } -} -// ---- -// Warning: (87-93): Unused local variable. -// Warning: (105-111): Unused local variable. diff --git a/test/libsolidity/syntaxTests/scoping/scoping.sol b/test/libsolidity/syntaxTests/scoping/scoping.sol index 34b055d9..dae5a42d 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() public { { @@ -8,4 +7,4 @@ contract test { } } // ---- -// DeclarationError: (123-124): Undeclared identifier. +// DeclarationError: (93-94): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_activation.sol b/test/libsolidity/syntaxTests/scoping/scoping_activation.sol index 7334bc49..8522a0e3 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_activation.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_activation.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { x = 3; @@ -6,4 +5,4 @@ contract test { } } // ---- -// DeclarationError: (85-86): Undeclared identifier. Did you mean "x"? +// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol b/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol index d893a889..8522a0e3 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_activation_old.sol @@ -4,3 +4,5 @@ contract test { uint x; } } +// ---- +// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for.sol b/test/libsolidity/syntaxTests/scoping/scoping_for.sol index 6e5b7095..a882d1ca 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (uint x = 0; x < 10; x ++){ diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for2.sol b/test/libsolidity/syntaxTests/scoping/scoping_for2.sol index eb74b8ab..f8c5c19b 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for2.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for2.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (uint x = 0; x < 10; x ++) diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for3.sol b/test/libsolidity/syntaxTests/scoping/scoping_for3.sol index 1814cb47..81e34562 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for3.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for3.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (uint x = 0; x < 10; x ++){ @@ -8,4 +7,4 @@ contract test { } } // ---- -// DeclarationError: (154-155): Undeclared identifier. +// DeclarationError: (124-125): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol b/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol index 3e80b385..28b88525 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_for_decl_in_body.sol @@ -1,4 +1,3 @@ -pragma experimental "v0.5.0"; contract test { function f() pure public { for (;; y++){ @@ -7,4 +6,4 @@ contract test { } } // ---- -// DeclarationError: (93-94): Undeclared identifier. +// DeclarationError: (63-64): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_old.sol b/test/libsolidity/syntaxTests/scoping/scoping_old.sol index 83f6b60b..70e5ee0c 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_old.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_old.sol @@ -4,3 +4,5 @@ contract test { uint256 x = 2; } } +// ---- +// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol b/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol index 9e2c0171..a5087c57 100644 --- a/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol +++ b/test/libsolidity/syntaxTests/scoping/scoping_self_use.sol @@ -3,3 +3,5 @@ contract test { uint a = a; } } +// ---- +// DeclarationError: (64-65): Undeclared identifier. "a" is not (or not yet) visible at this point. diff --git a/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol b/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol deleted file mode 100644 index ab3dcefb..00000000 --- a/test/libsolidity/syntaxTests/scoping/scoping_self_use_050.sol +++ /dev/null @@ -1,8 +0,0 @@ -pragma experimental "v0.5.0"; -contract test { - function f() pure public { - uint a = a; - } -} -// ---- -// DeclarationError: (94-95): Undeclared identifier. Did you mean "a"? |