@@ -677,4 +677,145 @@ inline popcount_exprt &to_popcount_expr(exprt &expr)
677677 return ret;
678678}
679679
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+
680821#endif // CPROVER_UTIL_BITVECTOR_EXPR_H
0 commit comments