mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fallback functions.
This commit is contained in:
parent
3701543ae8
commit
cfb55901cc
18
AST.cpp
18
AST.cpp
@ -56,7 +56,12 @@ void ContractDefinition::checkTypeRequirements()
|
||||
FunctionDefinition const* constructor = getConstructor();
|
||||
if (constructor && !constructor->getReturnParameters().empty())
|
||||
BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError(
|
||||
"Non-empty \"returns\" directive for constructor."));
|
||||
"Non-empty \"returns\" directive for constructor."));
|
||||
|
||||
FunctionDefinition const* fallbackFunction = getFallbackFunction();
|
||||
if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty())
|
||||
BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError(
|
||||
"Fallback function cannot take parameters."));
|
||||
|
||||
for (ASTPointer<ModifierDefinition> const& modifier: getFunctionModifiers())
|
||||
modifier->checkTypeRequirements();
|
||||
@ -99,6 +104,15 @@ FunctionDefinition const* ContractDefinition::getConstructor() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FunctionDefinition const* ContractDefinition::getFallbackFunction() const
|
||||
{
|
||||
for (ContractDefinition const* contract: getLinearizedBaseContracts())
|
||||
for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions())
|
||||
if (f->getName().empty())
|
||||
return f.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ContractDefinition::checkIllegalOverrides() const
|
||||
{
|
||||
// TODO unify this at a later point. for this we need to put the constness and the access specifier
|
||||
@ -147,7 +161,7 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::getIn
|
||||
for (ContractDefinition const* contract: getLinearizedBaseContracts())
|
||||
{
|
||||
for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions())
|
||||
if (f->isPublic() && !f->isConstructor() && functionsSeen.count(f->getName()) == 0)
|
||||
if (f->isPublic() && !f->isConstructor() && !f->getName().empty() && functionsSeen.count(f->getName()) == 0)
|
||||
{
|
||||
functionsSeen.insert(f->getName());
|
||||
FixedHash<4> hash(dev::sha3(f->getCanonicalSignature()));
|
||||
|
4
AST.h
4
AST.h
@ -235,8 +235,10 @@ public:
|
||||
std::vector<ContractDefinition const*> const& getLinearizedBaseContracts() const { return m_linearizedBaseContracts; }
|
||||
void setLinearizedBaseContracts(std::vector<ContractDefinition const*> const& _bases) { m_linearizedBaseContracts = _bases; }
|
||||
|
||||
/// Returns the constructor or nullptr if no constructor was specified
|
||||
/// Returns the constructor or nullptr if no constructor was specified.
|
||||
FunctionDefinition const* getConstructor() const;
|
||||
/// Returns the fallback function or nullptr if no constructor was specified.
|
||||
FunctionDefinition const* getFallbackFunction() const;
|
||||
|
||||
private:
|
||||
void checkIllegalOverrides() const;
|
||||
|
14
Compiler.cpp
14
Compiler.cpp
@ -146,8 +146,8 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
map<FixedHash<4>, const eth::AssemblyItem> callDataUnpackerEntryPoints;
|
||||
|
||||
// retrieve the function signature hash from the calldata
|
||||
m_context << u256(1) << u256(0);
|
||||
CompilerUtils(m_context).loadFromMemory(0, 4, false, true);
|
||||
if (!interfaceFunctions.empty())
|
||||
CompilerUtils(m_context).loadFromMemory(0, 4, false, true);
|
||||
|
||||
// stack now is: 1 0 <funhash>
|
||||
for (auto const& it: interfaceFunctions)
|
||||
@ -156,7 +156,15 @@ void Compiler::appendFunctionSelector(ContractDefinition const& _contract)
|
||||
m_context << eth::dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << eth::Instruction::EQ;
|
||||
m_context.appendConditionalJumpTo(callDataUnpackerEntryPoints.at(it.first));
|
||||
}
|
||||
m_context << eth::Instruction::STOP; // function not found
|
||||
if (FunctionDefinition const* fallback = _contract.getFallbackFunction())
|
||||
{
|
||||
eth::AssemblyItem returnTag = m_context.pushNewTag();
|
||||
fallback->accept(*this);
|
||||
m_context << returnTag;
|
||||
appendReturnValuePacker(FunctionType(*fallback).getReturnParameterTypes());
|
||||
}
|
||||
else
|
||||
m_context << eth::Instruction::STOP; // function not found
|
||||
|
||||
for (auto const& it: interfaceFunctions)
|
||||
{
|
||||
|
@ -189,7 +189,11 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A
|
||||
docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral());
|
||||
|
||||
expectToken(Token::FUNCTION);
|
||||
ASTPointer<ASTString> name(expectIdentifierToken());
|
||||
ASTPointer<ASTString> name;
|
||||
if (m_scanner->getCurrentToken() == Token::LPAREN)
|
||||
name = make_shared<ASTString>(); // anonymous function
|
||||
else
|
||||
name = expectIdentifierToken();
|
||||
ASTPointer<ParameterList> parameters(parseParameterList());
|
||||
bool isDeclaredConst = false;
|
||||
vector<ASTPointer<ModifierInvocation>> modifiers;
|
||||
|
@ -494,7 +494,7 @@ MemberList const& ContractType::getMembers() const
|
||||
{
|
||||
for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts())
|
||||
for (ASTPointer<FunctionDefinition> const& function: base->getDefinedFunctions())
|
||||
if (!function->isConstructor())
|
||||
if (!function->isConstructor() && !function->getName().empty())
|
||||
members.insert(make_pair(function->getName(), make_shared<FunctionType>(*function, true)));
|
||||
}
|
||||
else
|
||||
@ -808,7 +808,7 @@ MemberList const& TypeType::getMembers() const
|
||||
// We are accessing the type of a base contract, so add all public and private
|
||||
// functions. Note that this does not add inherited functions on purpose.
|
||||
for (ASTPointer<FunctionDefinition> const& f: contract.getDefinedFunctions())
|
||||
if (!f->isConstructor())
|
||||
if (!f->isConstructor() && !f->getName().empty())
|
||||
members[f->getName()] = make_shared<FunctionType>(*f);
|
||||
}
|
||||
m_members.reset(new MemberList(members));
|
||||
|
Loading…
Reference in New Issue
Block a user