diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/ControlFlowBuilder.cpp | 9 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 11 | ||||
-rw-r--r-- | libsolidity/codegen/ContractCompiler.cpp | 28 | ||||
-rw-r--r-- | libsolidity/formal/SMTChecker.cpp | 6 |
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. |