let translate_C_expr_to_term ?(cast=true) expr =
  (* if cast is true, the term should have the type of expr (which is a C type) *)
  (* otherwise, the term should have type integer
     (or real if the C type of expr if not a subtype of integer: TODO) *)

  let e_typ = Cil.typeOf expr in
  let aterm = Logic_utils.expr_to_term ~cast:false expr in
  let term =
    if cast then
      begin
        (* expr_to_term_with_cast expr *)
        (* not used since it adds casts everywhere (not pretty):
           since sub-expressions are also checked for annotation,
           might as well cast only top expression *)

        match aterm.term_node with
          | TCastE(_,_) -> (* no point in recasting *) aterm
          | TConst _    -> (* constants are not cast,
                              though in some cases they should (big const) *)
 aterm
          | TLval _     -> aterm
          | _           ->
              if (Cil.isIntegralType e_typ || Cil.isFloatingType e_typ)
              then
                Logic_const.term
                  (TCastE
                     (e_typ,
                      Logic_const.term
                        aterm.term_node
                        (Logic_utils.typ_to_logic_type e_typ))) (Ctype e_typ)
              else aterm
      end
    else aterm
  in
(*
    debug ~level:2
      "input expr: %a (%a)\n" Cil.d_exp expr Cil.d_type (Cil.typeOf expr)
    ;
    let t1,t2 = expr_to_term ~cast:false expr, expr_to_term ~cast:true expr
    in
      debug ~level:2
        "output integer term: %a (%a)\n" Cil.d_term t1 Cil.d_logic_type t1.term_type
      ;
      debug ~level:2
        "output (C cast) term: %a (%a)\n" Cil.d_term t2 Cil.d_logic_type t2.term_type
      ;
*)

      term