Skip to content

Commit b21323f

Browse files
authored
Merge pull request #8420 from remi-delmas-3000/contracts-fix-do-while-latch
CONTRACTS: fix do while latch
2 parents dae5af0 + 159abec commit b21323f

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

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

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ void dfcc_check_loop_normal_form(goto_programt &goto_program, messaget &log)
153153
// IF g THEN GOTO HEAD
154154
// --------------------------
155155
// IF !g THEN GOTO EXIT
156-
// GOTO HEAD
156+
// IF TRUE GOTO HEAD
157157
// EXIT: SKIP
158158
// ```
159159
if(latch->has_condition() && !latch->condition().is_true())
@@ -162,24 +162,38 @@ void dfcc_check_loop_normal_form(goto_programt &goto_program, messaget &log)
162162
const auto &exit =
163163
goto_program.insert_after(latch, goto_programt::make_skip(loc));
164164

165+
// Insert the loop exit jump `F !g THEN GOTO EXIT`
165166
insert_before_and_update_jumps(
166167
goto_program,
167168
latch,
168169
goto_programt::make_goto(
169170
exit, not_exprt(latch->condition()), latch->source_location()));
170171

171-
// CAUTION: The condition expression needs to be updated in place because
172-
// this is where loop contract clauses are stored as extra ireps.
173-
// Overwriting this expression with a fresh expression will also lose the
174-
// loop contract.
175-
exprt latch_condition = latch->condition();
176-
latch_condition.set(ID_value, ID_true);
177-
*latch = goto_programt::make_goto(head, latch_condition, loc);
178-
}
172+
// Rewrite the latch node `IF g THEN GOTO HEAD`
173+
// into `IF true THEN GOTO HEAD`
174+
// and transplanting contract clauses
175+
exprt new_condition = true_exprt();
176+
177+
// Extract the contract clauses from the existing latch condition,
178+
const exprt &latch_condition = latch->condition();
179+
irept latch_assigns = latch_condition.find(ID_C_spec_assigns);
180+
if(latch_assigns.is_not_nil())
181+
new_condition.add(ID_C_spec_assigns).swap(latch_assigns);
182+
183+
irept latch_loop_invariant =
184+
latch_condition.find(ID_C_spec_loop_invariant);
185+
if(latch_loop_invariant.is_not_nil())
186+
new_condition.add(ID_C_spec_loop_invariant).swap(latch_loop_invariant);
179187

180-
// The latch node is now an unconditional jump.
188+
irept latch_decreases = latch_condition.find(ID_C_spec_decreases);
189+
if(latch_decreases.is_not_nil())
190+
new_condition.add(ID_C_spec_decreases).swap(latch_decreases);
191+
192+
latch->condition_nonconst() = new_condition;
193+
// The latch node is now an unconditional jump with contract clauses
194+
}
181195

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

0 commit comments

Comments
 (0)