diff --git a/AST.cpp b/AST.cpp index f2fbc5284..c0a120b82 100644 --- a/AST.cpp +++ b/AST.cpp @@ -490,7 +490,7 @@ void FunctionCall::checkTypeRequirements() if (functionType->getLocation() != FunctionType::Location::SHA3 && parameterTypes.size() != m_arguments.size()) BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for function call.")); - if (m_names.empty()) // LTODO: Totally ignoring sha3 case for named arguments for now just for the rebase to work + if (m_names.empty()) { for (size_t i = 0; i < m_arguments.size(); ++i) { @@ -501,14 +501,14 @@ void FunctionCall::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("SHA3 called with argument that can't live outside storage")); #endif if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[0])) - BOOST_THROW_EXCEPTION(createTypeError(std::string("SHA3 argument ") + - boost::lexical_cast(i + 1) + - std::string("can't be converted to hash"))); + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("SHA3 argument can't be converted to hash")); } else if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); } } + else if (functionType->getLocation() == FunctionType::Location::SHA3) + BOOST_THROW_EXCEPTION(createTypeError("Named arguments can't be used for SHA3.")); else { auto const& parameterNames = functionType->getParameterNames(); diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index e2c632a3c..fbf5cbcfd 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -275,7 +275,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << u256(0) << eth::Instruction::CODECOPY; unsigned length = bytecode.size(); - length += appendArgumentsCopyToMemory(function.getParameterTypes(), arguments, length); + length += appendArgumentsCopyToMemory(arguments, function.getParameterTypes(), length); // size, offset, endowment m_context << u256(length) << u256(0); if (function.valueSet()) @@ -327,7 +327,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; case Location::SHA3: { - unsigned length = appendSameTypeArgumentsCopyToMemory(function.getParameterTypes().front(), arguments, 0); + unsigned length = appendArgumentsCopyToMemory(arguments); m_context << u256(length) << u256(0) << eth::Instruction::SHA3; break; } @@ -800,7 +800,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio // reserve space for the function identifier unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset; - dataOffset += appendArgumentsCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset); + dataOffset += appendArgumentsCopyToMemory(_arguments, _functionType.getParameterTypes(), dataOffset); //@todo only return the first return value for now Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : @@ -836,38 +836,44 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio } } -unsigned ExpressionCompiler::appendArgumentsCopyToMemory(TypePointers const& _types, - vector> const& _arguments, +unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector> const& _arguments, + TypePointers const& _types, unsigned _memoryOffset) { unsigned length = 0; + if (!_types.empty()) + { + for (unsigned i = 0; i < _arguments.size(); ++i) + length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); + return length; + } + + // without type conversion for (unsigned i = 0; i < _arguments.size(); ++i) - length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); + { + _arguments[i]->accept(*this); + length += moveTypeToMemory(*_arguments[i]->getType(), _arguments[i]->getLocation(), _memoryOffset + length); + } return length; } -unsigned ExpressionCompiler::appendSameTypeArgumentsCopyToMemory(TypePointer const& _type, - vector> const& _arguments, - unsigned _memoryOffset) +unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset) { - unsigned length = 0; - for (unsigned i = 0; i < _arguments.size(); ++i) - length += appendExpressionCopyToMemory(*_type, *_arguments[i], _memoryOffset + length); - return length; + unsigned const c_numBytes = CompilerUtils::getPaddedSize(_type.getCalldataEncodedSize()); + if (c_numBytes == 0 || c_numBytes > 32) + BOOST_THROW_EXCEPTION(CompilerError() + << errinfo_sourceLocation(_location) + << errinfo_comment("Type " + _type.toString() + " not yet supported.")); + bool const c_leftAligned = _type.getCategory() == Type::Category::STRING; + bool const c_padToWords = true; + return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, c_padToWords); } unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, Location const& _location, unsigned _memoryOffset) { appendTypeConversion(_type, _expectedType, true); - unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); - if (c_numBytes == 0 || c_numBytes > 32) - BOOST_THROW_EXCEPTION(CompilerError() - << errinfo_sourceLocation(_location) - << 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); + return moveTypeToMemory(_expectedType, _location, _memoryOffset); } unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h index 90a60afc7..70cc2426b 100644 --- a/ExpressionCompiler.h +++ b/ExpressionCompiler.h @@ -94,19 +94,16 @@ 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 appendArgumentsCopyToMemory(TypePointers const& _types, - std::vector> const& _arguments, + unsigned appendArgumentsCopyToMemory(std::vector> const& _arguments, + TypePointers const& _types = {}, unsigned _memoryOffset = 0); /// Appends code that copies a type to memory. /// @returns the number of bytes copied to memory unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, Location const& _location, unsigned _memoryOffset = 0); - /// Appends code that copies the given arguments that should all have the - /// same @a _type to memory (with optional offset). + /// Appends code that moves a type to memory /// @returns the number of bytes copied to memory - unsigned appendSameTypeArgumentsCopyToMemory(TypePointer const& _type, - std::vector> const& _arguments, - unsigned _memoryOffset = 0); + unsigned moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset); /// 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,