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