@@ -40,6 +40,7 @@ Date: February 2016
40
40
#include < util/pointer_offset_size.h>
41
41
#include < util/pointer_predicates.h>
42
42
#include < util/replace_symbol.h>
43
+ #include < util/simplify_expr.h>
43
44
#include < util/std_code.h>
44
45
45
46
#include " memory_predicates.h"
@@ -1129,7 +1130,9 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
1129
1130
return true ;
1130
1131
}
1131
1132
1132
- if (check_for_looped_mallocs (function_obj->second .body ))
1133
+ auto &goto_program = function_obj->second .body ;
1134
+
1135
+ if (check_for_looped_mallocs (goto_program))
1133
1136
{
1134
1137
return true ;
1135
1138
}
@@ -1150,14 +1153,17 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
1150
1153
for (const auto ¶m : to_code_type (target.type ).parameters ())
1151
1154
assigns.add_to_write_set (ns.lookup (param.get_identifier ()).symbol_expr ());
1152
1155
1153
- auto instruction_it = function_obj-> second . body .instructions .begin ();
1156
+ auto instruction_it = goto_program .instructions .begin ();
1154
1157
for (const auto &car : assigns.get_write_set ())
1155
1158
{
1156
1159
auto snapshot_instructions = car.generate_snapshot_instructions ();
1157
1160
insert_before_swap_and_advance (
1158
- function_obj-> second . body , instruction_it, snapshot_instructions);
1161
+ goto_program , instruction_it, snapshot_instructions);
1159
1162
};
1160
1163
1164
+ // restore internal coherence in the programs
1165
+ goto_functions.update ();
1166
+
1161
1167
// Full inlining of the function body
1162
1168
// Inlining is performed so that function calls to a same function
1163
1169
// occurring under different write sets get instrumented specifically
@@ -1169,9 +1175,17 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
1169
1175
decorated.get_recursive_function_warnings_count () == 0 ,
1170
1176
" Recursive functions found during inlining" );
1171
1177
1172
- // restore internal invariants
1178
+ // clean up possible fake loops that are due to `IF 0!=0 GOTO i` instructions
1179
+ simplify_gotos (goto_program);
1180
+
1181
+ // restore internal coherence in the programs
1173
1182
goto_functions.update ();
1174
1183
1184
+ INVARIANT (
1185
+ is_loop_free (goto_program),
1186
+ " Loops remain in function '" + id2string (function) +
1187
+ " ', assigns clause checking instrumentation cannot be applied." );
1188
+
1175
1189
// Insert write set inclusion checks.
1176
1190
check_frame_conditions (
1177
1191
function_obj->first ,
@@ -1637,3 +1651,62 @@ bool code_contractst::is_auxiliary_decl_dead_or_assign(
1637
1651
return false ;
1638
1652
}
1639
1653
1654
+ void code_contractst::simplify_gotos (goto_programt &goto_program)
1655
+ {
1656
+ for (auto &instruction : goto_program.instructions )
1657
+ {
1658
+ if (instruction.is_goto ())
1659
+ {
1660
+ const auto &condition = instruction.get_condition ();
1661
+ const auto &simplified = simplify_expr (condition, ns);
1662
+ if (simplified.is_false ())
1663
+ instruction.turn_into_skip ();
1664
+ }
1665
+ }
1666
+ }
1667
+
1668
+ bool code_contractst::is_loop_free (const goto_programt &goto_program)
1669
+ {
1670
+ // create cfg from instruction list
1671
+ cfg_baset<empty_cfg_nodet> cfg;
1672
+ cfg (goto_program);
1673
+
1674
+ // check that all nodes are there
1675
+ INVARIANT (
1676
+ goto_program.instructions .size () == cfg.size (),
1677
+ " Instruction list vs CFG size mismatch." );
1678
+
1679
+ // compute SCCs
1680
+ std::vector<node_indext> node_to_scc (cfg.size (), -1 );
1681
+ auto nof_sccs = cfg.SCCs (node_to_scc);
1682
+
1683
+ // compute size of each SCC
1684
+ std::vector<int > scc_size (nof_sccs, 0 );
1685
+ for (auto scc : node_to_scc)
1686
+ {
1687
+ INVARIANT (
1688
+ 0 <= scc && scc < nof_sccs, " Could not determine SCC for instruction" );
1689
+ scc_size[scc]++;
1690
+ }
1691
+
1692
+ // check they are all of size 1
1693
+ for (size_t scc_id = 0 ; scc_id < nof_sccs; scc_id++)
1694
+ {
1695
+ auto size = scc_size[scc_id];
1696
+ if (size > 1 )
1697
+ {
1698
+ log.error () << " Found CFG SCC with size " << size << messaget::eom;
1699
+ for (const auto &node_id : node_to_scc)
1700
+ {
1701
+ if (node_to_scc[node_id] == scc_id)
1702
+ {
1703
+ const auto &pc = cfg[node_id].PC ;
1704
+ goto_program.output_instruction (ns, " " , log.error (), *pc);
1705
+ log.error () << messaget::eom;
1706
+ }
1707
+ }
1708
+ return false ;
1709
+ }
1710
+ }
1711
+ return true ;
1712
+ }
0 commit comments