libsolidity/formal/BMC.cpp
// Here we consider the execution of two branches:
// Branch 1 assumes the loop condition to be true and executes the loop once,
// after resetting touched variables.
// Branch 2 assumes the loop condition to be false and skips the loop after
// visiting the condition (it might contain side-effects, they need to be considered)
// and does not erase knowledge.
// If the loop is a do-while, condition side-effects are lost since the body,
// executed once before the condition, might reassign variables.
// Variables touched by the loop are merged with Branch 2.
Here we consider the execution of two branches:
Branch 1 assumes the loop condition to be true and executes the loop once,
after resetting touched variables.
Branch 2 assumes the loop condition to be false and skips the loop after
visiting the condition (it might contain side-effects, they need to be considered)
and does not erase knowledge.
If the loop is a do-while, condition side-effects are lost since the body,
executed once before the condition, might reassign variables.
Variables touched by the loop are merged with Branch 2.
Here we consider the execution of two branches : Branch 1 assumes the loop condition to be true and executes the loop once after resetting touched variables . Branch 2 assumes the loop condition to be false and skips the loop after visiting the condition ( it might contain side - effects they need to be considered ) and does not erase knowledge . If the loop is a do - while condition side - effects are lost since the body executed once before the condition might reassign variables . Variables touched by the loop are merged with Branch 2 .
bool BMC::visit(WhileStatement const& _node)
{
	auto indicesBeforeLoop = copyVariableIndices();
	auto touchedVars = touchedVariables(_node);
	m_context.resetVariables(touchedVars);
	decltype(indicesBeforeLoop) indicesAfterLoop;
	if (_node.isDoWhile())
	{
		indicesAfterLoop = visitBranch(&_node.body());
		_node.condition().accept(*this);
		if (isRootFunction())
			addVerificationTarget(
				VerificationTarget::Type::ConstantCondition,
				expr(_node.condition()),
				&_node.condition()
			);
	}
	else
	{
		_node.condition().accept(*this);
		if (isRootFunction())
			addVerificationTarget(
				VerificationTarget::Type::ConstantCondition,
				expr(_node.condition()),
				&_node.condition()
			);
		indicesAfterLoop = visitBranch(&_node.body(), expr(_node.condition()));
	}
	resetVariableIndices(indicesBeforeLoop);
	if (!_node.isDoWhile())
		_node.condition().accept(*this);
	mergeVariables(touchedVars, expr(_node.condition()), indicesAfterLoop, copyVariableIndices());
	m_loopExecutionHappened = true;
	return false;
}
bool BMC :: visit ( WhileStatement const & _node ) { auto indicesBeforeLoop = copyVariableIndices ( ) ; auto touchedVars = touchedVariables ( _node ) ; m_context . resetVariables ( touchedVars ) ; decltype ( indicesBeforeLoop ) indicesAfterLoop ; if ( _node . isDoWhile ( ) ) { indicesAfterLoop = visitBranch ( & _node . body ( ) ) ; _node . condition ( ) . accept ( * this ) ; if ( isRootFunction ( ) ) addVerificationTarget ( VerificationTarget :: Type :: ConstantCondition , expr ( _node . condition ( ) ) , & _node . condition ( ) ) ; } else { _node . condition ( ) . accept ( * this ) ; if ( isRootFunction ( ) ) addVerificationTarget ( VerificationTarget :: Type :: ConstantCondition , expr ( _node . condition ( ) ) , & _node . condition ( ) ) ; indicesAfterLoop = visitBranch ( & _node . body ( ) , expr ( _node . condition ( ) ) ) ; } resetVariableIndices ( indicesBeforeLoop ) ; if ( ! _node . isDoWhile ( ) ) _node . condition ( ) . accept ( * this ) ; mergeVariables ( touchedVars , expr ( _node . condition ( ) ) , indicesAfterLoop , copyVariableIndices ( ) ) ; m_loopExecutionHappened = true ; return false ; }
Here we consider the execution of two branches:
Branch 1 assumes the loop condition to be true and executes the loop once,
after resetting touched variables.
Here we consider the execution of two branches : Branch 1 assumes the loop condition to be true and executes the loop once after resetting touched variables .
// TODO the assertions generated in the body should still be active in the condition // We reset the execution to before the loop // and visit the condition in case it's not a do-while. // A do-while's body might have non-precise information // in its first run about variables that are touched.