Skip to content

Commit

Permalink
CONTRACTS: fix loop latch nodes normalization
Browse files Browse the repository at this point in the history
We now ensure that latch nodes are uncondtional
and carry contract clauses. Allows to treat
do-while loops just like do-loops and for-loops.
  • Loading branch information
Remi Delmas committed Aug 20, 2024
1 parent 3877e0f commit 5f22ef7
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 11 deletions.
2 changes: 1 addition & 1 deletion regression/contracts/loop_contracts_do_while/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ int main()
do
// clang-format off
__CPROVER_assigns(x)
__CPROVER_loop_invariant(0 <= x && x <= 10)
__CPROVER_loop_invariant(0 <= x && x < 10)
__CPROVER_decreases(20 - x)
// clang-format on
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void dfcc_check_loop_normal_form(goto_programt &goto_program, messaget &log)
// IF g THEN GOTO HEAD
// --------------------------
// IF !g THEN GOTO EXIT
// GOTO HEAD
// IF TRUE GOTO HEAD
// EXIT: SKIP
// ```
if(latch->has_condition() && !latch->condition().is_true())
Expand All @@ -162,24 +162,38 @@ void dfcc_check_loop_normal_form(goto_programt &goto_program, messaget &log)
const auto &exit =
goto_program.insert_after(latch, goto_programt::make_skip(loc));

// Insert the loop exit jump `F !g THEN GOTO EXIT`

Check warning on line 165 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L165

Added line #L165 was not covered by tests
insert_before_and_update_jumps(
goto_program,
latch,
goto_programt::make_goto(
exit, not_exprt(latch->condition()), latch->source_location()));

// CAUTION: The condition expression needs to be updated in place because
// this is where loop contract clauses are stored as extra ireps.
// Overwriting this expression with a fresh expression will also lose the
// loop contract.
// Rewrite the latch node `IF g THEN GOTO HEAD`
// into `IF true THEN GOTO HEAD`
// and transplanting contract clauses
exprt new_condition = true_exprt();

Check warning on line 175 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L174-L175

Added lines #L174 - L175 were not covered by tests

// Extract the contract clauses from the existing latch condition,

Check warning on line 177 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L177

Added line #L177 was not covered by tests
exprt latch_condition = latch->condition();
latch_condition.set(ID_value, ID_true);
*latch = goto_programt::make_goto(head, latch_condition, loc);
}
irept latch_assigns = latch_condition.find(ID_C_spec_assigns);

Check warning on line 179 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L179

Added line #L179 was not covered by tests
if(latch_assigns.is_not_nil())
new_condition.add(ID_C_spec_assigns).swap(latch_assigns);

Check warning on line 181 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L181

Added line #L181 was not covered by tests

irept latch_loop_invariant =
latch_condition.find(ID_C_spec_loop_invariant);

Check warning on line 184 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L183-L184

Added lines #L183 - L184 were not covered by tests
if(latch_loop_invariant.is_not_nil())
new_condition.add(ID_C_spec_loop_invariant).swap(latch_loop_invariant);

Check warning on line 186 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L186

Added line #L186 was not covered by tests

// The latch node is now an unconditional jump.
irept latch_decreases = latch_condition.find(ID_C_spec_decreases);

Check warning on line 188 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L188

Added line #L188 was not covered by tests
if(latch_decreases.is_not_nil())
new_condition.add(ID_C_spec_decreases).swap(latch_decreases);

Check warning on line 190 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L190

Added line #L190 was not covered by tests

latch->condition_nonconst() = new_condition;

Check warning on line 192 in src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-instrument/contracts/dynamic-frames/dfcc_check_loop_normal_form.cpp#L192

Added line #L192 was not covered by tests
// The latch node is now an unconditional jump with contract clauses
}

// insert a SKIP pre-head node and reroute all incoming edges to that node,
// Insert a SKIP pre-head node and reroute all incoming edges to that node,
// except for edge coming from the latch.
insert_before_and_update_jumps(
goto_program, head, goto_programt::make_skip(head->source_location()));
Expand Down

0 comments on commit 5f22ef7

Please sign in to comment.