diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 63132a124..3dbb4012d 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -504,6 +504,12 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) } BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid member access to " + type.toString())); } + case Type::Category::ByteArray: + { + solAssert(member == "length", "Illegal bytearray member."); + m_context << eth::Instruction::SLOAD; + break; + } default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type.")); } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index b1029ec6f..33cc8a1ec 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -541,6 +541,8 @@ unsigned ByteArrayType::getSizeOnStack() const return 1; } +const MemberList ByteArrayType::s_byteArrayMemberList = MemberList({{"length", make_shared(256)}}); + bool ContractType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 627bc76f0..5a0e2c429 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -292,11 +292,13 @@ public: virtual bool operator==(const Type& _other) const override; virtual unsigned getSizeOnStack() const override; virtual std::string toString() const override { return "bytes"; } + virtual MemberList const& getMembers() const override { return s_byteArrayMemberList; } Location getLocation() const { return m_location; } private: Location m_location; + static const MemberList s_byteArrayMemberList; }; /** diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index a57eb2700..71cb4a6f1 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2409,6 +2409,21 @@ BOOST_AUTO_TEST_CASE(bytes_inside_mappings) BOOST_CHECK(m_state.storage(m_contractAddress).empty()); } +BOOST_AUTO_TEST_CASE(bytes_length_member) +{ + char const* sourceCode = R"( + contract c { + function set() returns (bool) { data = msg.data; return true; } + function getLength() returns (uint) { return data.length; } + bytes data; + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("getLength()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("set()", 1, 2) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("getLength()") == encodeArgs(4+32+32)); +} + BOOST_AUTO_TEST_SUITE_END() }