@@ -668,6 +668,91 @@ bool goto_programt::instructiont::equals(const instructiont &other) const
668
668
// clang-format on
669
669
}
670
670
671
+ void goto_programt::instructiont::validate (
672
+ const namespacet &ns,
673
+ const validation_modet vm) const
674
+ {
675
+ validate_code_full_pick (code, ns, vm);
676
+ validate_expr_full_pick (guard, ns, vm);
677
+
678
+ auto evaluates_to_boolean = [](const exprt &e) -> bool {
679
+ // typecast to Boolean
680
+ if (e.id () == ID_typecast)
681
+ return e.type ().id () == ID_bool;
682
+
683
+ // Boolean constants
684
+ if (e.id () == ID_true || e.id () == ID_false)
685
+ return true ;
686
+ if (e.id () == ID_constant && e.type ().id () == ID_bool)
687
+ return true ;
688
+
689
+ // Symbols
690
+ if (e.id () == ID_symbol)
691
+ {
692
+ if (e.type ().id () == ID_code) // function call
693
+ return to_code_type (e.type ()).return_type ().id () == ID_bool;
694
+ else // Boolean variable
695
+ return e.type ().id () == ID_bool;
696
+ }
697
+
698
+ // arithmetic relations
699
+ if (e.id () == ID_equal || e.id () == ID_notequal)
700
+ return true ;
701
+ if (e.id () == ID_ieee_float_equal || e.id () == ID_ieee_float_notequal)
702
+ return true ;
703
+ if (e.id () == ID_ge || e.id () == ID_gt)
704
+ return true ;
705
+ if (e.id () == ID_le || e.id () == ID_lt)
706
+ return true ;
707
+
708
+ // propositional operators
709
+ if (
710
+ e.id () == ID_not || e.id () == ID_and || e.id () == ID_or ||
711
+ e.id () == ID_implies)
712
+ return true ;
713
+ if (e.id () == ID_exists || e.id () == ID_forall)
714
+ return true ;
715
+
716
+ // weird
717
+ if (
718
+ e.id () == ID_isfinite || e.id () == ID_isnormal || e.id () == ID_isinf ||
719
+ e.id () == ID_isnan)
720
+ return true ;
721
+
722
+ return false ;
723
+ };
724
+
725
+ switch (type)
726
+ {
727
+ case ASSIGN:
728
+ DATA_CHECK (
729
+ code.get_statement () == ID_assign,
730
+ " assign instruction should contain an assign statement" );
731
+ DATA_CHECK (targets.empty (), " assign instruction should not have a target" );
732
+ break ;
733
+ case ASSUME:
734
+ DATA_CHECK_WITH_DIAGNOSTICS (
735
+ targets.empty (),
736
+ " assume instruction should not have a target" ,
737
+ source_location);
738
+ DATA_CHECK_WITH_DIAGNOSTICS (
739
+ evaluates_to_boolean (guard),
740
+ " assuming non-boolean condition\n " + guard.pretty (),
741
+ source_location);
742
+ case ASSERT:
743
+ DATA_CHECK_WITH_DIAGNOSTICS (
744
+ targets.empty (),
745
+ " assert instruction should not have a target" ,
746
+ source_location);
747
+ DATA_CHECK_WITH_DIAGNOSTICS (
748
+ evaluates_to_boolean (guard),
749
+ " asserting non-boolean condition\n " + guard.pretty (),
750
+ source_location);
751
+ default :
752
+ break ;
753
+ }
754
+ }
755
+
671
756
bool goto_programt::equals (const goto_programt &other) const
672
757
{
673
758
if (instructions.size () != other.instructions .size ())
0 commit comments