@@ -29,40 +29,15 @@ Date: March 2023
29
29
#include " dfcc_root_object.h"
30
30
#include " dfcc_utils.h"
31
31
32
- // / Extracts the assigns clause expression from the latch condition
33
- static const exprt::operandst &
34
- get_assigns (const goto_programt::const_targett &latch_target)
35
- {
36
- return static_cast <const exprt &>(
37
- latch_target->condition ().find (ID_C_spec_assigns))
38
- .operands ();
39
- }
40
-
41
- // / Extracts the invariant clause expression from the latch condition
42
- static const exprt::operandst &
43
- get_invariants (const goto_programt::const_targett &latch_target)
44
- {
45
- return static_cast <const exprt &>(
46
- latch_target->condition ().find (ID_C_spec_loop_invariant))
47
- .operands ();
48
- }
49
-
50
- // / Extracts the decreases clause expression from the latch condition
51
- static const exprt::operandst &
52
- get_decreases (const goto_programt::const_targett &latch_target)
53
- {
54
- return static_cast <const exprt &>(
55
- latch_target->condition ().find (ID_C_spec_decreases))
56
- .operands ();
57
- }
58
-
59
32
// / Returns true iff some contract clause expression is attached
60
33
// / to the latch condition of this loop
61
- static bool has_contract (const goto_programt::const_targett &latch_target)
34
+ static bool has_contract (
35
+ const goto_programt::const_targett &latch_target,
36
+ const bool check_side_effect)
62
37
{
63
- return ! get_assigns (latch_target).empty () ||
64
- ! get_invariants (latch_target). empty () ||
65
- ! get_decreases (latch_target). empty ();
38
+ return get_loop_assigns (latch_target).is_not_nil () ||
39
+ get_loop_invariants (latch_target, check_side_effect). is_not_nil () ||
40
+ get_loop_decreases (latch_target, check_side_effect). is_not_nil ();
66
41
}
67
42
68
43
void dfcc_loop_infot::output (std::ostream &out) const
@@ -155,16 +130,20 @@ dfcc_loop_infot::find_latch(goto_programt &goto_program) const
155
130
static std::optional<goto_programt::targett> check_has_contract_rec (
156
131
const dfcc_loop_nesting_grapht &loop_nesting_graph,
157
132
const std::size_t loop_idx,
158
- const bool must_have_contract)
133
+ const bool must_have_contract,
134
+ const bool check_side_effect)
159
135
{
160
136
const auto &node = loop_nesting_graph[loop_idx];
161
- if (must_have_contract && !has_contract (node.latch ))
137
+ if (must_have_contract && !has_contract (node.latch , check_side_effect ))
162
138
return node.head ;
163
139
164
140
for (const auto pred_idx : loop_nesting_graph.get_predecessors (loop_idx))
165
141
{
166
142
auto result = check_has_contract_rec (
167
- loop_nesting_graph, pred_idx, has_contract (node.latch ));
143
+ loop_nesting_graph,
144
+ pred_idx,
145
+ has_contract (node.latch , check_side_effect),
146
+ check_side_effect);
168
147
if (result.has_value ())
169
148
return result;
170
149
}
@@ -175,13 +154,15 @@ static std::optional<goto_programt::targett> check_has_contract_rec(
175
154
// / loops nested in loops that have contracts also have contracts.
176
155
// / Return the head of the first offending loop if it exists, nothing otherwise.
177
156
static std::optional<goto_programt::targett> check_inner_loops_have_contracts (
178
- const dfcc_loop_nesting_grapht &loop_nesting_graph)
157
+ const dfcc_loop_nesting_grapht &loop_nesting_graph,
158
+ const bool check_side_effect)
179
159
{
180
160
for (std::size_t idx = 0 ; idx < loop_nesting_graph.size (); idx++)
181
161
{
182
162
if (loop_nesting_graph.get_successors (idx).empty ())
183
163
{
184
- auto result = check_has_contract_rec (loop_nesting_graph, idx, false );
164
+ auto result = check_has_contract_rec (
165
+ loop_nesting_graph, idx, false , check_side_effect);
185
166
if (result.has_value ())
186
167
return result;
187
168
}
@@ -349,18 +330,21 @@ static struct contract_clausest default_loop_contract_clauses(
349
330
const std::size_t loop_id,
350
331
const irep_idt &function_id,
351
332
local_may_aliast &local_may_alias,
333
+ const bool check_side_effect,
352
334
message_handlert &message_handler,
353
335
const namespacet &ns)
354
336
{
355
337
messaget log (message_handler);
356
338
const auto &loop = loop_nesting_graph[loop_id];
357
339
358
340
// Process loop contract clauses
359
- exprt::operandst invariant_clauses = get_invariants (loop.latch );
360
- exprt::operandst assigns_clauses = get_assigns (loop.latch );
341
+ exprt::operandst invariant_clauses =
342
+ get_loop_invariants (loop.latch , check_side_effect).operands ();
343
+ exprt::operandst assigns_clauses = get_loop_assigns (loop.latch ).operands ();
361
344
362
345
// Initialise defaults
363
- struct contract_clausest result (get_decreases(loop.latch));
346
+ struct contract_clausest result (
347
+ get_loop_decreases (loop.latch, check_side_effect).operands());
364
348
365
349
// Generate defaults for all clauses if at least one type of clause is defined
366
350
if (
@@ -435,6 +419,7 @@ static dfcc_loop_infot gen_dfcc_loop_info(
435
419
const std::map<std::size_t , dfcc_loop_infot> &loop_info_map,
436
420
dirtyt &dirty,
437
421
local_may_aliast &local_may_alias,
422
+ const bool check_side_effect,
438
423
message_handlert &message_handler,
439
424
dfcc_libraryt &library,
440
425
symbol_table_baset &symbol_table)
@@ -454,6 +439,7 @@ static dfcc_loop_infot gen_dfcc_loop_info(
454
439
loop_id,
455
440
function_id,
456
441
local_may_alias,
442
+ check_side_effect,
457
443
message_handler,
458
444
ns);
459
445
@@ -523,7 +509,8 @@ dfcc_cfg_infot::dfcc_cfg_infot(
523
509
dfcc_check_loop_normal_form (goto_program, log );
524
510
loop_nesting_graph = build_loop_nesting_graph (goto_program);
525
511
526
- const auto head = check_inner_loops_have_contracts (loop_nesting_graph);
512
+ const auto head = check_inner_loops_have_contracts (
513
+ loop_nesting_graph, loop_contract_config.check_side_effect );
527
514
if (head.has_value ())
528
515
{
529
516
throw invalid_source_file_exceptiont (
@@ -571,6 +558,7 @@ dfcc_cfg_infot::dfcc_cfg_infot(
571
558
loop_info_map,
572
559
dirty,
573
560
local_may_alias,
561
+ loop_contract_config.check_side_effect ,
574
562
message_handler,
575
563
library,
576
564
symbol_table)});
0 commit comments