mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Explicit calls to base class function.
This commit is contained in:
		
							parent
							
								
									4d833bc86b
								
							
						
					
					
						commit
						6e111d5d1d
					
				
							
								
								
									
										5
									
								
								AST.cpp
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								AST.cpp
									
									
									
									
									
								
							| @ -373,7 +373,8 @@ void MemberAccess::checkTypeRequirements() | ||||
| 	Type const& type = *m_expression->getType(); | ||||
| 	m_type = type.getMemberType(*m_memberName); | ||||
| 	if (!m_type) | ||||
| 		BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found in " + type.toString())); | ||||
| 		BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not " | ||||
| 											  "visible in " + type.toString())); | ||||
| 	//@todo later, this will not always be STORAGE
 | ||||
| 	m_lvalue = type.getCategory() == Type::Category::STRUCT ? LValueType::STORAGE : LValueType::NONE; | ||||
| } | ||||
| @ -423,7 +424,7 @@ void Identifier::checkTypeRequirements() | ||||
| 	ContractDefinition const* contractDef = dynamic_cast<ContractDefinition const*>(m_referencedDeclaration); | ||||
| 	if (contractDef) | ||||
| 	{ | ||||
| 		m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef)); | ||||
| 		m_type = make_shared<TypeType>(make_shared<ContractType>(*contractDef), m_currentContract); | ||||
| 		return; | ||||
| 	} | ||||
| 	MagicVariableDeclaration const* magicVariable = dynamic_cast<MagicVariableDeclaration const*>(m_referencedDeclaration); | ||||
|  | ||||
							
								
								
									
										19
									
								
								AST.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								AST.h
									
									
									
									
									
								
							| @ -595,7 +595,7 @@ public: | ||||
| 	virtual void accept(ASTConstVisitor& _visitor) const override; | ||||
| 	virtual void checkTypeRequirements() override; | ||||
| 
 | ||||
| 	void setFunctionReturnParameters(ParameterList& _parameters) { m_returnParameters = &_parameters; } | ||||
| 	void setFunctionReturnParameters(ParameterList const& _parameters) { m_returnParameters = &_parameters; } | ||||
| 	ParameterList const& getFunctionReturnParameters() const | ||||
| 	{ | ||||
| 		solAssert(m_returnParameters, ""); | ||||
| @ -607,7 +607,7 @@ private: | ||||
| 	ASTPointer<Expression> m_expression; ///< value to return, optional
 | ||||
| 
 | ||||
| 	/// Pointer to the parameter list of the function, filled by the @ref NameAndTypeResolver.
 | ||||
| 	ParameterList* m_returnParameters; | ||||
| 	ParameterList const* m_returnParameters; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -884,21 +884,30 @@ class Identifier: public PrimaryExpression | ||||
| { | ||||
| public: | ||||
| 	Identifier(Location const& _location, ASTPointer<ASTString> const& _name): | ||||
| 		PrimaryExpression(_location), m_name(_name), m_referencedDeclaration(nullptr) {} | ||||
| 		PrimaryExpression(_location), m_name(_name) {} | ||||
| 	virtual void accept(ASTVisitor& _visitor) override; | ||||
| 	virtual void accept(ASTConstVisitor& _visitor) const override; | ||||
| 	virtual void checkTypeRequirements() override; | ||||
| 
 | ||||
| 	ASTString const& getName() const { return *m_name; } | ||||
| 
 | ||||
| 	void setReferencedDeclaration(Declaration const& _referencedDeclaration) { m_referencedDeclaration = &_referencedDeclaration; } | ||||
| 	void setReferencedDeclaration(Declaration const& _referencedDeclaration, | ||||
| 								  ContractDefinition const* _currentContract = nullptr) | ||||
| 	{ | ||||
| 		m_referencedDeclaration = &_referencedDeclaration; | ||||
| 		m_currentContract = _currentContract; | ||||
| 	} | ||||
| 	Declaration const* getReferencedDeclaration() const { return m_referencedDeclaration; } | ||||
| 	ContractDefinition const* getCurrentContract() const { return m_currentContract; } | ||||
| 
 | ||||
| private: | ||||
| 	ASTPointer<ASTString> m_name; | ||||
| 
 | ||||
| 	/// Declaration the name refers to.
 | ||||
| 	Declaration const* m_referencedDeclaration; | ||||
| 	Declaration const* m_referencedDeclaration = nullptr; | ||||
| 	/// Stores a reference to the current contract. This is needed because types of base contracts
 | ||||
| 	/// change depending on the context.
 | ||||
| 	ContractDefinition const* m_currentContract = nullptr; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -419,6 +419,22 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) | ||||
| 		m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess); | ||||
| 		break; | ||||
| 	} | ||||
| 	case Type::Category::TYPE: | ||||
| 	{ | ||||
| 		TypeType const& type = dynamic_cast<TypeType const&>(*_memberAccess.getExpression().getType()); | ||||
| 		if (type.getMembers().getMemberType(member)) | ||||
| 		{ | ||||
| 			ContractDefinition const& contract = dynamic_cast<ContractType const&>(*type.getActualType()) | ||||
| 													.getContractDefinition(); | ||||
| 			for (ASTPointer<FunctionDefinition> const& function: contract.getDefinedFunctions()) | ||||
| 				if (function->getName() == member) | ||||
| 				{ | ||||
| 					m_context << m_context.getFunctionEntryLabel(*function).pushTag(); | ||||
| 					return; | ||||
| 				} | ||||
| 		} | ||||
| 		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString())); | ||||
| 	} | ||||
| 	default: | ||||
| 		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type.")); | ||||
| 	} | ||||
| @ -449,20 +465,22 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier) | ||||
| 	{ | ||||
| 		if (magicVar->getType()->getCategory() == Type::Category::CONTRACT) // must be "this"
 | ||||
| 			m_context << eth::Instruction::ADDRESS; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration)) | ||||
| 	{ | ||||
| 	else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration)) | ||||
| 		m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag(); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (dynamic_cast<VariableDeclaration const*>(declaration)) | ||||
| 	else if (dynamic_cast<VariableDeclaration const*>(declaration)) | ||||
| 	{ | ||||
| 		m_currentLValue.fromIdentifier(_identifier, *declaration); | ||||
| 		m_currentLValue.retrieveValueIfLValueNotRequested(_identifier); | ||||
| 		return; | ||||
| 	} | ||||
| 	BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context.")); | ||||
| 	else if (dynamic_cast<ContractDefinition const*>(declaration)) | ||||
| 	{ | ||||
| 		// no-op
 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Identifier type not expected in expression context.")); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ExpressionCompiler::endVisit(Literal const& _literal) | ||||
|  | ||||
| @ -49,7 +49,7 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) | ||||
| 	m_currentScope = &m_scopes[nullptr]; | ||||
| 
 | ||||
| 	for (ASTPointer<Identifier> const& baseContract: _contract.getBaseContracts()) | ||||
| 		ReferencesResolver resolver(*baseContract, *this, nullptr); | ||||
| 		ReferencesResolver resolver(*baseContract, *this, &_contract, nullptr); | ||||
| 
 | ||||
| 	m_currentScope = &m_scopes[&_contract]; | ||||
| 
 | ||||
| @ -58,13 +58,13 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) | ||||
| 		importInheritedScope(*base); | ||||
| 
 | ||||
| 	for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs()) | ||||
| 		ReferencesResolver resolver(*structDef, *this, nullptr); | ||||
| 		ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); | ||||
| 	for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables()) | ||||
| 		ReferencesResolver resolver(*variable, *this, nullptr); | ||||
| 		ReferencesResolver resolver(*variable, *this, &_contract, nullptr); | ||||
| 	for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions()) | ||||
| 	{ | ||||
| 		m_currentScope = &m_scopes[function.get()]; | ||||
| 		ReferencesResolver referencesResolver(*function, *this, | ||||
| 		ReferencesResolver referencesResolver(*function, *this, &_contract, | ||||
| 											  function->getReturnParameterList().get()); | ||||
| 	} | ||||
| } | ||||
| @ -267,8 +267,10 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio | ||||
| } | ||||
| 
 | ||||
| ReferencesResolver::ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver, | ||||
| 									   ParameterList* _returnParameters, bool _allowLazyTypes): | ||||
| 	m_resolver(_resolver), m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes) | ||||
| 									   ContractDefinition const* _currentContract, | ||||
| 									   ParameterList const* _returnParameters, bool _allowLazyTypes): | ||||
| 	m_resolver(_resolver), m_currentContract(_currentContract), | ||||
| 	m_returnParameters(_returnParameters), m_allowLazyTypes(_allowLazyTypes) | ||||
| { | ||||
| 	_root.accept(*this); | ||||
| } | ||||
| @ -316,7 +318,7 @@ bool ReferencesResolver::visit(Identifier& _identifier) | ||||
| 	if (!declaration) | ||||
| 		BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_identifier.getLocation()) | ||||
| 												 << errinfo_comment("Undeclared identifier.")); | ||||
| 	_identifier.setReferencedDeclaration(*declaration); | ||||
| 	_identifier.setReferencedDeclaration(*declaration, m_currentContract); | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -120,7 +120,9 @@ class ReferencesResolver: private ASTVisitor | ||||
| { | ||||
| public: | ||||
| 	ReferencesResolver(ASTNode& _root, NameAndTypeResolver& _resolver, | ||||
| 					   ParameterList* _returnParameters, bool _allowLazyTypes = true); | ||||
| 					   ContractDefinition const* _currentContract, | ||||
| 					   ParameterList const* _returnParameters, | ||||
| 					   bool _allowLazyTypes = true); | ||||
| 
 | ||||
| private: | ||||
| 	virtual void endVisit(VariableDeclaration& _variable) override; | ||||
| @ -130,7 +132,8 @@ private: | ||||
| 	virtual bool visit(Return& _return) override; | ||||
| 
 | ||||
| 	NameAndTypeResolver& m_resolver; | ||||
| 	ParameterList* m_returnParameters; | ||||
| 	ContractDefinition const* m_currentContract; | ||||
| 	ParameterList const* m_returnParameters; | ||||
| 	bool m_allowLazyTypes; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										23
									
								
								Types.cpp
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								Types.cpp
									
									
									
									
									
								
							| @ -695,6 +695,29 @@ bool TypeType::operator==(Type const& _other) const | ||||
| 	return *getActualType() == *other.getActualType(); | ||||
| } | ||||
| 
 | ||||
| MemberList const& TypeType::getMembers() const | ||||
| { | ||||
| 	// We need to lazy-initialize it because of recursive references.
 | ||||
| 	if (!m_members) | ||||
| 	{ | ||||
| 		map<string, TypePointer> members; | ||||
| 		if (m_actualType->getCategory() == Category::CONTRACT && m_currentContract != nullptr) | ||||
| 		{ | ||||
| 			ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).getContractDefinition(); | ||||
| 			vector<ContractDefinition const*> currentBases = m_currentContract->getLinearizedBaseContracts(); | ||||
| 			if (find(currentBases.begin(), currentBases.end(), &contract) != currentBases.end()) | ||||
| 				// 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->getName() != contract.getName()) | ||||
| 						members[f->getName()] = make_shared<FunctionType>(*f); | ||||
| 		} | ||||
| 		m_members.reset(new MemberList(members)); | ||||
| 	} | ||||
| 	return *m_members; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| MagicType::MagicType(MagicType::Kind _kind): | ||||
| 	m_kind(_kind) | ||||
| { | ||||
|  | ||||
							
								
								
									
										8
									
								
								Types.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								Types.h
									
									
									
									
									
								
							| @ -442,7 +442,8 @@ class TypeType: public Type | ||||
| { | ||||
| public: | ||||
| 	virtual Category getCategory() const override { return Category::TYPE; } | ||||
| 	TypeType(TypePointer const& _actualType): m_actualType(_actualType) {} | ||||
| 	TypeType(TypePointer const& _actualType, ContractDefinition const* _currentContract = nullptr): | ||||
| 		m_actualType(_actualType), m_currentContract(_currentContract) {} | ||||
| 	TypePointer const& getActualType() const { return m_actualType; } | ||||
| 
 | ||||
| 	virtual TypePointer binaryOperatorResult(Token::Value, TypePointer const&) const override { return TypePointer(); } | ||||
| @ -451,9 +452,14 @@ public: | ||||
| 	virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); } | ||||
| 	virtual bool canLiveOutsideStorage() const override { return false; } | ||||
| 	virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; } | ||||
| 	virtual MemberList const& getMembers() const override; | ||||
| 
 | ||||
| private: | ||||
| 	TypePointer m_actualType; | ||||
| 	/// Context in which this type is used (influences visibility etc.), can be nullptr.
 | ||||
| 	ContractDefinition const* m_currentContract; | ||||
| 	/// List of member types, will be lazy-initialized because of recursive references.
 | ||||
| 	mutable std::unique_ptr<MemberList> m_members; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user