@@ -44,7 +44,7 @@ static bool is_symbol_member(const exprt &expr)
44
44
static exprt
45
45
make_assigns_assertion (const exprt::operandst &assigns, const exprt &lhs)
46
46
{
47
- // trivial?
47
+ // trivial match ?
48
48
if (is_symbol_member (lhs))
49
49
{
50
50
for (auto &a : assigns)
@@ -56,11 +56,28 @@ make_assigns_assertion(const exprt::operandst &assigns, const exprt &lhs)
56
56
57
57
for (auto &a : assigns)
58
58
{
59
- auto a_address = make_address (a);
60
- auto lhs_address = make_address (lhs);
61
- lhs_address =
62
- typecast_exprt::conditional_cast (lhs_address, a_address.type ());
63
- disjuncts.push_back (equal_exprt (a_address, lhs_address));
59
+ if (a.id () == ID_conditional_target_group)
60
+ {
61
+ auto &condition = to_binary_expr (a).op0 ();
62
+ auto &targets = to_multi_ary_expr (to_binary_expr (a).op1 ());
63
+ for (auto &target : targets.operands ())
64
+ {
65
+ auto target_address = make_address (target);
66
+ auto lhs_address = make_address (lhs);
67
+ lhs_address =
68
+ typecast_exprt::conditional_cast (lhs_address, target_address.type ());
69
+ disjuncts.push_back (
70
+ and_exprt (condition, equal_exprt (target_address, lhs_address)));
71
+ }
72
+ }
73
+ else
74
+ {
75
+ auto target_address = make_address (a);
76
+ auto lhs_address = make_address (lhs);
77
+ lhs_address =
78
+ typecast_exprt::conditional_cast (lhs_address, target_address.type ());
79
+ disjuncts.push_back (equal_exprt (target_address, lhs_address));
80
+ }
64
81
}
65
82
66
83
return disjunction (disjuncts);
@@ -288,6 +305,9 @@ void replace_function_calls_by_contracts(
288
305
replace_symbol.insert (
289
306
symbol_exprt (" __CPROVER_return_value" , call_lhs.type ()), call_lhs);
290
307
308
+ goto_programt dest;
309
+
310
+ // assert the preconditions
291
311
for (auto &precondition : contract.requires ())
292
312
{
293
313
auto location = it->source_location ();
@@ -298,32 +318,57 @@ void replace_function_calls_by_contracts(
298
318
auto replaced_precondition = precondition;
299
319
replace_symbol (replaced_precondition);
300
320
301
- auto assertion_instruction =
302
- goto_programt::make_assertion (replaced_precondition, location);
303
-
304
- body.insert_before_swap (it, assertion_instruction);
321
+ dest.add (
322
+ goto_programt::make_assertion (replaced_precondition, location));
305
323
}
306
324
307
- // advance the iterator
308
- it = std::next (it, contract.requires ().size ());
309
-
310
325
// havoc the 'assigned' variables
311
- for (auto &lhs : contract.assigns ())
326
+ for (auto &assigns_clause : contract.assigns ())
312
327
{
313
328
auto location = it->source_location ();
314
329
315
- auto rhs = side_effect_expr_nondett (lhs.type (), location);
316
- auto replaced_lhs = lhs;
317
- replace_symbol (replaced_lhs);
330
+ if (assigns_clause.id () == ID_conditional_target_group)
331
+ {
332
+ const auto &condition = to_binary_expr (assigns_clause).op0 ();
333
+ auto replaced_condition = condition;
334
+ replace_symbol (replaced_condition);
318
335
319
- auto assignment_instruction =
320
- goto_programt::make_assignment (replaced_lhs, rhs, location);
336
+ const auto &targets =
337
+ to_multi_ary_expr (to_binary_expr (assigns_clause).op1 ())
338
+ .operands ();
321
339
322
- body.insert_before_swap (it, assignment_instruction);
323
- }
340
+ for (auto &target : targets)
341
+ {
342
+ auto rhs = side_effect_expr_nondett (target.type (), location);
324
343
325
- // advance the iterator
326
- it = std::next (it, contract.assigns ().size ());
344
+ auto replaced_lhs = target;
345
+ replace_symbol (replaced_lhs);
346
+
347
+ auto goto_instruction =
348
+ dest.add (goto_programt::make_incomplete_goto (
349
+ not_exprt (replaced_condition), location));
350
+
351
+ dest.add (
352
+ goto_programt::make_assignment (replaced_lhs, rhs, location));
353
+
354
+ auto skip_instruction =
355
+ dest.add (goto_programt::make_skip (location));
356
+
357
+ goto_instruction->complete_goto (skip_instruction);
358
+ }
359
+ }
360
+ else
361
+ {
362
+ const auto &lhs = assigns_clause;
363
+ auto rhs = side_effect_expr_nondett (lhs.type (), location);
364
+
365
+ auto replaced_lhs = lhs;
366
+ replace_symbol (replaced_lhs);
367
+
368
+ dest.add (
369
+ goto_programt::make_assignment (replaced_lhs, rhs, location));
370
+ }
371
+ }
327
372
328
373
// assume the postconditions
329
374
for (auto &postcondition : contract.ensures ())
@@ -333,17 +378,15 @@ void replace_function_calls_by_contracts(
333
378
auto replaced_postcondition = postcondition;
334
379
replace_symbol (replaced_postcondition);
335
380
336
- auto assumption_instruction =
337
- goto_programt::make_assumption (replaced_postcondition, location);
338
-
339
- body.insert_before_swap (it, assumption_instruction);
381
+ dest.add (
382
+ goto_programt::make_assumption (replaced_postcondition, location));
340
383
}
341
384
342
- // advance the iterator
343
- it = std::next (it, contract.ensures ().size ());
344
-
345
385
// remove the function call
346
386
it->turn_into_skip ();
387
+
388
+ // insert after 'it' to preserve branches to the call
389
+ body.destructive_insert (std::next (it), dest);
347
390
}
348
391
}
349
392
}
0 commit comments