Move external type clash check.

This commit is contained in:
chriseth 2018-11-29 18:32:06 +01:00
parent 4f4f623273
commit 6d1644e55c
4 changed files with 40 additions and 40 deletions

View File

@ -42,6 +42,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract)
checkBaseConstructorArguments(_contract); checkBaseConstructorArguments(_contract);
checkConstructor(_contract); checkConstructor(_contract);
checkFallbackFunction(_contract); checkFallbackFunction(_contract);
checkExternalTypeClashes(_contract);
return Error::containsOnlyWarnings(m_errorReporter.errors()); return Error::containsOnlyWarnings(m_errorReporter.errors());
} }
@ -383,3 +384,39 @@ void ContractLevelChecker::checkFallbackFunction(ContractDefinition const& _cont
if (fallback->visibility() != FunctionDefinition::Visibility::External) if (fallback->visibility() != FunctionDefinition::Visibility::External)
m_errorReporter.typeError(fallback->location(), "Fallback function must be defined as \"external\"."); m_errorReporter.typeError(fallback->location(), "Fallback function must be defined as \"external\".");
} }
void ContractLevelChecker::checkExternalTypeClashes(ContractDefinition const& _contract)
{
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
{
for (FunctionDefinition const* f: contract->definedFunctions())
if (f->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*f);
// under non error circumstances this should be true
if (functionType->interfaceFunctionType())
externalDeclarations[functionType->externalSignature()].push_back(
make_pair(f, functionType->asCallableFunction(false))
);
}
for (VariableDeclaration const* v: contract->stateVariables())
if (v->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*v);
// under non error circumstances this should be true
if (functionType->interfaceFunctionType())
externalDeclarations[functionType->externalSignature()].push_back(
make_pair(v, functionType->asCallableFunction(false))
);
}
}
for (auto const& it: externalDeclarations)
for (size_t i = 0; i < it.second.size(); ++i)
for (size_t j = i + 1; j < it.second.size(); ++j)
if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second))
m_errorReporter.typeError(
it.second[j].first->location(),
"Function overload clash during conversion to external types for arguments."
);
}

View File

@ -72,6 +72,9 @@ private:
); );
void checkConstructor(ContractDefinition const& _contract); void checkConstructor(ContractDefinition const& _contract);
void checkFallbackFunction(ContractDefinition const& _contract); void checkFallbackFunction(ContractDefinition const& _contract);
/// Checks that different functions with external visibility end up having different
/// external argument types (i.e. different signature).
void checkExternalTypeClashes(ContractDefinition const& _contract);
langutil::ErrorReporter& m_errorReporter; langutil::ErrorReporter& m_errorReporter;
}; };

View File

@ -93,7 +93,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
for (auto const& n: _contract.subNodes()) for (auto const& n: _contract.subNodes())
n->accept(*this); n->accept(*this);
checkContractExternalTypeClashes(_contract);
// check for hash collisions in function signatures // check for hash collisions in function signatures
set<FixedHash<4>> hashes; set<FixedHash<4>> hashes;
for (auto const& it: _contract.interfaceFunctionList()) for (auto const& it: _contract.interfaceFunctionList())
@ -113,42 +112,6 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
return false; return false;
} }
void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _contract)
{
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
{
for (FunctionDefinition const* f: contract->definedFunctions())
if (f->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*f);
// under non error circumstances this should be true
if (functionType->interfaceFunctionType())
externalDeclarations[functionType->externalSignature()].push_back(
make_pair(f, functionType->asCallableFunction(false))
);
}
for (VariableDeclaration const* v: contract->stateVariables())
if (v->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*v);
// under non error circumstances this should be true
if (functionType->interfaceFunctionType())
externalDeclarations[functionType->externalSignature()].push_back(
make_pair(v, functionType->asCallableFunction(false))
);
}
}
for (auto const& it: externalDeclarations)
for (size_t i = 0; i < it.second.size(); ++i)
for (size_t j = i + 1; j < it.second.size(); ++j)
if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second))
m_errorReporter.typeError(
it.second[j].first->location(),
"Function overload clash during conversion to external types for arguments."
);
}
void TypeChecker::checkLibraryRequirements(ContractDefinition const& _contract) void TypeChecker::checkLibraryRequirements(ContractDefinition const& _contract)
{ {
solAssert(_contract.isLibrary(), ""); solAssert(_contract.isLibrary(), "");

View File

@ -66,9 +66,6 @@ public:
private: private:
bool visit(ContractDefinition const& _contract) override; bool visit(ContractDefinition const& _contract) override;
/// Checks that different functions with external visibility end up having different
/// external argument types (i.e. different signature).
void checkContractExternalTypeClashes(ContractDefinition const& _contract);
/// Checks that all requirements for a library are fulfilled if this is a library. /// Checks that all requirements for a library are fulfilled if this is a library.
void checkLibraryRequirements(ContractDefinition const& _contract); void checkLibraryRequirements(ContractDefinition const& _contract);
/// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage.