let do_cast ~with_alarms t expr =
  let treat inttype =
    match inttype with
    | TInt(kind,_) ->
        let size = Int.of_int (bitsSizeOf inttype) in
        let signed = isSigned kind in
        V.cast ~with_alarms ~signed ~size expr
    | TFloat (FFloat,_) ->
        let addresses, overflow, res = V.cast_float expr in
        if addresses
        then Value_parameters.warning ~current:true ~once:true
          "addresses in float";
        if overflow then Value_parameters.warning ~current:true ~once:true
          "overflow in float: %a -> %a. assert(Ook)"
          V.pretty expr V.pretty res;
        res
    | TFloat (FDouble,_) ->
      expr
    | TFloat (FLongDouble,_) ->
      expr
    | _ -> assert false
  in
  match unrollType t with
  | TInt _ | TFloat _  as t' ->
      treat t'
  | TPtr _ ->
      treat theMachine.upointType
  | TEnum _ ->
      if theMachine.enum_are_signed then
        treat (TInt(IInt,[]))
      else treat (TInt(IUInt,[]))
  | TComp _ -> expr (* see test [struct_call.c] *)
  | TBuiltin_va_list _ ->
      (match with_alarms.CilE.imprecision_tracing with
       | CilE.Aignore -> ()
       | CilE.Acall f -> f ()
       | CilE.Alog ->
           Value_parameters.warning ~once:true ~current:true
             "cast to __builtin_va_list is not precisely implemented yet");
      V.topify_arith_origin expr
  | TFun _ -> expr
  | TNamed _ -> assert false
  | TVoid _ -> assert false
  | TArray _ -> assert false