mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Move duplication checks.
This commit is contained in:
parent
0bd9db480f
commit
d054a3b85d
@ -31,7 +31,92 @@ using namespace langutil;
|
||||
using namespace dev::solidity;
|
||||
|
||||
|
||||
bool ContractLevelChecker::check(ContractDefinition const&)
|
||||
bool ContractLevelChecker::check(ContractDefinition const& _contract)
|
||||
{
|
||||
checkContractDuplicateFunctions(_contract);
|
||||
checkContractDuplicateEvents(_contract);
|
||||
|
||||
return Error::containsOnlyWarnings(m_errorReporter.errors());
|
||||
}
|
||||
|
||||
void ContractLevelChecker::checkContractDuplicateFunctions(ContractDefinition const& _contract)
|
||||
{
|
||||
/// Checks that two functions with the same name defined in this contract have different
|
||||
/// argument types and that there is at most one constructor.
|
||||
map<string, vector<FunctionDefinition const*>> functions;
|
||||
FunctionDefinition const* constructor = nullptr;
|
||||
FunctionDefinition const* fallback = nullptr;
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
if (function->isConstructor())
|
||||
{
|
||||
if (constructor)
|
||||
m_errorReporter.declarationError(
|
||||
function->location(),
|
||||
SecondarySourceLocation().append("Another declaration is here:", constructor->location()),
|
||||
"More than one constructor defined."
|
||||
);
|
||||
constructor = function;
|
||||
}
|
||||
else if (function->isFallback())
|
||||
{
|
||||
if (fallback)
|
||||
m_errorReporter.declarationError(
|
||||
function->location(),
|
||||
SecondarySourceLocation().append("Another declaration is here:", fallback->location()),
|
||||
"Only one fallback function is allowed."
|
||||
);
|
||||
fallback = function;
|
||||
}
|
||||
else
|
||||
{
|
||||
solAssert(!function->name().empty(), "");
|
||||
functions[function->name()].push_back(function);
|
||||
}
|
||||
|
||||
findDuplicateDefinitions(functions, "Function with same name and arguments defined twice.");
|
||||
}
|
||||
|
||||
void ContractLevelChecker::checkContractDuplicateEvents(ContractDefinition const& _contract)
|
||||
{
|
||||
/// Checks that two events with the same name defined in this contract have different
|
||||
/// argument types
|
||||
map<string, vector<EventDefinition const*>> events;
|
||||
for (EventDefinition const* event: _contract.events())
|
||||
events[event->name()].push_back(event);
|
||||
|
||||
findDuplicateDefinitions(events, "Event with same name and arguments defined twice.");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions, string _message)
|
||||
{
|
||||
for (auto const& it: _definitions)
|
||||
{
|
||||
vector<T> const& overloads = it.second;
|
||||
set<size_t> reported;
|
||||
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
|
||||
{
|
||||
SecondarySourceLocation ssl;
|
||||
|
||||
for (size_t j = i + 1; j < overloads.size(); ++j)
|
||||
if (FunctionType(*overloads[i]).asCallableFunction(false)->hasEqualParameterTypes(
|
||||
*FunctionType(*overloads[j]).asCallableFunction(false))
|
||||
)
|
||||
{
|
||||
ssl.append("Other declaration is here:", overloads[j]->location());
|
||||
reported.insert(j);
|
||||
}
|
||||
|
||||
if (ssl.infos.size() > 0)
|
||||
{
|
||||
ssl.limitSize(_message);
|
||||
|
||||
m_errorReporter.declarationError(
|
||||
overloads[i]->location(),
|
||||
ssl,
|
||||
_message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,13 @@ public:
|
||||
bool check(ContractDefinition const& _contract);
|
||||
|
||||
private:
|
||||
/// Checks that two functions defined in this contract with the same name have different
|
||||
/// arguments and that there is at most one constructor.
|
||||
void checkContractDuplicateFunctions(ContractDefinition const& _contract);
|
||||
void checkContractDuplicateEvents(ContractDefinition const& _contract);
|
||||
template <class T>
|
||||
void findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions, std::string _message);
|
||||
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
};
|
||||
|
||||
|
@ -96,8 +96,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
||||
ASTNode::listAccept(_contract.definedStructs(), *this);
|
||||
ASTNode::listAccept(_contract.baseContracts(), *this);
|
||||
|
||||
checkContractDuplicateFunctions(_contract);
|
||||
checkContractDuplicateEvents(_contract);
|
||||
checkContractIllegalOverrides(_contract);
|
||||
checkContractAbstractFunctions(_contract);
|
||||
checkContractBaseConstructorArguments(_contract);
|
||||
@ -162,88 +160,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
||||
return false;
|
||||
}
|
||||
|
||||
void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _contract)
|
||||
{
|
||||
/// Checks that two functions with the same name defined in this contract have different
|
||||
/// argument types and that there is at most one constructor.
|
||||
map<string, vector<FunctionDefinition const*>> functions;
|
||||
FunctionDefinition const* constructor = nullptr;
|
||||
FunctionDefinition const* fallback = nullptr;
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
if (function->isConstructor())
|
||||
{
|
||||
if (constructor)
|
||||
m_errorReporter.declarationError(
|
||||
function->location(),
|
||||
SecondarySourceLocation().append("Another declaration is here:", constructor->location()),
|
||||
"More than one constructor defined."
|
||||
);
|
||||
constructor = function;
|
||||
}
|
||||
else if (function->isFallback())
|
||||
{
|
||||
if (fallback)
|
||||
m_errorReporter.declarationError(
|
||||
function->location(),
|
||||
SecondarySourceLocation().append("Another declaration is here:", fallback->location()),
|
||||
"Only one fallback function is allowed."
|
||||
);
|
||||
fallback = function;
|
||||
}
|
||||
else
|
||||
{
|
||||
solAssert(!function->name().empty(), "");
|
||||
functions[function->name()].push_back(function);
|
||||
}
|
||||
|
||||
findDuplicateDefinitions(functions, "Function with same name and arguments defined twice.");
|
||||
}
|
||||
|
||||
void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract)
|
||||
{
|
||||
/// Checks that two events with the same name defined in this contract have different
|
||||
/// argument types
|
||||
map<string, vector<EventDefinition const*>> events;
|
||||
for (EventDefinition const* event: _contract.events())
|
||||
events[event->name()].push_back(event);
|
||||
|
||||
findDuplicateDefinitions(events, "Event with same name and arguments defined twice.");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void TypeChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions, string _message)
|
||||
{
|
||||
for (auto const& it: _definitions)
|
||||
{
|
||||
vector<T> const& overloads = it.second;
|
||||
set<size_t> reported;
|
||||
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
|
||||
{
|
||||
SecondarySourceLocation ssl;
|
||||
|
||||
for (size_t j = i + 1; j < overloads.size(); ++j)
|
||||
if (FunctionType(*overloads[i]).asCallableFunction(false)->hasEqualParameterTypes(
|
||||
*FunctionType(*overloads[j]).asCallableFunction(false))
|
||||
)
|
||||
{
|
||||
ssl.append("Other declaration is here:", overloads[j]->location());
|
||||
reported.insert(j);
|
||||
}
|
||||
|
||||
if (ssl.infos.size() > 0)
|
||||
{
|
||||
ssl.limitSize(_message);
|
||||
|
||||
m_errorReporter.declarationError(
|
||||
overloads[i]->location(),
|
||||
ssl,
|
||||
_message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract)
|
||||
{
|
||||
// Mapping from name to function definition (exactly one per argument type equality class) and
|
||||
|
@ -66,10 +66,6 @@ public:
|
||||
private:
|
||||
|
||||
bool visit(ContractDefinition const& _contract) override;
|
||||
/// Checks that two functions defined in this contract with the same name have different
|
||||
/// arguments and that there is at most one constructor.
|
||||
void checkContractDuplicateFunctions(ContractDefinition const& _contract);
|
||||
void checkContractDuplicateEvents(ContractDefinition const& _contract);
|
||||
void checkContractIllegalOverrides(ContractDefinition const& _contract);
|
||||
/// Reports a type error with an appropriate message if overridden function signature differs.
|
||||
/// Also stores the direct super function in the AST annotations.
|
||||
@ -157,9 +153,6 @@ private:
|
||||
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
||||
void endVisit(Literal const& _literal) override;
|
||||
|
||||
template <class T>
|
||||
void findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions, std::string _message);
|
||||
|
||||
bool contractDependenciesAreCyclic(
|
||||
ContractDefinition const& _contract,
|
||||
std::set<ContractDefinition const*> const& _seenContracts = std::set<ContractDefinition const*>()
|
||||
|
Loading…
Reference in New Issue
Block a user