mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4306 from ethereum/remove_050_workaround_scoping
[BREAKING] C99 scoping rules by default (remove 050 workaround)
This commit is contained in:
commit
0d1047181d
@ -16,6 +16,7 @@ Breaking Changes:
|
|||||||
``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``,
|
``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``,
|
||||||
``sizeof``, ``supports``, ``typedef`` and ``unchecked``.
|
``sizeof``, ``supports``, ``typedef`` and ``unchecked``.
|
||||||
* General: Remove assembly instruction aliases ``sha3`` and ``suicide``
|
* 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.
|
* Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence.
|
||||||
* Parser: Disallow trailing dots that are not followed by a number.
|
* Parser: Disallow trailing dots that are not followed by a number.
|
||||||
* Type Checker: Disallow arithmetic operations for boolean variables.
|
* Type Checker: Disallow arithmetic operations for boolean variables.
|
||||||
@ -26,6 +27,7 @@ Breaking Changes:
|
|||||||
Language Features:
|
Language Features:
|
||||||
* General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions.
|
* General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions.
|
||||||
* General: Support ``pop()`` for storage arrays.
|
* General: Support ``pop()`` for storage arrays.
|
||||||
|
* General: Scoping rules now follow the C99-style.
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
* Type Checker: Show named argument in case of error.
|
* Type Checker: Show named argument in case of error.
|
||||||
|
@ -1323,6 +1323,7 @@ custom types without the overhead of external function calls:
|
|||||||
if (carry > 0) {
|
if (carry > 0) {
|
||||||
// too bad, we have to add a limb
|
// too bad, we have to add a limb
|
||||||
uint[] memory newLimbs = new uint[](r.limbs.length + 1);
|
uint[] memory newLimbs = new uint[](r.limbs.length + 1);
|
||||||
|
uint i;
|
||||||
for (i = 0; i < r.limbs.length; ++i)
|
for (i = 0; i < r.limbs.length; ++i)
|
||||||
newLimbs[i] = r.limbs[i];
|
newLimbs[i] = r.limbs[i];
|
||||||
newLimbs[i] = carry;
|
newLimbs[i] = carry;
|
||||||
|
@ -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``
|
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.
|
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
|
Scoping in Solidity follows the widespread scoping rules of C99
|
||||||
(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
|
|
||||||
(and many other languages): Variables are visible from the point right after their declaration
|
(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
|
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.
|
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
|
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.
|
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
|
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,
|
the two variables have the same name but disjoint scopes.
|
||||||
they have the same scope (the function ``minimalScoping``) and thus it does
|
|
||||||
not compile there.
|
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity >0.4.24;
|
||||||
pragma experimental "v0.5.0";
|
|
||||||
contract C {
|
contract C {
|
||||||
function minimalScoping() pure public {
|
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 solidity >0.4.24;
|
||||||
pragma experimental "v0.5.0";
|
|
||||||
contract C {
|
contract C {
|
||||||
function f() pure public returns (uint) {
|
function f() pure public returns (uint) {
|
||||||
uint x = 1;
|
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
|
.. index:: ! exception, ! throw, ! assert, ! require, ! revert
|
||||||
|
|
||||||
Error handling: Assert, Require, Revert and Exceptions
|
Error handling: Assert, Require, Revert and Exceptions
|
||||||
|
@ -58,7 +58,7 @@ public:
|
|||||||
/// @returns whether declaration is valid, and if not also returns previous declaration.
|
/// @returns whether declaration is valid, and if not also returns previous declaration.
|
||||||
Declaration const* conflictingDeclaration(Declaration const& _declaration, ASTString const* _name = nullptr) const;
|
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.
|
/// VariableDeclarationStatements.
|
||||||
void activateVariable(ASTString const& _name);
|
void activateVariable(ASTString const& _name);
|
||||||
|
|
||||||
|
@ -54,11 +54,10 @@ NameAndTypeResolver::NameAndTypeResolver(
|
|||||||
|
|
||||||
bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode const* _currentScope)
|
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.
|
// The helper registers all declarations in m_scopes as a side-effect of its construction.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, useC99Scoping, m_errorReporter, _currentScope);
|
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errorReporter, _currentScope);
|
||||||
}
|
}
|
||||||
catch (FatalError const&)
|
catch (FatalError const&)
|
||||||
{
|
{
|
||||||
@ -449,11 +448,9 @@ string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const
|
|||||||
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
|
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
|
||||||
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
|
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
|
||||||
ASTNode& _astRoot,
|
ASTNode& _astRoot,
|
||||||
bool _useC99Scoping,
|
|
||||||
ErrorReporter& _errorReporter,
|
ErrorReporter& _errorReporter,
|
||||||
ASTNode const* _currentScope
|
ASTNode const* _currentScope
|
||||||
):
|
):
|
||||||
m_useC99Scoping(_useC99Scoping),
|
|
||||||
m_scopes(_scopes),
|
m_scopes(_scopes),
|
||||||
m_currentScope(_currentScope),
|
m_currentScope(_currentScope),
|
||||||
m_errorReporter(_errorReporter)
|
m_errorReporter(_errorReporter)
|
||||||
@ -629,29 +626,25 @@ void DeclarationRegistrationHelper::endVisit(ModifierDefinition&)
|
|||||||
bool DeclarationRegistrationHelper::visit(Block& _block)
|
bool DeclarationRegistrationHelper::visit(Block& _block)
|
||||||
{
|
{
|
||||||
_block.setScope(m_currentScope);
|
_block.setScope(m_currentScope);
|
||||||
if (m_useC99Scoping)
|
enterNewSubScope(_block);
|
||||||
enterNewSubScope(_block);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclarationRegistrationHelper::endVisit(Block&)
|
void DeclarationRegistrationHelper::endVisit(Block&)
|
||||||
{
|
{
|
||||||
if (m_useC99Scoping)
|
closeCurrentScope();
|
||||||
closeCurrentScope();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeclarationRegistrationHelper::visit(ForStatement& _for)
|
bool DeclarationRegistrationHelper::visit(ForStatement& _for)
|
||||||
{
|
{
|
||||||
_for.setScope(m_currentScope);
|
_for.setScope(m_currentScope);
|
||||||
if (m_useC99Scoping)
|
enterNewSubScope(_for);
|
||||||
enterNewSubScope(_for);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclarationRegistrationHelper::endVisit(ForStatement&)
|
void DeclarationRegistrationHelper::endVisit(ForStatement&)
|
||||||
{
|
{
|
||||||
if (m_useC99Scoping)
|
closeCurrentScope();
|
||||||
closeCurrentScope();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclarationRegistrationHelper::endVisit(VariableDeclarationStatement& _variableDeclarationStatement)
|
void DeclarationRegistrationHelper::endVisit(VariableDeclarationStatement& _variableDeclarationStatement)
|
||||||
@ -716,9 +709,8 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
|
|||||||
if (fun->isConstructor())
|
if (fun->isConstructor())
|
||||||
warnAboutShadowing = false;
|
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 =
|
bool inactive =
|
||||||
m_useC99Scoping &&
|
|
||||||
(dynamic_cast<Block const*>(m_currentScope) || dynamic_cast<ForStatement const*>(m_currentScope));
|
(dynamic_cast<Block const*>(m_currentScope) || dynamic_cast<ForStatement const*>(m_currentScope));
|
||||||
|
|
||||||
registerDeclaration(*m_scopes[m_currentScope], _declaration, nullptr, nullptr, warnAboutShadowing, inactive, m_errorReporter);
|
registerDeclaration(*m_scopes[m_currentScope], _declaration, nullptr, nullptr, warnAboutShadowing, inactive, m_errorReporter);
|
||||||
|
@ -69,7 +69,7 @@ public:
|
|||||||
/// that create their own scope.
|
/// that create their own scope.
|
||||||
/// @returns false in case of error.
|
/// @returns false in case of error.
|
||||||
bool updateDeclaration(Declaration const& _declaration);
|
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.
|
/// VariableDeclarationStatements.
|
||||||
void activateVariable(std::string const& _name);
|
void activateVariable(std::string const& _name);
|
||||||
|
|
||||||
@ -142,7 +142,6 @@ public:
|
|||||||
DeclarationRegistrationHelper(
|
DeclarationRegistrationHelper(
|
||||||
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
|
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
|
||||||
ASTNode& _astRoot,
|
ASTNode& _astRoot,
|
||||||
bool _useC99Scoping,
|
|
||||||
ErrorReporter& _errorReporter,
|
ErrorReporter& _errorReporter,
|
||||||
ASTNode const* _currentScope = nullptr
|
ASTNode const* _currentScope = nullptr
|
||||||
);
|
);
|
||||||
@ -190,7 +189,6 @@ private:
|
|||||||
/// @returns the canonical name of the current scope.
|
/// @returns the canonical name of the current scope.
|
||||||
std::string currentCanonicalName() const;
|
std::string currentCanonicalName() const;
|
||||||
|
|
||||||
bool m_useC99Scoping = false;
|
|
||||||
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes;
|
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes;
|
||||||
ASTNode const* m_currentScope = nullptr;
|
ASTNode const* m_currentScope = nullptr;
|
||||||
VariableScope* m_currentFunction = nullptr;
|
VariableScope* m_currentFunction = nullptr;
|
||||||
|
@ -48,9 +48,7 @@ bool ReferencesResolver::visit(Block const& _block)
|
|||||||
if (!m_resolveInsideCode)
|
if (!m_resolveInsideCode)
|
||||||
return false;
|
return false;
|
||||||
m_experimental050Mode = _block.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
|
m_experimental050Mode = _block.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
|
||||||
// C99-scoped variables
|
m_resolver.setScope(&_block);
|
||||||
if (m_experimental050Mode)
|
|
||||||
m_resolver.setScope(&_block);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,9 +57,7 @@ void ReferencesResolver::endVisit(Block const& _block)
|
|||||||
if (!m_resolveInsideCode)
|
if (!m_resolveInsideCode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// C99-scoped variables
|
m_resolver.setScope(_block.scope());
|
||||||
if (m_experimental050Mode)
|
|
||||||
m_resolver.setScope(_block.scope());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReferencesResolver::visit(ForStatement const& _for)
|
bool ReferencesResolver::visit(ForStatement const& _for)
|
||||||
@ -69,9 +65,7 @@ bool ReferencesResolver::visit(ForStatement const& _for)
|
|||||||
if (!m_resolveInsideCode)
|
if (!m_resolveInsideCode)
|
||||||
return false;
|
return false;
|
||||||
m_experimental050Mode = _for.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
|
m_experimental050Mode = _for.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
|
||||||
// C99-scoped variables
|
m_resolver.setScope(&_for);
|
||||||
if (m_experimental050Mode)
|
|
||||||
m_resolver.setScope(&_for);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,18 +73,16 @@ void ReferencesResolver::endVisit(ForStatement const& _for)
|
|||||||
{
|
{
|
||||||
if (!m_resolveInsideCode)
|
if (!m_resolveInsideCode)
|
||||||
return;
|
return;
|
||||||
if (m_experimental050Mode)
|
m_resolver.setScope(_for.scope());
|
||||||
m_resolver.setScope(_for.scope());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReferencesResolver::endVisit(VariableDeclarationStatement const& _varDeclStatement)
|
void ReferencesResolver::endVisit(VariableDeclarationStatement const& _varDeclStatement)
|
||||||
{
|
{
|
||||||
if (!m_resolveInsideCode)
|
if (!m_resolveInsideCode)
|
||||||
return;
|
return;
|
||||||
if (m_experimental050Mode)
|
for (auto const& var: _varDeclStatement.declarations())
|
||||||
for (auto const& var: _varDeclStatement.declarations())
|
if (var)
|
||||||
if (var)
|
m_resolver.activateVariable(var->name());
|
||||||
m_resolver.activateVariable(var->name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReferencesResolver::visit(Identifier const& _identifier)
|
bool ReferencesResolver::visit(Identifier const& _identifier)
|
||||||
@ -99,9 +91,14 @@ bool ReferencesResolver::visit(Identifier const& _identifier)
|
|||||||
if (declarations.empty())
|
if (declarations.empty())
|
||||||
{
|
{
|
||||||
string suggestions = m_resolver.similarNameSuggestions(_identifier.name());
|
string suggestions = m_resolver.similarNameSuggestions(_identifier.name());
|
||||||
string errorMessage =
|
string errorMessage = "Undeclared identifier.";
|
||||||
"Undeclared identifier." +
|
if (!suggestions.empty())
|
||||||
(suggestions.empty()? "": " Did you mean " + std::move(suggestions) + "?");
|
{
|
||||||
|
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);
|
declarationError(_identifier.location(), errorMessage);
|
||||||
}
|
}
|
||||||
else if (declarations.size() == 1)
|
else if (declarations.size() == 1)
|
||||||
|
@ -536,8 +536,9 @@ contract provider is module, safeMath, announcementTypes {
|
|||||||
address provAddr;
|
address provAddr;
|
||||||
uint256 provHeight;
|
uint256 provHeight;
|
||||||
bool interest = false;
|
bool interest = false;
|
||||||
|
uint256 a;
|
||||||
var rate = clients[msg.sender].lastRate;
|
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) {
|
if (globalFunds[a].reward > 0 && globalFunds[a].supply > 0) {
|
||||||
provAddr = clients[msg.sender].providerAddress;
|
provAddr = clients[msg.sender].providerAddress;
|
||||||
provHeight = clients[msg.sender].providerHeight;
|
provHeight = clients[msg.sender].providerHeight;
|
||||||
@ -585,8 +586,9 @@ contract provider is module, safeMath, announcementTypes {
|
|||||||
uint256 steps;
|
uint256 steps;
|
||||||
uint256 currHeight = providers[addr].currentHeight;
|
uint256 currHeight = providers[addr].currentHeight;
|
||||||
uint256 LTSID = providers[addr].data[currHeight].lastSupplyID;
|
uint256 LTSID = providers[addr].data[currHeight].lastSupplyID;
|
||||||
|
uint256 a;
|
||||||
var rate = providers[addr].data[currHeight].lastPaidRate;
|
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 (globalFunds[a].reward > 0 && globalFunds[a].supply > 0) {
|
||||||
if ( providers[addr].data[currHeight].rateHistory[a].valid ) {
|
if ( providers[addr].data[currHeight].rateHistory[a].valid ) {
|
||||||
rate = providers[addr].data[currHeight].rateHistory[a].value;
|
rate = providers[addr].data[currHeight].rateHistory[a].value;
|
||||||
|
@ -155,7 +155,8 @@ library strings {
|
|||||||
// Starting at ptr-31 means the LSB will be the byte we care about
|
// Starting at ptr-31 means the LSB will be the byte we care about
|
||||||
var ptr = self._ptr - 31;
|
var ptr = self._ptr - 31;
|
||||||
var end = ptr + self._len;
|
var end = ptr + self._len;
|
||||||
for (uint len = 0; ptr < end; len++) {
|
uint len;
|
||||||
|
for (len = 0; ptr < end; len++) {
|
||||||
uint8 b;
|
uint8 b;
|
||||||
assembly { b := and(mload(ptr), 0xFF) }
|
assembly { b := and(mload(ptr), 0xFF) }
|
||||||
if (b < 0x80) {
|
if (b < 0x80) {
|
||||||
@ -695,7 +696,7 @@ library strings {
|
|||||||
uint retptr;
|
uint retptr;
|
||||||
assembly { retptr := add(ret, 32) }
|
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);
|
memcpy(retptr, parts[i]._ptr, parts[i]._len);
|
||||||
retptr += parts[i]._len;
|
retptr += parts[i]._len;
|
||||||
if (i < parts.length - 1) {
|
if (i < parts.length - 1) {
|
||||||
|
@ -133,22 +133,6 @@ BOOST_AUTO_TEST_CASE(assignment_in_declaration)
|
|||||||
CHECK_SUCCESS_NO_WARNINGS(text);
|
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)
|
BOOST_AUTO_TEST_CASE(function_call_does_not_clear_local_vars)
|
||||||
{
|
{
|
||||||
string text = R"(
|
string text = R"(
|
||||||
|
@ -5011,7 +5011,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition)
|
|||||||
if (data.length != i) return 0x1000 + i;
|
if (data.length != i) return 0x1000 + i;
|
||||||
if (data[data.length - 1] != byte(i)) return 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;
|
if (data[i - 1] != byte(i)) return 0x1000000 + i;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
contract test {
|
contract test {
|
||||||
function f() pure public {
|
function f() pure public {
|
||||||
uint256 x;
|
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.
|
||||||
|
@ -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.
|
|
@ -2,3 +2,5 @@ contract B {
|
|||||||
function f() mod(x) pure public { uint x = 7; }
|
function f() mod(x) pure public { uint x = 7; }
|
||||||
modifier mod(uint a) { if (a > 0) _; }
|
modifier mod(uint a) { if (a > 0) _; }
|
||||||
}
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError: (34-35): Undeclared identifier.
|
||||||
|
@ -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.
|
|
@ -1,5 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
function f() internal {
|
function f() internal {
|
||||||
{
|
{
|
||||||
@ -9,4 +7,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (130-131): Undeclared identifier.
|
// DeclarationError: (99-100): Undeclared identifier.
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
|
|
||||||
contract C {
|
contract C {
|
||||||
function f() internal {
|
function f() internal {
|
||||||
{
|
{
|
||||||
@ -8,6 +6,6 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (110-111): Undeclared identifier. Did you mean "a"?
|
// DeclarationError: (79-80): Undeclared identifier. "a" is not (or not yet) visible at this point.
|
||||||
// DeclarationError: (113-114): Undeclared identifier. Did you mean "b"?
|
// DeclarationError: (82-83): Undeclared identifier. "b" is not (or not yet) visible at this point.
|
||||||
// DeclarationError: (116-117): Undeclared identifier. Did you mean "c"?
|
// DeclarationError: (85-86): Undeclared identifier. "c" is not (or not yet) visible at this point.
|
||||||
|
@ -3,4 +3,4 @@ contract c {
|
|||||||
function g() public { f(); }
|
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.
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
contract C {
|
|
||||||
function f() pure public {
|
|
||||||
a = 7;
|
|
||||||
uint a;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,8 @@
|
|||||||
contract A {
|
contract A {
|
||||||
function f() {
|
function f() public pure {
|
||||||
uint y = 1;
|
uint y = 1;
|
||||||
uint x = 3 < 0 ? x = 3 : 6;
|
uint x = 3 < 0 ? y = 3 : 6;
|
||||||
true ? x = 3 : 4;
|
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
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
contract test {
|
contract test {
|
||||||
function fun(uint256 a) {
|
function fun() public pure {
|
||||||
while (true) { uint256 x = 1; break; continue; } x = 9;
|
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
|
|
||||||
|
@ -5,4 +5,5 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (77-83): Identifier already declared.
|
// Warning: (57-63): Unused local variable.
|
||||||
|
// Warning: (77-83): Unused local variable.
|
||||||
|
@ -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.
|
|
@ -5,4 +5,5 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (75-81): Identifier already declared.
|
// Warning: (57-63): Unused local variable.
|
||||||
|
// Warning: (75-81): Unused local variable.
|
||||||
|
@ -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.
|
|
@ -1,4 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
contract test {
|
contract test {
|
||||||
function f() public {
|
function f() public {
|
||||||
{
|
{
|
||||||
@ -8,4 +7,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (123-124): Undeclared identifier.
|
// DeclarationError: (93-94): Undeclared identifier.
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
contract test {
|
contract test {
|
||||||
function f() pure public {
|
function f() pure public {
|
||||||
x = 3;
|
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.
|
||||||
|
@ -4,3 +4,5 @@ contract test {
|
|||||||
uint x;
|
uint x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point.
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
contract test {
|
contract test {
|
||||||
function f() pure public {
|
function f() pure public {
|
||||||
for (uint x = 0; x < 10; x ++){
|
for (uint x = 0; x < 10; x ++){
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
contract test {
|
contract test {
|
||||||
function f() pure public {
|
function f() pure public {
|
||||||
for (uint x = 0; x < 10; x ++)
|
for (uint x = 0; x < 10; x ++)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
contract test {
|
contract test {
|
||||||
function f() pure public {
|
function f() pure public {
|
||||||
for (uint x = 0; x < 10; x ++){
|
for (uint x = 0; x < 10; x ++){
|
||||||
@ -8,4 +7,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (154-155): Undeclared identifier.
|
// DeclarationError: (124-125): Undeclared identifier.
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pragma experimental "v0.5.0";
|
|
||||||
contract test {
|
contract test {
|
||||||
function f() pure public {
|
function f() pure public {
|
||||||
for (;; y++){
|
for (;; y++){
|
||||||
@ -7,4 +6,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (93-94): Undeclared identifier.
|
// DeclarationError: (63-64): Undeclared identifier.
|
||||||
|
@ -4,3 +4,5 @@ contract test {
|
|||||||
uint256 x = 2;
|
uint256 x = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError: (55-56): Undeclared identifier. "x" is not (or not yet) visible at this point.
|
||||||
|
@ -3,3 +3,5 @@ contract test {
|
|||||||
uint a = a;
|
uint a = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// ----
|
||||||
|
// DeclarationError: (64-65): Undeclared identifier. "a" is not (or not yet) visible at this point.
|
||||||
|
@ -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"?
|
|
Loading…
Reference in New Issue
Block a user