diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 2791fed7e..5fea91d6e 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -44,18 +44,12 @@ NameAndTypeResolver::NameAndTypeResolver( m_scopes[nullptr]->registerDeclaration(*declaration); } -bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit) +bool NameAndTypeResolver::registerDeclarations(ASTNode& _sourceUnit) { - if (!m_scopes[&_sourceUnit]) - // By importing, it is possible that the container already exists. - m_scopes[&_sourceUnit].reset(new DeclarationContainer(nullptr, m_scopes[nullptr].get())); - m_currentScope = m_scopes[&_sourceUnit].get(); - // The helper registers all declarations in m_scopes as a side-effect of its construction. try { DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors); - _sourceUnit.annotation().exportedSymbols = m_scopes[&_sourceUnit]->declarations(); } catch (FatalError const&) { @@ -458,11 +452,26 @@ DeclarationRegistrationHelper::DeclarationRegistrationHelper( ErrorList& _errors ): m_scopes(_scopes), - m_currentScope(&_astRoot), + m_currentScope(nullptr), m_errors(_errors) { - solAssert(!!m_scopes.at(m_currentScope), ""); _astRoot.accept(*this); + solAssert(m_currentScope == nullptr, "Scopes not correctly closed."); +} + +bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit) +{ + if (!m_scopes[&_sourceUnit]) + // By importing, it is possible that the container already exists. + m_scopes[&_sourceUnit].reset(new DeclarationContainer(nullptr, m_scopes[nullptr].get())); + m_currentScope = &_sourceUnit; + return true; +} + +void DeclarationRegistrationHelper::endVisit(SourceUnit& _sourceUnit) +{ + _sourceUnit.annotation().exportedSymbols = m_scopes[&_sourceUnit]->declarations(); + closeCurrentScope(); } bool DeclarationRegistrationHelper::visit(ImportDirective& _import) @@ -583,12 +592,13 @@ void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declara void DeclarationRegistrationHelper::closeCurrentScope() { - solAssert(m_currentScope, "Closed non-existing scope."); + solAssert(m_currentScope && m_scopes.count(m_currentScope), "Closed non-existing scope."); m_currentScope = m_scopes[m_currentScope]->enclosingNode(); } void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope) { + solAssert(m_currentScope && m_scopes.count(m_currentScope), "No current scope."); if (!m_scopes[m_currentScope]->registerDeclaration(_declaration, nullptr, !_declaration.isVisibleInContract())) { SourceLocation firstDeclarationLocation; diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index fb018d749..67a6c0e4b 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -43,9 +43,9 @@ class NameAndTypeResolver: private boost::noncopyable { public: NameAndTypeResolver(std::vector const& _globals, ErrorList& _errors); - /// Registers all declarations found in the source unit. + /// Registers all declarations found in the AST node, usually a source unit. /// @returns false in case of error. - bool registerDeclarations(SourceUnit& _sourceUnit); + bool registerDeclarations(ASTNode& _sourceUnit); /// Applies the effect of import directives. bool performImports(SourceUnit& _sourceUnit, std::map const& _sourceUnits); /// Resolves all names and types referenced from the given AST Node. @@ -133,6 +133,8 @@ public: ); private: + bool visit(SourceUnit& _sourceUnit) override; + void endVisit(SourceUnit& _sourceUnit) override; bool visit(ImportDirective& _declaration) override; bool visit(ContractDefinition& _contract) override; void endVisit(ContractDefinition& _contract) override; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 533c787b7..be59d3d26 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -32,11 +32,11 @@ using namespace dev; using namespace dev::solidity; -bool TypeChecker::checkTypeRequirements(ContractDefinition const& _contract) +bool TypeChecker::checkTypeRequirements(ASTNode const& _contract) { try { - visit(_contract); + _contract.accept(*this); } catch (FatalError const&) { diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 143b15b26..46d8230ab 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -47,7 +47,7 @@ public: /// Performs type checking on the given contract and all of its sub-nodes. /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings - bool checkTypeRequirements(ContractDefinition const& _contract); + bool checkTypeRequirements(ASTNode const& _contract); /// @returns the type of an expression and asserts that it is present. TypePointer const& type(Expression const& _expression) const;