Merge pull request #4849 from lastmjs/develop

Introduce static elementary types to use
This commit is contained in:
chriseth 2018-09-14 00:54:53 +02:00 committed by GitHub
commit 5f4a2d2cad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 9 deletions

View File

@ -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``, ``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc --testpath ./test``,
where ``TestName`` can be a wildcard ``*``. 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). ``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. Travis CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target.

View File

@ -535,7 +535,7 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c
toString(arguments.size()) + toString(arguments.size()) +
" were provided." " 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( m_errorReporter.typeError(
arguments.front()->location(), arguments.front()->location(),
"Invalid type for argument in function call. " "Invalid type for argument in function call. "
@ -2131,7 +2131,7 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
"after argument-dependent lookup in " + exprType->toString() + "after argument-dependent lookup in " + exprType->toString() +
(memberName == "value" ? " - did you forget the \"payable\" modifier?" : "."); (memberName == "value" ? " - did you forget the \"payable\" modifier?" : ".");
if (exprType->category() == Type::Category::Contract) 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) if (addressMember.name == memberName)
{ {
Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression()); Identifier const* var = dynamic_cast<Identifier const*>(&_memberAccess.expression());

View File

@ -319,6 +319,9 @@ protected:
class AddressType: public Type class AddressType: public Type
{ {
public: public:
static AddressType& address() { static std::shared_ptr<AddressType> addr(std::make_shared<AddressType>(StateMutability::NonPayable)); return *addr; }
static AddressType& addressPayable() { static std::shared_ptr<AddressType> addr(std::make_shared<AddressType>(StateMutability::Payable)); return *addr; }
virtual Category category() const override { return Category::Address; } virtual Category category() const override { return Category::Address; }
explicit AddressType(StateMutability _stateMutability); explicit AddressType(StateMutability _stateMutability);
@ -361,6 +364,7 @@ public:
{ {
Unsigned, Signed Unsigned, Signed
}; };
virtual Category category() const override { return Category::Integer; } virtual Category category() const override { return Category::Integer; }
explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned); explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned);
@ -661,6 +665,9 @@ protected:
class ArrayType: public ReferenceType class ArrayType: public ReferenceType
{ {
public: public:
static ArrayType& bytesMemory() { static std::shared_ptr<ArrayType> addr(std::make_shared<ArrayType>(DataLocation::Memory)); return *addr; }
static ArrayType& stringMemory() { static std::shared_ptr<ArrayType> addr(std::make_shared<ArrayType>(DataLocation::Memory, true)); return *addr; }
virtual Category category() const override { return Category::Array; } virtual Category category() const override { return Category::Array; }
/// Constructor for a byte array ("bytes") and string. /// Constructor for a byte array ("bytes") and string.

View File

@ -710,9 +710,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
arguments.front()->accept(*this); arguments.front()->accept(*this);
// Optimization: If type is bytes or string, then do not encode, // Optimization: If type is bytes or string, then do not encode,
// but directly compute keccak256 on memory. // 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; m_context << Instruction::SWAP1 << u256(0x20) << Instruction::ADD;
} }
else else
@ -1086,7 +1086,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
utils().abiDecode(targetTypes, false); utils().abiDecode(targetTypes, false);
else else
{ {
utils().convertType(*firstArgType, ArrayType(DataLocation::Memory)); utils().convertType(*firstArgType, ArrayType::bytesMemory());
m_context << Instruction::DUP1 << u256(32) << Instruction::ADD; m_context << Instruction::DUP1 << u256(32) << Instruction::ADD;
m_context << Instruction::SWAP1 << Instruction::MLOAD; m_context << Instruction::SWAP1 << Instruction::MLOAD;
// stack now: <mem_pos> <length> // stack now: <mem_pos> <length>
@ -1259,7 +1259,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
identifier = FunctionType(*function).externalIdentifier(); identifier = FunctionType(*function).externalIdentifier();
else else
solAssert(false, "Contract member is neither variable nor function."); 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; m_context << identifier;
} }
else else
@ -1277,7 +1277,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{ {
utils().convertType( utils().convertType(
*_memberAccess.expression().annotation().type, *_memberAccess.expression().annotation().type,
AddressType(StateMutability::NonPayable), AddressType::address(),
true true
); );
m_context << Instruction::BALANCE; m_context << Instruction::BALANCE;
@ -1294,7 +1294,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member)) else if ((set<string>{"call", "callcode", "delegatecall", "staticcall"}).count(member))
utils().convertType( utils().convertType(
*_memberAccess.expression().annotation().type, *_memberAccess.expression().annotation().type,
AddressType(StateMutability::NonPayable), AddressType::address(),
true true
); );
else else