mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	final changes to typechecker, the expression compiler, and a couple more tests for good measure
This commit is contained in:
		
							parent
							
								
									c7df6d0310
								
							
						
					
					
						commit
						ac664e7f86
					
				| @ -781,10 +781,12 @@ bool TypeChecker::visit(TupleExpression const& _tuple) | ||||
| { | ||||
| 	vector<ASTPointer<Expression>> const& components = _tuple.components(); | ||||
| 	TypePointers types; | ||||
| 	TypePointer internalArrayType; | ||||
| 	bool isArray = _tuple.isInlineArray(); | ||||
| 	TypePointer inlineArrayType; | ||||
| 
 | ||||
| 	if (_tuple.annotation().lValueRequested) | ||||
| 	{ | ||||
| 		if (_tuple.isInlineArray()) | ||||
| 			fatalTypeError(_tuple.location(), "Inline array type cannot be declared as LValue."); | ||||
| 		for (auto const& component: components) | ||||
| 			if (component) | ||||
| 			{ | ||||
| @ -811,26 +813,34 @@ bool TypeChecker::visit(TupleExpression const& _tuple) | ||||
| 			{ | ||||
| 				components[i]->accept(*this); | ||||
| 				types.push_back(type(*components[i])); | ||||
| 				if (i == 0 && isArray) | ||||
| 					internalArrayType = types[i]->mobileType(); | ||||
| 				else if (isArray && internalArrayType && types[i]->mobileType()) | ||||
| 					internalArrayType = Type::commonType(internalArrayType, types[i]->mobileType()); | ||||
| 				if (_tuple.isInlineArray()) | ||||
| 					solAssert(!!types[i], "Inline array cannot have empty components"); | ||||
| 				if (i == 0 && _tuple.isInlineArray()) | ||||
| 					inlineArrayType = types[i]->mobileType(); | ||||
| 				else if (_tuple.isInlineArray() && inlineArrayType) | ||||
| 					inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType()); | ||||
| 			} | ||||
| 			else | ||||
| 				types.push_back(TypePointer()); | ||||
| 		} | ||||
| 		if (components.size() == 1 && !isArray) | ||||
| 			_tuple.annotation().type = type(*components[0]); | ||||
| 		else if (!internalArrayType && isArray)  | ||||
| 			fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); | ||||
| 		else if (isArray) | ||||
| 			_tuple.annotation().type = make_shared<ArrayType>(DataLocation::Memory, internalArrayType, types.size()); | ||||
| 		if (_tuple.isInlineArray()) | ||||
| 		{ | ||||
| 			if (!inlineArrayType)  | ||||
| 				fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); | ||||
| 			_tuple.annotation().type = make_shared<ArrayType>(DataLocation::Memory, inlineArrayType, types.size()); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (components.size() == 2 && !components[1]) | ||||
| 				types.pop_back(); | ||||
| 			_tuple.annotation().type = make_shared<TupleType>(types); | ||||
| 			if (components.size() == 1) | ||||
| 				_tuple.annotation().type = type(*components[0]); | ||||
| 			else | ||||
| 			{ | ||||
| 				if (components.size() == 2 && !components[1]) | ||||
| 					types.pop_back(); | ||||
| 				_tuple.annotation().type = make_shared<TupleType>(types); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| @ -186,7 +186,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) | ||||
| 		_assignment.leftHandSide().annotation().type | ||||
| 	); | ||||
| 	utils().convertType(*_assignment.rightHandSide().annotation().type, *type); | ||||
| 	 | ||||
| 
 | ||||
| 	_assignment.leftHandSide().accept(*this); | ||||
| 	solAssert(!!m_currentLValue, "LValue not retrieved."); | ||||
| 
 | ||||
| @ -222,18 +222,17 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) | ||||
| 	if (_tuple.isInlineArray()) | ||||
| 	{ | ||||
| 		ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); | ||||
| 		auto components = _tuple.components(); | ||||
| 		 | ||||
| 		solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); | ||||
| 		m_context << max(u256(32u), arrayType.memorySize()); | ||||
| 		utils().allocateMemory(); | ||||
| 		m_context << eth::Instruction::DUP1; | ||||
| 	 | ||||
| 		for (unsigned i = 0; i < components.size(); ++i) | ||||
| 		for (auto const& component: _tuple.components()) | ||||
| 		{ | ||||
| 			components[i]->accept(*this); | ||||
| 			utils().convertType(*components[i]->annotation().type, *arrayType.baseType(), true); | ||||
| 			components[i]->annotation().type = arrayType.baseType(); //force conversion
 | ||||
| 			utils().storeInMemoryDynamic(*components[i]->annotation().type, true);				 | ||||
| 			component->accept(*this); | ||||
| 			utils().convertType(*component->annotation().type, *arrayType.baseType(), true); | ||||
| 			utils().storeInMemoryDynamic(*arrayType.baseType(), true);				 | ||||
| 		} | ||||
| 		 | ||||
| 		m_context << eth::Instruction::POP; | ||||
| @ -1155,7 +1154,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) | ||||
| 		break; // will be done during conversion
 | ||||
| 	default: | ||||
| 		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now.")); | ||||
| 	}	 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation) | ||||
|  | ||||
| @ -2862,6 +2862,31 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) | ||||
| 	BOOST_CHECK(expectError(text) == Error::Type::TypeError); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(dynamic_inline_array) | ||||
| { | ||||
| 	char const* text = R"( | ||||
| 		contract C { | ||||
| 			function f() { | ||||
| 				uint[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	BOOST_CHECK(expectError(text) == Error::Type::TypeError); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) | ||||
| { | ||||
| 	char const* text = R"( | ||||
| 		contract C { | ||||
| 			function f() { | ||||
| 				[1, 2, 3]++; | ||||
| 				[1, 2, 3] = [4, 5, 6]; | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	BOOST_CHECK(expectError(text) == Error::Type::TypeError); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user