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(); | 	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( | ||||||
| 								  "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()) | 	for (ASTPointer<ModifierDefinition> const& modifier: getFunctionModifiers()) | ||||||
| 		modifier->checkTypeRequirements(); | 		modifier->checkTypeRequirements(); | ||||||
| @ -99,6 +104,15 @@ FunctionDefinition const* ContractDefinition::getConstructor() const | |||||||
| 	return nullptr; | 	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 | void ContractDefinition::checkIllegalOverrides() const | ||||||
| { | { | ||||||
| 	// TODO unify this at a later point. for this we need to put the constness and the access specifier
 | 	// 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 (ContractDefinition const* contract: getLinearizedBaseContracts()) | ||||||
| 		{ | 		{ | ||||||
| 			for (ASTPointer<FunctionDefinition> const& f: contract->getDefinedFunctions()) | 			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()); | 					functionsSeen.insert(f->getName()); | ||||||
| 					FixedHash<4> hash(dev::sha3(f->getCanonicalSignature())); | 					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; } | 	std::vector<ContractDefinition const*> const& getLinearizedBaseContracts() const { return m_linearizedBaseContracts; } | ||||||
| 	void setLinearizedBaseContracts(std::vector<ContractDefinition const*> const& _bases) { m_linearizedBaseContracts = _bases; } | 	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; | 	FunctionDefinition const* getConstructor() const; | ||||||
|  | 	/// Returns the fallback function or nullptr if no constructor was specified.
 | ||||||
|  | 	FunctionDefinition const* getFallbackFunction() const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	void checkIllegalOverrides() const; | 	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; | 	map<FixedHash<4>, const eth::AssemblyItem> callDataUnpackerEntryPoints; | ||||||
| 
 | 
 | ||||||
| 	// retrieve the function signature hash from the calldata
 | 	// retrieve the function signature hash from the calldata
 | ||||||
| 	m_context << u256(1) << u256(0); | 	if (!interfaceFunctions.empty()) | ||||||
| 	CompilerUtils(m_context).loadFromMemory(0, 4, false, true); | 		CompilerUtils(m_context).loadFromMemory(0, 4, false, true); | ||||||
| 
 | 
 | ||||||
| 	// stack now is: 1 0 <funhash>
 | 	// stack now is: 1 0 <funhash>
 | ||||||
| 	for (auto const& it: interfaceFunctions) | 	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 << eth::dupInstruction(1) << u256(FixedHash<4>::Arith(it.first)) << eth::Instruction::EQ; | ||||||
| 		m_context.appendConditionalJumpTo(callDataUnpackerEntryPoints.at(it.first)); | 		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) | 	for (auto const& it: interfaceFunctions) | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
| @ -189,7 +189,11 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic, A | |||||||
| 		docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral()); | 		docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral()); | ||||||
| 
 | 
 | ||||||
| 	expectToken(Token::FUNCTION); | 	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()); | 	ASTPointer<ParameterList> parameters(parseParameterList()); | ||||||
| 	bool isDeclaredConst = false; | 	bool isDeclaredConst = false; | ||||||
| 	vector<ASTPointer<ModifierInvocation>> modifiers; | 	vector<ASTPointer<ModifierInvocation>> modifiers; | ||||||
|  | |||||||
| @ -494,7 +494,7 @@ MemberList const& ContractType::getMembers() const | |||||||
| 		{ | 		{ | ||||||
| 			for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts()) | 			for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts()) | ||||||
| 				for (ASTPointer<FunctionDefinition> const& function: base->getDefinedFunctions()) | 				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))); | 						members.insert(make_pair(function->getName(), make_shared<FunctionType>(*function, true))); | ||||||
| 		} | 		} | ||||||
| 		else | 		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
 | 				// 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.
 | 				// functions. Note that this does not add inherited functions on purpose.
 | ||||||
| 				for (ASTPointer<FunctionDefinition> const& f: contract.getDefinedFunctions()) | 				for (ASTPointer<FunctionDefinition> const& f: contract.getDefinedFunctions()) | ||||||
| 					if (!f->isConstructor()) | 					if (!f->isConstructor() && !f->getName().empty()) | ||||||
| 						members[f->getName()] = make_shared<FunctionType>(*f); | 						members[f->getName()] = make_shared<FunctionType>(*f); | ||||||
| 		} | 		} | ||||||
| 		m_members.reset(new MemberList(members)); | 		m_members.reset(new MemberList(members)); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user