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;
|
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());
|
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);
|
bool check(ContractDefinition const& _contract);
|
||||||
|
|
||||||
private:
|
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;
|
langutil::ErrorReporter& m_errorReporter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,8 +96,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);
|
||||||
|
|
||||||
checkContractDuplicateFunctions(_contract);
|
|
||||||
checkContractDuplicateEvents(_contract);
|
|
||||||
checkContractIllegalOverrides(_contract);
|
checkContractIllegalOverrides(_contract);
|
||||||
checkContractAbstractFunctions(_contract);
|
checkContractAbstractFunctions(_contract);
|
||||||
checkContractBaseConstructorArguments(_contract);
|
checkContractBaseConstructorArguments(_contract);
|
||||||
@ -162,88 +160,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
return false;
|
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)
|
void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
// Mapping from name to function definition (exactly one per argument type equality class) and
|
// Mapping from name to function definition (exactly one per argument type equality class) and
|
||||||
|
@ -66,10 +66,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
bool visit(ContractDefinition const& _contract) override;
|
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);
|
void checkContractIllegalOverrides(ContractDefinition const& _contract);
|
||||||
/// Reports a type error with an appropriate message if overridden function signature differs.
|
/// Reports a type error with an appropriate message if overridden function signature differs.
|
||||||
/// Also stores the direct super function in the AST annotations.
|
/// Also stores the direct super function in the AST annotations.
|
||||||
@ -157,9 +153,6 @@ private:
|
|||||||
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
||||||
void endVisit(Literal const& _literal) 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(
|
bool contractDependenciesAreCyclic(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
std::set<ContractDefinition const*> const& _seenContracts = std::set<ContractDefinition const*>()
|
std::set<ContractDefinition const*> const& _seenContracts = std::set<ContractDefinition const*>()
|
||||||
|
Loading…
Reference in New Issue
Block a user