@@ -329,7 +329,7 @@ static struct contract_clausest default_loop_contract_clauses(
329
329
const dfcc_loop_nesting_grapht &loop_nesting_graph,
330
330
const std::size_t loop_id,
331
331
const irep_idt &function_id,
332
- local_may_aliast &local_may_alias ,
332
+ const assignst &inferred_assigns ,
333
333
const bool check_side_effect,
334
334
message_handlert &message_handler,
335
335
const namespacet &ns)
@@ -380,13 +380,11 @@ static struct contract_clausest default_loop_contract_clauses(
380
380
else
381
381
{
382
382
// infer assigns clause targets if none given
383
- auto inferred = dfcc_infer_loop_assigns (
384
- local_may_alias, loop.instructions , loop.head ->source_location (), ns);
385
383
log .warning () << " No assigns clause provided for loop " << function_id
386
384
<< " ." << loop.latch ->loop_number << " at "
387
385
<< loop.head ->source_location () << " . The inferred set {" ;
388
386
bool first = true ;
389
- for (const auto &expr : inferred )
387
+ for (const auto &expr : inferred_assigns )
390
388
{
391
389
if (!first)
392
390
{
@@ -398,7 +396,7 @@ static struct contract_clausest default_loop_contract_clauses(
398
396
log .warning () << " } might be incomplete or imprecise, please provide an "
399
397
" assigns clause if the analysis fails."
400
398
<< messaget::eom;
401
- result.assigns . swap (inferred) ;
399
+ result.assigns = inferred_assigns ;
402
400
}
403
401
404
402
if (result.decreases_clauses .empty ())
@@ -416,14 +414,16 @@ static dfcc_loop_infot gen_dfcc_loop_info(
416
414
const dfcc_loop_nesting_grapht &loop_nesting_graph,
417
415
const std::size_t loop_id,
418
416
const irep_idt &function_id,
417
+ goto_functiont &goto_function,
419
418
const std::map<std::size_t , dfcc_loop_infot> &loop_info_map,
420
419
dirtyt &dirty,
421
- local_may_aliast &local_may_alias ,
420
+ const assignst &inferred_assigns ,
422
421
const bool check_side_effect,
423
422
message_handlert &message_handler,
424
423
dfcc_libraryt &library,
425
424
symbol_table_baset &symbol_table)
426
425
{
426
+ const namespacet ns (symbol_table);
427
427
std::unordered_set<irep_idt> loop_locals =
428
428
gen_loop_locals_set (loop_nesting_graph, loop_id);
429
429
@@ -433,12 +433,11 @@ static dfcc_loop_infot gen_dfcc_loop_info(
433
433
dirty,
434
434
loop_info_map);
435
435
436
- const namespacet ns (symbol_table);
437
436
struct contract_clausest contract_clauses = default_loop_contract_clauses (
438
437
loop_nesting_graph,
439
438
loop_id,
440
439
function_id,
441
- local_may_alias ,
440
+ inferred_assigns ,
442
441
check_side_effect,
443
442
message_handler,
444
443
ns);
@@ -489,6 +488,7 @@ static dfcc_loop_infot gen_dfcc_loop_info(
489
488
}
490
489
491
490
dfcc_cfg_infot::dfcc_cfg_infot (
491
+ goto_modelt &goto_model,
492
492
const irep_idt &function_id,
493
493
goto_functiont &goto_function,
494
494
const exprt &top_level_write_set,
@@ -507,6 +507,9 @@ dfcc_cfg_infot::dfcc_cfg_infot(
507
507
// Clean up possible fake loops that are due to do { ... } while(0);
508
508
simplify_gotos (goto_program, ns);
509
509
510
+ // From loop number to the inferred loop assigns.
511
+ std::map<std::size_t , assignst> inferred_loop_assigns_map;
512
+
510
513
if (loop_contract_config.apply_loop_contracts )
511
514
{
512
515
messaget log (message_handler);
@@ -527,9 +530,23 @@ dfcc_cfg_infot::dfcc_cfg_infot(
527
530
528
531
auto topsorted = loop_nesting_graph.topsort ();
529
532
533
+ bool has_loops_with_contracts = false ;
530
534
for (const auto idx : topsorted)
531
535
{
532
536
topsorted_loops.push_back (idx);
537
+ has_loops_with_contracts |= has_contract (
538
+ loop_nesting_graph[idx].latch , loop_contract_config.check_side_effect );
539
+ }
540
+
541
+ // We infer loop assigns for all loops in the function.
542
+ if (has_loops_with_contracts)
543
+ {
544
+ dfcc_infer_loop_assigns_for_function (
545
+ inferred_loop_assigns_map,
546
+ goto_model.goto_functions ,
547
+ goto_function,
548
+ message_handler,
549
+ ns);
533
550
}
534
551
}
535
552
@@ -549,19 +566,21 @@ dfcc_cfg_infot::dfcc_cfg_infot(
549
566
550
567
// generate dfcc_cfg_loop_info for loops and add to loop_info_map
551
568
dirtyt dirty (goto_function);
552
- local_may_aliast local_may_alias (goto_function);
553
569
554
570
for (const auto &loop_id : topsorted_loops)
555
571
{
572
+ auto inferred_loop_assigns =
573
+ inferred_loop_assigns_map[loop_nesting_graph[loop_id].latch ->loop_number ];
556
574
loop_info_map.insert (
557
575
{loop_id,
558
576
gen_dfcc_loop_info (
559
577
loop_nesting_graph,
560
578
loop_id,
561
579
function_id,
580
+ goto_function,
562
581
loop_info_map,
563
582
dirty,
564
- local_may_alias ,
583
+ inferred_loop_assigns ,
565
584
loop_contract_config.check_side_effect ,
566
585
message_handler,
567
586
library,
0 commit comments