mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop
Conflicts: test/SolidityEndToEndTest.cpp test/SolidityNameAndTypeResolution.cpp test/SolidityParser.cpp
This commit is contained in:
		
						commit
						8e84dc27a7
					
				
							
								
								
									
										14
									
								
								AST.cpp
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								AST.cpp
									
									
									
									
									
								
							| @ -285,6 +285,20 @@ void ModifierInvocation::checkTypeRequirements() | ||||
| 			BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in modifier invocation.")); | ||||
| } | ||||
| 
 | ||||
| void EventDefinition::checkTypeRequirements() | ||||
| { | ||||
| 	int numIndexed = 0; | ||||
| 	for (ASTPointer<VariableDeclaration> const& var: getParameters()) | ||||
| 	{ | ||||
| 		if (var->isIndexed()) | ||||
| 			numIndexed++; | ||||
| 		if (!var->getType()->canLiveOutsideStorage()) | ||||
| 			BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); | ||||
| 	} | ||||
| 	if (numIndexed > 3) | ||||
| 		BOOST_THROW_EXCEPTION(createTypeError("More than 3 indexed arguments for event.")); | ||||
| } | ||||
| 
 | ||||
| void Block::checkTypeRequirements() | ||||
| { | ||||
| 	for (shared_ptr<Statement> const& statement: m_statements) | ||||
|  | ||||
							
								
								
									
										49
									
								
								AST.h
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								AST.h
									
									
									
									
									
								
							| @ -202,13 +202,15 @@ public: | ||||
| 					   std::vector<ASTPointer<StructDefinition>> const& _definedStructs, | ||||
| 					   std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables, | ||||
| 					   std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions, | ||||
| 					   std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers): | ||||
| 					   std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers, | ||||
| 					   std::vector<ASTPointer<EventDefinition>> const& _events): | ||||
| 		Declaration(_location, _name), Documented(_documentation), | ||||
| 		m_baseContracts(_baseContracts), | ||||
| 		m_definedStructs(_definedStructs), | ||||
| 		m_stateVariables(_stateVariables), | ||||
| 		m_definedFunctions(_definedFunctions), | ||||
| 		m_functionModifiers(_functionModifiers) | ||||
| 		m_functionModifiers(_functionModifiers), | ||||
| 		m_events(_events) | ||||
| 	{} | ||||
| 
 | ||||
| 	virtual void accept(ASTVisitor& _visitor) override; | ||||
| @ -219,6 +221,7 @@ public: | ||||
| 	std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; } | ||||
| 	std::vector<ASTPointer<ModifierDefinition>> const& getFunctionModifiers() const { return m_functionModifiers; } | ||||
| 	std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; } | ||||
| 	std::vector<ASTPointer<EventDefinition>> const& getEvents() const { return m_events; } | ||||
| 
 | ||||
| 	virtual TypePointer getType(ContractDefinition const* m_currentContract) const override; | ||||
| 
 | ||||
| @ -250,6 +253,7 @@ private: | ||||
| 	std::vector<ASTPointer<VariableDeclaration>> m_stateVariables; | ||||
| 	std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions; | ||||
| 	std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers; | ||||
| 	std::vector<ASTPointer<EventDefinition>> m_events; | ||||
| 
 | ||||
| 	std::vector<ContractDefinition const*> m_linearizedBaseContracts; | ||||
| 	mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList; | ||||
| @ -382,8 +386,10 @@ class VariableDeclaration: public Declaration | ||||
| { | ||||
| public: | ||||
| 	VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type, | ||||
| 							ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false): | ||||
| 	Declaration(_location, _name), m_typeName(_type), m_isPublic(_isPublic), m_isStateVariable(_isStateVar) {} | ||||
| 						ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false, | ||||
| 						bool _isIndexed = false): | ||||
| 		Declaration(_location, _name), m_typeName(_type), | ||||
| 		m_isPublic(_isPublic), m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {} | ||||
| 	virtual void accept(ASTVisitor& _visitor) override; | ||||
| 	virtual void accept(ASTConstVisitor& _visitor) const override; | ||||
| 
 | ||||
| @ -398,12 +404,13 @@ public: | ||||
| 	bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); } | ||||
| 	bool isPublic() const { return m_isPublic; } | ||||
| 	bool isStateVariable() const { return m_isStateVariable; } | ||||
| 
 | ||||
| 	bool isIndexed() const { return m_isIndexed; } | ||||
| 
 | ||||
| private: | ||||
| 	ASTPointer<TypeName> m_typeName;    ///< can be empty ("var")
 | ||||
| 	bool m_isPublic;                    ///< Whether there is an accessor for it or not
 | ||||
| 	bool m_isStateVariable;             ///< Whether or not this is a contract state variable
 | ||||
| 	bool m_isIndexed;                   ///< Whether this is an indexed variable (used by events).
 | ||||
| 
 | ||||
| 	std::shared_ptr<Type const> m_type; ///< derived type, initially empty
 | ||||
| }; | ||||
| @ -431,7 +438,6 @@ public: | ||||
| 
 | ||||
| 	virtual TypePointer getType(ContractDefinition const* = nullptr) const override; | ||||
| 
 | ||||
| 
 | ||||
| 	void checkTypeRequirements(); | ||||
| 
 | ||||
| private: | ||||
| @ -462,6 +468,37 @@ private: | ||||
| 	std::vector<ASTPointer<Expression>> m_arguments; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Definition of a (loggable) event. | ||||
|  */ | ||||
| class EventDefinition: public Declaration, public Documented | ||||
| { | ||||
| public: | ||||
| 	EventDefinition(Location const& _location, | ||||
| 					ASTPointer<ASTString> const& _name, | ||||
| 					ASTPointer<ASTString> const& _documentation, | ||||
| 					ASTPointer<ParameterList> const& _parameters): | ||||
| 		Declaration(_location, _name), Documented(_documentation), m_parameters(_parameters) {} | ||||
| 
 | ||||
| 	virtual void accept(ASTVisitor& _visitor) override; | ||||
| 	virtual void accept(ASTConstVisitor& _visitor) const override; | ||||
| 
 | ||||
| 	std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); } | ||||
| 	ParameterList const& getParameterList() const { return *m_parameters; } | ||||
| 	Block const& getBody() const { return *m_body; } | ||||
| 
 | ||||
| 	virtual TypePointer getType(ContractDefinition const* = nullptr) const override | ||||
| 	{ | ||||
| 		return std::make_shared<FunctionType>(*this); | ||||
| 	} | ||||
| 
 | ||||
| 	void checkTypeRequirements(); | ||||
| 
 | ||||
| private: | ||||
| 	ASTPointer<ParameterList> m_parameters; | ||||
| 	ASTPointer<Block> m_body; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global | ||||
|  * functions when such an identifier is encountered. Will never have a valid location in the source code. | ||||
|  | ||||
| @ -45,6 +45,7 @@ class FunctionDefinition; | ||||
| class VariableDeclaration; | ||||
| class ModifierDefinition; | ||||
| class ModifierInvocation; | ||||
| class EventDefinition; | ||||
| class MagicVariableDeclaration; | ||||
| class TypeName; | ||||
| class ElementaryTypeName; | ||||
|  | ||||
| @ -108,6 +108,13 @@ bool ASTPrinter::visit(ModifierInvocation const& _node) | ||||
| 	return goDeeper(); | ||||
| } | ||||
| 
 | ||||
| bool ASTPrinter::visit(EventDefinition const& _node) | ||||
| { | ||||
| 	writeLine("EventDefinition \"" + _node.getName() + "\""); | ||||
| 	printSourcePart(_node); | ||||
| 	return goDeeper(); | ||||
| } | ||||
| 
 | ||||
| bool ASTPrinter::visit(TypeName const& _node) | ||||
| { | ||||
| 	writeLine("TypeName"); | ||||
| @ -365,6 +372,11 @@ void ASTPrinter::endVisit(ModifierInvocation const&) | ||||
| 	m_indentation--; | ||||
| } | ||||
| 
 | ||||
| void ASTPrinter::endVisit(EventDefinition const&) | ||||
| { | ||||
| 	m_indentation--; | ||||
| } | ||||
| 
 | ||||
| void ASTPrinter::endVisit(TypeName const&) | ||||
| { | ||||
| 	m_indentation--; | ||||
|  | ||||
| @ -51,6 +51,7 @@ public: | ||||
| 	bool visit(VariableDeclaration const& _node) override; | ||||
| 	bool visit(ModifierDefinition const& _node) override; | ||||
| 	bool visit(ModifierInvocation const& _node) override; | ||||
| 	bool visit(EventDefinition const& _node) override; | ||||
| 	bool visit(TypeName const& _node) override; | ||||
| 	bool visit(ElementaryTypeName const& _node) override; | ||||
| 	bool visit(UserDefinedTypeName const& _node) override; | ||||
| @ -89,6 +90,7 @@ public: | ||||
| 	void endVisit(VariableDeclaration const&) override; | ||||
| 	void endVisit(ModifierDefinition const&) override; | ||||
| 	void endVisit(ModifierInvocation const&) override; | ||||
| 	void endVisit(EventDefinition const&) override; | ||||
| 	void endVisit(TypeName const&) override; | ||||
| 	void endVisit(ElementaryTypeName const&) override; | ||||
| 	void endVisit(UserDefinedTypeName const&) override; | ||||
|  | ||||
| @ -52,6 +52,7 @@ public: | ||||
| 	virtual bool visit(VariableDeclaration&) { return true; } | ||||
| 	virtual bool visit(ModifierDefinition&) { return true; } | ||||
| 	virtual bool visit(ModifierInvocation&) { return true; } | ||||
| 	virtual bool visit(EventDefinition&) { return true; } | ||||
| 	virtual bool visit(TypeName&) { return true; } | ||||
| 	virtual bool visit(ElementaryTypeName&) { return true; } | ||||
| 	virtual bool visit(UserDefinedTypeName&) { return true; } | ||||
| @ -92,6 +93,7 @@ public: | ||||
| 	virtual void endVisit(VariableDeclaration&) { } | ||||
| 	virtual void endVisit(ModifierDefinition&) { } | ||||
| 	virtual void endVisit(ModifierInvocation&) { } | ||||
| 	virtual void endVisit(EventDefinition&) { } | ||||
| 	virtual void endVisit(TypeName&) { } | ||||
| 	virtual void endVisit(ElementaryTypeName&) { } | ||||
| 	virtual void endVisit(UserDefinedTypeName&) { } | ||||
| @ -136,6 +138,7 @@ public: | ||||
| 	virtual bool visit(VariableDeclaration const&) { return true; } | ||||
| 	virtual bool visit(ModifierDefinition const&) { return true; } | ||||
| 	virtual bool visit(ModifierInvocation const&) { return true; } | ||||
| 	virtual bool visit(EventDefinition const&) { return true; } | ||||
| 	virtual bool visit(TypeName const&) { return true; } | ||||
| 	virtual bool visit(ElementaryTypeName const&) { return true; } | ||||
| 	virtual bool visit(UserDefinedTypeName const&) { return true; } | ||||
| @ -176,6 +179,7 @@ public: | ||||
| 	virtual void endVisit(VariableDeclaration const&) { } | ||||
| 	virtual void endVisit(ModifierDefinition const&) { } | ||||
| 	virtual void endVisit(ModifierInvocation const&) { } | ||||
| 	virtual void endVisit(EventDefinition const&) { } | ||||
| 	virtual void endVisit(TypeName const&) { } | ||||
| 	virtual void endVisit(ElementaryTypeName const&) { } | ||||
| 	virtual void endVisit(UserDefinedTypeName const&) { } | ||||
|  | ||||
							
								
								
									
										20
									
								
								AST_accept.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								AST_accept.h
									
									
									
									
									
								
							| @ -64,8 +64,9 @@ void ContractDefinition::accept(ASTVisitor& _visitor) | ||||
| 		listAccept(m_baseContracts, _visitor); | ||||
| 		listAccept(m_definedStructs, _visitor); | ||||
| 		listAccept(m_stateVariables, _visitor); | ||||
| 		listAccept(m_definedFunctions, _visitor); | ||||
| 		listAccept(m_events, _visitor); | ||||
| 		listAccept(m_functionModifiers, _visitor); | ||||
| 		listAccept(m_definedFunctions, _visitor); | ||||
| 	} | ||||
| 	_visitor.endVisit(*this); | ||||
| } | ||||
| @ -77,8 +78,9 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const | ||||
| 		listAccept(m_baseContracts, _visitor); | ||||
| 		listAccept(m_definedStructs, _visitor); | ||||
| 		listAccept(m_stateVariables, _visitor); | ||||
| 		listAccept(m_definedFunctions, _visitor); | ||||
| 		listAccept(m_events, _visitor); | ||||
| 		listAccept(m_functionModifiers, _visitor); | ||||
| 		listAccept(m_definedFunctions, _visitor); | ||||
| 	} | ||||
| 	_visitor.endVisit(*this); | ||||
| } | ||||
| @ -219,6 +221,20 @@ void ModifierInvocation::accept(ASTConstVisitor& _visitor) const | ||||
| 	_visitor.endVisit(*this); | ||||
| } | ||||
| 
 | ||||
| void EventDefinition::accept(ASTVisitor& _visitor) | ||||
| { | ||||
| 	if (_visitor.visit(*this)) | ||||
| 		m_parameters->accept(_visitor); | ||||
| 	_visitor.endVisit(*this); | ||||
| } | ||||
| 
 | ||||
| void EventDefinition::accept(ASTConstVisitor& _visitor) const | ||||
| { | ||||
| 	if (_visitor.visit(*this)) | ||||
| 		m_parameters->accept(_visitor); | ||||
| 	_visitor.endVisit(*this); | ||||
| } | ||||
| 
 | ||||
| void TypeName::accept(ASTVisitor& _visitor) | ||||
| { | ||||
| 	_visitor.visit(*this); | ||||
|  | ||||
| @ -23,6 +23,7 @@ | ||||
| #include <utility> | ||||
| #include <numeric> | ||||
| #include <libdevcore/Common.h> | ||||
| #include <libdevcrypto/SHA3.h> | ||||
| #include <libsolidity/AST.h> | ||||
| #include <libsolidity/ExpressionCompiler.h> | ||||
| #include <libsolidity/CompilerContext.h> | ||||
| @ -304,10 +305,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | ||||
| 			m_context << eth::Instruction::SUICIDE; | ||||
| 			break; | ||||
| 		case Location::SHA3: | ||||
| 			arguments.front()->accept(*this); | ||||
| 			appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); | ||||
| 			// @todo move this once we actually use memory
 | ||||
| 			CompilerUtils(m_context).storeInMemory(0); | ||||
| 			appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front()); | ||||
| 			m_context << u256(32) << u256(0) << eth::Instruction::SHA3; | ||||
| 			break; | ||||
| 		case Location::LOG0: | ||||
| @ -317,14 +315,41 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | ||||
| 		case Location::LOG4: | ||||
| 		{ | ||||
| 			unsigned logNumber = int(function.getLocation()) - int(Location::LOG0); | ||||
| 			for (int arg = logNumber; arg >= 0; --arg) | ||||
| 			for (unsigned arg = logNumber; arg > 0; --arg) | ||||
| 			{ | ||||
| 				arguments[arg]->accept(*this); | ||||
| 				appendTypeConversion(*arguments[arg]->getType(), *function.getParameterTypes()[arg], true); | ||||
| 			} | ||||
| 			// @todo move this once we actually use memory
 | ||||
| 			CompilerUtils(m_context).storeInMemory(0); | ||||
| 			m_context << u256(32) << u256(0) << eth::logInstruction(logNumber); | ||||
| 			unsigned length = appendExpressionCopyToMemory(*function.getParameterTypes().front(), | ||||
| 														   *arguments.front()); | ||||
| 			solAssert(length == 32, "Log data should be 32 bytes long (for now)."); | ||||
| 			m_context << u256(length) << u256(0) << eth::logInstruction(logNumber); | ||||
| 			break; | ||||
| 		} | ||||
| 		case Location::EVENT: | ||||
| 		{ | ||||
| 			_functionCall.getExpression().accept(*this); | ||||
| 			auto const& event = dynamic_cast<EventDefinition const&>(function.getDeclaration()); | ||||
| 			// Copy all non-indexed arguments to memory (data)
 | ||||
| 			unsigned numIndexed = 0; | ||||
| 			unsigned memLength = 0; | ||||
| 			for (unsigned arg = 0; arg < arguments.size(); ++arg) | ||||
| 				if (!event.getParameters()[arg]->isIndexed()) | ||||
| 					memLength += appendExpressionCopyToMemory(*function.getParameterTypes()[arg], | ||||
| 															  *arguments[arg], memLength); | ||||
| 			// All indexed arguments go to the stack
 | ||||
| 			for (unsigned arg = arguments.size(); arg > 0; --arg) | ||||
| 				if (event.getParameters()[arg - 1]->isIndexed()) | ||||
| 				{ | ||||
| 					++numIndexed; | ||||
| 					arguments[arg - 1]->accept(*this); | ||||
| 					appendTypeConversion(*arguments[arg - 1]->getType(), | ||||
| 										 *function.getParameterTypes()[arg - 1], true); | ||||
| 				} | ||||
| 			m_context << u256(h256::Arith(dev::sha3(function.getCanonicalSignature(event.getName())))); | ||||
| 			++numIndexed; | ||||
| 			solAssert(numIndexed <= 4, "Too many indexed arguments."); | ||||
| 			m_context << u256(memLength) << u256(0) << eth::logInstruction(numIndexed); | ||||
| 			break; | ||||
| 		} | ||||
| 		case Location::BLOCKHASH: | ||||
| @ -459,14 +484,13 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) | ||||
| bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) | ||||
| { | ||||
| 	_indexAccess.getBaseExpression().accept(*this); | ||||
| 	_indexAccess.getIndexExpression().accept(*this); | ||||
| 	appendTypeConversion(*_indexAccess.getIndexExpression().getType(), | ||||
| 						 *dynamic_cast<MappingType const&>(*_indexAccess.getBaseExpression().getType()).getKeyType(), | ||||
| 						 true); | ||||
| 
 | ||||
| 	TypePointer const& keyType = dynamic_cast<MappingType const&>(*_indexAccess.getBaseExpression().getType()).getKeyType(); | ||||
| 	unsigned length = appendExpressionCopyToMemory(*keyType, _indexAccess.getIndexExpression()); | ||||
| 	solAssert(length == 32, "Mapping key has to take 32 bytes in memory (for now)."); | ||||
| 	// @todo move this once we actually use memory
 | ||||
| 	CompilerUtils(m_context).storeInMemory(0); | ||||
| 	CompilerUtils(m_context).storeInMemory(32); | ||||
| 	m_context << u256(64) << u256(0) << eth::Instruction::SHA3; | ||||
| 	length += CompilerUtils(m_context).storeInMemory(length); | ||||
| 	m_context << u256(length) << u256(0) << eth::Instruction::SHA3; | ||||
| 
 | ||||
| 	m_currentLValue = LValue(m_context, LValue::STORAGE, *_indexAccess.getType()); | ||||
| 	m_currentLValue.retrieveValueIfLValueNotRequested(_indexAccess); | ||||
| @ -495,6 +519,10 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) | ||||
| 	{ | ||||
| 		// no-op
 | ||||
| 	} | ||||
| 	else if (dynamic_cast<EventDefinition const*>(declaration)) | ||||
| 	{ | ||||
| 		// no-op
 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context.")); | ||||
| @ -791,22 +819,25 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ | ||||
| { | ||||
| 	unsigned length = 0; | ||||
| 	for (unsigned i = 0; i < _arguments.size(); ++i) | ||||
| 	{ | ||||
| 		_arguments[i]->accept(*this); | ||||
| 		appendTypeConversion(*_arguments[i]->getType(), *_types[i], true); | ||||
| 		unsigned const c_numBytes = _types[i]->getCalldataEncodedSize(); | ||||
| 		if (c_numBytes == 0 || c_numBytes > 32) | ||||
| 			BOOST_THROW_EXCEPTION(CompilerError() | ||||
| 								  << errinfo_sourceLocation(_arguments[i]->getLocation()) | ||||
| 								  << errinfo_comment("Type " + _types[i]->toString() + " not yet supported.")); | ||||
| 		bool const c_leftAligned = _types[i]->getCategory() == Type::Category::STRING; | ||||
| 		bool const c_padToWords = true; | ||||
| 		length += CompilerUtils(m_context).storeInMemory(_memoryOffset + length, c_numBytes, | ||||
| 														 c_leftAligned, c_padToWords); | ||||
| 	} | ||||
| 		length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); | ||||
| 	return length; | ||||
| } | ||||
| 
 | ||||
| unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, | ||||
| 														  Expression const& _expression, unsigned _memoryOffset) | ||||
| { | ||||
| 	_expression.accept(*this); | ||||
| 	appendTypeConversion(*_expression.getType(), _expectedType, true); | ||||
| 	unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); | ||||
| 	if (c_numBytes == 0 || c_numBytes > 32) | ||||
| 		BOOST_THROW_EXCEPTION(CompilerError() | ||||
| 							  << errinfo_sourceLocation(_expression.getLocation()) | ||||
| 							  << errinfo_comment("Type " + _expectedType.toString() + " not yet supported.")); | ||||
| 	bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; | ||||
| 	bool const c_padToWords = true; | ||||
| 	return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); | ||||
| } | ||||
| 
 | ||||
| void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) | ||||
| { | ||||
| 	m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType()); | ||||
|  | ||||
| @ -94,8 +94,13 @@ private: | ||||
| 									bool bare = false); | ||||
| 	/// Appends code that copies the given arguments to memory (with optional offset).
 | ||||
| 	/// @returns the number of bytes copied to memory
 | ||||
| 	unsigned appendArgumentCopyToMemory(TypePointers const& _functionType, std::vector<ASTPointer<Expression const>> const& _arguments, | ||||
| 	unsigned appendArgumentCopyToMemory(TypePointers const& _types, | ||||
| 										std::vector<ASTPointer<Expression const>> const& _arguments, | ||||
| 										unsigned _memoryOffset = 0); | ||||
| 	/// Appends code that evaluates a single expression and copies it to memory (with optional offset).
 | ||||
| 	/// @returns the number of bytes copied to memory
 | ||||
| 	unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, | ||||
| 										  unsigned _memoryOffset = 0); | ||||
| 
 | ||||
| 	/// Appends code for a State Variable accessor function
 | ||||
| 	void appendStateVariableAccessor(VariableDeclaration const& _varDecl); | ||||
|  | ||||
| @ -60,6 +60,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) | ||||
| 		ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); | ||||
| 	for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables()) | ||||
| 		ReferencesResolver resolver(*variable, *this, &_contract, nullptr); | ||||
| 	for (ASTPointer<EventDefinition> const& event: _contract.getEvents()) | ||||
| 		ReferencesResolver resolver(*event, *this, &_contract, nullptr); | ||||
| 	for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers()) | ||||
| 	{ | ||||
| 		m_currentScope = &m_scopes[modifier.get()]; | ||||
| @ -259,6 +261,12 @@ bool DeclarationRegistrationHelper::visit(VariableDeclaration& _declaration) | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool DeclarationRegistrationHelper::visit(EventDefinition& _event) | ||||
| { | ||||
| 	registerDeclaration(_event, false); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declaration) | ||||
| { | ||||
| 	map<ASTNode const*, DeclarationContainer>::iterator iter; | ||||
|  | ||||
| @ -104,6 +104,7 @@ private: | ||||
| 	void endVisit(ModifierDefinition& _modifier); | ||||
| 	void endVisit(VariableDefinition& _variableDefinition); | ||||
| 	bool visit(VariableDeclaration& _declaration); | ||||
| 	bool visit(EventDefinition& _event); | ||||
| 
 | ||||
| 	void enterNewSubScope(Declaration const& _declaration); | ||||
| 	void closeCurrentScope(); | ||||
|  | ||||
							
								
								
									
										59
									
								
								Parser.cpp
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								Parser.cpp
									
									
									
									
									
								
							| @ -122,6 +122,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() | ||||
| 	vector<ASTPointer<VariableDeclaration>> stateVariables; | ||||
| 	vector<ASTPointer<FunctionDefinition>> functions; | ||||
| 	vector<ASTPointer<ModifierDefinition>> modifiers; | ||||
| 	vector<ASTPointer<EventDefinition>> events; | ||||
| 	if (m_scanner->getCurrentToken() == Token::IS) | ||||
| 		do | ||||
| 		{ | ||||
| @ -149,19 +150,23 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() | ||||
| 		else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING || | ||||
| 				 Token::isElementaryTypeName(currentToken)) | ||||
| 		{ | ||||
| 			bool const allowVar = false; | ||||
| 			stateVariables.push_back(parseVariableDeclaration(allowVar, visibilityIsPublic, true)); | ||||
| 			VarDeclParserOptions options; | ||||
| 			options.isPublic = visibilityIsPublic; | ||||
| 			options.isStateVariable = true; | ||||
| 			stateVariables.push_back(parseVariableDeclaration(options)); | ||||
| 			expectToken(Token::SEMICOLON); | ||||
| 		} | ||||
| 		else if (currentToken == Token::MODIFIER) | ||||
| 			modifiers.push_back(parseModifierDefinition()); | ||||
| 		else if (currentToken == Token::EVENT) | ||||
| 			events.push_back(parseEventDefinition()); | ||||
| 		else | ||||
| 			BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected.")); | ||||
| 	} | ||||
| 	nodeFactory.markEndPosition(); | ||||
| 	expectToken(Token::RBRACE); | ||||
| 	return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs, | ||||
| 													  stateVariables, functions, modifiers); | ||||
| 													  stateVariables, functions, modifiers, events); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier() | ||||
| @ -240,8 +245,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition() | ||||
| 	expectToken(Token::LBRACE); | ||||
| 	while (m_scanner->getCurrentToken() != Token::RBRACE) | ||||
| 	{ | ||||
| 		bool const allowVar = false; | ||||
| 		members.push_back(parseVariableDeclaration(allowVar)); | ||||
| 		members.push_back(parseVariableDeclaration()); | ||||
| 		expectToken(Token::SEMICOLON); | ||||
| 	} | ||||
| 	nodeFactory.markEndPosition(); | ||||
| @ -249,12 +253,20 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition() | ||||
| 	return nodeFactory.createNode<StructDefinition>(name, members); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar, bool _isPublic, bool _isStateVariable) | ||||
| ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOptions const& _options) | ||||
| { | ||||
| 	ASTNodeFactory nodeFactory(*this); | ||||
| 	ASTPointer<TypeName> type = parseTypeName(_allowVar); | ||||
| 	ASTPointer<TypeName> type = parseTypeName(_options.allowVar); | ||||
| 	bool isIndexed = false; | ||||
| 	if (_options.allowIndexed && m_scanner->getCurrentToken() == Token::INDEXED) | ||||
| 	{ | ||||
| 		isIndexed = true; | ||||
| 		m_scanner->next(); | ||||
| 	} | ||||
| 	nodeFactory.markEndPosition(); | ||||
| 	return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), _isPublic, _isStateVariable); | ||||
| 	return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), | ||||
| 													   _options.isPublic, _options.isStateVariable, | ||||
| 													   isIndexed); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() | ||||
| @ -284,6 +296,23 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() | ||||
| 	return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<EventDefinition> Parser::parseEventDefinition() | ||||
| { | ||||
| 	ASTNodeFactory nodeFactory(*this); | ||||
| 	ASTPointer<ASTString> docstring; | ||||
| 	if (m_scanner->getCurrentCommentLiteral() != "") | ||||
| 		docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral()); | ||||
| 
 | ||||
| 	expectToken(Token::EVENT); | ||||
| 	ASTPointer<ASTString> name(expectIdentifierToken()); | ||||
| 	ASTPointer<ParameterList> parameters; | ||||
| 	if (m_scanner->getCurrentToken() == Token::LPAREN) | ||||
| 		parameters = parseParameterList(true, true); | ||||
| 	nodeFactory.markEndPosition(); | ||||
| 	expectToken(Token::SEMICOLON); | ||||
| 	return nodeFactory.createNode<EventDefinition>(name, docstring, parameters); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<ModifierInvocation> Parser::parseModifierInvocation() | ||||
| { | ||||
| 	ASTNodeFactory nodeFactory(*this); | ||||
| @ -356,19 +385,20 @@ ASTPointer<Mapping> Parser::parseMapping() | ||||
| 	return nodeFactory.createNode<Mapping>(keyType, valueType); | ||||
| } | ||||
| 
 | ||||
| ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty) | ||||
| ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty, bool _allowIndexed) | ||||
| { | ||||
| 	ASTNodeFactory nodeFactory(*this); | ||||
| 	vector<ASTPointer<VariableDeclaration>> parameters; | ||||
| 	VarDeclParserOptions options; | ||||
| 	options.allowIndexed = _allowIndexed; | ||||
| 	expectToken(Token::LPAREN); | ||||
| 	if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) | ||||
| 	{ | ||||
| 		bool const allowVar = false; | ||||
| 		parameters.push_back(parseVariableDeclaration(allowVar)); | ||||
| 		parameters.push_back(parseVariableDeclaration(options)); | ||||
| 		while (m_scanner->getCurrentToken() != Token::RPAREN) | ||||
| 		{ | ||||
| 			expectToken(Token::COMMA); | ||||
| 			parameters.push_back(parseVariableDeclaration(allowVar)); | ||||
| 			parameters.push_back(parseVariableDeclaration(options)); | ||||
| 		} | ||||
| 	} | ||||
| 	nodeFactory.markEndPosition(); | ||||
| @ -510,8 +540,9 @@ ASTPointer<Statement> Parser::parseVarDefOrExprStmt() | ||||
| ASTPointer<VariableDefinition> Parser::parseVariableDefinition() | ||||
| { | ||||
| 	ASTNodeFactory nodeFactory(*this); | ||||
| 	bool const allowVar = true; | ||||
| 	ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(allowVar); | ||||
| 	VarDeclParserOptions options; | ||||
| 	options.allowVar = true; | ||||
| 	ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(options); | ||||
| 	ASTPointer<Expression> value; | ||||
| 	if (m_scanner->getCurrentToken() == Token::ASSIGN) | ||||
| 	{ | ||||
|  | ||||
							
								
								
									
										13
									
								
								Parser.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Parser.h
									
									
									
									
									
								
							| @ -45,6 +45,14 @@ private: | ||||
| 	/// End position of the current token
 | ||||
| 	int getEndPosition() const; | ||||
| 
 | ||||
| 	struct VarDeclParserOptions { | ||||
| 		VarDeclParserOptions() {} | ||||
| 		bool allowVar = false; | ||||
| 		bool isPublic = false; | ||||
| 		bool isStateVariable = false; | ||||
| 		bool allowIndexed = false; | ||||
| 	}; | ||||
| 
 | ||||
| 	///@{
 | ||||
| 	///@name Parsing functions for the AST nodes
 | ||||
| 	ASTPointer<ImportDirective> parseImportDirective(); | ||||
| @ -52,13 +60,14 @@ private: | ||||
| 	ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier(); | ||||
| 	ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName); | ||||
| 	ASTPointer<StructDefinition> parseStructDefinition(); | ||||
| 	ASTPointer<VariableDeclaration> parseVariableDeclaration(bool _allowVar, bool _isPublic = false, bool _isStateVar = false); | ||||
| 	ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); | ||||
| 	ASTPointer<ModifierDefinition> parseModifierDefinition(); | ||||
| 	ASTPointer<EventDefinition> parseEventDefinition(); | ||||
| 	ASTPointer<ModifierInvocation> parseModifierInvocation(); | ||||
| 	ASTPointer<Identifier> parseIdentifier(); | ||||
| 	ASTPointer<TypeName> parseTypeName(bool _allowVar); | ||||
| 	ASTPointer<Mapping> parseMapping(); | ||||
| 	ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true); | ||||
| 	ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true, bool _allowIndexed = false); | ||||
| 	ASTPointer<Block> parseBlock(); | ||||
| 	ASTPointer<Statement> parseStatement(); | ||||
| 	ASTPointer<IfStatement> parseIfStatement(); | ||||
|  | ||||
							
								
								
									
										2
									
								
								Token.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Token.h
									
									
									
									
									
								
							| @ -153,7 +153,9 @@ namespace solidity | ||||
| 	K(DEFAULT, "default", 0)                                           \ | ||||
| 	K(DO, "do", 0)                                                     \ | ||||
| 	K(ELSE, "else", 0)                                                 \ | ||||
| 	K(EVENT, "event", 0)                                               \ | ||||
| 	K(IS, "is", 0)                                                     \ | ||||
| 	K(INDEXED, "indexed", 0)                                           \ | ||||
| 	K(FOR, "for", 0)                                                   \ | ||||
| 	K(FUNCTION, "function", 0)                                         \ | ||||
| 	K(IF, "if", 0)                                                     \ | ||||
|  | ||||
							
								
								
									
										16
									
								
								Types.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Types.cpp
									
									
									
									
									
								
							| @ -633,6 +633,22 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): | ||||
| 	swap(retParamNames, m_returnParameterNames); | ||||
| } | ||||
| 
 | ||||
| FunctionType::FunctionType(const EventDefinition& _event): | ||||
| 	m_location(Location::EVENT), m_declaration(&_event) | ||||
| { | ||||
| 	TypePointers params; | ||||
| 	vector<string> paramNames; | ||||
| 	params.reserve(_event.getParameters().size()); | ||||
| 	paramNames.reserve(_event.getParameters().size()); | ||||
| 	for (ASTPointer<VariableDeclaration> const& var: _event.getParameters()) | ||||
| 	{ | ||||
| 		paramNames.push_back(var->getName()); | ||||
| 		params.push_back(var->getType()); | ||||
| 	} | ||||
| 	swap(params, m_parameterTypes); | ||||
| 	swap(paramNames, m_parameterNames); | ||||
| } | ||||
| 
 | ||||
| bool FunctionType::operator==(Type const& _other) const | ||||
| { | ||||
| 	if (_other.getCategory() != getCategory()) | ||||
|  | ||||
							
								
								
									
										4
									
								
								Types.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Types.h
									
									
									
									
									
								
							| @ -350,16 +350,18 @@ public: | ||||
| 	/// INTERNAL: jump tag, EXTERNAL: contract address + function identifier,
 | ||||
| 	/// BARE: contract address (non-abi contract call)
 | ||||
| 	/// OTHERS: special virtual function, nothing on the stack
 | ||||
| 	/// @todo This documentation is outdated, and Location should rather be named "Type"
 | ||||
| 	enum class Location { INTERNAL, EXTERNAL, CREATION, SEND, | ||||
| 						  SHA3, SUICIDE, | ||||
| 						  ECRECOVER, SHA256, RIPEMD160, | ||||
| 						  LOG0, LOG1, LOG2, LOG3, LOG4, | ||||
| 						  LOG0, LOG1, LOG2, LOG3, LOG4, EVENT, | ||||
| 						  SET_GAS, SET_VALUE, BLOCKHASH, | ||||
| 						  BARE }; | ||||
| 
 | ||||
| 	virtual Category getCategory() const override { return Category::FUNCTION; } | ||||
| 	explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); | ||||
| 	explicit FunctionType(VariableDeclaration const& _varDecl); | ||||
| 	explicit FunctionType(EventDefinition const& _event); | ||||
| 	FunctionType(strings const& _parameterTypes, strings const& _returnParameterTypes, | ||||
| 				 Location _location = Location::INTERNAL): | ||||
| 		FunctionType(parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes), | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user