diff options
author | chriseth <c@ethdev.com> | 2016-02-04 04:34:24 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-02-10 00:07:04 +0800 |
commit | 29faf1b298030f23076e8322dafd87df2154b40f (patch) | |
tree | 5e2d1d37aac3ab11b3015365a33f945bf9a145aa /libsolidity | |
parent | fad2d4df222f3fc306eda84a6a3842955541f9d0 (diff) | |
download | dexon-solidity-29faf1b298030f23076e8322dafd87df2154b40f.tar.gz dexon-solidity-29faf1b298030f23076e8322dafd87df2154b40f.tar.zst dexon-solidity-29faf1b298030f23076e8322dafd87df2154b40f.zip |
Index access for bytesXX.
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 18 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 5 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 1 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 26 |
4 files changed, 50 insertions, 0 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 0d74ddba..756f0e4f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1253,6 +1253,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) arrayType.isDynamicallySized() ); } + else if (exprType->category() == Type::Category::FixedBytes) + annotation.isLValue = false; return false; } @@ -1317,6 +1319,22 @@ bool TypeChecker::visit(IndexAccess const& _access) } break; } + case Type::Category::FixedBytes: + { + FixedBytesType const& bytesType = dynamic_cast<FixedBytesType const&>(*baseType); + if (!index) + typeError(_access.location(), "Index expression cannot be omitted."); + else + { + expectType(*index, IntegerType(256)); + if (auto integerType = dynamic_cast<IntegerConstantType const*>(type(*index).get())) + if (bytesType.numBytes() <= integerType->literalValue(nullptr)) + typeError(_access.location(), "Out of bounds array access."); + } + resultType = make_shared<FixedBytesType>(1); + isLValue = false; // @todo this heavily depends on how it is embedded + break; + } default: fatalTypeError( _access.baseExpression().location(), diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 79e5bb02..01d1cb37 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -638,6 +638,11 @@ TypePointer FixedBytesType::binaryOperatorResult(Token::Value _operator, TypePoi return TypePointer(); } +MemberList::MemberMap FixedBytesType::nativeMembers(const ContractDefinition*) const +{ + return MemberList::MemberMap{MemberList::Member{"length", make_shared<IntegerType>(8)}}; +} + bool FixedBytesType::operator==(Type const& _other) const { if (_other.category() != category()) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 723d633b..90a0509b 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -399,6 +399,7 @@ public: virtual bool isValueType() const override { return true; } virtual std::string toString(bool) const override { return "bytes" + dev::toString(m_bytes); } + virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override; virtual TypePointer encodingType() const override { return shared_from_this(); } virtual TypePointer interfaceType(bool) const override { return shared_from_this(); } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 9536c727..58db07b1 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1004,6 +1004,16 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) solAssert(false, "Illegal array member."); break; } + case Type::Category::FixedBytes: + { + auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type); + utils().popStackElement(type); + if (member == "length") + m_context << u256(type.numBytes()); + else + solAssert(false, "Illegal fixed bytes member."); + break; + } default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type.")); } @@ -1085,6 +1095,22 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) break; } } + else if (baseType.category() == Type::Category::FixedBytes) + { + FixedBytesType const& fixedBytesType = dynamic_cast<FixedBytesType const&>(baseType); + solAssert(_indexAccess.indexExpression(), "Index expression expected."); + + _indexAccess.indexExpression()->accept(*this); + // stack layout: <value> <index> + // check out-of-bounds access + m_context << u256(fixedBytesType.numBytes()); + m_context << eth::Instruction::DUP2 << eth::Instruction::LT << eth::Instruction::ISZERO; + // out-of-bounds access throws exception + m_context.appendConditionalJumpTo(m_context.errorTag()); + + m_context << eth::Instruction::BYTE; + m_context << (u256(1) << (256 - 8)) << eth::Instruction::MUL; + } else if (baseType.category() == Type::Category::TypeType) { solAssert(baseType.sizeOnStack() == 0, ""); |