/* This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. cpp-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ /** * @author Christian * @date 2014 * Parser part that determines the declarations corresponding to names and the types of expressions. */ #pragma once #include #include #include #include #include namespace dev { namespace solidity { /** * Resolves name references, types and checks types of all expressions. * Specifically, it checks that all operations are valid for the inferred types. * An exception is throw on the first error. */ class NameAndTypeResolver: private boost::noncopyable { public: explicit NameAndTypeResolver(std::vector const& _globals); /// Registers all declarations found in the source unit. void registerDeclarations(SourceUnit& _sourceUnit); /// Resolves all names and types referenced from the given contract. void resolveNamesAndTypes(ContractDefinition& _contract); /// Check all type requirements in the given contract. void checkTypeRequirements(ContractDefinition& _contract); /// Updates the given global declaration (used for "this"). Not to be used with declarations /// that create their own scope. void updateDeclaration(Declaration const& _declaration); /// Resolves the given @a _name inside the scope @a _scope. If @a _scope is omitted, /// the global scope is used (i.e. the one containing only the contract). /// @returns a pointer to the declaration on success or nullptr on failure. std::set resolveName(ASTString const& _name, Declaration const* _scope = nullptr) const; /// Resolves a name in the "current" scope. Should only be called during the initial /// resolving phase. std::set getNameFromCurrentScope(ASTString const& _name, bool _recursive = true); private: void reset(); /// Either imports all non-function members or all function 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, bool _importFunctions); /// Computes "C3-Linearization" of base contracts and stores it inside the contract. void linearizeBaseContracts(ContractDefinition& _contract) const; /// Computes the C3-merge of the given list of lists of bases. /// @returns the linearized vector or an empty vector if linearization is not possible. template static std::vector<_T const*> cThreeMerge(std::list>& _toMerge); /// Maps nodes declaring a scope to scopes, i.e. ContractDefinition and FunctionDeclaration, /// where nullptr denotes the global scope. Note that structs are not scope since they do /// not contain code. std::map m_scopes; DeclarationContainer* m_currentScope = nullptr; }; /** * Traverses the given AST upon construction and fills _scopes with all declarations inside the * AST. */ class DeclarationRegistrationHelper: private ASTVisitor { public: DeclarationRegistrationHelper(std::map& _scopes, ASTNode& _astRoot); private: bool visit(ContractDefinition& _contract) override; void endVisit(ContractDefinition& _contract) override; bool visit(StructDefinition& _struct) override; void endVisit(StructDefinition& _struct) override; bool visit(EnumDefinition& _enum) override; void endVisit(EnumDefinition& _enum) override; bool visit(EnumValue& _value) override; bool visit(FunctionDefinition& _function) override; void endVisit(FunctionDefinition& _function) override; bool visit(ModifierDefinition& _modifier) override; void endVisit(ModifierDefinition& _modifier) override; void endVisit(VariableDeclarationStatement& _variableDeclarationStatement) override; bool visit(VariableDeclaration& _declaration) override; bool visit(EventDefinition& _event) override; void endVisit(EventDefinition& _event) override; void enterNewSubScope(Declaration const& _declaration); void closeCurrentScope(); void registerDeclaration(Declaration& _declaration, bool _opensScope); std::map& m_scopes; Declaration const* m_currentScope; VariableScope* m_currentFunction; }; /** * Resolves references to declarations (of variables and types) and also establishes the link * between a return statement and the return parameter list. */ class ReferencesResolver: private ASTVisitor { public: ReferencesResolver( ASTNode& _root, NameAndTypeResolver& _resolver, ContractDefinition const* _currentContract, ParameterList const* _returnParameters, bool _resolveInsideCode = false, bool _allowLazyTypes = true ); private: virtual void endVisit(VariableDeclaration& _variable) override; virtual bool visit(Block&) override { return m_resolveInsideCode; } virtual bool visit(Identifier& _identifier) override; virtual bool visit(UserDefinedTypeName& _typeName) override; virtual bool visit(Mapping&) override; virtual bool visit(Return& _return) override; NameAndTypeResolver& m_resolver; ContractDefinition const* m_currentContract; ParameterList const* m_returnParameters; bool m_resolveInsideCode; bool m_allowLazyTypes; }; } }