@@ -1115,6 +1115,63 @@ inline is_cstring_exprt &to_is_cstring_expr(exprt &expr)
11151115 return ret;
11161116}
11171117
1118+ // / An expression, akin to ISO C's strlen, that denotes the
1119+ // / length of a zero-terminated string that starts at the
1120+ // / given address. The trailing zero is not included in the count.
1121+ class cstrlen_exprt : public unary_exprt
1122+ {
1123+ public:
1124+ cstrlen_exprt (exprt address, typet type)
1125+ : unary_exprt(ID_cstrlen, std::move(address), std::move(type))
1126+ {
1127+ PRECONDITION (as_const (*this ).address ().type ().id () == ID_pointer);
1128+ }
1129+
1130+ exprt &address ()
1131+ {
1132+ return op0 ();
1133+ }
1134+
1135+ const exprt &address () const
1136+ {
1137+ return op0 ();
1138+ }
1139+ };
1140+
1141+ template <>
1142+ inline bool can_cast_expr<cstrlen_exprt>(const exprt &base)
1143+ {
1144+ return base.id () == ID_cstrlen;
1145+ }
1146+
1147+ inline void validate_expr (const cstrlen_exprt &value)
1148+ {
1149+ validate_operands (value, 1 , " cstrlen must have one operand" );
1150+ }
1151+
1152+ // / \brief Cast an exprt to a \ref cstrlen_exprt
1153+ // /
1154+ // / \a expr must be known to be \ref cstrlen_exprt.
1155+ // /
1156+ // / \param expr: Source expression
1157+ // / \return Object of type \ref cstrlen_exprt
1158+ inline const cstrlen_exprt &to_cstrlen_expr (const exprt &expr)
1159+ {
1160+ PRECONDITION (expr.id () == ID_cstrlen);
1161+ const cstrlen_exprt &ret = static_cast <const cstrlen_exprt &>(expr);
1162+ validate_expr (ret);
1163+ return ret;
1164+ }
1165+
1166+ // / \copydoc to_cstrlen_expr(const exprt &)
1167+ inline cstrlen_exprt &to_cstrlen_expr (exprt &expr)
1168+ {
1169+ PRECONDITION (expr.id () == ID_cstrlen);
1170+ cstrlen_exprt &ret = static_cast <cstrlen_exprt &>(expr);
1171+ validate_expr (ret);
1172+ return ret;
1173+ }
1174+
11181175// / A predicate that indicates that the object pointed to is live
11191176class live_object_exprt : public unary_predicate_exprt
11201177{
0 commit comments