mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
compileExpression(_whileStatement.condition());
|
||||
m_context << Instruction::ISZERO;
|
||||
m_context.appendConditionalJumpTo(loopEnd);
|
||||
}
|
||||
|
||||
_whileStatement.body().accept(*this);
|
||||
|
||||
// Do-while loops have the condition appended
|
||||
if (_whileStatement.isDoWhile())
|
||||
{
|
||||
eth::AssemblyItem condition = m_context.newTag();
|
||||
m_continueTags.push_back(condition);
|
||||
|
||||
_whileStatement.body().accept(*this);
|
||||
|
||||
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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user