@@ -873,4 +873,62 @@ to_annotated_pointer_constant_expr(exprt &expr)
873873 return ret;
874874}
875875
876+ // / The offset (in bytes) of a pointer relative to the object
877+ class pointer_offset_exprt : public unary_exprt
878+ {
879+ public:
880+ explicit pointer_offset_exprt (exprt pointer, typet type)
881+ : unary_exprt(ID_pointer_offset, std::move(pointer), std::move(type))
882+ {
883+ }
884+
885+ exprt &pointer ()
886+ {
887+ return op0 ();
888+ }
889+
890+ const exprt &pointer () const
891+ {
892+ return op0 ();
893+ }
894+ };
895+
896+ template <>
897+ inline bool can_cast_expr<pointer_offset_exprt>(const exprt &base)
898+ {
899+ return base.id () == ID_pointer_offset;
900+ }
901+
902+ inline void validate_expr (const pointer_offset_exprt &value)
903+ {
904+ validate_operands (value, 1 , " pointer_offset must have one operand" );
905+ DATA_INVARIANT (
906+ value.pointer ().type ().id () == ID_pointer,
907+ " pointer_offset must have pointer-typed operand" );
908+ }
909+
910+ // / \brief Cast an exprt to a \ref pointer_offset_exprt
911+ // /
912+ // / \a expr must be known to be \ref pointer_offset_exprt.
913+ // /
914+ // / \param expr: Source expression
915+ // / \return Object of type \ref pointer_offset_exprt
916+ inline const pointer_offset_exprt &to_pointer_offset_expr (const exprt &expr)
917+ {
918+ PRECONDITION (expr.id () == ID_pointer_offset);
919+ const pointer_offset_exprt &ret =
920+ static_cast <const pointer_offset_exprt &>(expr);
921+ validate_expr (ret);
922+ return ret;
923+ }
924+
925+ // / \copydoc to_pointer_offset_expr(const exprt &)
926+ inline pointer_offset_exprt &to_pointer_offset_expr (exprt &expr)
927+ {
928+ PRECONDITION (expr.id () == ID_pointer_offset);
929+ pointer_offset_exprt &ret = static_cast <pointer_offset_exprt &>(expr);
930+ validate_expr (ret);
931+ return ret;
932+ }
933+
876934#endif // CPROVER_UTIL_POINTER_EXPR_H
0 commit comments