diff options
author | chriseth <chris@ethereum.org> | 2018-11-30 00:51:57 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-11-30 23:30:19 +0800 |
commit | 57a62429c9d0be4b3a8a9cc98fa7eb46a6015165 (patch) | |
tree | 96ddfc01a0f6ffb4780bf96cd44d25de35d232ec | |
parent | 89cf6a5a38b02c3da1377279fcd98d690a58a978 (diff) | |
download | dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.tar dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.tar.gz dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.tar.bz2 dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.tar.lz dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.tar.xz dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.tar.zst dexon-solidity-57a62429c9d0be4b3a8a9cc98fa7eb46a6015165.zip |
Move abstract function check.
-rw-r--r-- | libsolidity/analysis/ContractLevelChecker.cpp | 45 | ||||
-rw-r--r-- | libsolidity/analysis/ContractLevelChecker.h | 1 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 45 | ||||
-rw-r--r-- | libsolidity/analysis/TypeChecker.h | 1 |
4 files changed, 46 insertions, 46 deletions
diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index bf132d63..74ac665f 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -24,6 +24,8 @@ #include <liblangutil/ErrorReporter.h> +#include <boost/range/adaptor/reversed.hpp> + using namespace std; using namespace dev; @@ -36,6 +38,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkContractDuplicateFunctions(_contract); checkContractDuplicateEvents(_contract); checkContractIllegalOverrides(_contract); + checkContractAbstractFunctions(_contract); return Error::containsOnlyWarnings(m_errorReporter.errors()); } @@ -203,3 +206,45 @@ void ContractLevelChecker::overrideError(FunctionDefinition const& function, Fun ); } +void ContractLevelChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) +{ + // Mapping from name to function definition (exactly one per argument type equality class) and + // flag to indicate whether it is fully implemented. + using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>; + map<string, vector<FunTypeAndFlag>> functions; + + // Search from base to derived + for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) + for (FunctionDefinition const* function: contract->definedFunctions()) + { + // Take constructors out of overload hierarchy + if (function->isConstructor()) + continue; + auto& overloads = functions[function->name()]; + FunctionTypePointer funType = make_shared<FunctionType>(*function)->asCallableFunction(false); + auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) + { + return funType->hasEqualParameterTypes(*_funAndFlag.first); + }); + if (it == overloads.end()) + overloads.push_back(make_pair(funType, function->isImplemented())); + else if (it->second) + { + if (!function->isImplemented()) + m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract"); + } + else if (function->isImplemented()) + it->second = true; + } + + // Set to not fully implemented if at least one flag is false. + for (auto const& it: functions) + for (auto const& funAndFlag: it.second) + if (!funAndFlag.second) + { + FunctionDefinition const* function = dynamic_cast<FunctionDefinition const*>(&funAndFlag.first->declaration()); + solAssert(function, ""); + _contract.annotation().unimplementedFunctions.push_back(function); + break; + } +} diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 400979c0..1746153b 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -63,6 +63,7 @@ private: /// Also stores the direct super function in the AST annotations. void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super); void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message); + void checkContractAbstractFunctions(ContractDefinition const& _contract); langutil::ErrorReporter& m_errorReporter; }; diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 07d32563..2b79e29b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -35,7 +35,6 @@ #include <boost/algorithm/cxx11/all_of.hpp> #include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/join.hpp> -#include <boost/range/adaptor/reversed.hpp> #include <memory> #include <vector> @@ -96,7 +95,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) ASTNode::listAccept(_contract.definedStructs(), *this); ASTNode::listAccept(_contract.baseContracts(), *this); - checkContractAbstractFunctions(_contract); checkContractBaseConstructorArguments(_contract); FunctionDefinition const* function = _contract.constructor(); @@ -159,49 +157,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract) return false; } -void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract) -{ - // Mapping from name to function definition (exactly one per argument type equality class) and - // flag to indicate whether it is fully implemented. - using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>; - map<string, vector<FunTypeAndFlag>> functions; - - // Search from base to derived - for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) - for (FunctionDefinition const* function: contract->definedFunctions()) - { - // Take constructors out of overload hierarchy - if (function->isConstructor()) - continue; - auto& overloads = functions[function->name()]; - FunctionTypePointer funType = make_shared<FunctionType>(*function)->asCallableFunction(false); - auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) - { - return funType->hasEqualParameterTypes(*_funAndFlag.first); - }); - if (it == overloads.end()) - overloads.push_back(make_pair(funType, function->isImplemented())); - else if (it->second) - { - if (!function->isImplemented()) - m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract"); - } - else if (function->isImplemented()) - it->second = true; - } - - // Set to not fully implemented if at least one flag is false. - for (auto const& it: functions) - for (auto const& funAndFlag: it.second) - if (!funAndFlag.second) - { - FunctionDefinition const* function = dynamic_cast<FunctionDefinition const*>(&funAndFlag.first->declaration()); - solAssert(function, ""); - _contract.annotation().unimplementedFunctions.push_back(function); - break; - } -} - void TypeChecker::checkContractBaseConstructorArguments(ContractDefinition const& _contract) { vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts; diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 7d718ff9..61eee386 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -66,7 +66,6 @@ public: private: bool visit(ContractDefinition const& _contract) override; - void checkContractAbstractFunctions(ContractDefinition const& _contract); void checkContractBaseConstructorArguments(ContractDefinition const& _contract); void annotateBaseConstructorArguments( ContractDefinition const& _currentContract, |