aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-02-04 04:34:24 +0800
committerchriseth <c@ethdev.com>2016-02-10 00:07:04 +0800
commit29faf1b298030f23076e8322dafd87df2154b40f (patch)
tree5e2d1d37aac3ab11b3015365a33f945bf9a145aa /libsolidity
parentfad2d4df222f3fc306eda84a6a3842955541f9d0 (diff)
downloaddexon-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.cpp18
-rw-r--r--libsolidity/ast/Types.cpp5
-rw-r--r--libsolidity/ast/Types.h1
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp26
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, "");