From 04aa0cc9baa9a9d657f7d9da984c35e7bdc54149 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 3 Feb 2015 14:02:58 +0100 Subject: [PATCH 01/21] Solidity SHA3 can now take multiple arguments --- libsolidity/AST.cpp | 19 ++++++++++++++++--- libsolidity/ExpressionCompiler.cpp | 23 ++++++++++++++++++----- libsolidity/ExpressionCompiler.h | 8 +++++--- test/SolidityEndToEndTest.cpp | 19 +++++++++++++++++++ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index d1c7d5371..c4fd7e2dd 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -487,14 +487,27 @@ void FunctionCall::checkTypeRequirements() // and then ask if that is implicitly convertible to the struct represented by the // function parameters TypePointers const& parameterTypes = functionType->getParameterTypes(); - if (parameterTypes.size() != m_arguments.size()) + 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()) + if (m_names.empty()) // LTODO: Totally ignoring sha3 case for named arguments for now just for the rebase to work { for (size_t i = 0; i < m_arguments.size(); ++i) - if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) + { + if (functionType->getLocation() == FunctionType::Location::SHA3) + { +#if 0 // are we sure we want that? Literal constant nums can't live outside storage and so sha3(42) will fail + if (!m_arguments[i]->getType()->canLiveOutsideStorage()) + 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) + + std::string("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 { diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 875e00bc2..8672611a4 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -206,7 +206,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) TypePointers const& parameterTypes = function.getParameterTypes(); vector> const& callArguments = _functionCall.getArguments(); vector> const& callArgumentNames = _functionCall.getNames(); - solAssert(callArguments.size() == parameterTypes.size(), ""); + if (function.getLocation() != Location::SHA3) + solAssert(callArguments.size() == parameterTypes.size(), ""); vector> arguments; if (callArgumentNames.empty()) @@ -325,9 +326,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << eth::Instruction::SUICIDE; break; case Location::SHA3: - appendExpressionCopyToMemory(*function.getParameterTypes().front(), *arguments.front()); - m_context << u256(32) << u256(0) << eth::Instruction::SHA3; + { + unsigned length = appendSameTypeArgumentsCopyToMemory(function.getParameterTypes().front(), arguments, 0); + m_context << u256(length) << u256(0) << eth::Instruction::SHA3; break; + } case Location::LOG0: case Location::LOG1: case Location::LOG2: @@ -843,8 +846,18 @@ unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _typ return length; } -unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset) +unsigned ExpressionCompiler::appendSameTypeArgumentsCopyToMemory(TypePointer const& _type, + vector> const& _arguments, + unsigned _memoryOffset) +{ + unsigned length = 0; + for (unsigned i = 0; i < _arguments.size(); ++i) + length += appendExpressionCopyToMemory(*_type, *_arguments[i], _memoryOffset + length); + return length; +} + +unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, + Expression const& _expression, unsigned _memoryOffset) { appendTypeConversion(_type, _expectedType, true); unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 7de577e6c..b977657b1 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -97,10 +97,12 @@ private: unsigned appendArgumentCopyToMemory(TypePointers const& _types, std::vector> const& _arguments, unsigned _memoryOffset = 0); - /// Appends code that copies a type to memory. + /// Appends code that copies the given arguments that should all have the + /// same @a _type to memory (with optional offset). /// @returns the number of bytes copied to memory - unsigned appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset = 0); + unsigned appendSameTypeArgumentsCopyToMemory(TypePointer const& _type, + std::vector> 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, diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index f248a5a07..824519fd2 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2095,6 +2095,25 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); } +BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) +{ + char const* sourceCode = R"( + contract c { + // function foo(uint a) returns (hash d) + function foo(uint a, uint b, uint c) returns (hash d) + { + d = sha3(a, b, c); + } + })"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10 , 12, 13) == encodeArgs( + dev::sha3( + toBigEndian(u256(10)) + + toBigEndian(u256(12)) + + toBigEndian(u256(13))))); +} + BOOST_AUTO_TEST_SUITE_END() } From 5b1adccf6de0a946d5f45a75bd1160a14449ce4e Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 3 Feb 2015 14:21:08 +0100 Subject: [PATCH 02/21] Renaming a function for clarity --- libsolidity/AST.cpp | 2 +- libsolidity/ExpressionCompiler.cpp | 10 +++++----- libsolidity/ExpressionCompiler.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index c4fd7e2dd..39ba10f32 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -502,7 +502,7 @@ void FunctionCall::checkTypeRequirements() #endif if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[0])) BOOST_THROW_EXCEPTION(createTypeError(std::string("SHA3 argument ") + - boost::lexical_cast(i) + + boost::lexical_cast(i + 1) + std::string("can't be converted to hash"))); } else if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 8672611a4..0acc9c9ed 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -275,7 +275,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << u256(0) << eth::Instruction::CODECOPY; unsigned length = bytecode.size(); - length += appendArgumentCopyToMemory(function.getParameterTypes(), arguments, length); + length += appendArgumentsCopyToMemory(function.getParameterTypes(), arguments, length); // size, offset, endowment m_context << u256(length) << u256(0); if (function.valueSet()) @@ -800,7 +800,7 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio // reserve space for the function identifier unsigned dataOffset = bare ? 0 : CompilerUtils::dataStartOffset; - dataOffset += appendArgumentCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset); + dataOffset += appendArgumentsCopyToMemory(_functionType.getParameterTypes(), _arguments, dataOffset); //@todo only return the first return value for now Type const* firstType = _functionType.getReturnParameterTypes().empty() ? nullptr : @@ -836,9 +836,9 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio } } -unsigned ExpressionCompiler::appendArgumentCopyToMemory(TypePointers const& _types, - vector> const& _arguments, - unsigned _memoryOffset) +unsigned ExpressionCompiler::appendArgumentsCopyToMemory(TypePointers const& _types, + vector> const& _arguments, + unsigned _memoryOffset) { unsigned length = 0; for (unsigned i = 0; i < _arguments.size(); ++i) diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index b977657b1..1f42d8225 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -94,9 +94,9 @@ 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& _types, - std::vector> const& _arguments, - unsigned _memoryOffset = 0); + unsigned appendArgumentsCopyToMemory(TypePointers const& _types, + std::vector> const& _arguments, + unsigned _memoryOffset = 0); /// Appends code that copies the given arguments that should all have the /// same @a _type to memory (with optional offset). /// @returns the number of bytes copied to memory From d3f9c89ee0bfc63e50253e133771dd1bb522846b Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Thu, 5 Feb 2015 15:05:58 +0100 Subject: [PATCH 03/21] Fixes after rebase --- libsolidity/AST.cpp | 2 +- libsolidity/ExpressionCompiler.cpp | 4 ++-- libsolidity/ExpressionCompiler.h | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 39ba10f32..f2fbc5284 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -487,7 +487,7 @@ void FunctionCall::checkTypeRequirements() // and then ask if that is implicitly convertible to the struct represented by the // function parameters TypePointers const& parameterTypes = functionType->getParameterTypes(); - if (functionType->getLocation() !=FunctionType::Location::SHA3 && parameterTypes.size() != m_arguments.size()) + 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 diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 0acc9c9ed..e2c632a3c 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -856,8 +856,8 @@ unsigned ExpressionCompiler::appendSameTypeArgumentsCopyToMemory(TypePointer con return length; } -unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, - Expression const& _expression, unsigned _memoryOffset) +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()); diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 1f42d8225..90a60afc7 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -97,6 +97,10 @@ private: unsigned appendArgumentsCopyToMemory(TypePointers const& _types, std::vector> const& _arguments, 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). /// @returns the number of bytes copied to memory From bbede4c31c845bba44d6ac541e2d0b386ed9d698 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 6 Feb 2015 10:42:24 +0100 Subject: [PATCH 04/21] appendArgumentsCopyToMemory() has more complicated logic now - Plus other fixes. --- libsolidity/AST.cpp | 8 ++--- libsolidity/ExpressionCompiler.cpp | 48 +++++++++++++++++------------- libsolidity/ExpressionCompiler.h | 11 +++---- test/SolidityEndToEndTest.cpp | 2 +- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index f2fbc5284..c0a120b82 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/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/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index e2c632a3c..fbf5cbcfd 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/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,40 +836,46 @@ 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; - for (unsigned i = 0; i < _arguments.size(); ++i) - length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); - return length; -} + if (!_types.empty()) + { + for (unsigned i = 0; i < _arguments.size(); ++i) + length += appendExpressionCopyToMemory(*_types[i], *_arguments[i], _memoryOffset + length); + return length; + } -unsigned ExpressionCompiler::appendSameTypeArgumentsCopyToMemory(TypePointer const& _type, - vector> const& _arguments, - unsigned _memoryOffset) -{ - unsigned length = 0; + // without type conversion for (unsigned i = 0; i < _arguments.size(); ++i) - length += appendExpressionCopyToMemory(*_type, *_arguments[i], _memoryOffset + length); + { + _arguments[i]->accept(*this); + length += moveTypeToMemory(*_arguments[i]->getType(), _arguments[i]->getLocation(), _memoryOffset + length); + } return length; } -unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset) +unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset) { - appendTypeConversion(_type, _expectedType, true); - unsigned const c_numBytes = CompilerUtils::getPaddedSize(_expectedType.getCalldataEncodedSize()); + 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 " + _expectedType.toString() + " not yet supported.")); - bool const c_leftAligned = _expectedType.getCategory() == Type::Category::STRING; + << 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); + return moveTypeToMemory(_expectedType, _location, _memoryOffset); +} + unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned _memoryOffset) diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 90a60afc7..70cc2426b 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/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, diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 824519fd2..083f55025 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2107,7 +2107,7 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10 , 12, 13) == encodeArgs( + BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( dev::sha3( toBigEndian(u256(10)) + toBigEndian(u256(12)) + From deea982c00ca81aae97ff687afe87c51d2b434ba Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 6 Feb 2015 13:42:51 +0100 Subject: [PATCH 05/21] getRealType() introduced --- libsolidity/ExpressionCompiler.cpp | 2 +- libsolidity/Types.cpp | 8 ++++++++ libsolidity/Types.h | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index fbf5cbcfd..39593a6ed 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -852,7 +852,7 @@ unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vectoraccept(*this); - length += moveTypeToMemory(*_arguments[i]->getType(), _arguments[i]->getLocation(), _memoryOffset + length); + length += moveTypeToMemory(*_arguments[i]->getType()->getRealType(), _arguments[i]->getLocation(), _memoryOffset + length); } return length; } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 648cf9cb2..a9051a2ca 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -361,6 +361,14 @@ u256 IntegerConstantType::literalValue(Literal const* _literal) const return value; } +TypePointer IntegerConstantType::getRealType() const +{ + auto intType = getIntegerType(); + if (!intType) + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("getRealType called with invalid integer constant" + toString())); + return intType; +} + shared_ptr IntegerConstantType::getIntegerType() const { bigint value = m_value; diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 1f4d27a25..18a53f9a5 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -130,6 +130,8 @@ public: /// i.e. it behaves differently in lvalue context and in value context. virtual bool isValueType() const { return false; } virtual unsigned getSizeOnStack() const { return 1; } + /// @returns the real type of some types, like e.g: IntegerConstant + virtual TypePointer getRealType() const { return TypePointer(); } /// Returns the list of all members of this type. Default implementation: no members. virtual MemberList const& getMembers() const { return EmptyMemberList; } @@ -140,7 +142,7 @@ public: virtual u256 literalValue(Literal const*) const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested " - "for type without literals.")); + "for type without literals.")); } protected: @@ -175,6 +177,7 @@ public: virtual MemberList const& getMembers() const { return isAddress() ? AddressMemberList : EmptyMemberList; } virtual std::string toString() const override; + virtual TypePointer getRealType() const { return std::make_shared(m_bits, m_modifier); } int getNumBits() const { return m_bits; } bool isHash() const { return m_modifier == Modifier::HASH || m_modifier == Modifier::ADDRESS; } @@ -214,6 +217,7 @@ public: virtual std::string toString() const override; virtual u256 literalValue(Literal const* _literal) const override; + virtual TypePointer getRealType() const override; /// @returns the smallest integer type that can hold the value or an empty pointer if not possible. std::shared_ptr getIntegerType() const; From 8d239921e98995d3c03fca3bc2dbf25120bd38a4 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 6 Feb 2015 16:27:41 +0100 Subject: [PATCH 06/21] SHA3 of string literals now should work --- libsolidity/AST.cpp | 14 ++-------- libsolidity/ExpressionCompiler.cpp | 11 ++++---- libsolidity/ExpressionCompiler.h | 2 +- libsolidity/Types.h | 1 + test/SolidityEndToEndTest.cpp | 45 +++++++++++++++++++++++++++++- 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index c0a120b82..26897ddae 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -493,19 +493,9 @@ void FunctionCall::checkTypeRequirements() if (m_names.empty()) { for (size_t i = 0; i < m_arguments.size(); ++i) - { - if (functionType->getLocation() == FunctionType::Location::SHA3) - { -#if 0 // are we sure we want that? Literal constant nums can't live outside storage and so sha3(42) will fail - if (!m_arguments[i]->getType()->canLiveOutsideStorage()) - 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(m_arguments[i]->createTypeError("SHA3 argument can't be converted to hash")); - - } else if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) + if (functionType->getLocation() != FunctionType::Location::SHA3 && + !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.")); diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 39593a6ed..4f091db4c 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -851,22 +851,23 @@ unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vectorgetType()->getCategory() == Type::Category::STRING) ? false : true; _arguments[i]->accept(*this); - length += moveTypeToMemory(*_arguments[i]->getType()->getRealType(), _arguments[i]->getLocation(), _memoryOffset + length); + length += moveTypeToMemory(*_arguments[i]->getType()->getRealType(), _arguments[i]->getLocation(), _memoryOffset + length, wantPadding); } return length; } -unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset) +unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries) { - unsigned const c_numBytes = CompilerUtils::getPaddedSize(_type.getCalldataEncodedSize()); + unsigned const encodedSize = _type.getCalldataEncodedSize(); + unsigned const c_numBytes = _padToWordBoundaries ? CompilerUtils::getPaddedSize(encodedSize) : encodedSize; 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); + return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, _padToWordBoundaries); } unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 70cc2426b..006858cb8 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -103,7 +103,7 @@ private: Location const& _location, unsigned _memoryOffset = 0); /// Appends code that moves a type to memory /// @returns the number of bytes copied to memory - unsigned moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset); + unsigned moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries = true); /// 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, diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 18a53f9a5..677e5e49e 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -249,6 +249,7 @@ public: virtual std::string toString() const override { return "string" + dev::toString(m_bytes); } virtual u256 literalValue(Literal const* _literal) const override; + virtual TypePointer getRealType() const override { return std::make_shared(m_bytes); } int getNumBytes() const { return m_bytes; } diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 083f55025..bd473af56 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2099,7 +2099,6 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) { char const* sourceCode = R"( contract c { - // function foo(uint a) returns (hash d) function foo(uint a, uint b, uint c) returns (hash d) { d = sha3(a, b, c); @@ -2114,6 +2113,50 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) toBigEndian(u256(13))))); } +BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals) +{ + char const* sourceCode = R"( + contract c { + function foo(uint a, uint16 b) returns (hash d) + { + d = sha3(a, b, 145); + } + })"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( + dev::sha3( + toBigEndian(u256(10)) + + toBigEndian(u256(12)) + + toBigEndian(u256(145))))); +} + +BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) +{ + char const* sourceCode = R"( + contract c { + function foo() returns (hash d) + { + d = sha3("foo"); + } + function bar(uint a, uint16 b) returns (hash d) + { + d = sha3(a, b, 145, "foo"); + } + })"; + compileAndRun(sourceCode); + + BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::sha3("foo"))); +#if 0 // work in progress + BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs( + dev::sha3( + toBigEndian(u256(10)) + + toBigEndian(u256(12)) + + toBigEndian(u256(145)) + + asBytes("foo"))))); +#endif +} + BOOST_AUTO_TEST_SUITE_END() } From 351cfecae987489c49c14dc7e0fdac2a0627f8d7 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 6 Feb 2015 17:25:29 +0100 Subject: [PATCH 07/21] Small fixes for proper multitype/multiarg SHA3 --- libsolidity/ExpressionCompiler.cpp | 2 +- test/SolidityEndToEndTest.cpp | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 4f091db4c..0ce19ecd1 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -851,7 +851,7 @@ unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vectorgetType()->getCategory() == Type::Category::STRING) ? false : true; + const bool wantPadding = false; _arguments[i]->accept(*this); length += moveTypeToMemory(*_arguments[i]->getType()->getRealType(), _arguments[i]->getLocation(), _memoryOffset + length, wantPadding); } diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index bd473af56..0fd71ac51 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -576,7 +576,7 @@ BOOST_AUTO_TEST_CASE(simple_mapping) " }\n" "}"; compileAndRun(sourceCode); - + BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(byte(0x00))); BOOST_CHECK(callContractFunction("get(uint8)", byte(0xa7)) == encodeArgs(byte(0x00))); @@ -933,7 +933,7 @@ BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); - BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(toBigEndian(u256(123))))); + BOOST_CHECK(callContractFunction("a_hash()") == encodeArgs(dev::sha3(bytes({0x7b})))); BOOST_CHECK(callContractFunction("an_address()") == encodeArgs(toBigEndian(u160(0x1337)))); BOOST_CHECK(callContractFunction("super_secret_data()") == bytes()); } @@ -2127,8 +2127,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals) BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( dev::sha3( toBigEndian(u256(10)) + - toBigEndian(u256(12)) + - toBigEndian(u256(145))))); + bytes({0x0, 0xc}) + + bytes({0x91})))); } BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) @@ -2147,14 +2147,13 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::sha3("foo"))); -#if 0 // work in progress + BOOST_CHECK(callContractFunction("bar(uint256,uint16)", 10, 12) == encodeArgs( dev::sha3( toBigEndian(u256(10)) + - toBigEndian(u256(12)) + - toBigEndian(u256(145)) + - asBytes("foo"))))); -#endif + bytes({0x0, 0xc}) + + bytes({0x91}) + + bytes({0x66, 0x6f, 0x6f})))); } BOOST_AUTO_TEST_SUITE_END() From 490cb5608e33051ebdf5f0a8eb259e358a44a1ae Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Fri, 6 Feb 2015 20:57:04 +0100 Subject: [PATCH 08/21] Small fixes in Types and ExpressionCompiler --- libsolidity/ExpressionCompiler.cpp | 4 ++-- libsolidity/Types.cpp | 3 +-- libsolidity/Types.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 0ce19ecd1..cd133222c 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -860,8 +860,8 @@ unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector 32) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index a9051a2ca..6a1282027 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -364,8 +364,7 @@ u256 IntegerConstantType::literalValue(Literal const* _literal) const TypePointer IntegerConstantType::getRealType() const { auto intType = getIntegerType(); - if (!intType) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("getRealType called with invalid integer constant" + toString())); + solAssert(!!intType, std::string("getRealType called with invalid integer constant") + toString()); return intType; } diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 677e5e49e..fcd6d9560 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -131,7 +131,7 @@ public: virtual bool isValueType() const { return false; } virtual unsigned getSizeOnStack() const { return 1; } /// @returns the real type of some types, like e.g: IntegerConstant - virtual TypePointer getRealType() const { return TypePointer(); } + virtual TypePointer getRealType() const { return shared_from_this(); } /// Returns the list of all members of this type. Default implementation: no members. virtual MemberList const& getMembers() const { return EmptyMemberList; } From 23c597ae29f8bce91256ca9d00edcfef4cbe25fa Mon Sep 17 00:00:00 2001 From: guanqun Date: Sun, 25 Jan 2015 19:35:47 +0800 Subject: [PATCH 09/21] remove AST.h Utils.h's x permission --- libsolidity/AST.h | 0 libsolidity/Utils.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 libsolidity/AST.h mode change 100755 => 100644 libsolidity/Utils.h diff --git a/libsolidity/AST.h b/libsolidity/AST.h old mode 100755 new mode 100644 diff --git a/libsolidity/Utils.h b/libsolidity/Utils.h old mode 100755 new mode 100644 From 833164b742738fd9fcacb6c48b141eeab50a584c Mon Sep 17 00:00:00 2001 From: Lu Guanqun Date: Sun, 8 Feb 2015 19:22:45 +0800 Subject: [PATCH 10/21] simplify two statements with selectToken() --- libsolidity/Scanner.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libsolidity/Scanner.cpp b/libsolidity/Scanner.cpp index b283ca10e..6a8ecd9dc 100644 --- a/libsolidity/Scanner.cpp +++ b/libsolidity/Scanner.cpp @@ -458,10 +458,7 @@ void Scanner::scanToken() // - -- -= advance(); if (m_char == '-') - { - advance(); - token = Token::DEC; - } + token = selectToken(Token::DEC); else if (m_char == '=') token = selectToken(Token::ASSIGN_SUB); else From a7a14c07ba48baf845375ff8f2ca75fe1b1dfba5 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 9 Feb 2015 00:49:35 +0100 Subject: [PATCH 11/21] Small cleanup. --- libsolidity/AST.cpp | 20 +++++++++----------- libsolidity/Types.cpp | 2 +- libsolidity/Types.h | 2 -- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 6f5b1f387..ab9dccf61 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -478,7 +478,7 @@ void FunctionCall::checkTypeRequirements() if (m_arguments.size() != 1) BOOST_THROW_EXCEPTION(createTypeError("More than one argument for explicit type conversion.")); if (!m_names.empty()) - BOOST_THROW_EXCEPTION(createTypeError("Type conversion can't allow named arguments.")); + BOOST_THROW_EXCEPTION(createTypeError("Type conversion cannot allow named arguments.")); if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type.getActualType())) BOOST_THROW_EXCEPTION(createTypeError("Explicit type conversion not allowed.")); m_type = type.getActualType(); @@ -496,24 +496,22 @@ void FunctionCall::checkTypeRequirements() { for (size_t i = 0; i < m_arguments.size(); ++i) if (functionType->getLocation() != FunctionType::Location::SHA3 && - !m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) - BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in function call.")); + !m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameterTypes[i])) + BOOST_THROW_EXCEPTION(m_arguments[i]->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 { + if (functionType->getLocation() == FunctionType::Location::SHA3) + BOOST_THROW_EXCEPTION(createTypeError("Named arguments cannnot be used for SHA3.")); auto const& parameterNames = functionType->getParameterNames(); if (parameterNames.size() != m_names.size()) BOOST_THROW_EXCEPTION(createTypeError("Some argument names are missing.")); // check duplicate names - for (size_t i = 0; i < m_names.size(); i++) { - for (size_t j = i + 1; j < m_names.size(); j++) { + for (size_t i = 0; i < m_names.size(); i++) + for (size_t j = i + 1; j < m_names.size(); j++) if (*m_names[i] == *m_names[j]) - BOOST_THROW_EXCEPTION(createTypeError("Duplicate named argument.")); - } - } + BOOST_THROW_EXCEPTION(m_arguments[i]->createTypeError("Duplicate named argument.")); for (size_t i = 0; i < m_names.size(); i++) { bool found = false; @@ -528,7 +526,7 @@ void FunctionCall::checkTypeRequirements() } } if (!found) - BOOST_THROW_EXCEPTION(createTypeError("Named argument doesn't match function declaration.")); + BOOST_THROW_EXCEPTION(createTypeError("Named argument does not match function declaration.")); } } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 7a7672c64..f30085ec2 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -360,7 +360,7 @@ u256 IntegerConstantType::literalValue(Literal const*) const TypePointer IntegerConstantType::getRealType() const { auto intType = getIntegerType(); - solAssert(!!intType, std::string("getRealType called with invalid integer constant") + toString()); + solAssert(!!intType, "getRealType called with invalid integer constant " + toString()); return intType; } diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 7118f7462..80a777942 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -177,7 +177,6 @@ public: virtual MemberList const& getMembers() const { return isAddress() ? AddressMemberList : EmptyMemberList; } virtual std::string toString() const override; - virtual TypePointer getRealType() const { return std::make_shared(m_bits, m_modifier); } int getNumBits() const { return m_bits; } bool isHash() const { return m_modifier == Modifier::HASH || m_modifier == Modifier::ADDRESS; } @@ -248,7 +247,6 @@ public: virtual std::string toString() const override { return "string" + dev::toString(m_bytes); } virtual u256 literalValue(Literal const* _literal) const override; - virtual TypePointer getRealType() const override { return std::make_shared(m_bytes); } int getNumBytes() const { return m_bytes; } From 2fd33d98cc5d71ad4ce8f5b2f096581e70112a07 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 9 Feb 2015 02:06:30 +0100 Subject: [PATCH 12/21] - implemented Empty parameter name story. Now the name of input/return parameters of function can be not specified. - added appropriate tests Conflicts: test/SolidityEndToEndTest.cpp test/SolidityNameAndTypeResolution.cpp --- libsolidity/AST.cpp | 19 +++++-- libsolidity/AST.h | 2 +- libsolidity/DeclarationContainer.cpp | 4 ++ libsolidity/DeclarationContainer.h | 4 +- libsolidity/Parser.cpp | 20 ++++++-- libsolidity/Parser.h | 1 + test/SolidityABIJSON.cpp | 71 ++++++++++++++++++++++++++ test/SolidityEndToEndTest.cpp | 27 ++++++++++ test/SolidityNameAndTypeResolution.cpp | 42 +++++++++++++++ 9 files changed, 179 insertions(+), 11 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 6f5b1f387..dbc326642 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -58,10 +58,21 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( "Non-empty \"returns\" directive for constructor.")); - FunctionDefinition const* fallbackFunction = getFallbackFunction(); - if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty()) - BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError( - "Fallback function cannot take parameters.")); + FunctionDefinition const* fallbackFunction = nullptr; + for (ASTPointer const& function: getDefinedFunctions()) + { + if (function->getName().empty()) + { + if (fallbackFunction) + BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Only one fallback function is allowed.")); + else + { + fallbackFunction = function.get(); + if (!fallbackFunction->getParameters().empty()) + BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters.")); + } + } + } for (ASTPointer const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 47f2a40ca..98f28afb0 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -250,7 +250,7 @@ public: /// Returns the constructor or nullptr if no constructor was specified. FunctionDefinition const* getConstructor() const; - /// Returns the fallback function or nullptr if no constructor was specified. + /// Returns the fallback function or nullptr if no fallback function was specified. FunctionDefinition const* getFallbackFunction() const; private: diff --git a/libsolidity/DeclarationContainer.cpp b/libsolidity/DeclarationContainer.cpp index c7081bc78..2e810a4cf 100644 --- a/libsolidity/DeclarationContainer.cpp +++ b/libsolidity/DeclarationContainer.cpp @@ -30,6 +30,9 @@ namespace solidity bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update) { + if (_declaration.getName().empty()) + return true; + if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end()) return false; m_declarations[_declaration.getName()] = &_declaration; @@ -38,6 +41,7 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, Declaration const* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const { + solAssert(!_name.empty(), "Attempt to resolve empty name."); auto result = m_declarations.find(_name); if (result != m_declarations.end()) return result->second; diff --git a/libsolidity/DeclarationContainer.h b/libsolidity/DeclarationContainer.h index e4b793259..1216fcef2 100644 --- a/libsolidity/DeclarationContainer.h +++ b/libsolidity/DeclarationContainer.h @@ -42,8 +42,8 @@ public: explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr, DeclarationContainer const* _enclosingContainer = nullptr): m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {} - /// Registers the declaration in the scope unless its name is already declared. - /// @returns true iff it was not yet declared. + /// Registers the declaration in the scope unless its name is already declared or the name is empty. + /// @returns false if the name was already declared. bool registerDeclaration(Declaration const& _declaration, bool _update = false); Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const; Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index d8c15c36d..2f5b18a04 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -268,17 +268,28 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp ASTNodeFactory nodeFactory(*this); ASTPointer type = parseTypeName(_options.allowVar); bool isIndexed = false; + ASTPointer identifier; Token::Value token = m_scanner->getCurrentToken(); + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); + if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) + visibility = parseVisibilitySpecifier(token); if (_options.allowIndexed && token == Token::INDEXED) { isIndexed = true; m_scanner->next(); } - Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); - if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) - visibility = parseVisibilitySpecifier(token); + if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER) + { + identifier = make_shared(""); + nodeFactory.setEndPositionFromNode(type); + } + else + { + nodeFactory.markEndPosition(); + identifier = expectIdentifierToken(); + } nodeFactory.markEndPosition(); - return nodeFactory.createNode(type, expectIdentifierToken(), + return nodeFactory.createNode(type, identifier, visibility, _options.isStateVariable, isIndexed); } @@ -402,6 +413,7 @@ ASTPointer Parser::parseParameterList(bool _allowEmpty, bool _all vector> parameters; VarDeclParserOptions options; options.allowIndexed = _allowIndexed; + options.allowEmptyName = true; expectToken(Token::LPAREN); if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) { diff --git a/libsolidity/Parser.h b/libsolidity/Parser.h index 19e0af1aa..5816fec40 100644 --- a/libsolidity/Parser.h +++ b/libsolidity/Parser.h @@ -50,6 +50,7 @@ private: bool allowVar = false; bool isStateVariable = false; bool allowIndexed = false; + bool allowEmptyName = false; }; ///@{ diff --git a/test/SolidityABIJSON.cpp b/test/SolidityABIJSON.cpp index 13e65761f..d600340eb 100644 --- a/test/SolidityABIJSON.cpp +++ b/test/SolidityABIJSON.cpp @@ -409,7 +409,78 @@ BOOST_AUTO_TEST_CASE(inherited) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) +{ + char const* sourceCode = R"( + contract test { + function f(uint, uint k) returns(uint ret_k, uint ret_g){ + uint g = 8; + ret_k = k; + ret_g = g; + } + })"; + + char const* interface = R"([ + { + "name": "f", + "constant": false, + "type": "function", + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "k", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "ret_k", + "type": "uint256" + }, + { + "name": "ret_g", + "type": "uint256" + } + ] + } + ])"; + checkInterface(sourceCode, interface); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter) +{ + char const* sourceCode = R"( + contract test { + function f(uint k) returns(uint){ + return k; + } + })"; + + char const* interface = R"([ + { + "name": "f", + "constant": false, + "type": "function", + "inputs": [ + { + "name": "k", + "type": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + } + ])"; + checkInterface(sourceCode, interface); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 56ee631b9..5bd1e8578 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2113,6 +2113,33 @@ BOOST_AUTO_TEST_CASE(event_lots_of_data) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit(address,hash256,uint256,bool)"))); } +BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) +{ + char const* sourceCode = R"( + contract test { + function f(uint, uint k) returns(uint ret_k, uint ret_g){ + uint g = 8; + ret_k = k; + ret_g = g; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8)); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8)); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter) +{ + char const* sourceCode = R"( + contract test { + function f(uint k) returns(uint){ + return k; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9)); +} + BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) { char const* sourceCode = R"( diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 05ce6ed66..f4be31f4b 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -904,6 +904,48 @@ BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } +BOOST_AUTO_TEST_CASE(empty_name_input_parameter) +{ + char const* text = R"( + contract test { + function f(uint){ + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter) +{ + char const* text = R"( + contract test { + function f() returns(bool){ + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) +{ + char const* text = R"( + contract test { + function f(uint, uint k) returns(uint ret_k){ + return k; + } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) +{ + char const* text = R"( + contract test { + function f() returns(uint ret_k, uint){ + return 5; + } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) { char const* sourceCode = "contract c { function f() { var x = f(); } }"; From 1db350b06a8b741a67664cf47696bb3ccfbff406 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 9 Feb 2015 02:24:57 +0100 Subject: [PATCH 13/21] - removed unnesessary braces but one in if statement is still there because of warrning about ambiguous "else" - added marking of position in node factory to the function Conflicts: libsolidity/Parser.cpp --- libsolidity/AST.cpp | 3 --- libsolidity/Parser.cpp | 11 ++++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index dbc326642..79d724fc4 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -60,7 +60,6 @@ void ContractDefinition::checkTypeRequirements() FunctionDefinition const* fallbackFunction = nullptr; for (ASTPointer const& function: getDefinedFunctions()) - { if (function->getName().empty()) { if (fallbackFunction) @@ -72,8 +71,6 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters.")); } } - } - for (ASTPointer const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 2f5b18a04..491b5f848 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -180,7 +180,7 @@ ASTPointer Parser::parseInheritanceSpecifier() Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token) { - Declaration::Visibility visibility = Declaration::Visibility::DEFAULT; + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); if (_token == Token::PUBLIC) visibility = Declaration::Visibility::PUBLIC; else if (_token == Token::PROTECTED) @@ -278,20 +278,17 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp isIndexed = true; m_scanner->next(); } + nodeFactory.markEndPosition(); if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER) { identifier = make_shared(""); nodeFactory.setEndPositionFromNode(type); } else - { - nodeFactory.markEndPosition(); identifier = expectIdentifierToken(); - } - nodeFactory.markEndPosition(); return nodeFactory.createNode(type, identifier, - visibility, _options.isStateVariable, - isIndexed); + visibility, _options.isStateVariable, + isIndexed); } ASTPointer Parser::parseModifierDefinition() From 5a3cc313f1661450a1156708568b1edf05c4d441 Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 6 Feb 2015 16:42:27 +0100 Subject: [PATCH 14/21] - some more changes --- libsolidity/Parser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 491b5f848..a542d9b70 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -267,6 +267,8 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp { ASTNodeFactory nodeFactory(*this); ASTPointer type = parseTypeName(_options.allowVar); + if (type != nullptr) + nodeFactory.setEndPositionFromNode(type); bool isIndexed = false; ASTPointer identifier; Token::Value token = m_scanner->getCurrentToken(); From 2c7bf410477603ef685c5c368e1fb7e0bc9d3a37 Mon Sep 17 00:00:00 2001 From: liana Date: Fri, 6 Feb 2015 16:57:26 +0100 Subject: [PATCH 15/21] - added assertion --- libsolidity/Parser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index a542d9b70..4d5a50b3c 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -284,6 +284,7 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER) { identifier = make_shared(""); + solAssert(!!type, ""); nodeFactory.setEndPositionFromNode(type); } else From f6b64f0dbdcc98f8e7de0e4c177f8ee5d1281413 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 9 Feb 2015 11:09:03 +0100 Subject: [PATCH 16/21] trying to avoid win_build problems --- libsolidity/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 4d5a50b3c..c4bb54829 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -284,7 +284,7 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER) { identifier = make_shared(""); - solAssert(!!type, ""); + solAssert(type != nullptr, ""); nodeFactory.setEndPositionFromNode(type); } else From b98a40fdbc1962f743a137c4cc34fcfdb9004a95 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 9 Feb 2015 12:44:45 +0100 Subject: [PATCH 17/21] Bug fix: Using constructor with parameters not working. --- mix/ClientModel.cpp | 6 ++-- mix/qml/ProjectList.qml | 4 +++ mix/qml/TransactionDialog.qml | 58 ++++++++++++++++++----------------- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index e18b23ab3..602940078 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -236,8 +236,8 @@ void ClientModel::executeSequence(std::vector const& _seque } if (!f) BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString())); - - encoder.encode(f); + if (!transaction.functionId.isEmpty()) + encoder.encode(f); for (int p = 0; p < transaction.parameterValues.size(); p++) { if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type()) @@ -247,6 +247,8 @@ void ClientModel::executeSequence(std::vector const& _seque if (transaction.functionId.isEmpty()) { + bytes param = encoder.encodedData(); + contractCode.insert(contractCode.end(), param.begin(), param.end()); Address newAddress = deployContract(contractCode, transaction); if (newAddress != m_contractAddress) { diff --git a/mix/qml/ProjectList.qml b/mix/qml/ProjectList.qml index 65eebcdbb..cf114390b 100644 --- a/mix/qml/ProjectList.qml +++ b/mix/qml/ProjectList.qml @@ -127,6 +127,10 @@ Item { } } + onNewProject: { + sectionModel.clear(); + } + onProjectLoaded: { addDocToSubModel(); if (modelData === "Contracts") diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 4d50db7b1..3e6cf0236 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -60,15 +60,39 @@ Window { else { var parameters = codeModel.code.contract.constructor.parameters; - for (var p = 0; p < parameters.length; p++) { - var pname = parameters[p].name; - paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" }); - } + for (var p = 0; p < parameters.length; p++) + loadParameter(parameters[p]); } visible = true; valueField.focus = true; } + function loadParameter(parameter) + { + var type = parameter.type; + var pname = parameter.name; + var varComponent; + + if (type.indexOf("int") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); + else if (type.indexOf("real") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); + else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); + else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); + else if (type.indexOf("bool") !== -1) + varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); + + var param = varComponent.createObject(modalTransactionDialog); + var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; + + param.setValue(value); + param.setDeclaration(parameter); + qType.push({ name: pname, value: param }); + paramsModel.append({ name: pname, type: type, value: value }); + } + function loadParameters() { paramsModel.clear(); if (!paramsModel) @@ -76,30 +100,8 @@ Window { if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { var func = codeModel.code.contract.functions[functionComboBox.currentIndex]; var parameters = func.parameters; - for (var p = 0; p < parameters.length; p++) { - var pname = parameters[p].name; - var varComponent; - var type = parameters[p].type; - - if (type.indexOf("int") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); - else if (type.indexOf("real") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); - else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); - else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); - else if (type.indexOf("bool") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); - - var param = varComponent.createObject(modalTransactionDialog); - var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; - - param.setValue(value); - param.setDeclaration(parameters[p]); - qType.push({ name: pname, value: param }); - paramsModel.append({ name: pname, type: parameters[p].type, value: value }); - } + for (var p = 0; p < parameters.length; p++) + loadParameter(parameters[p]); } } From 16bda2824bf1405b1064a8f4af2e90deeaf7807f Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 9 Feb 2015 13:40:37 +0100 Subject: [PATCH 18/21] Some cleanup in "move to memory" functions. --- libsolidity/ExpressionCompiler.cpp | 44 ++++++++++++------------------ libsolidity/ExpressionCompiler.h | 22 +++++++-------- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 4a1110dbb..5561af9b3 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -327,7 +327,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; case Location::SHA3: { - unsigned length = appendArgumentsCopyToMemory(arguments); + unsigned length = appendArgumentsCopyToMemory(arguments, TypePointers(), 0, false); m_context << u256(length) << u256(0) << eth::Instruction::SHA3; break; } @@ -838,27 +838,23 @@ void ExpressionCompiler::appendExternalFunctionCall(FunctionType const& _functio unsigned ExpressionCompiler::appendArgumentsCopyToMemory(vector> const& _arguments, TypePointers const& _types, - unsigned _memoryOffset) + unsigned _memoryOffset, + bool _padToWordBoundaries) { + solAssert(_types.empty() || _types.size() == _arguments.size(), ""); unsigned length = 0; - if (!_types.empty()) + for (size_t i = 0; i < _arguments.size(); ++i) { - 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) - { - const bool wantPadding = false; _arguments[i]->accept(*this); - length += moveTypeToMemory(*_arguments[i]->getType()->getRealType(), _arguments[i]->getLocation(), _memoryOffset + length, wantPadding); + TypePointer const& expectedType = _types.empty() ? _arguments[i]->getType()->getRealType() : _types[i]; + appendTypeConversion(*_arguments[i]->getType(), *expectedType, true); + length += appendTypeMoveToMemory(*expectedType, _arguments[i]->getLocation(), + _memoryOffset + length, _padToWordBoundaries); } return length; } -unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries) +unsigned ExpressionCompiler::appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries) { unsigned const c_encodedSize = _type.getCalldataEncodedSize(); unsigned const c_numBytes = _padToWordBoundaries ? CompilerUtils::getPaddedSize(c_encodedSize) : c_encodedSize; @@ -870,19 +866,13 @@ unsigned ExpressionCompiler::moveTypeToMemory(Type const& _type, Location const& return CompilerUtils(m_context).storeInMemory(_memoryOffset, c_numBytes, c_leftAligned, _padToWordBoundaries); } -unsigned ExpressionCompiler::appendTypeConversionAndMoveToMemory(Type const& _expectedType, Type const& _type, - Location const& _location, unsigned _memoryOffset) -{ - appendTypeConversion(_type, _expectedType, true); - return moveTypeToMemory(_expectedType, _location, _memoryOffset); -} - unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned _memoryOffset) { _expression.accept(*this); - return appendTypeConversionAndMoveToMemory(_expectedType, *_expression.getType(), _expression.getLocation(), _memoryOffset); + appendTypeConversion(*_expression.getType(), _expectedType, true); + return appendTypeMoveToMemory(_expectedType, _expression.getLocation(), _memoryOffset); } void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) @@ -890,20 +880,20 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& FunctionType accessorType(_varDecl); unsigned length = 0; - TypePointers const& params = accessorType.getParameterTypes(); + TypePointers const& paramTypes = accessorType.getParameterTypes(); // move arguments to memory - for (TypePointer const& param: boost::adaptors::reverse(params)) - length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length); + for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes)) + length += appendTypeMoveToMemory(*paramType, Location(), length); // retrieve the position of the variable m_context << m_context.getStorageLocationOfVariable(_varDecl); TypePointer returnType = _varDecl.getType(); - for (TypePointer const& param: params) + for (TypePointer const& paramType: paramTypes) { // move offset to memory CompilerUtils(m_context).storeInMemory(length); - unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize()); + unsigned argLen = CompilerUtils::getPaddedSize(paramType->getCalldataEncodedSize()); length -= argLen; m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index 006858cb8..ad0b36921 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -92,20 +92,18 @@ private: /// Appends code to call a function of the given type with the given arguments. void appendExternalFunctionCall(FunctionType const& _functionType, std::vector> const& _arguments, bool bare = false); - /// Appends code that copies the given arguments to memory (with optional offset). - /// @returns the number of bytes copied to memory + /// Appends code that evaluates the given arguments and moves the result to memory (with optional offset). + /// @returns the number of bytes moven to memory 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 moves a type to memory - /// @returns the number of bytes copied to memory - unsigned moveTypeToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, bool _padToWordBoundaries = true); - /// Appends code that evaluates a single expression and copies it to memory (with optional offset). - /// @returns the number of bytes copied to memory + unsigned _memoryOffset = 0, + bool _padToWordBoundaries = true); + /// Appends code that moves a stack element of the given type to memory + /// @returns the number of bytes moved to memory + unsigned appendTypeMoveToMemory(Type const& _type, Location const& _location, unsigned _memoryOffset, + bool _padToWordBoundaries = true); + /// Appends code that evaluates a single expression and moves the result to memory (with optional offset). + /// @returns the number of bytes moved to memory unsigned appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression, unsigned _memoryOffset = 0); From ae4fd535f8bd564414dbe31c100575463b0c2c32 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 9 Feb 2015 15:35:20 +0100 Subject: [PATCH 19/21] Project Files - ux improvement. --- mix/qml/FilesSection.qml | 21 ++++++++++++++------- mix/qml/ProjectList.qml | 15 +++++++++++++-- mix/qml/Style.qml | 9 +++++---- mix/qml/js/ProjectModel.js | 2 +- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/mix/qml/FilesSection.qml b/mix/qml/FilesSection.qml index d532fb2b1..f0a6e3745 100644 --- a/mix/qml/FilesSection.qml +++ b/mix/qml/FilesSection.qml @@ -54,6 +54,12 @@ ColumnLayout { source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf" } + FontLoader + { + id: semiBoldFont + source: "qrc:/qml/fonts/SourceSansPro-Bold.ttf" + } + RowLayout { anchors.top: parent.top @@ -64,12 +70,12 @@ ColumnLayout { Image { source: "qrc:/qml/img/opentriangleindicator_filesproject.png" width: 15 - sourceSize.width: 15 + sourceSize.width: 12 id: imgArrow anchors.right: section.left - anchors.rightMargin: 5 + anchors.rightMargin: 8 anchors.top: parent.top - anchors.topMargin: 8 + anchors.topMargin: 6 } Text @@ -79,10 +85,8 @@ ColumnLayout { anchors.left: parent.left anchors.leftMargin: Style.general.leftMargin color: Style.documentsList.sectionColor - font.family: fileNameFont.name - font.pointSize: Style.documentsList.fontSize - font.weight: Font.Bold - font.letterSpacing: 1 + font.family: semiBoldFont.name + font.pointSize: Style.documentsList.sectionFontSize states: [ State { name: "hidden" @@ -154,6 +158,9 @@ ColumnLayout { rootItem.isSelected = true; else rootItem.isSelected = false; + + if (rootItem.isSelected && section.state === "hidden") + section.state = ""; } } } diff --git a/mix/qml/ProjectList.qml b/mix/qml/ProjectList.qml index cf114390b..138e86fe9 100644 --- a/mix/qml/ProjectList.qml +++ b/mix/qml/ProjectList.qml @@ -15,7 +15,7 @@ Item { FontLoader { id: srcSansProLight - source: "qrc:/qml/fonts/SourceSansPro-Regular.ttf" + source: "qrc:/qml/fonts/SourceSansPro-Light.ttf" } Rectangle @@ -54,6 +54,7 @@ Item { font.family: srcSansProLight.name font.pointSize: Style.title.pointSize anchors.verticalCenter: parent.verticalCenter + font.weight: Font.Light } } @@ -79,7 +80,7 @@ Item { spacing: 0 Repeater { - model: ["Contracts", "Javascript", "HTML", "Styles", "Images", "Misc"] + model: [qsTr("Contracts"), qsTr("Javascript"), qsTr("Web Pages"), qsTr("Styles"), qsTr("Images"), qsTr("Misc")]; signal selected(string doc, string groupName) id: sectionRepeater FilesSection @@ -127,6 +128,11 @@ Item { } } + onDocumentOpened: { + if (document.groupName === modelData) + sectionRepeater.selected(document.documentId, modelData); + } + onNewProject: { sectionModel.clear(); } @@ -145,7 +151,12 @@ Item { { var newDoc = projectModel.getDocument(documentId); if (newDoc.groupName === modelData) + { sectionModel.append(newDoc); + projectModel.openDocument(newDoc.documentId); + sectionRepeater.selected(newDoc.documentId, modelData); + } + } } } diff --git a/mix/qml/Style.qml b/mix/qml/Style.qml index 91745749f..348d8c4d1 100644 --- a/mix/qml/Style.qml +++ b/mix/qml/Style.qml @@ -12,7 +12,7 @@ QtObject { property QtObject title: QtObject { property string color: "#808080" property string background: "#f0f0f0" - property int height: 70 + property int height: 55 property int pointSize: 18 } @@ -22,8 +22,9 @@ QtObject { property string sectionColor: "#808080" property string selectedColor: "white" property string highlightColor: "#4a90e2" - property int height: 32 - property int fileNameHeight: 45 - property int fontSize: 15 + property int height: 25 + property int fileNameHeight: 30 + property int fontSize: 13 + property int sectionFontSize: 13 } } diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 19a56432e..ac44dffa9 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -90,7 +90,7 @@ function addFile(fileName) { var isJs = extension === ".js"; var isImg = extension === ".png" || extension === ".gif" || extension === ".jpg" || extension === ".svg"; var syntaxMode = isContract ? "solidity" : isJs ? "javascript" : isHtml ? "htmlmixed" : isCss ? "css" : ""; - var groupName = isContract ? "Contracts" : isJs ? "Javascript" : isHtml ? "HTML" : isCss ? "Styles" : isImg ? "Images" : "Misc"; + var groupName = isContract ? qsTr("Contracts") : isJs ? qsTr("Javascript") : isHtml ? qsTr("Web Pages") : isCss ? qsTr("Styles") : isImg ? qsTr("Images") : qsTr("Misc"); var docData = { contract: false, path: p, From a523ebeaef130c59174825c96d8d0ebf110f8e00 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 9 Feb 2015 15:40:06 +0100 Subject: [PATCH 20/21] project files - ux improvement --- mix/qml/FilesSection.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix/qml/FilesSection.qml b/mix/qml/FilesSection.qml index f0a6e3745..32202f839 100644 --- a/mix/qml/FilesSection.qml +++ b/mix/qml/FilesSection.qml @@ -56,7 +56,7 @@ ColumnLayout { FontLoader { - id: semiBoldFont + id: boldFont source: "qrc:/qml/fonts/SourceSansPro-Bold.ttf" } @@ -85,7 +85,7 @@ ColumnLayout { anchors.left: parent.left anchors.leftMargin: Style.general.leftMargin color: Style.documentsList.sectionColor - font.family: semiBoldFont.name + font.family: boldFont.name font.pointSize: Style.documentsList.sectionFontSize states: [ State { From 1e1c4501dde5ea0aeceae4bfed933233dfa675b3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 9 Feb 2015 16:45:59 +0100 Subject: [PATCH 21/21] Typo fix. --- libsolidity/ExpressionCompiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/ExpressionCompiler.h b/libsolidity/ExpressionCompiler.h index ad0b36921..adfe8e524 100644 --- a/libsolidity/ExpressionCompiler.h +++ b/libsolidity/ExpressionCompiler.h @@ -93,7 +93,7 @@ private: void appendExternalFunctionCall(FunctionType const& _functionType, std::vector> const& _arguments, bool bare = false); /// Appends code that evaluates the given arguments and moves the result to memory (with optional offset). - /// @returns the number of bytes moven to memory + /// @returns the number of bytes moved to memory unsigned appendArgumentsCopyToMemory(std::vector> const& _arguments, TypePointers const& _types = {}, unsigned _memoryOffset = 0,