@@ -473,18 +473,19 @@ code_contractst::create_ensures_instruction(
473
473
}
474
474
475
475
bool code_contractst::apply_function_contract (
476
- goto_programt &goto_program,
477
- goto_programt::targett target)
476
+ const irep_idt &function,
477
+ goto_programt &function_body,
478
+ goto_programt::targett &target)
478
479
{
479
480
// Return if the function is not named in the call; currently we don't handle
480
481
// function pointers.
481
- PRECONDITION (as_const (* target). call_function ().id () == ID_symbol);
482
+ PRECONDITION (as_const (target)-> call_function ().id () == ID_symbol);
482
483
483
484
// Retrieve the function type, which is needed to extract the contract
484
485
// components.
485
- const irep_idt &function =
486
- to_symbol_expr (as_const (* target). call_function ()).get_identifier ();
487
- const symbolt &function_symbol = ns.lookup (function );
486
+ const irep_idt &target_function =
487
+ to_symbol_expr (as_const (target)-> call_function ()).get_identifier ();
488
+ const symbolt &function_symbol = ns.lookup (target_function );
488
489
const auto &type = to_code_with_contract_type (function_symbol.type );
489
490
490
491
// Isolate each component of the contract.
@@ -499,15 +500,15 @@ bool code_contractst::apply_function_contract(
499
500
if (type.return_type () != empty_typet ())
500
501
{
501
502
// Check whether the function's return value is not disregarded.
502
- if (as_const (* target). call_lhs ().is_not_nil ())
503
+ if (target-> call_lhs ().is_not_nil ())
503
504
{
504
505
// If so, have it replaced appropriately.
505
506
// For example, if foo() ensures that its return value is > 5, then
506
507
// rewrite calls to foo as follows:
507
508
// x = foo() -> assume(__CPROVER_return_value > 5) -> assume(x > 5)
508
509
symbol_exprt ret_val (
509
- CPROVER_PREFIX " return_value" , as_const (* target). call_lhs ().type ());
510
- common_replace.insert (ret_val, as_const (* target). call_lhs ());
510
+ CPROVER_PREFIX " return_value" , as_const (target)-> call_lhs ().type ());
511
+ common_replace.insert (ret_val, as_const (target)-> call_lhs ());
511
512
}
512
513
else
513
514
{
@@ -521,10 +522,10 @@ bool code_contractst::apply_function_contract(
521
522
// fresh variable to replace __CPROVER_return_value with.
522
523
const symbolt &fresh = get_fresh_aux_symbol (
523
524
type.return_type (),
524
- id2string (function ),
525
+ id2string (target_function ),
525
526
" ignored_return_value" ,
526
- target->source_location ,
527
- symbol_table.lookup_ref (function ).mode ,
527
+ as_const ( target) ->source_location ,
528
+ symbol_table.lookup_ref (target_function ).mode ,
528
529
ns,
529
530
symbol_table);
530
531
symbol_exprt ret_val (CPROVER_PREFIX " return_value" , type.return_type ());
@@ -534,7 +535,7 @@ bool code_contractst::apply_function_contract(
534
535
}
535
536
536
537
// Replace formal parameters
537
- const auto &arguments = target->call_arguments ();
538
+ const auto &arguments = as_const ( target) ->call_arguments ();
538
539
auto a_it = arguments.begin ();
539
540
for (auto p_it = type.parameters ().begin ();
540
541
p_it != type.parameters ().end () && a_it != arguments.end ();
@@ -551,9 +552,9 @@ bool code_contractst::apply_function_contract(
551
552
// and only refer to the common symbols to be replaced.
552
553
common_replace (assigns);
553
554
554
- const auto &mode = symbol_table.lookup_ref (function ).mode ;
555
+ const auto &mode = symbol_table.lookup_ref (target_function ).mode ;
555
556
556
- is_fresh_replacet is_fresh (*this , log , function );
557
+ is_fresh_replacet is_fresh (*this , log , target_function );
557
558
is_fresh.create_declarations ();
558
559
559
560
// Insert assertion of the precondition immediately before the call site.
@@ -567,14 +568,14 @@ bool code_contractst::apply_function_contract(
567
568
converter.goto_convert (
568
569
code_assertt (requires),
569
570
assertion,
570
- symbol_table.lookup_ref (function ).mode );
571
+ symbol_table.lookup_ref (target_function ).mode );
571
572
assertion.instructions .back ().source_location = requires.source_location ();
572
573
assertion.instructions .back ().source_location .set_comment (
573
574
" Check requires clause" );
574
575
assertion.instructions .back ().source_location .set_property_class (
575
576
ID_precondition);
576
577
is_fresh.update_requires (assertion);
577
- insert_before_swap_and_advance (goto_program , target, assertion);
578
+ insert_before_swap_and_advance (function_body , target, assertion);
578
579
}
579
580
580
581
// Gather all the instructions required to handle history variables
@@ -590,11 +591,11 @@ bool code_contractst::apply_function_contract(
590
591
ensures_pair = create_ensures_instruction (
591
592
assumption,
592
593
ensures.source_location (),
593
- symbol_table.lookup_ref (function ).mode );
594
+ symbol_table.lookup_ref (target_function ).mode );
594
595
595
596
// add all the history variable initialization instructions
596
597
// to the goto program
597
- insert_before_swap_and_advance (goto_program , target, ensures_pair.second );
598
+ insert_before_swap_and_advance (function_body , target, ensures_pair.second );
598
599
}
599
600
600
601
// Create a series of non-deterministic assignments to havoc the variables
@@ -604,9 +605,8 @@ bool code_contractst::apply_function_contract(
604
605
assigns_clauset assigns_clause (assigns, log , ns);
605
606
606
607
// Retrieve assigns clause of the caller function if exists.
607
- const irep_idt &caller_function = target->source_location .get_function ();
608
608
auto caller_assigns =
609
- to_code_with_contract_type (ns.lookup (caller_function ).type ).assigns ();
609
+ to_code_with_contract_type (ns.lookup (function ).type ).assigns ();
610
610
611
611
if (caller_assigns.is_not_nil ())
612
612
{
@@ -617,31 +617,32 @@ bool code_contractst::apply_function_contract(
617
617
caller_assigns_clause.generate_subset_check (assigns_clause),
618
618
assigns_clause.location ));
619
619
subset_check_assertion.instructions .back ().source_location .set_comment (
620
- " Check that " + id2string (function) +
621
- " 's assigns clause is a subset of " + id2string (caller_function) +
620
+ " Check that " + id2string (target_function) +
621
+ " 's assigns clause is a subset of " +
622
+ id2string (as_const (target)->source_location .get_function ()) +
622
623
" 's assigns clause" );
623
624
insert_before_swap_and_advance (
624
- goto_program , target, subset_check_assertion);
625
+ function_body , target, subset_check_assertion);
625
626
}
626
627
627
628
// Havoc all targets in global write set
628
629
auto assigns_havoc = assigns_clause.generate_havoc_code ();
629
630
630
631
// Insert the non-deterministic assignment immediately before the call site.
631
- insert_before_swap_and_advance (goto_program , target, assigns_havoc);
632
+ insert_before_swap_and_advance (function_body , target, assigns_havoc);
632
633
}
633
634
634
635
// To remove the function call, insert statements related to the assumption.
635
636
// Then, replace the function call with a SKIP statement.
636
637
if (!ensures.is_false ())
637
638
{
638
639
is_fresh.update_ensures (ensures_pair.first );
639
- insert_before_swap_and_advance (goto_program , target, ensures_pair.first );
640
+ insert_before_swap_and_advance (function_body , target, ensures_pair.first );
640
641
}
641
642
*target = goto_programt::make_skip ();
642
643
643
644
// Add this function to the set of replaced functions.
644
- summarized.insert (function );
645
+ summarized.insert (target_function );
645
646
return false ;
646
647
}
647
648
@@ -1223,7 +1224,8 @@ bool code_contractst::replace_calls(const std::set<std::string> &functions)
1223
1224
if (found == functions.end ())
1224
1225
continue ;
1225
1226
1226
- fail |= apply_function_contract (goto_function.second .body , ins);
1227
+ fail |= apply_function_contract (
1228
+ goto_function.first , goto_function.second .body , ins);
1227
1229
}
1228
1230
}
1229
1231
}
0 commit comments