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()
|
void ContractDefinition::checkTypeRequirements()
|
||||||
{
|
{
|
||||||
|
checkIllegalOverrides();
|
||||||
|
|
||||||
FunctionDefinition const* constructor = getConstructor();
|
FunctionDefinition const* constructor = getConstructor();
|
||||||
if (constructor && !constructor->getReturnParameters().empty())
|
if (constructor && !constructor->getReturnParameters().empty())
|
||||||
BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError(
|
BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError(
|
||||||
@ -52,7 +54,6 @@ void ContractDefinition::checkTypeRequirements()
|
|||||||
function->checkTypeRequirements();
|
function->checkTypeRequirements();
|
||||||
|
|
||||||
// check for hash collisions in function signatures
|
// check for hash collisions in function signatures
|
||||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> exportedFunctionList = getInterfaceFunctionList();
|
|
||||||
set<FixedHash<4>> hashes;
|
set<FixedHash<4>> hashes;
|
||||||
for (auto const& hashAndFunction: getInterfaceFunctionList())
|
for (auto const& hashAndFunction: getInterfaceFunctionList())
|
||||||
{
|
{
|
||||||
@ -83,17 +84,43 @@ FunctionDefinition const* ContractDefinition::getConstructor() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> ContractDefinition::getInterfaceFunctionList() const
|
void ContractDefinition::checkIllegalOverrides() const
|
||||||
{
|
{
|
||||||
vector<pair<FixedHash<4>, FunctionDefinition const*>> exportedFunctions;
|
map<string, FunctionDefinition const*> functions;
|
||||||
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()));
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
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<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
|
||||||
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
|
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
|
||||||
|
|
||||||
/// Checks that the constructor does not have a "returns" statement and calls
|
/// Checks that there are no illegal overrides, that the constructor does not have a "returns"
|
||||||
/// checkTypeRequirements on all its functions.
|
/// and calls checkTypeRequirements on all its functions.
|
||||||
void checkTypeRequirements();
|
void checkTypeRequirements();
|
||||||
|
|
||||||
/// @return A shared pointer of an ASTString.
|
/// @return A shared pointer of an ASTString.
|
||||||
@ -199,7 +199,9 @@ public:
|
|||||||
FunctionDefinition const* getConstructor() const;
|
FunctionDefinition const* getConstructor() const;
|
||||||
|
|
||||||
private:
|
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<Identifier>> m_baseContracts;
|
||||||
std::vector<ASTPointer<StructDefinition>> m_definedStructs;
|
std::vector<ASTPointer<StructDefinition>> m_definedStructs;
|
||||||
@ -208,6 +210,7 @@ private:
|
|||||||
ASTPointer<ASTString> m_documentation;
|
ASTPointer<ASTString> m_documentation;
|
||||||
|
|
||||||
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
std::vector<ContractDefinition const*> m_linearizedBaseContracts;
|
||||||
|
mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionDefinition const*>>> m_interfaceFunctionList;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StructDefinition: public Declaration
|
class StructDefinition: public Declaration
|
||||||
|
@ -102,7 +102,8 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base)
|
|||||||
for (auto const& nameAndDeclaration: iterator->second.getDeclarations())
|
for (auto const& nameAndDeclaration: iterator->second.getDeclarations())
|
||||||
{
|
{
|
||||||
Declaration const* declaration = nameAndDeclaration.second;
|
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);
|
m_currentScope->registerDeclaration(*declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user