mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move abstract function check.
This commit is contained in:
parent
89cf6a5a38
commit
57a62429c9
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include <liblangutil/ErrorReporter.h>
|
#include <liblangutil/ErrorReporter.h>
|
||||||
|
|
||||||
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
@ -36,6 +38,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract)
|
|||||||
checkContractDuplicateFunctions(_contract);
|
checkContractDuplicateFunctions(_contract);
|
||||||
checkContractDuplicateEvents(_contract);
|
checkContractDuplicateEvents(_contract);
|
||||||
checkContractIllegalOverrides(_contract);
|
checkContractIllegalOverrides(_contract);
|
||||||
|
checkContractAbstractFunctions(_contract);
|
||||||
|
|
||||||
return Error::containsOnlyWarnings(m_errorReporter.errors());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -63,6 +63,7 @@ private:
|
|||||||
/// Also stores the direct super function in the AST annotations.
|
/// Also stores the direct super function in the AST annotations.
|
||||||
void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super);
|
void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super);
|
||||||
void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message);
|
void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message);
|
||||||
|
void checkContractAbstractFunctions(ContractDefinition const& _contract);
|
||||||
|
|
||||||
langutil::ErrorReporter& m_errorReporter;
|
langutil::ErrorReporter& m_errorReporter;
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include <boost/algorithm/cxx11/all_of.hpp>
|
#include <boost/algorithm/cxx11/all_of.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string/join.hpp>
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/range/adaptor/reversed.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -96,7 +95,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
ASTNode::listAccept(_contract.definedStructs(), *this);
|
ASTNode::listAccept(_contract.definedStructs(), *this);
|
||||||
ASTNode::listAccept(_contract.baseContracts(), *this);
|
ASTNode::listAccept(_contract.baseContracts(), *this);
|
||||||
|
|
||||||
checkContractAbstractFunctions(_contract);
|
|
||||||
checkContractBaseConstructorArguments(_contract);
|
checkContractBaseConstructorArguments(_contract);
|
||||||
|
|
||||||
FunctionDefinition const* function = _contract.constructor();
|
FunctionDefinition const* function = _contract.constructor();
|
||||||
@ -159,49 +157,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
return false;
|
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)
|
void TypeChecker::checkContractBaseConstructorArguments(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
|
vector<ContractDefinition const*> const& bases = _contract.annotation().linearizedBaseContracts;
|
||||||
|
@ -66,7 +66,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
bool visit(ContractDefinition const& _contract) override;
|
bool visit(ContractDefinition const& _contract) override;
|
||||||
void checkContractAbstractFunctions(ContractDefinition const& _contract);
|
|
||||||
void checkContractBaseConstructorArguments(ContractDefinition const& _contract);
|
void checkContractBaseConstructorArguments(ContractDefinition const& _contract);
|
||||||
void annotateBaseConstructorArguments(
|
void annotateBaseConstructorArguments(
|
||||||
ContractDefinition const& _currentContract,
|
ContractDefinition const& _currentContract,
|
||||||
|
Loading…
Reference in New Issue
Block a user