@@ -329,7 +329,7 @@ static struct contract_clausest default_loop_contract_clauses(
329329 const dfcc_loop_nesting_grapht &loop_nesting_graph,
330330 const std::size_t loop_id,
331331 const irep_idt &function_id,
332- local_may_aliast &local_may_alias ,
332+ const assignst &inferred_assigns ,
333333 const bool check_side_effect,
334334 message_handlert &message_handler,
335335 const namespacet &ns)
@@ -380,13 +380,11 @@ static struct contract_clausest default_loop_contract_clauses(
380380 else
381381 {
382382 // 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);
385383 log.warning () << " No assigns clause provided for loop " << function_id
386384 << " ." << loop.latch ->loop_number << " at "
387385 << loop.head ->source_location () << " . The inferred set {" ;
388386 bool first = true ;
389- for (const auto &expr : inferred )
387+ for (const auto &expr : inferred_assigns )
390388 {
391389 if (!first)
392390 {
@@ -398,7 +396,7 @@ static struct contract_clausest default_loop_contract_clauses(
398396 log.warning () << " } might be incomplete or imprecise, please provide an "
399397 " assigns clause if the analysis fails."
400398 << messaget::eom;
401- result.assigns . swap (inferred) ;
399+ result.assigns = inferred_assigns ;
402400 }
403401
404402 if (result.decreases_clauses .empty ())
@@ -416,14 +414,16 @@ static dfcc_loop_infot gen_dfcc_loop_info(
416414 const dfcc_loop_nesting_grapht &loop_nesting_graph,
417415 const std::size_t loop_id,
418416 const irep_idt &function_id,
417+ goto_functiont &goto_function,
419418 const std::map<std::size_t , dfcc_loop_infot> &loop_info_map,
420419 dirtyt &dirty,
421- local_may_aliast &local_may_alias ,
420+ const assignst &inferred_assigns ,
422421 const bool check_side_effect,
423422 message_handlert &message_handler,
424423 dfcc_libraryt &library,
425424 symbol_table_baset &symbol_table)
426425{
426+ const namespacet ns (symbol_table);
427427 std::unordered_set<irep_idt> loop_locals =
428428 gen_loop_locals_set (loop_nesting_graph, loop_id);
429429
@@ -433,12 +433,11 @@ static dfcc_loop_infot gen_dfcc_loop_info(
433433 dirty,
434434 loop_info_map);
435435
436- const namespacet ns (symbol_table);
437436 struct contract_clausest contract_clauses = default_loop_contract_clauses (
438437 loop_nesting_graph,
439438 loop_id,
440439 function_id,
441- local_may_alias ,
440+ inferred_assigns ,
442441 check_side_effect,
443442 message_handler,
444443 ns);
@@ -489,6 +488,7 @@ static dfcc_loop_infot gen_dfcc_loop_info(
489488}
490489
491490dfcc_cfg_infot::dfcc_cfg_infot (
491+ goto_modelt &goto_model,
492492 const irep_idt &function_id,
493493 goto_functiont &goto_function,
494494 const exprt &top_level_write_set,
@@ -507,6 +507,9 @@ dfcc_cfg_infot::dfcc_cfg_infot(
507507 // Clean up possible fake loops that are due to do { ... } while(0);
508508 simplify_gotos (goto_program, ns);
509509
510+ // From loop number to the inferred loop assigns.
511+ std::map<std::size_t , assignst> inferred_loop_assigns_map;
512+
510513 if (loop_contract_config.apply_loop_contracts )
511514 {
512515 messaget log (message_handler);
@@ -527,9 +530,23 @@ dfcc_cfg_infot::dfcc_cfg_infot(
527530
528531 auto topsorted = loop_nesting_graph.topsort ();
529532
533+ bool has_loops_with_contracts = false ;
530534 for (const auto idx : topsorted)
531535 {
532536 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);
533550 }
534551 }
535552
@@ -549,19 +566,21 @@ dfcc_cfg_infot::dfcc_cfg_infot(
549566
550567 // generate dfcc_cfg_loop_info for loops and add to loop_info_map
551568 dirtyt dirty (goto_function);
552- local_may_aliast local_may_alias (goto_function);
553569
554570 for (const auto &loop_id : topsorted_loops)
555571 {
572+ auto inferred_loop_assigns =
573+ inferred_loop_assigns_map[loop_nesting_graph[loop_id].latch ->loop_number ];
556574 loop_info_map.insert (
557575 {loop_id,
558576 gen_dfcc_loop_info (
559577 loop_nesting_graph,
560578 loop_id,
561579 function_id,
580+ goto_function,
562581 loop_info_map,
563582 dirty,
564- local_may_alias ,
583+ inferred_loop_assigns ,
565584 loop_contract_config.check_side_effect ,
566585 message_handler,
567586 library,
0 commit comments