diff options
author | chriseth <chris@ethereum.org> | 2018-02-09 23:53:52 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-02-27 19:17:25 +0800 |
commit | e6d48bb72a82e2b3140d5a98da2961e401430a25 (patch) | |
tree | 174e49e2eddf6b92fe2fd24960af928e2b9444a8 | |
parent | 5f20129e65f5b8b714189145d177067152a21ac1 (diff) | |
download | dexon-solidity-e6d48bb72a82e2b3140d5a98da2961e401430a25.tar.gz dexon-solidity-e6d48bb72a82e2b3140d5a98da2961e401430a25.tar.zst dexon-solidity-e6d48bb72a82e2b3140d5a98da2961e401430a25.zip |
Blocks and for loops can be scopes.
-rw-r--r-- | libsolidity/analysis/NameAndTypeResolver.cpp | 24 | ||||
-rw-r--r-- | libsolidity/analysis/NameAndTypeResolver.h | 4 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.cpp | 31 | ||||
-rw-r--r-- | libsolidity/analysis/ReferencesResolver.h | 5 | ||||
-rw-r--r-- | libsolidity/ast/AST.cpp | 12 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 8 |
6 files changed, 78 insertions, 6 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 953b788d..1566df94 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -610,6 +610,30 @@ void DeclarationRegistrationHelper::endVisit(ModifierDefinition&) closeCurrentScope(); } +bool DeclarationRegistrationHelper::visit(Block& _block) +{ + enterNewSubScope(_block); + return true; +} + +void DeclarationRegistrationHelper::endVisit(Block&) +{ + closeCurrentScope(); +} + +bool DeclarationRegistrationHelper::visit(ForStatement& _for) +{ + // TODO special scoping rules for the init statement - if it is a block, then it should + // not open its own scope. + enterNewSubScope(_for); + return true; +} + +void DeclarationRegistrationHelper::endVisit(ForStatement&) +{ + closeCurrentScope(); +} + void DeclarationRegistrationHelper::endVisit(VariableDeclarationStatement& _variableDeclarationStatement) { // Register the local variables with the function diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index d1fbe53c..7a6e813e 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -167,6 +167,10 @@ private: void endVisit(FunctionDefinition& _function) override; bool visit(ModifierDefinition& _modifier) override; void endVisit(ModifierDefinition& _modifier) override; + bool visit(Block& _block) override; + void endVisit(Block& _block) override; + bool visit(ForStatement& _forLoop) override; + void endVisit(ForStatement& _forLoop) override; void endVisit(VariableDeclarationStatement& _variableDeclarationStatement) override; bool visit(VariableDeclaration& _declaration) override; bool visit(EventDefinition& _event) override; diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 0bb5e3fe..bee42e77 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -43,6 +43,37 @@ bool ReferencesResolver::resolve(ASTNode const& _root) return !m_errorOccurred; } +bool ReferencesResolver::visit(Block const& _block) +{ + if (!m_resolveInsideCode) + return false; + m_resolver.setScope(&_block); + return true; +} + +void ReferencesResolver::endVisit(Block const& _block) +{ + if (!m_resolveInsideCode) + return; + + m_resolver.setScope(_block.scope()); +} + +bool ReferencesResolver::visit(ForStatement const& _for) +{ + if (!m_resolveInsideCode) + return false; + m_resolver.setScope(&_for); + return true; +} + +void ReferencesResolver::endVisit(ForStatement const& _for) +{ + if (!m_resolveInsideCode) + return; + m_resolver.setScope(_for.scope()); +} + bool ReferencesResolver::visit(Identifier const& _identifier) { auto declarations = m_resolver.nameFromCurrentScope(_identifier.name()); diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index fef2e73f..5bfd6c5a 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -57,7 +57,10 @@ public: bool resolve(ASTNode const& _root); private: - virtual bool visit(Block const&) override { return m_resolveInsideCode; } + virtual bool visit(Block const& _block) override; + virtual void endVisit(Block const& _block) override; + virtual bool visit(ForStatement const& _for) override; + virtual void endVisit(ForStatement const& _for) override; virtual bool visit(Identifier const& _identifier) override; virtual bool visit(ElementaryTypeName const& _typeName) override; virtual bool visit(FunctionDefinition const& _functionDefinition) override; diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index af007908..60a15aeb 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -415,6 +415,15 @@ bool VariableDeclaration::isLValue() const return !isExternalCallableParameter() && !m_isConstant; } +bool VariableDeclaration::isLocalVariable() const +{ + auto s = scope(); + return + dynamic_cast<CallableDeclaration const*>(s) || + dynamic_cast<Block const*>(s) || + dynamic_cast<ForStatement const*>(s); +} + bool VariableDeclaration::isCallableParameter() const { auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()); @@ -460,8 +469,7 @@ bool VariableDeclaration::isExternalCallableParameter() const bool VariableDeclaration::canHaveAutoType() const { - auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()); - return (!!callable && !isCallableParameter()); + return isLocalVariable() && !isCallableParameter(); } TypePointer VariableDeclaration::type() const diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index a0089d64..1e4c6591 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -299,6 +299,8 @@ private: /** * Abstract class that is added to each AST node that can store local variables. + * Local variables in functions are always added to functions, even though they are not + * in scope for the whole function. */ class VariableScope { @@ -672,7 +674,7 @@ public: virtual bool isLValue() const override; virtual bool isPartOfExternalInterface() const override { return isPublic(); } - bool isLocalVariable() const { return !!dynamic_cast<CallableDeclaration const*>(scope()); } + bool isLocalVariable() const; /// @returns true if this variable is a parameter or return parameter of a function. bool isCallableParameter() const; /// @returns true if this variable is a return parameter of a function. @@ -1014,7 +1016,7 @@ private: /** * Brace-enclosed block containing zero or more statements. */ -class Block: public Statement +class Block: public Statement, public Scopable { public: Block( @@ -1121,7 +1123,7 @@ private: /** * For loop statement */ -class ForStatement: public BreakableStatement +class ForStatement: public BreakableStatement, public Scopable { public: ForStatement( |