diff options
author | chriseth <chris@ethereum.org> | 2018-12-03 17:46:44 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-03 17:46:44 +0800 |
commit | 3f613a44eca674e6de60565657c40da3f8e6bbfc (patch) | |
tree | 38d9308bcbadcfa94441223ac2073951a34e4d65 /libsolidity/analysis | |
parent | 25c63dde28f4f3d2565646c4f8831d71e0f2fd7b (diff) | |
parent | 0668a9ecfb60ab0e00bfb2c4a4a97ce523860832 (diff) | |
download | dexon-solidity-3f613a44eca674e6de60565657c40da3f8e6bbfc.tar.gz dexon-solidity-3f613a44eca674e6de60565657c40da3f8e6bbfc.tar.zst dexon-solidity-3f613a44eca674e6de60565657c40da3f8e6bbfc.zip |
Merge pull request #5557 from ethereum/fixInterfaceImplementedByPublicStateVariable
Public state variables are implementing external functions.
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/ContractLevelChecker.cpp | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 58dcfe4d..6dc564de 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -219,29 +219,40 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con 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()) + auto registerFunction = [&](Declaration const& _declaration, FunctionTypePointer const& _type, bool _implemented) + { + auto& overloads = functions[_declaration.name()]; + auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag) { - // 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; + return _type->hasEqualParameterTypes(*_funAndFlag.first); + }); + if (it == overloads.end()) + overloads.push_back(make_pair(_type, _implemented)); + else if (it->second) + { + if (!_implemented) + m_errorReporter.typeError(_declaration.location(), "Redeclaring an already implemented function as abstract"); } + else if (_implemented) + it->second = true; + }; + + // Search from base to derived, collect all functions and update + // the 'implemented' flag. + for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts)) + { + for (VariableDeclaration const* v: contract->stateVariables()) + if (v->isPartOfExternalInterface()) + registerFunction(*v, make_shared<FunctionType>(*v), true); + + for (FunctionDefinition const* function: contract->definedFunctions()) + if (!function->isConstructor()) + registerFunction( + *function, + make_shared<FunctionType>(*function)->asCallableFunction(false), + function->isImplemented() + ); + } // Set to not fully implemented if at least one flag is false. for (auto const& it: functions) |