From fc8e50f688bad9c13259fc926142b838d7aba5d3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 27 Jan 2017 18:27:59 +0100 Subject: Refactor NameAndTypeResolver and SyntaxChecker to allow other entry points. --- libsolidity/analysis/NameAndTypeResolver.cpp | 96 +++++++++++++--------------- libsolidity/analysis/NameAndTypeResolver.h | 9 +-- libsolidity/analysis/ReferencesResolver.cpp | 27 +++++++- libsolidity/analysis/ReferencesResolver.h | 9 ++- libsolidity/analysis/SyntaxChecker.cpp | 4 +- libsolidity/analysis/SyntaxChecker.h | 2 +- 6 files changed, 86 insertions(+), 61 deletions(-) (limited to 'libsolidity/analysis') diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index b0a82715..2791fed7 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -132,68 +132,64 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map(&_node)) + { + m_currentScope = m_scopes[contract->scope()].get(); + solAssert(!!m_currentScope, ""); - ReferencesResolver resolver(m_errors, *this, nullptr); - bool success = true; - for (ASTPointer const& baseContract: _contract.baseContracts()) - if (!resolver.resolve(*baseContract)) - success = false; + for (ASTPointer const& baseContract: contract->baseContracts()) + if (!resolveNamesAndTypes(*baseContract, false)) + success = false; - m_currentScope = m_scopes[&_contract].get(); + m_currentScope = m_scopes[contract].get(); - if (success) - { - linearizeBaseContracts(_contract); - vector properBases( - ++_contract.annotation().linearizedBaseContracts.begin(), - _contract.annotation().linearizedBaseContracts.end() - ); - - for (ContractDefinition const* base: properBases) - importInheritedScope(*base); - } + if (success) + { + linearizeBaseContracts(*contract); + vector properBases( + ++contract->annotation().linearizedBaseContracts.begin(), + contract->annotation().linearizedBaseContracts.end() + ); - // these can contain code, only resolve parameters for now - for (ASTPointer const& node: _contract.subNodes()) - { - m_currentScope = m_scopes[m_scopes.count(node.get()) ? node.get() : &_contract].get(); - if (!resolver.resolve(*node)) - success = false; - } + for (ContractDefinition const* base: properBases) + importInheritedScope(*base); + } - if (!success) - return false; + // these can contain code, only resolve parameters for now + for (ASTPointer const& node: contract->subNodes()) + { + m_currentScope = m_scopes[contract].get(); + if (!resolveNamesAndTypes(*node, false)) + success = false; + } - m_currentScope = m_scopes[&_contract].get(); + if (!success) + return false; - // now resolve references inside the code - for (ModifierDefinition const* modifier: _contract.functionModifiers()) - { - m_currentScope = m_scopes[modifier].get(); - ReferencesResolver resolver(m_errors, *this, nullptr, true); - if (!resolver.resolve(*modifier)) - success = false; - } + if (!_resolveInsideCode) + return success; - for (FunctionDefinition const* function: _contract.definedFunctions()) + m_currentScope = m_scopes[contract].get(); + + // now resolve references inside the code + for (ASTPointer const& node: contract->subNodes()) + { + m_currentScope = m_scopes[contract].get(); + if (!resolveNamesAndTypes(*node, true)) + success = false; + } + } + else { - m_currentScope = m_scopes[function].get(); - if (!ReferencesResolver( - m_errors, - *this, - function->returnParameterList().get(), - true - ).resolve(*function)) - success = false; + if (m_scopes.count(&_node)) + m_currentScope = m_scopes[&_node].get(); + return ReferencesResolver(m_errors, *this, _resolveInsideCode).resolve(_node); } - if (!success) - return false; } catch (FatalError const&) { @@ -201,7 +197,7 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) throw; // Something is weird here, rather throw again. return false; } - return true; + return success; } bool NameAndTypeResolver::updateDeclaration(Declaration const& _declaration) diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index 68c3ffa1..fb018d74 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -48,9 +48,12 @@ public: bool registerDeclarations(SourceUnit& _sourceUnit); /// Applies the effect of import directives. bool performImports(SourceUnit& _sourceUnit, std::map const& _sourceUnits); - /// Resolves all names and types referenced from the given contract. + /// Resolves all names and types referenced from the given AST Node. + /// This is usually only called at the contract level, but with a bit of care, it can also + /// be called at deeper levels. + /// @param _avoidCode if false, does not descend into nodes that contain code. /// @returns false in case of error. - bool resolveNamesAndTypes(ContractDefinition& _contract); + bool resolveNamesAndTypes(ASTNode& _node, bool _resolveInsideCode = true); /// Updates the given global declaration (used for "this"). Not to be used with declarations /// that create their own scope. /// @returns false in case of error. @@ -77,8 +80,6 @@ public: ); private: - void reset(); - /// Imports all members declared directly in the given contract (i.e. does not import inherited members) /// into the current scope if they are not present already. void importInheritedScope(ContractDefinition const& _base); diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index d589f4a0..c06181d8 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -65,6 +65,30 @@ bool ReferencesResolver::visit(ElementaryTypeName const& _typeName) return true; } +bool ReferencesResolver::visit(FunctionDefinition const& _functionDefinition) +{ + m_returnParameters.push_back(_functionDefinition.returnParameterList().get()); + return true; +} + +void ReferencesResolver::endVisit(FunctionDefinition const&) +{ + solAssert(!m_returnParameters.empty(), ""); + m_returnParameters.pop_back(); +} + +bool ReferencesResolver::visit(ModifierDefinition const&) +{ + m_returnParameters.push_back(nullptr); + return true; +} + +void ReferencesResolver::endVisit(ModifierDefinition const&) +{ + solAssert(!m_returnParameters.empty(), ""); + m_returnParameters.pop_back(); +} + void ReferencesResolver::endVisit(UserDefinedTypeName const& _typeName) { Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath()); @@ -161,7 +185,8 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly) bool ReferencesResolver::visit(Return const& _return) { - _return.annotation().functionReturnParameters = m_returnParameters; + solAssert(!m_returnParameters.empty(), ""); + _return.annotation().functionReturnParameters = m_returnParameters.back(); return true; } diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index caa3a78f..23ac6b07 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -45,12 +45,10 @@ public: ReferencesResolver( ErrorList& _errors, NameAndTypeResolver& _resolver, - ParameterList const* _returnParameters, bool _resolveInsideCode = false ): m_errors(_errors), m_resolver(_resolver), - m_returnParameters(_returnParameters), m_resolveInsideCode(_resolveInsideCode) {} @@ -61,6 +59,10 @@ private: virtual bool visit(Block const&) override { return m_resolveInsideCode; } virtual bool visit(Identifier const& _identifier) override; virtual bool visit(ElementaryTypeName const& _typeName) override; + virtual bool visit(FunctionDefinition const& _functionDefinition) override; + virtual void endVisit(FunctionDefinition const& _functionDefinition) override; + virtual bool visit(ModifierDefinition const& _modifierDefinition) override; + virtual void endVisit(ModifierDefinition const& _modifierDefinition) override; virtual void endVisit(UserDefinedTypeName const& _typeName) override; virtual void endVisit(FunctionTypeName const& _typeName) override; virtual void endVisit(Mapping const& _typeName) override; @@ -83,7 +85,8 @@ private: ErrorList& m_errors; NameAndTypeResolver& m_resolver; - ParameterList const* m_returnParameters; + /// Stack of return parameters. + std::vector m_returnParameters; bool const m_resolveInsideCode; bool m_errorOccurred = false; }; diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index 0a4943fe..89014133 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -26,9 +26,9 @@ using namespace dev; using namespace dev::solidity; -bool SyntaxChecker::checkSyntax(SourceUnit const& _sourceUnit) +bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot) { - _sourceUnit.accept(*this); + _astRoot.accept(*this); return Error::containsOnlyWarnings(m_errors); } diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index c24bae09..308e128b 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -39,7 +39,7 @@ public: /// @param _errors the reference to the list of errors and warnings to add them found during type checking. SyntaxChecker(ErrorList& _errors): m_errors(_errors) {} - bool checkSyntax(SourceUnit const& _sourceUnit); + bool checkSyntax(ASTNode const& _astRoot); private: /// Adds a new error to the list of errors. -- cgit