@@ -586,143 +586,159 @@ optionalt<cext> cegis_verifiert::verify()
586
586
}
587
587
588
588
properties = checker->get_properties ();
589
- // Find the violation and construct counterexample from its trace.
590
- for (const auto &property_it : properties)
589
+ bool target_violation_found = false ;
590
+ auto target_violation_info = properties.begin ()->second ;
591
+
592
+ // Find target violation---the violation we want to fix next.
593
+ // A target violation is an assignable violation or the first violation that
594
+ // is not assignable violation.
595
+ for (const auto &property : properties)
591
596
{
592
- if (property_it .second .status != property_statust::FAIL)
597
+ if (property .second .status != property_statust::FAIL)
593
598
continue ;
594
599
595
- // Store the violation that we want to fix with synthesized
596
- // assigns/invariant.
597
- first_violation = property_it.first ;
598
-
599
- // Type of the violation
600
- cext::violation_typet violation_type = cext::violation_typet::cex_other;
601
-
602
- // Decide the violation type from the description of violation
603
-
604
- // The violation is a pointer OOB check.
605
- if ((property_it.second .description .find (
606
- " dereference failure: pointer outside object bounds in" ) !=
607
- std::string::npos))
600
+ // assignable violation found
601
+ if (property.second .description .find (" assignable" ) != std::string::npos)
608
602
{
609
- violation_type = cext::violation_typet::cex_out_of_boundary;
610
- }
611
-
612
- // The violation is a null pointer check.
613
- if (property_it.second .description .find (" pointer NULL" ) != std::string::npos)
614
- {
615
- violation_type = cext::violation_typet::cex_null_pointer;
603
+ target_violation = property.first ;
604
+ target_violation_info = property.second ;
605
+ break ;
616
606
}
617
607
618
- // The violation is a loop-invariant-preservation check.
619
- if (property_it.second .description .find (" preserved" ) != std::string::npos)
608
+ // Store the violation that we want to fix with synthesized
609
+ // assigns/invariant.
610
+ if (!target_violation_found)
620
611
{
621
- violation_type = cext::violation_typet::cex_not_preserved;
612
+ target_violation = property.first ;
613
+ target_violation_info = property.second ;
614
+ target_violation_found = true ;
622
615
}
616
+ }
623
617
624
- // The violation is a loop-invariant-preservation check.
625
- if (
626
- property_it.second .description .find (" invariant before entry" ) !=
627
- std::string::npos)
628
- {
629
- violation_type = cext::violation_typet::cex_not_hold_upon_entry;
630
- }
618
+ // Construct counterexample from first violation's trace.
619
+ // Type of the violation
620
+ cext::violation_typet violation_type = cext::violation_typet::cex_other;
631
621
632
- // The violation is an assignable check.
633
- if (property_it.second .description .find (" assignable" ) != std::string::npos)
634
- {
635
- violation_type = cext::violation_typet::cex_assignable;
636
- }
622
+ // Decide the violation type from the description of violation
637
623
638
- // Compute the cause loop---the loop for which we synthesize loop contracts,
639
- // and the counterexample.
624
+ // The violation is a pointer OOB check.
625
+ if ((target_violation_info.description .find (
626
+ " dereference failure: pointer outside object bounds in" ) !=
627
+ std::string::npos))
628
+ {
629
+ violation_type = cext::violation_typet::cex_out_of_boundary;
630
+ }
640
631
641
- // If the violation is an assignable check, we synthesize assigns targets.
642
- // In the case, cause loops are all loops the violation is in. We keep
643
- // adding the new assigns target to the most-inner loop that does not
644
- // contain the new target until the assignable violation is resolved.
632
+ // The violation is a null pointer check.
633
+ if (
634
+ target_violation_info.description .find (" pointer NULL" ) != std::string::npos)
635
+ {
636
+ violation_type = cext::violation_typet::cex_null_pointer;
637
+ }
645
638
646
- // For other cases, we synthesize loop invariant clauses. We synthesize
647
- // invariants for one loop at a time. So we return only the first cause loop
648
- // although there can be multiple ones.
639
+ // The violation is a loop-invariant-preservation check.
640
+ if (target_violation_info.description .find (" preserved" ) != std::string::npos)
641
+ {
642
+ violation_type = cext::violation_typet::cex_not_preserved;
643
+ }
649
644
650
- log.debug () << " Start to compute cause loop ids." << messaget::eom;
645
+ // The violation is a loop-invariant-preservation check.
646
+ if (
647
+ target_violation_info.description .find (" invariant before entry" ) !=
648
+ std::string::npos)
649
+ {
650
+ violation_type = cext::violation_typet::cex_not_hold_upon_entry;
651
+ }
651
652
652
- const auto &trace = checker->get_traces ()[property_it.first ];
653
+ // The violation is an assignable check.
654
+ if (target_violation_info.description .find (" assignable" ) != std::string::npos)
655
+ {
656
+ violation_type = cext::violation_typet::cex_assignable;
657
+ }
653
658
654
- // Doing assigns-synthesis or invariant-synthesis
655
- if (violation_type == cext::violation_typet::cex_assignable)
656
- {
657
- cext result (violation_type);
658
- result.cause_loop_ids = get_cause_loop_id_for_assigns (trace);
659
- result.checked_pointer = static_cast <const exprt &>(
660
- property_it.second .pc ->condition ().find (ID_checked_assigns));
661
- restore_functions ();
662
- return result;
663
- }
659
+ // Compute the cause loop---the loop for which we synthesize loop contracts,
660
+ // and the counterexample.
664
661
665
- // We construct the full counterexample only for violations other than
666
- // assignable checks.
662
+ // If the violation is an assignable check, we synthesize assigns targets.
663
+ // In the case, cause loops are all loops the violation is in. We keep
664
+ // adding the new assigns target to the most-inner loop that does not
665
+ // contain the new target until the assignable violation is resolved.
667
666
668
- // Although there can be multiple cause loop ids. We only synthesize
669
- // loop invariants for the first cause loop.
670
- const std::list<loop_idt> cause_loop_ids =
671
- get_cause_loop_id (trace, property_it.second .pc );
667
+ // For other cases, we synthesize loop invariant clauses. We synthesize
668
+ // invariants for one loop at a time. So we return only the first cause loop
669
+ // although there can be multiple ones.
672
670
673
- if (cause_loop_ids.empty ())
674
- {
675
- log.debug () << " No cause loop found!" << messaget::eom;
676
- restore_functions ();
671
+ log.debug () << " Start to compute cause loop ids." << messaget::eom;
677
672
678
- return cext (violation_type);
679
- }
673
+ const auto &trace = checker->get_traces ()[target_violation];
674
+ // Doing assigns-synthesis or invariant-synthesis
675
+ if (violation_type == cext::violation_typet::cex_assignable)
676
+ {
677
+ cext result (violation_type);
678
+ result.cause_loop_ids = get_cause_loop_id_for_assigns (trace);
679
+ result.checked_pointer = static_cast <const exprt &>(
680
+ target_violation_info.pc ->condition ().find (ID_checked_assigns));
681
+ restore_functions ();
682
+ return result;
683
+ }
680
684
681
- log.debug () << " Found cause loop with function id: "
682
- << cause_loop_ids.front ().function_id
683
- << " , and loop number: " << cause_loop_ids.front ().loop_number
684
- << messaget::eom;
685
+ // We construct the full counterexample only for violations other than
686
+ // assignable checks.
685
687
686
- auto violation_location = cext::violation_locationt::in_loop;
687
- // We always strengthen in_clause if the violation is
688
- // invariant-not-preserved.
689
- if (violation_type != cext::violation_typet::cex_not_preserved)
690
- {
691
- // Get the location of the violation
692
- violation_location = get_violation_location (
693
- cause_loop_ids.front (),
694
- goto_model.get_goto_function (cause_loop_ids.front ().function_id ),
695
- property_it.second .pc ->location_number );
696
- }
688
+ // Although there can be multiple cause loop ids. We only synthesize
689
+ // loop invariants for the first cause loop.
690
+ const std::list<loop_idt> cause_loop_ids =
691
+ get_cause_loop_id (trace, target_violation_info.pc );
697
692
693
+ if (cause_loop_ids.empty ())
694
+ {
695
+ log.debug () << " No cause loop found!" << messaget::eom;
698
696
restore_functions ();
699
697
700
- auto return_cex = build_cex (
701
- trace,
702
- get_loop_head (
703
- cause_loop_ids.front ().loop_number ,
704
- goto_model.goto_functions
705
- .function_map [cause_loop_ids.front ().function_id ])
706
- ->source_location ());
707
- return_cex.violated_predicate = property_it.second .pc ->condition ();
708
- return_cex.cause_loop_ids = cause_loop_ids;
709
- return_cex.violation_location = violation_location;
710
- return_cex.violation_type = violation_type;
711
-
712
- // The pointer checked in the null-pointer-check violation.
713
- if (violation_type == cext::violation_typet::cex_null_pointer)
714
- {
715
- return_cex.checked_pointer = property_it.second .pc ->condition ()
716
- .operands ()[0 ]
717
- .operands ()[1 ]
718
- .operands ()[0 ];
719
- INVARIANT (
720
- return_cex.checked_pointer .id () == ID_symbol,
721
- " Checking pointer symbol" );
722
- }
698
+ return cext (violation_type);
699
+ }
723
700
724
- return return_cex;
701
+ log.debug () << " Found cause loop with function id: "
702
+ << cause_loop_ids.front ().function_id
703
+ << " , and loop number: " << cause_loop_ids.front ().loop_number
704
+ << messaget::eom;
705
+
706
+ auto violation_location = cext::violation_locationt::in_loop;
707
+ // We always strengthen in_clause if the violation is
708
+ // invariant-not-preserved.
709
+ if (violation_type != cext::violation_typet::cex_not_preserved)
710
+ {
711
+ // Get the location of the violation
712
+ violation_location = get_violation_location (
713
+ cause_loop_ids.front (),
714
+ goto_model.get_goto_function (cause_loop_ids.front ().function_id ),
715
+ target_violation_info.pc ->location_number );
716
+ }
717
+
718
+ restore_functions ();
719
+
720
+ auto return_cex = build_cex (
721
+ trace,
722
+ get_loop_head (
723
+ cause_loop_ids.front ().loop_number ,
724
+ goto_model.goto_functions
725
+ .function_map [cause_loop_ids.front ().function_id ])
726
+ ->source_location ());
727
+ return_cex.violated_predicate = target_violation_info.pc ->condition ();
728
+ return_cex.cause_loop_ids = cause_loop_ids;
729
+ return_cex.violation_location = violation_location;
730
+ return_cex.violation_type = violation_type;
731
+
732
+ // The pointer checked in the null-pointer-check violation.
733
+ if (violation_type == cext::violation_typet::cex_null_pointer)
734
+ {
735
+ return_cex.checked_pointer = target_violation_info.pc ->condition ()
736
+ .operands ()[0 ]
737
+ .operands ()[1 ]
738
+ .operands ()[0 ];
739
+ INVARIANT (
740
+ return_cex.checked_pointer .id () == ID_symbol, " Checking pointer symbol" );
725
741
}
726
742
727
- UNREACHABLE ;
743
+ return return_cex ;
728
744
}
0 commit comments