mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #13739 from ethereum/code-reshuffling-before-operators
Code reshuffling before custom operators
This commit is contained in:
		
						commit
						33f27098e9
					
				| @ -1751,7 +1751,9 @@ bool TypeChecker::visit(UnaryOperation const& _operation) | |||||||
| 	else | 	else | ||||||
| 		_operation.annotation().type = result.get(); | 		_operation.annotation().type = result.get(); | ||||||
| 	_operation.annotation().isConstant = false; | 	_operation.annotation().isConstant = false; | ||||||
| 	_operation.annotation().isPure = !modifying && *_operation.subExpression().annotation().isPure; | 	_operation.annotation().isPure = | ||||||
|  | 		!modifying && | ||||||
|  | 		*_operation.subExpression().annotation().isPure; | ||||||
| 	_operation.annotation().isLValue = false; | 	_operation.annotation().isLValue = false; | ||||||
| 
 | 
 | ||||||
| 	return false; | 	return false; | ||||||
| @ -3750,8 +3752,9 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) | |||||||
| 			solAssert(m_errorReporter.hasErrors()); | 			solAssert(m_errorReporter.hasErrors()); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		solAssert(_usingFor.typeName()->annotation().type); | 		Type const* usingForType = _usingFor.typeName()->annotation().type; | ||||||
| 		if (Declaration const* typeDefinition = _usingFor.typeName()->annotation().type->typeDefinition()) | 		solAssert(usingForType); | ||||||
|  | 		if (Declaration const* typeDefinition = usingForType->typeDefinition()) | ||||||
| 		{ | 		{ | ||||||
| 			if (typeDefinition->scope() != m_currentSourceUnit) | 			if (typeDefinition->scope() != m_currentSourceUnit) | ||||||
| 				m_errorReporter.typeError( | 				m_errorReporter.typeError( | ||||||
| @ -3785,10 +3788,12 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	solAssert(_usingFor.typeName()->annotation().type); | 	Type const* usingForType = _usingFor.typeName()->annotation().type; | ||||||
|  | 	solAssert(usingForType); | ||||||
|  | 
 | ||||||
| 	Type const* normalizedType = TypeProvider::withLocationIfReference( | 	Type const* normalizedType = TypeProvider::withLocationIfReference( | ||||||
| 		DataLocation::Storage, | 		DataLocation::Storage, | ||||||
| 		_usingFor.typeName()->annotation().type | 		usingForType | ||||||
| 	); | 	); | ||||||
| 	solAssert(normalizedType); | 	solAssert(normalizedType); | ||||||
| 
 | 
 | ||||||
| @ -3824,7 +3829,7 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) | |||||||
| 					"The function \"{}\" cannot be bound to the type \"{}\" because the type cannot " | 					"The function \"{}\" cannot be bound to the type \"{}\" because the type cannot " | ||||||
| 					"be implicitly converted to the first argument of the function (\"{}\"){}", | 					"be implicitly converted to the first argument of the function (\"{}\"){}", | ||||||
| 					joinHumanReadable(path->path(), "."), | 					joinHumanReadable(path->path(), "."), | ||||||
| 					_usingFor.typeName()->annotation().type->toString(true /* withoutDataLocation */), | 					usingForType->toString(true /* withoutDataLocation */), | ||||||
| 					functionType->selfType()->humanReadableName(), | 					functionType->selfType()->humanReadableName(), | ||||||
| 					result.message().empty() ? "." : ": " +  result.message() | 					result.message().empty() ? "." : ": " +  result.message() | ||||||
| 				) | 				) | ||||||
|  | |||||||
| @ -323,16 +323,23 @@ ViewPureChecker::MutabilityAndLocation const& ViewPureChecker::modifierMutabilit | |||||||
| 	return m_inferredMutability.at(&_modifier); | 	return m_inferredMutability.at(&_modifier); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ViewPureChecker::reportFunctionCallMutability(StateMutability _mutability, langutil::SourceLocation const& _location) | ||||||
|  | { | ||||||
|  | 	// We only require "nonpayable" to call a payable function.
 | ||||||
|  | 	if (_mutability == StateMutability::Payable) | ||||||
|  | 		_mutability = StateMutability::NonPayable; | ||||||
|  | 	reportMutability(_mutability, _location); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ViewPureChecker::endVisit(FunctionCall const& _functionCall) | void ViewPureChecker::endVisit(FunctionCall const& _functionCall) | ||||||
| { | { | ||||||
| 	if (*_functionCall.annotation().kind != FunctionCallKind::FunctionCall) | 	if (*_functionCall.annotation().kind != FunctionCallKind::FunctionCall) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	StateMutability mutability = dynamic_cast<FunctionType const&>(*_functionCall.expression().annotation().type).stateMutability(); | 	reportFunctionCallMutability( | ||||||
| 	// We only require "nonpayable" to call a payble function.
 | 		dynamic_cast<FunctionType const&>(*_functionCall.expression().annotation().type).stateMutability(), | ||||||
| 	if (mutability == StateMutability::Payable) | 		_functionCall.location() | ||||||
| 		mutability = StateMutability::NonPayable; | 	); | ||||||
| 	reportMutability(mutability, _functionCall.location()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ViewPureChecker::visit(MemberAccess const& _memberAccess) | bool ViewPureChecker::visit(MemberAccess const& _memberAccess) | ||||||
|  | |||||||
| @ -73,6 +73,8 @@ private: | |||||||
| 		std::optional<langutil::SourceLocation> const& _nestedLocation = {} | 		std::optional<langutil::SourceLocation> const& _nestedLocation = {} | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
|  | 	void reportFunctionCallMutability(StateMutability _mutability, langutil::SourceLocation const& _location); | ||||||
|  | 
 | ||||||
| 	/// Determines the mutability of modifier if not already cached.
 | 	/// Determines the mutability of modifier if not already cached.
 | ||||||
| 	MutabilityAndLocation const& modifierMutability(ModifierDefinition const& _modifier); | 	MutabilityAndLocation const& modifierMutability(ModifierDefinition const& _modifier); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -48,6 +48,7 @@ | |||||||
| #include <range/v3/view/reverse.hpp> | #include <range/v3/view/reverse.hpp> | ||||||
| #include <range/v3/view/tail.hpp> | #include <range/v3/view/tail.hpp> | ||||||
| #include <range/v3/view/transform.hpp> | #include <range/v3/view/transform.hpp> | ||||||
|  | #include <range/v3/view/filter.hpp> | ||||||
| 
 | 
 | ||||||
| #include <limits> | #include <limits> | ||||||
| #include <unordered_set> | #include <unordered_set> | ||||||
| @ -337,7 +338,10 @@ Type const* Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c | |||||||
| 	return encodingType; | 	return encodingType; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope) | namespace | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, ASTNode const& _scope) | ||||||
| { | { | ||||||
| 	vector<UsingForDirective const*> usingForDirectives; | 	vector<UsingForDirective const*> usingForDirectives; | ||||||
| 	SourceUnit const* sourceUnit = dynamic_cast<SourceUnit const*>(&_scope); | 	SourceUnit const* sourceUnit = dynamic_cast<SourceUnit const*>(&_scope); | ||||||
| @ -362,6 +366,25 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc | |||||||
| 	if (auto refType = dynamic_cast<ReferenceType const*>(&_type)) | 	if (auto refType = dynamic_cast<ReferenceType const*>(&_type)) | ||||||
| 		typeLocation = refType->location(); | 		typeLocation = refType->location(); | ||||||
| 
 | 
 | ||||||
|  | 	return usingForDirectives | ranges::views::filter([&](UsingForDirective const* _directive) -> bool { | ||||||
|  | 		// Convert both types to pointers for comparison to see if the `using for` directive applies.
 | ||||||
|  | 		// Note that at this point we don't yet know if the functions are actually usable with the type.
 | ||||||
|  | 		// `_type` may not be convertible to the function parameter type.
 | ||||||
|  | 		return | ||||||
|  | 			!_directive->typeName() || | ||||||
|  | 			*TypeProvider::withLocationIfReference(typeLocation, &_type, true) == | ||||||
|  | 			*TypeProvider::withLocationIfReference( | ||||||
|  | 				typeLocation, | ||||||
|  | 				_directive->typeName()->annotation().type, | ||||||
|  | 				true | ||||||
|  | 			); | ||||||
|  | 	}) | ranges::to<vector<UsingForDirective const*>>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope) | ||||||
|  | { | ||||||
| 	MemberList::MemberMap members; | 	MemberList::MemberMap members; | ||||||
| 
 | 
 | ||||||
| 	set<pair<string, Declaration const*>> seenFunctions; | 	set<pair<string, Declaration const*>> seenFunctions; | ||||||
| @ -381,27 +404,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc | |||||||
| 				members.emplace_back(&_function, asBoundFunction, *_name); | 				members.emplace_back(&_function, asBoundFunction, *_name); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	for (UsingForDirective const* ufd: usingForDirectives) | 	for (UsingForDirective const* ufd: usingForDirectivesForType(_type, _scope)) | ||||||
| 	{ | 		for (auto const& identifierPath: ufd->functionsOrLibrary()) | ||||||
| 		// Convert both types to pointers for comparison to see if the `using for`
 |  | ||||||
| 		// directive applies.
 |  | ||||||
| 		// Further down, we check more detailed for each function if `_type` is
 |  | ||||||
| 		// convertible to the function parameter type.
 |  | ||||||
| 		if ( |  | ||||||
| 			ufd->typeName() && |  | ||||||
| 			*TypeProvider::withLocationIfReference(typeLocation, &_type, true) != |  | ||||||
| 			*TypeProvider::withLocationIfReference( |  | ||||||
| 				typeLocation, |  | ||||||
| 				ufd->typeName()->annotation().type, |  | ||||||
| 				true |  | ||||||
| 			) |  | ||||||
| 		) |  | ||||||
| 			continue; |  | ||||||
| 
 |  | ||||||
| 		for (auto const& pathPointer: ufd->functionsOrLibrary()) |  | ||||||
| 		{ | 		{ | ||||||
| 			solAssert(pathPointer); | 			solAssert(identifierPath); | ||||||
| 			Declaration const* declaration = pathPointer->annotation().referencedDeclaration; | 			Declaration const* declaration = identifierPath->annotation().referencedDeclaration; | ||||||
| 			solAssert(declaration); | 			solAssert(declaration); | ||||||
| 
 | 
 | ||||||
| 			if (ContractDefinition const* library = dynamic_cast<ContractDefinition const*>(declaration)) | 			if (ContractDefinition const* library = dynamic_cast<ContractDefinition const*>(declaration)) | ||||||
| @ -417,10 +424,9 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc | |||||||
| 			else | 			else | ||||||
| 				addFunction( | 				addFunction( | ||||||
| 					dynamic_cast<FunctionDefinition const&>(*declaration), | 					dynamic_cast<FunctionDefinition const&>(*declaration), | ||||||
| 					pathPointer->path().back() | 					identifierPath->path().back() | ||||||
| 				); | 				); | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	return members; | 	return members; | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user