let cast ~with_alarms ~size ~signed expr =
    try
      let i = project_ival expr in
        inject_ival (Ival.cast ~size ~signed ~value:i)
    with
      | Not_based_on_null ->
          if Int.compare size (Int.of_int (Bit_utils.sizeofpointer ())) >= 0
            || (match expr with Top _ -> true | _ -> false)
          then expr
          else begin
             if is_bottom expr || is_imprecise expr then expr
             else begin
                       (match with_alarms.imprecision_tracing with
                 | Aignore -> ()
                 | Acall f -> f ()
                 | Alog -> CilE.warn_once
                     "casting address to a type smaller than sizeof(void*): @[%a@]"
                       Location_Bytes.pretty expr);
               topify_arith_origin expr
             end
          end