mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Check overrides and provide inherited public interface.
This commit is contained in:
parent
914fcedd0e
commit
6633fbb603
47
AST.cpp
47
AST.cpp
@ -43,6 +43,8 @@ TypeError ASTNode::createTypeError(string const& _description) const
|
||||
|
||||
void ContractDefinition::checkTypeRequirements()
|
||||
{
|
||||
checkIllegalOverrides();
|
||||
|
||||
FunctionDefinition const* constructor = getConstructor();
|
||||
if (constructor && !constructor->getReturnParameters().empty())
|
||||
BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError(
|
||||
@ -52,7 +54,6 @@ void ContractDefinition::checkTypeRequirements()
|
||||
function->checkTypeRequirements();
|
||||
|
||||
// check for hash collisions in function signatures
|
||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> exportedFunctionList = getInterfaceFunctionList();
|
||||
set<FixedHash<4>> hashes;
|
||||
for (auto const& hashAndFunction: getInterfaceFunctionList())
|
||||
{
|
||||
@ -83,17 +84,43 @@ FunctionDefinition const* ContractDefinition::getConstructor() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> ContractDefinition::getInterfaceFunctionList() const
|
||||
void ContractDefinition::checkIllegalOverrides() const
|
||||
{
|
||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> exportedFunctions;
|
||||
for (ASTPointer<FunctionDefinition> const& f: m_definedFunctions)
|
||||
if (f->isPublic() && f->getName() != getName())
|
||||
{
|
||||
FixedHash<4> hash(dev::sha3(f->getCanonicalSignature()));
|
||||
exportedFunctions.push_back(make_pair(hash, f.get()));
|
||||
}
|
||||
map<string, FunctionDefinition const*> functions;
|
||||
|
||||
return exportedFunctions;
|
||||
// We search from derived to base, so the stored item causes the error.
|
||||
for (ContractDefinition const* contract: getLinearizedBaseContracts())
|
||||
for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
|
||||
{
|
||||
if (function->getName() == contract->getName())
|
||||
continue; // constructors can neither be overriden nor override anything
|
||||
FunctionDefinition const*& override = functions[function->getName()];
|
||||
if (!override)
|
||||
override = function.get();
|
||||
else if (override->isPublic() != function->isPublic() ||
|
||||
override->isDeclaredConst() != function->isDeclaredConst() ||
|
||||
FunctionType(*override) != FunctionType(*function))
|
||||
BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature."));
|
||||
}
|
||||
}
|
||||
|
||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> const& ContractDefinition::getInterfaceFunctionList() const
|
||||
{
|
||||
if (!m_interfaceFunctionList)
|
||||
{
|
||||
set<string> functionsSeen;
|
||||
m_interfaceFunctionList.reset(new vector<pair<FixedHash<4>, FunctionDefinition const*>>());
|
||||
for (ContractDefinition const* contract: getLinearizedBaseContracts())
|
||||
for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions())
|
||||
if (f->isPublic() && f->getName() != contract->getName() &&
|
||||
functionsSeen.count(f->getName()) == 0)
|
||||
{
|
||||
functionsSeen.insert(f->getName());
|
||||
FixedHash<4> hash(dev::sha3(f->getCanonicalSignature()));
|
||||
m_interfaceFunctionList->push_back(make_pair(hash, f.get()));
|
||||
}
|
||||
}
|
||||
return *m_interfaceFunctionList;
|
||||
}
|
||||
|
||||
void StructDefinition::checkMemberTypes() const
|
||||
|
9
AST.h
9
AST.h
@ -178,8 +178,8 @@ public:
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
|
||||
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
|
||||
|
||||
/// Checks that the constructor does not have a "returns" statement and calls
|
||||
/// checkTypeRequirements on all its functions.
|
||||
/// Checks that there are no illegal overrides, that the constructor does not have a "returns"
|
||||
/// and calls checkTypeRequirements on all its functions.
|
||||
void checkTypeRequirements();
|
||||
|
||||
/// @return A shared pointer of an ASTString.
|
||||
@ -199,7 +199,9 @@ public:
|
||||
FunctionDefinition const* getConstructor() const;
|
||||
|
||||
private:
|
||||
std::vector<std::pair<FixedHash<4>, FunctionDefinition const*>> getInterfaceFunctionList() const;
|
||||
void checkIllegalOverrides() const;
|
||||
|
||||
std::vector<std::pair<FixedHash<4>, FunctionDefinition const*>> const& getInterfaceFunctionList() const;
|
||||
|
||||
std::vector<ASTPointer<Identifier>> m_baseContracts;
|
||||
std::vector<ASTPointer<StructDefinition>> m_definedStructs;
|
||||
@ -208,6 +210,7 @@ private:
|
||||
ASTPointer<ASTString> m_documentation;
|
||||
|
||||
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
||||
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionDefinition const*>>> m_interfaceFunctionList;
|
||||
};
|
||||
|
||||
class StructDefinition: public Declaration
|
||||
|
@ -102,7 +102,8 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base)
|
||||
for (auto const& nameAndDeclaration: iterator->second.getDeclarations())
|
||||
{
|
||||
Declaration const* declaration = nameAndDeclaration.second;
|
||||
if (declaration->getScope() == &_base)
|
||||
// Import if it was declared in the base and is not the constructor
|
||||
if (declaration->getScope() == &_base && declaration->getName() != _base.getName())
|
||||
m_currentScope->registerDeclaration(*declaration);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user