/* This file is part of solidity. solidity 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. solidity 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 solidity. If not, see . */ /** * Component that verifies overloads, abstract contracts, function clashes and others * checks at contract or function level. */ #pragma once #include #include #include namespace langutil { class ErrorReporter; } namespace dev { namespace solidity { /** * Component that verifies overloads, abstract contracts, function clashes and others * checks at contract or function level. */ class ContractLevelChecker { public: /// @param _errorReporter provides the error logging functionality. explicit ContractLevelChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter) {} /// Performs checks on the given contract. /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings bool check(ContractDefinition const& _contract); private: /** * Comparator that compares * - functions such that equality means that the functions override each other * - modifiers by name * - contracts by AST id. */ struct LessFunction { bool operator()(ModifierDefinition const* _a, ModifierDefinition const* _b) const; bool operator()(FunctionDefinition const* _a, FunctionDefinition const* _b) const; bool operator()(ContractDefinition const* _a, ContractDefinition const* _b) const; }; using FunctionMultiSet = std::multiset; using ModifierMultiSet = std::multiset; /// Checks that two functions defined in this contract with the same name have different /// arguments and that there is at most one constructor. void checkDuplicateFunctions(ContractDefinition const& _contract); void checkDuplicateEvents(ContractDefinition const& _contract); template void findDuplicateDefinitions(std::map> const& _definitions, std::string _message); void checkIllegalOverrides(ContractDefinition const& _contract); /// Performs various checks related to @a _overriding overriding @a _super like /// different return type, invalid visibility change, etc. /// Works on functions, modifiers and public state variables. /// Also stores @a _super as a base function of @a _function in its AST annotations. template void checkOverride(T const& _overriding, U const& _super); void overrideListError( CallableDeclaration const& _callable, std::set _secondary, std::string const& _message1, std::string const& _message2 ); void overrideError( Declaration const& _overriding, Declaration const& _super, std::string _message, std::string _secondaryMsg = "Overridden function is here:" ); void checkAbstractFunctions(ContractDefinition const& _contract); /// Checks that the base constructor arguments are properly provided. /// Fills the list of unimplemented functions in _contract's annotations. void checkBaseConstructorArguments(ContractDefinition const& _contract); void annotateBaseConstructorArguments( ContractDefinition const& _currentContract, FunctionDefinition const* _baseConstructor, ASTNode const* _argumentNode ); /// Checks that different functions with external visibility end up having different /// external argument types (i.e. different signature). void checkExternalTypeClashes(ContractDefinition const& _contract); /// Checks for hash collisions in external function signatures. void checkHashCollisions(ContractDefinition const& _contract); /// Checks that all requirements for a library are fulfilled if this is a library. void checkLibraryRequirements(ContractDefinition const& _contract); /// Checks base contracts for ABI compatibility void checkBaseABICompatibility(ContractDefinition const& _contract); /// Checks for functions in different base contracts which conflict with each /// other and thus need to be overridden explicitly. void checkAmbiguousOverrides(ContractDefinition const& _contract) const; /// Resolves an override list of UserDefinedTypeNames to a list of contracts. std::set resolveOverrideList(OverrideSpecifier const& _overrides) const; template void checkOverrideList( std::multiset const& _funcSet, T const& _function ); /// Returns all functions of bases that have not yet been overwritten. /// May contain the same function multiple times when used with shared bases. FunctionMultiSet const& inheritedFunctions(ContractDefinition const& _contract) const; ModifierMultiSet const& inheritedModifiers(ContractDefinition const& _contract) const; /// Warns if the contract has a payable fallback, but no receive ether function. void checkPayableFallbackWithoutReceive(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; /// Cache for inheritedFunctions(). std::map mutable m_inheritedFunctions; std::map mutable m_contractBaseModifiers; }; } }