diff --git a/docs/contributing.rst b/docs/contributing.rst index 8a83ca553..6fe96be48 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -92,7 +92,7 @@ To run a subset of tests, filters can be used: ``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc --testpath ./test``, where ``TestName`` can be a wildcard ``*``. -Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests and runs +Alternatively, there is a testing script at ``scripts/tests.sh`` which executes all tests and runs ``cpp-ethereum`` automatically if it is in the path (but does not download it). Travis CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e023dc38e..13294476f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -535,7 +535,7 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c toString(arguments.size()) + " were provided." ); - if (arguments.size() >= 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType(DataLocation::Memory))) + if (arguments.size() >= 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType::bytesMemory())) m_errorReporter.typeError( arguments.front()->location(), "Invalid type for argument in function call. " @@ -2131,7 +2131,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) "after argument-dependent lookup in " + exprType->toString() + (memberName == "value" ? " - did you forget the \"payable\" modifier?" : "."); if (exprType->category() == Type::Category::Contract) - for (auto const& addressMember: AddressType(StateMutability::Payable).nativeMembers(nullptr)) + for (auto const& addressMember: AddressType::addressPayable().nativeMembers(nullptr)) if (addressMember.name == memberName) { Identifier const* var = dynamic_cast(&_memberAccess.expression()); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index a2d18b0ae..65a70019c 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -319,6 +319,9 @@ protected: class AddressType: public Type { public: + static AddressType& address() { static std::shared_ptr addr(std::make_shared(StateMutability::NonPayable)); return *addr; } + static AddressType& addressPayable() { static std::shared_ptr addr(std::make_shared(StateMutability::Payable)); return *addr; } + virtual Category category() const override { return Category::Address; } explicit AddressType(StateMutability _stateMutability); @@ -361,6 +364,7 @@ public: { Unsigned, Signed }; + virtual Category category() const override { return Category::Integer; } explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned); @@ -661,6 +665,9 @@ protected: class ArrayType: public ReferenceType { public: + static ArrayType& bytesMemory() { static std::shared_ptr addr(std::make_shared(DataLocation::Memory)); return *addr; } + static ArrayType& stringMemory() { static std::shared_ptr addr(std::make_shared(DataLocation::Memory, true)); return *addr; } + virtual Category category() const override { return Category::Array; } /// Constructor for a byte array ("bytes") and string. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index bd863e058..8645f653c 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -710,9 +710,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) arguments.front()->accept(*this); // Optimization: If type is bytes or string, then do not encode, // but directly compute keccak256 on memory. - if (*argType == ArrayType(DataLocation::Memory) || *argType == ArrayType(DataLocation::Memory, true)) + if (*argType == ArrayType::bytesMemory() || *argType == ArrayType::stringMemory()) { - ArrayUtils(m_context).retrieveLength(ArrayType(DataLocation::Memory)); + ArrayUtils(m_context).retrieveLength(ArrayType::bytesMemory()); m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD; } else @@ -1086,7 +1086,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().abiDecode(targetTypes, false); else { - utils().convertType(*firstArgType, ArrayType(DataLocation::Memory)); + utils().convertType(*firstArgType, ArrayType::bytesMemory()); m_context << Instruction::DUP1 << u256(32) << Instruction::ADD; m_context << Instruction::SWAP1 << Instruction::MLOAD; // stack now: @@ -1259,7 +1259,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) identifier = FunctionType(*function).externalIdentifier(); else solAssert(false, "Contract member is neither variable nor function."); - utils().convertType(type, AddressType(type.isPayable() ? StateMutability::Payable : StateMutability::NonPayable), true); + utils().convertType(type, type.isPayable() ? AddressType::addressPayable() : AddressType::address(), true); m_context << identifier; } else @@ -1277,7 +1277,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) { utils().convertType( *_memberAccess.expression().annotation().type, - AddressType(StateMutability::NonPayable), + AddressType::address(), true ); m_context << Instruction::BALANCE; @@ -1294,7 +1294,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) else if ((set{"call", "callcode", "delegatecall", "staticcall"}).count(member)) utils().convertType( *_memberAccess.expression().annotation().type, - AddressType(StateMutability::NonPayable), + AddressType::address(), true ); else