aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/ControlFlowBuilder.cpp9
-rw-r--r--libsolidity/ast/Types.cpp11
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp28
-rw-r--r--libsolidity/formal/SMTChecker.cpp6
4 files changed, 28 insertions, 26 deletions
diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp
index 35d7687c..5bd39da3 100644
--- a/libsolidity/analysis/ControlFlowBuilder.cpp
+++ b/libsolidity/analysis/ControlFlowBuilder.cpp
@@ -159,15 +159,14 @@ bool ControlFlowBuilder::visit(WhileStatement const& _whileStatement)
{
auto afterWhile = newLabel();
auto whileBody = createLabelHere();
+ auto condition = newLabel();
{
- // Note that "continue" in this case currently indeed jumps to whileBody
- // and not to the condition. This is inconsistent with JavaScript and C and
- // therefore a bug. This will be fixed in the future (planned for 0.5.0)
- // and the Control Flow Graph will have to be adjusted accordingly.
- BreakContinueScope scope(*this, afterWhile, whileBody);
+ BreakContinueScope scope(*this, afterWhile, condition);
appendControlFlow(_whileStatement.body());
}
+
+ placeAndConnectLabel(condition);
appendControlFlow(_whileStatement.condition());
connect(m_currentNode, whileBody);
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 60e3183c..000b1063 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -476,7 +476,7 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return _convertTo.category() == category() ||
_convertTo.category() == Category::Contract ||
_convertTo.category() == Category::Enum ||
- _convertTo.category() == Category::FixedBytes ||
+ (_convertTo.category() == Category::FixedBytes && numBits() == dynamic_cast<FixedBytesType const&>(_convertTo).numBytes() * 8) ||
_convertTo.category() == Category::FixedPoint;
}
@@ -884,7 +884,10 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
TypePointer mobType = mobileType();
- return mobType && mobType->isExplicitlyConvertibleTo(_convertTo);
+ return
+ (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)) ||
+ (!isFractional() && _convertTo.category() == Category::FixedBytes)
+ ;
}
TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const
@@ -1281,7 +1284,7 @@ bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const
bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
- return _convertTo.category() == Category::Integer ||
+ return (_convertTo.category() == Category::Integer && numBytes() * 8 == dynamic_cast<IntegerType const&>(_convertTo).numBits()) ||
_convertTo.category() == Category::FixedPoint ||
_convertTo.category() == category();
}
@@ -1358,7 +1361,7 @@ TypePointer BoolType::binaryOperatorResult(Token::Value _operator, TypePointer c
{
if (category() != _other->category())
return TypePointer();
- if (Token::isCompareOp(_operator) || _operator == Token::And || _operator == Token::Or)
+ if (_operator == Token::Equal || _operator == Token::NotEqual || _operator == Token::And || _operator == Token::Or)
return _other;
else
return TypePointer();
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 0889ac7c..f195b416 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -666,32 +666,36 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
{
StackHeightChecker checker(m_context);
CompilerContext::LocationSetter locationSetter(m_context, _whileStatement);
+
eth::AssemblyItem loopStart = m_context.newTag();
eth::AssemblyItem loopEnd = m_context.newTag();
- m_continueTags.push_back(loopStart);
m_breakTags.push_back(loopEnd);
m_context << loopStart;
- // While loops have the condition prepended
- if (!_whileStatement.isDoWhile())
+ if (_whileStatement.isDoWhile())
{
- compileExpression(_whileStatement.condition());
- m_context << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(loopEnd);
- }
+ eth::AssemblyItem condition = m_context.newTag();
+ m_continueTags.push_back(condition);
- _whileStatement.body().accept(*this);
+ _whileStatement.body().accept(*this);
- // Do-while loops have the condition appended
- if (_whileStatement.isDoWhile())
+ m_context << condition;
+ compileExpression(_whileStatement.condition());
+ m_context << Instruction::ISZERO << Instruction::ISZERO;
+ m_context.appendConditionalJumpTo(loopStart);
+ }
+ else
{
+ m_continueTags.push_back(loopStart);
compileExpression(_whileStatement.condition());
m_context << Instruction::ISZERO;
m_context.appendConditionalJumpTo(loopEnd);
- }
- m_context.appendJumpTo(loopStart);
+ _whileStatement.body().accept(*this);
+
+ m_context.appendJumpTo(loopStart);
+ }
m_context << loopEnd;
m_continueTags.pop_back();
diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp
index 425c5c1e..8639317b 100644
--- a/libsolidity/formal/SMTChecker.cpp
+++ b/libsolidity/formal/SMTChecker.cpp
@@ -485,11 +485,7 @@ void SMTChecker::compareOperation(BinaryOperation const& _op)
solUnimplementedAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "Operation not yet supported");
value = make_shared<smt::Expression>(
op == Token::Equal ? (left == right) :
- op == Token::NotEqual ? (left != right) :
- op == Token::LessThan ? (!left && right) :
- op == Token::LessThanOrEqual ? (!left || right) :
- op == Token::GreaterThan ? (left && !right) :
- /*op == Token::GreaterThanOrEqual*/ (left || !right)
+ /*op == Token::NotEqual*/ (left != right)
);
}
// TODO: check that other values for op are not possible.