@@ -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 ((*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 ((*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" , (*target).call_lhs ().type ());
511
+ common_replace.insert (ret_val, (*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
527
target->source_location ,
527
- symbol_table.lookup_ref (function ).mode ,
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 ());
@@ -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,31 @@ 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 " + id2string (function ) +
622
622
" 's assigns clause" );
623
623
insert_before_swap_and_advance (
624
- goto_program , target, subset_check_assertion);
624
+ function_body , target, subset_check_assertion);
625
625
}
626
626
627
627
// Havoc all targets in global write set
628
628
auto assigns_havoc = assigns_clause.generate_havoc_code ();
629
629
630
630
// Insert the non-deterministic assignment immediately before the call site.
631
- insert_before_swap_and_advance (goto_program , target, assigns_havoc);
631
+ insert_before_swap_and_advance (function_body , target, assigns_havoc);
632
632
}
633
633
634
634
// To remove the function call, insert statements related to the assumption.
635
635
// Then, replace the function call with a SKIP statement.
636
636
if (!ensures.is_false ())
637
637
{
638
638
is_fresh.update_ensures (ensures_pair.first );
639
- insert_before_swap_and_advance (goto_program , target, ensures_pair.first );
639
+ insert_before_swap_and_advance (function_body , target, ensures_pair.first );
640
640
}
641
641
*target = goto_programt::make_skip ();
642
642
643
643
// Add this function to the set of replaced functions.
644
- summarized.insert (function );
644
+ summarized.insert (target_function );
645
645
return false ;
646
646
}
647
647
@@ -1223,7 +1223,8 @@ bool code_contractst::replace_calls(const std::set<std::string> &functions)
1223
1223
if (found == functions.end ())
1224
1224
continue ;
1225
1225
1226
- fail |= apply_function_contract (goto_function.second .body , ins);
1226
+ fail |= apply_function_contract (
1227
+ goto_function.first , goto_function.second .body , ins);
1227
1228
}
1228
1229
}
1229
1230
}
0 commit comments