@@ -25,7 +25,6 @@ Date: February 2016
25
25
#include < util/message.h>
26
26
#include < util/pointer_offset_size.h>
27
27
#include < util/pointer_predicates.h>
28
- #include < util/replace_symbol.h>
29
28
#include < util/std_code.h>
30
29
31
30
#include < goto-programs/goto_inline.h>
@@ -777,15 +776,12 @@ void code_contractst::apply_function_contract(
777
776
// Isolate each component of the contract.
778
777
const auto &type = get_contract (target_function, ns);
779
778
auto assigns_clause = type.assigns ();
780
- auto requires = conjunction (type.requires ());
781
- auto ensures = conjunction (type.ensures ());
782
779
auto requires_contract = type.requires_contract ();
783
780
auto ensures_contract = type.ensures_contract ();
784
781
785
- // Create a replace_symbolt object, for replacing expressions in the callee
782
+ // Prepare to instantiate expressions in the callee
786
783
// with expressions from the call site (e.g. the return value).
787
- // This object tracks replacements that are common to ENSURES and REQUIRES.
788
- replace_symbolt common_replace;
784
+ exprt::operandst instantiation_values;
789
785
790
786
// keep track of the call's return expression to make it nondet later
791
787
optionalt<exprt> call_ret_opt = {};
@@ -804,8 +800,7 @@ void code_contractst::apply_function_contract(
804
800
// x = foo() -> assume(__CPROVER_return_value > 5) -> assume(x > 5)
805
801
auto &lhs_expr = const_target->call_lhs ();
806
802
call_ret_opt = lhs_expr;
807
- symbol_exprt ret_val (CPROVER_PREFIX " return_value" , lhs_expr.type ());
808
- common_replace.insert (ret_val, lhs_expr);
803
+ instantiation_values.push_back (lhs_expr);
809
804
}
810
805
else
811
806
{
@@ -827,28 +822,16 @@ void code_contractst::apply_function_contract(
827
822
symbol_table.lookup_ref (target_function).mode ,
828
823
ns,
829
824
symbol_table);
830
- symbol_exprt ret_val (
831
- CPROVER_PREFIX " return_value" , function_type.return_type ());
832
825
auto fresh_sym_expr = fresh.symbol_expr ();
833
- common_replace.insert (ret_val, fresh_sym_expr);
834
826
call_ret_opt = fresh_sym_expr;
827
+ instantiation_values.push_back (fresh_sym_expr);
835
828
}
836
829
}
837
830
}
838
831
839
832
// Replace formal parameters
840
833
const auto &arguments = const_target->call_arguments ();
841
- auto a_it = arguments.begin ();
842
- for (auto p_it = type.parameters ().begin ();
843
- p_it != type.parameters ().end () && a_it != arguments.end ();
844
- ++p_it, ++a_it)
845
- {
846
- if (!p_it->get_identifier ().empty ())
847
- {
848
- symbol_exprt p (p_it->get_identifier (), p_it->type ());
849
- common_replace.insert (p, *a_it);
850
- }
851
- }
834
+ instantiation_values.insert (instantiation_values.end (), arguments.begin (), arguments.end ());
852
835
853
836
const auto &mode = function_symbol.mode ;
854
837
@@ -860,11 +843,16 @@ void code_contractst::apply_function_contract(
860
843
is_fresh.add_memory_map_decl (new_program);
861
844
862
845
// Insert assertion of the precondition immediately before the call site.
846
+ exprt::operandst requires_conjuncts;
847
+ for (const auto &r : type.requires ())
848
+ {
849
+ requires_conjuncts.push_back (to_lambda_expr (r).application (instantiation_values));
850
+ }
851
+ auto requires = conjunction (requires_conjuncts);
863
852
if (!requires.is_true ())
864
853
{
865
854
if (has_subexpr (requires, ID_exists) || has_subexpr (requires, ID_forall))
866
855
add_quantified_variable (requires, mode);
867
- common_replace (requires);
868
856
869
857
goto_programt assertion;
870
858
converter.goto_convert (code_assertt (requires), assertion, mode);
@@ -882,21 +870,25 @@ void code_contractst::apply_function_contract(
882
870
for (auto &expr : requires_contract)
883
871
{
884
872
assert_function_pointer_obeys_contract (
885
- to_function_pointer_obeys_contract_expr (expr),
873
+ to_function_pointer_obeys_contract_expr (to_lambda_expr ( expr). application (instantiation_values) ),
886
874
ID_precondition,
887
- common_replace,
888
875
mode,
889
876
new_program);
890
877
}
891
878
892
879
// Gather all the instructions required to handle history variables
893
880
// as well as the ensures clause
881
+ exprt::operandst ensures_conjuncts;
882
+ for (const auto &r : type.ensures ())
883
+ {
884
+ ensures_conjuncts.push_back (to_lambda_expr (r).application (instantiation_values));
885
+ }
886
+ auto ensures = conjunction (ensures_conjuncts);
894
887
std::pair<goto_programt, goto_programt> ensures_pair;
895
888
if (!ensures.is_false ())
896
889
{
897
890
if (has_subexpr (ensures, ID_exists) || has_subexpr (ensures, ID_forall))
898
891
add_quantified_variable (ensures, mode);
899
- common_replace (ensures);
900
892
901
893
auto assumption = code_assumet (ensures);
902
894
ensures_pair =
@@ -961,8 +953,7 @@ void code_contractst::apply_function_contract(
961
953
for (auto &expr : ensures_contract)
962
954
{
963
955
assume_function_pointer_obeys_contract (
964
- to_function_pointer_obeys_contract_expr (expr),
965
- common_replace,
956
+ to_function_pointer_obeys_contract_expr (to_lambda_expr (expr).application (instantiation_values)),
966
957
mode,
967
958
new_program);
968
959
}
@@ -1399,7 +1390,6 @@ void code_contractst::enforce_contract(const irep_idt &function)
1399
1390
void code_contractst::assert_function_pointer_obeys_contract (
1400
1391
const function_pointer_obeys_contract_exprt &expr,
1401
1392
const irep_idt &property_class,
1402
- const replace_symbolt &replace,
1403
1393
const irep_idt &mode,
1404
1394
goto_programt &dest)
1405
1395
{
@@ -1411,9 +1401,7 @@ void code_contractst::assert_function_pointer_obeys_contract(
1411
1401
<< " ' obeys contract '"
1412
1402
<< from_expr_using_mode (ns, mode, expr.contract ()) << " '" ;
1413
1403
loc.set_comment (comment.str ());
1414
- exprt function_pointer (expr.function_pointer ());
1415
- replace (function_pointer);
1416
- code_assertt assert_expr (equal_exprt{function_pointer, expr.contract ()});
1404
+ code_assertt assert_expr (equal_exprt{expr.function_pointer (), expr.contract ()});
1417
1405
assert_expr.add_source_location () = loc;
1418
1406
goto_programt instructions;
1419
1407
converter.goto_convert (assert_expr, instructions, mode);
@@ -1422,7 +1410,6 @@ void code_contractst::assert_function_pointer_obeys_contract(
1422
1410
1423
1411
void code_contractst::assume_function_pointer_obeys_contract (
1424
1412
const function_pointer_obeys_contract_exprt &expr,
1425
- const replace_symbolt &replace,
1426
1413
const irep_idt &mode,
1427
1414
goto_programt &dest)
1428
1415
{
@@ -1433,10 +1420,8 @@ void code_contractst::assume_function_pointer_obeys_contract(
1433
1420
<< " ' obeys contract '"
1434
1421
<< from_expr_using_mode (ns, mode, expr.contract ()) << " '" ;
1435
1422
loc.set_comment (comment.str ());
1436
- exprt function_pointer (expr.function_pointer ());
1437
- replace (function_pointer);
1438
1423
dest.add (
1439
- goto_programt::make_assignment (function_pointer, expr.contract (), loc));
1424
+ goto_programt::make_assignment (expr. function_pointer () , expr.contract (), loc));
1440
1425
}
1441
1426
1442
1427
void code_contractst::add_contract_check (
@@ -1448,8 +1433,6 @@ void code_contractst::add_contract_check(
1448
1433
1449
1434
const auto &code_type = get_contract (wrapper_function, ns);
1450
1435
auto assigns = code_type.assigns ();
1451
- auto requires = conjunction (code_type.requires ());
1452
- auto ensures = conjunction (code_type.ensures ());
1453
1436
auto requires_contract = code_type.requires_contract ();
1454
1437
auto ensures_contract = code_type.ensures_contract ();
1455
1438
// build:
@@ -1473,10 +1456,9 @@ void code_contractst::add_contract_check(
1473
1456
const symbolt &function_symbol = ns.lookup (mangled_function);
1474
1457
code_function_callt call (function_symbol.symbol_expr ());
1475
1458
1476
- // Create a replace_symbolt object, for replacing expressions in the callee
1459
+ // Prepare to instantiate expressions in the callee
1477
1460
// with expressions from the call site (e.g. the return value).
1478
- // This object tracks replacements that are common to ENSURES and REQUIRES.
1479
- replace_symbolt common_replace;
1461
+ exprt::operandst instantiation_values;
1480
1462
1481
1463
// decl ret
1482
1464
optionalt<code_returnt> return_stmt;
@@ -1493,8 +1475,7 @@ void code_contractst::add_contract_check(
1493
1475
call.lhs () = r;
1494
1476
return_stmt = code_returnt (r);
1495
1477
1496
- symbol_exprt ret_val (CPROVER_PREFIX " return_value" , call.lhs ().type ());
1497
- common_replace.insert (ret_val, r);
1478
+ instantiation_values.push_back (r);
1498
1479
}
1499
1480
1500
1481
// decl parameter1 ...
@@ -1519,18 +1500,23 @@ void code_contractst::add_contract_check(
1519
1500
1520
1501
call.arguments ().push_back (p);
1521
1502
1522
- common_replace. insert (parameter_symbol. symbol_expr (), p);
1503
+ instantiation_values. push_back ( p);
1523
1504
}
1524
1505
1525
1506
is_fresh_enforcet visitor (*this , log , wrapper_function);
1526
1507
visitor.create_declarations ();
1527
1508
visitor.add_memory_map_decl (check);
1528
1509
// Generate: assume(requires)
1510
+ exprt::operandst requires_conjuncts;
1511
+ for (const auto &r : code_type.requires ())
1512
+ {
1513
+ requires_conjuncts.push_back (to_lambda_expr (r).application (instantiation_values));
1514
+ }
1515
+ auto requires = conjunction (requires_conjuncts);
1529
1516
if (!requires.is_false ())
1530
1517
{
1531
1518
if (has_subexpr (requires, ID_exists) || has_subexpr (requires, ID_forall))
1532
1519
add_quantified_variable (requires, function_symbol.mode );
1533
- common_replace (requires);
1534
1520
1535
1521
goto_programt assumption;
1536
1522
converter.goto_convert (
@@ -1543,11 +1529,16 @@ void code_contractst::add_contract_check(
1543
1529
std::pair<goto_programt, goto_programt> ensures_pair;
1544
1530
1545
1531
// Generate: copies for history variables
1532
+ exprt::operandst ensures_conjuncts;
1533
+ for (const auto &r : code_type.ensures ())
1534
+ {
1535
+ ensures_conjuncts.push_back (to_lambda_expr (r).application (instantiation_values));
1536
+ }
1537
+ auto ensures = conjunction (ensures_conjuncts);
1546
1538
if (!ensures.is_true ())
1547
1539
{
1548
1540
if (has_subexpr (ensures, ID_exists) || has_subexpr (ensures, ID_forall))
1549
1541
add_quantified_variable (ensures, function_symbol.mode );
1550
- common_replace (ensures);
1551
1542
1552
1543
// get all the relevant instructions related to history variables
1553
1544
auto assertion = code_assertt (ensures);
@@ -1570,8 +1561,7 @@ void code_contractst::add_contract_check(
1570
1561
for (auto &expr : requires_contract)
1571
1562
{
1572
1563
assume_function_pointer_obeys_contract (
1573
- to_function_pointer_obeys_contract_expr (expr),
1574
- common_replace,
1564
+ to_function_pointer_obeys_contract_expr (to_lambda_expr (expr).application (instantiation_values)),
1575
1565
function_symbol.mode ,
1576
1566
check);
1577
1567
}
@@ -1589,9 +1579,8 @@ void code_contractst::add_contract_check(
1589
1579
for (auto &expr : ensures_contract)
1590
1580
{
1591
1581
assert_function_pointer_obeys_contract (
1592
- to_function_pointer_obeys_contract_expr (expr),
1582
+ to_function_pointer_obeys_contract_expr (to_lambda_expr ( expr). application (instantiation_values) ),
1593
1583
ID_postcondition,
1594
- common_replace,
1595
1584
function_symbol.mode ,
1596
1585
check);
1597
1586
}
0 commit comments