@@ -677,4 +677,145 @@ inline popcount_exprt &to_popcount_expr(exprt &expr)
677
677
return ret;
678
678
}
679
679
680
+ // / \brief A Boolean expression returning true, iff operation \c kind would
681
+ // / result in an overflow when applied to operands \c lhs and \c rhs.
682
+ class binary_overflow_exprt : public binary_predicate_exprt
683
+ {
684
+ public:
685
+ binary_overflow_exprt (exprt _lhs, const irep_idt &kind, exprt _rhs)
686
+ : binary_predicate_exprt(
687
+ std::move (_lhs),
688
+ "overflow-" + id2string(kind),
689
+ std::move(_rhs))
690
+ {
691
+ }
692
+
693
+ static void check (
694
+ const exprt &expr,
695
+ const validation_modet vm = validation_modet::INVARIANT)
696
+ {
697
+ binary_exprt::check (expr, vm);
698
+
699
+ if (expr.id () != ID_overflow_shl)
700
+ {
701
+ const binary_exprt &binary_expr = to_binary_expr (expr);
702
+ DATA_CHECK (
703
+ vm,
704
+ binary_expr.lhs ().type () == binary_expr.rhs ().type (),
705
+ " operand types must match" );
706
+ }
707
+ }
708
+
709
+ static void validate (
710
+ const exprt &expr,
711
+ const namespacet &,
712
+ const validation_modet vm = validation_modet::INVARIANT)
713
+ {
714
+ check (expr, vm);
715
+ }
716
+ };
717
+
718
+ template <>
719
+ inline bool can_cast_expr<binary_overflow_exprt>(const exprt &base)
720
+ {
721
+ return base.id () == ID_overflow_plus || base.id () == ID_overflow_mult ||
722
+ base.id () == ID_overflow_minus || base.id () == ID_overflow_shl;
723
+ }
724
+
725
+ inline void validate_expr (const binary_overflow_exprt &value)
726
+ {
727
+ validate_operands (
728
+ value, 2 , " binary overflow expression must have two operands" );
729
+ }
730
+
731
+ // / \brief Cast an exprt to a \ref binary_overflow_exprt
732
+ // /
733
+ // / \a expr must be known to be \ref binary_overflow_exprt.
734
+ // /
735
+ // / \param expr: Source expression
736
+ // / \return Object of type \ref binary_overflow_exprt
737
+ inline const binary_overflow_exprt &to_binary_overflow_expr (const exprt &expr)
738
+ {
739
+ PRECONDITION (
740
+ expr.id () == ID_overflow_plus || expr.id () == ID_overflow_mult ||
741
+ expr.id () == ID_overflow_minus || expr.id () == ID_overflow_shl);
742
+ const binary_overflow_exprt &ret =
743
+ static_cast <const binary_overflow_exprt &>(expr);
744
+ validate_expr (ret);
745
+ return ret;
746
+ }
747
+
748
+ // / \copydoc to_binary_overflow_expr(const exprt &)
749
+ inline binary_overflow_exprt &to_binary_overflow_expr (exprt &expr)
750
+ {
751
+ PRECONDITION (
752
+ expr.id () == ID_overflow_plus || expr.id () == ID_overflow_mult ||
753
+ expr.id () == ID_overflow_minus || expr.id () == ID_overflow_shl);
754
+ binary_overflow_exprt &ret = static_cast <binary_overflow_exprt &>(expr);
755
+ validate_expr (ret);
756
+ return ret;
757
+ }
758
+
759
+ // / \brief A Boolean expression returning true, iff operation \c kind would
760
+ // / result in an overflow when applied to the (single) operand.
761
+ class unary_overflow_exprt : public unary_predicate_exprt
762
+ {
763
+ public:
764
+ unary_overflow_exprt (const irep_idt &kind, exprt _op)
765
+ : unary_predicate_exprt(" overflow-" + id2string(kind), std::move(_op))
766
+ {
767
+ }
768
+
769
+ static void check (
770
+ const exprt &expr,
771
+ const validation_modet vm = validation_modet::INVARIANT)
772
+ {
773
+ unary_exprt::check (expr, vm);
774
+ }
775
+
776
+ static void validate (
777
+ const exprt &expr,
778
+ const namespacet &,
779
+ const validation_modet vm = validation_modet::INVARIANT)
780
+ {
781
+ check (expr, vm);
782
+ }
783
+ };
784
+
785
+ template <>
786
+ inline bool can_cast_expr<unary_overflow_exprt>(const exprt &base)
787
+ {
788
+ return base.id () == ID_overflow_unary_minus;
789
+ }
790
+
791
+ inline void validate_expr (const unary_overflow_exprt &value)
792
+ {
793
+ validate_operands (
794
+ value, 1 , " unary overflow expression must have one operand" );
795
+ }
796
+
797
+ // / \brief Cast an exprt to a \ref unary_overflow_exprt
798
+ // /
799
+ // / \a expr must be known to be \ref unary_overflow_exprt.
800
+ // /
801
+ // / \param expr: Source expression
802
+ // / \return Object of type \ref unary_overflow_exprt
803
+ inline const unary_overflow_exprt &to_unary_overflow_expr (const exprt &expr)
804
+ {
805
+ PRECONDITION (expr.id () == ID_overflow_unary_minus);
806
+ const unary_overflow_exprt &ret =
807
+ static_cast <const unary_overflow_exprt &>(expr);
808
+ validate_expr (ret);
809
+ return ret;
810
+ }
811
+
812
+ // / \copydoc to_unary_overflow_expr(const exprt &)
813
+ inline unary_overflow_exprt &to_unary_overflow_expr (exprt &expr)
814
+ {
815
+ PRECONDITION (expr.id () == ID_overflow_unary_minus);
816
+ unary_overflow_exprt &ret = static_cast <unary_overflow_exprt &>(expr);
817
+ validate_expr (ret);
818
+ return ret;
819
+ }
820
+
680
821
#endif // CPROVER_UTIL_BITVECTOR_EXPR_H
0 commit comments