diff --git a/src/plugins/e-acsl/src/analyses/typing.ml b/src/plugins/e-acsl/src/analyses/typing.ml
index 83e9a80da29b0d96972a8a25e8668cb0ac2ad65e..88a168eb010bc49502d7fa635c930a9e3f5092fa 100644
--- a/src/plugins/e-acsl/src/analyses/typing.ml
+++ b/src/plugins/e-acsl/src/analyses/typing.ml
@@ -116,7 +116,6 @@ let typ_of_lty = function
 
 type computed_info =
   { ty: Number_ty.t;  (* type required for the term *)
-    op: Number_ty.t; (* type required for the operation *)
     cast: Number_ty.t option; (* if not [None], type of the context which the term
                                  must be casted to. If [None], no cast needed. *)
   }
@@ -252,19 +251,19 @@ let ty_of_interv ?ctx ?(use_gmp_opt = false) = function
 
 (* compute a new {!computed_info} by coercing the given type [ty] to the given
    context [ctx]. [op] is the type for the operator. *)
-let coerce ~arith_operand ~ctx ~op ty =
+let coerce ~arith_operand ~ctx ty =
   if Number_ty.compare ty ctx = 1 then
     (* type larger than the expected context,
        so we must introduce an explicit cast *)
-    { ty; op; cast = Some ctx }
+    { ty; cast = Some ctx }
   else
     (* only add an explicit cast if the context is [Gmp] and [ty] is not;
        or if the term corresponding to [ty] is an operand of an arithmetic
        operation which must be explicitly coerced in order to force the
        operation to be of the expected type. *)
   if (ctx = Gmpz && ty <> Gmpz) || arith_operand
-  then { ty; op; cast = Some ctx }
-  else { ty; op; cast = None }
+  then { ty; cast = Some ctx }
+  else { ty; cast = None }
 
 let number_ty_of_typ ~post ty =
   (* Consider GMP types only in a post typing phase *)
@@ -346,7 +345,6 @@ let rec type_term
     ~profile
     t =
   let ctx = Option.map (mk_ctx ~use_gmp_opt) ctx in
-  let dup ty = ty, ty in
   let compute_ctx ?ctx i =
     (* in order to get a minimal amount of generated casts for operators, the
        result is typed in the given context [ctx], but not the operands.
@@ -354,7 +352,8 @@ let rec type_term
     match ctx with
     | None ->
       (* no context: factorize *)
-      dup (mk_ctx ~use_gmp_opt:true (ty_of_interv i))
+      let ctx =  mk_ctx ~use_gmp_opt:true (ty_of_interv i) in
+      ctx, ctx
     | Some ctx ->
       mk_ctx ~use_gmp_opt:true (ty_of_interv ~ctx i),
       mk_ctx ~use_gmp_opt:true (ty_of_interv i)
@@ -372,19 +371,16 @@ let rec type_term
       let i = Interval.get_from_profile ~profile t in
       (* a constant or a left value directly under a lambda should be a gmp
          if the infered context for the lambda is gmp *)
-      let ty = ty_of_interv ?ctx ~use_gmp_opt:under_lambda i in
-      dup ty
+      ty_of_interv ?ctx ~use_gmp_opt:under_lambda i
 
     | TLval ((TVar {lv_type = Ctype (TInt (ik, _))}, _) as tlv) ->
       type_term_lval ~profile tlv;
-      dup (C_integer ik)
+      C_integer ik
 
     | TLval tlv ->
       let i = Interval.get_from_profile ~profile t in
-      let ty = ty_of_interv ?ctx ~use_gmp_opt:under_lambda i in
       type_term_lval ~profile tlv;
-      (* Options.feedback "Type : %a" D.pretty ty; *)
-      dup ty
+      ty_of_interv ?ctx ~use_gmp_opt:under_lambda i
 
     | Toffset(_, t')
     | Tblock_length(_, t')
@@ -393,25 +389,37 @@ let rec type_term
       let i = Interval.get_from_profile ~profile t in
       (* [t'] must be typed, but it is a pointer *)
       ignore (type_term ~use_gmp_opt:true ~ctx:Nan ~profile t');
-      let ty = ty_of_interv ?ctx i in
-      dup ty
+      ty_of_interv ?ctx i
 
     | TBinOp (MinusPP, t1, t2) ->
       let i = Interval.get_from_profile ~profile t in
       (* [t1] and [t2] must be typed, but they are pointers *)
       ignore (type_term ~use_gmp_opt:true ~ctx:Nan ~profile t1);
       ignore (type_term ~use_gmp_opt:true ~ctx:Nan ~profile t2);
-      let ty = ty_of_interv ?ctx i in
-      dup ty
+      ty_of_interv ?ctx i
+
+    | TUnOp (LNot, t') ->
+      let ctx =
+        try
+          let i = Interval.get_from_profile ~profile t in
+          let i' = Interval.get_from_profile ~profile t' in
+          Some (mk_ctx ~use_gmp_opt:true (ty_of_interv (Interval.join i i')))
+        (* during the typing phase, we catch the Not_yet exception so that [t']
+           gets typed even if [t] is not. This prevents exceptions during the
+           translation phase *)
+        with Error.Not_yet _ ->
+          None
+      in
+      ignore (type_term ~use_gmp_opt:true ~arith_operand:true ?ctx ~profile t');
+      c_int (* converted into [t == 0] in case of GMP *)
 
-    | TUnOp (unop, t') ->
+    | TUnOp ((Neg | BNot), t') ->
       let i = Interval.get_from_profile ~profile t in
       let i' = Interval.get_from_profile ~profile t' in
       let ctx_res, ctx = compute_ctx ?ctx (Interval.join i i') in
       ignore (type_term ~use_gmp_opt:true ~arith_operand:true ~ctx ~profile t');
-      (match unop with
-       | LNot -> c_int, ctx_res (* converted into [t == 0] in case of GMP *)
-       | Neg | BNot -> dup ctx_res)
+      ctx_res
+
 
     | TBinOp ((PlusA | MinusA | Mult | Div | Mod | Shiftlt | Shiftrt | BAnd
               | BOr | BXor), t1, t2)
@@ -436,7 +444,7 @@ let rec type_term
         (type_term ~use_gmp_opt:true ~arith_operand:cast_first ~ctx ~profile t1);
       ignore
         (type_term ~use_gmp_opt:true ~arith_operand:(not cast_first) ~ctx ~profile t2);
-      dup ctx_res
+      ctx_res
 
     | TBinOp ((Lt | Gt | Le | Ge | Eq | Ne), t1, t2) ->
       assert
@@ -446,11 +454,7 @@ let rec type_term
       let ctx = ctx_relation ~profile t1 t2 in
       ignore (type_term ~use_gmp_opt:true ~ctx ~profile t1);
       ignore (type_term ~use_gmp_opt:true ~ctx ~profile t2);
-      let ty = match ctx with
-        | Nan -> c_int
-        | Real | Rational | Gmpz | C_float _ | C_integer _ -> ctx
-      in
-      c_int, ty
+      c_int
 
     | TBinOp ((LAnd | LOr), t1, t2) ->
       let i1 = Interval.get_from_profile ~profile t1 in
@@ -459,7 +463,7 @@ let rec type_term
       (* both operands fit in an int. *)
       ignore (type_term ~use_gmp_opt:true ~ctx:c_int ~profile t1);
       ignore (type_term ~use_gmp_opt:true ~ctx:c_int ~profile t2);
-      dup ty
+      ty
 
     | TCastE(_, t') ->
       (* compute the smallest interval from the whole term [t] *)
@@ -468,7 +472,7 @@ let rec type_term
          infer from the arguments of the cast. *)
       let ctx = ty_of_interv ?ctx i in
       ignore (type_term ~use_gmp_opt:true ~ctx ~profile t');
-      dup ctx
+      ctx
 
     | Tif (t1, t2, t3) ->
       let ctx1 =
@@ -482,29 +486,29 @@ let rec type_term
       let ctx = mk_ctx ~use_gmp_opt:true ctx in
       ignore (type_term ~use_gmp_opt:true ~ctx ~profile t2);
       ignore (type_term ~use_gmp_opt:true ~ctx ~profile t3);
-      dup ctx
+      ctx
 
     | Tat (t, _)
     | TLogic_coerce (_, t) ->
-      dup (type_term ~use_gmp_opt ~arith_operand ?ctx ~profile t).ty
+      (type_term ~use_gmp_opt ~arith_operand ?ctx ~profile t).ty
 
     | TAddrOf tlv
     | TStartOf tlv ->
       (* it is a pointer, but subterms must be typed. *)
       type_term_lval tlv ~profile;
-      dup Nan
+      Nan
 
     | Tbase_addr (_, t) ->
       (* it is a pointer, but subterms must be typed. *)
       ignore (type_term ~use_gmp_opt:true ~ctx:Nan ~profile t);
-      dup Nan
+      Nan
 
     | TBinOp ((PlusPI | MinusPI), t1, t2) ->
       (* both [t1] and [t2] must be typed. *)
       ignore (type_term ~use_gmp_opt:true ~ctx:Nan ~profile t1);
       let ctx = type_offset ~profile t2 in
       ignore (type_term ~use_gmp_opt:false ~ctx ~profile t2);
-      dup Nan
+      Nan
 
     | Tapp(li, _, args) ->
       if Builtins.mem li.l_var_info.lv_name then
@@ -517,7 +521,7 @@ let rec type_term
         List.iter2 typ_arg li.l_profile args;
         (* [li.l_type is [None] for predicate only: not possible here.
            Thus using [Option.get] is fine *)
-        dup (ty_of_logic_ty ~profile (Option.get li.l_type))
+        ty_of_logic_ty ~profile (Option.get li.l_type)
       else begin
         (* TODO: what if the type of the parameter is smaller than the infered
            type of the argument? For now, it is silently ignored (both
@@ -558,7 +562,7 @@ let rec type_term
             (fun () ->
                ignore (type_predicate ~profile:new_profile p))
             pending_typing;
-          dup c_int
+          c_int
         | LBterm t_body ->
           List.iter
             (fun x ->
@@ -610,9 +614,9 @@ let rec type_term
              inference *)
           (match li.l_type with
            | Some (Ctype (TInt (ikind, _))) ->
-             dup (C_integer ikind)
+             C_integer ikind
            | Some (Ctype (TFloat (fkind, _))) ->
-             dup (C_float fkind)
+             C_float fkind
            | None
            | Some (Ctype (TVoid _
                          | TPtr _
@@ -623,10 +627,10 @@ let rec type_term
                          | TComp _
                          | TBuiltin_va_list _))
            | Some (Linteger | Lreal | Ltype _ | Lvar _ | Larrow _) ->
-             dup (ty_of_interv
-                    ?ctx:ctx_body
-                    ~use_gmp_opt:(gmp && use_gmp_opt)
-                    (Interval.get_from_profile ~profile t)))
+             ty_of_interv
+               ?ctx:ctx_body
+               ~use_gmp_opt:(gmp && use_gmp_opt)
+               (Interval.get_from_profile ~profile t))
         | LBnone ->
           (match args with
            | [ t1; t2; {term_node = Tlambda([ _ ], _)} as lambda ] ->
@@ -642,7 +646,7 @@ let rec type_term
              let ival = Interval.get_from_profile ~profile t in
              let ty = ty_of_interv ival ~use_gmp_opt:true ?ctx in
              ignore (type_term ~use_gmp_opt:true ?ctx ~profile lambda);
-             dup ty
+             ty
            | [ ] | [ _ ] | [ _; _ ] | _ :: _ :: _ :: _ ->
              (* TODO : improve error message to distinguish error messages
                 corresponding to unsupported primitives and wrong application
@@ -666,15 +670,14 @@ let rec type_term
       ignore (type_term ~use_gmp_opt ~profile n1);
       ignore (type_term ~use_gmp_opt ~profile n2);
       let i = Interval.get_from_profile ~profile t in
-      let ty = ty_of_interv ?ctx i in
-      dup ty
+      ty_of_interv ?ctx i
 
     | Tlet(li, t) ->
       let li_t = Misc.term_of_li li in
       ignore (type_term ~use_gmp_opt:true ~profile li_t);
-      dup (type_term ~use_gmp_opt:true ?ctx ~profile t).ty
+      (type_term ~use_gmp_opt:true ?ctx ~profile t).ty
     | Tlambda ([ _ ],lt) ->
-      dup (type_term ~use_gmp_opt:true ~under_lambda:true ?ctx ~profile lt).ty;
+      (type_term ~use_gmp_opt:true ~under_lambda:true ?ctx ~profile lt).ty
     | Tlambda (_,_) -> Error.not_yet "lambda"
     | TDataCons (_,_) -> Error.not_yet "datacons"
     | TUpdate (_,_,_) -> Error.not_yet "update"
@@ -683,16 +686,16 @@ let rec type_term
     | TConst (LStr _ | LWStr _)
     | Ttypeof _
     | Ttype _
-    | Tempty_set  -> dup Nan
+    | Tempty_set  -> Nan
   in
   let t = Logic_normalizer.get_term t in
   match
     Memo.memo ~profile
       (fun t ->
-         let ty, op = infer t in
+         let ty = infer t in
          match ctx with
-         | None -> { ty; op; cast = None }
-         | Some ctx -> coerce ~arith_operand ~ctx ~op ty)
+         | None -> { ty; cast = None }
+         | Some ctx -> coerce ~arith_operand ~ctx ty)
       t
   with
   | Result.Ok res -> res
@@ -753,95 +756,91 @@ and type_bound_variables ~profile (t1, lv, t2) =
   ignore(type_term ~use_gmp_opt:false ~ctx ~profile t2)
 
 and type_predicate ~profile p =
+  let
+    do_both f g = (try f() with e -> try g(); raise e with | _ -> raise e); g()
+  in
   let p = Logic_normalizer.get_pred p in
   Cil.CurrentLoc.set p.pred_loc;
   (* this pattern matching also follows the formal rules of the JFLA's paper *)
-  let op =
-    match p.pred_content with
-    | Pfalse | Ptrue -> c_int
-    | Papp(li, _, args) ->
-      begin
-        match li.l_body with
-        | LBpred p ->
-          List.iter
-            (fun x -> ignore (type_term ~use_gmp_opt: true ~profile x))
-            args;
-          let new_profile =
-            Profile.make
-              li.l_profile
-              (List.map (Interval.get_from_profile ~profile) args)
-          in
-          ignore (type_predicate ~profile:new_profile p);
-        | LBnone -> ()
-        | LBreads _ -> ()
-        | LBinductive _ -> ()
-        | LBterm _ ->
-          Options.fatal "unexpected logic definition"
-            Printer.pp_predicate p
-      end;
-      c_int
-    | Pdangling _ -> Error.not_yet "\\dangling"
-    | Prel(_, t1, t2) ->
-      let ctx = ctx_relation ~profile t1 t2 in
-      ignore (type_term ~use_gmp_opt:true ~ctx ~profile t1);
-      ignore (type_term ~use_gmp_opt:true ~ctx ~profile t2);
-      (match ctx with
-       | Nan -> c_int
-       | Real | Rational | Gmpz | C_float _ | C_integer _ -> ctx)
-    | Pand(p1, p2)
-    | Por(p1, p2)
-    | Pxor(p1, p2)
-    | Pimplies(p1, p2)
-    | Piff(p1, p2) ->
-      ignore (type_predicate ~profile p1);
-      ignore (type_predicate ~profile p2);
-      c_int
-    | Pnot p ->
-      ignore (type_predicate ~profile p);
-      c_int
-    | Pif(t, p1, p2) ->
-      let ctx = mk_ctx ~use_gmp_opt:false c_int in
-      ignore (type_term ~use_gmp_opt:false ~ctx ~profile t);
-      ignore (type_predicate ~profile p1);
-      ignore (type_predicate ~profile p2);
-      c_int
-    | Plet(li, p) ->
-      let li_t = Misc.term_of_li li in
-      ignore (type_term ~use_gmp_opt:true ~profile li_t);
-      (type_predicate ~profile p).ty
-    | Pforall _
-    | Pexists _ ->
-      begin
-        let guards, goal =
-          Error.retrieve_preprocessing
-            "preprocessing of quantified predicate"
-            Bound_variables.get_preprocessed_quantifier
-            p
-            Printer.pp_predicate
-        in
+  match p.pred_content with
+  | Pfalse | Ptrue -> ()
+  | Papp(li, _, args) ->
+    begin
+      match li.l_body with
+      | LBpred p ->
         List.iter
-          (fun (t1, x, t2) -> type_bound_variables ~profile (t1, x, t2))
-          guards;
-        (type_predicate ~profile goal).ty
-      end
-    | Pseparated tlist ->
-      List.iter
-        (fun t -> ignore (type_term ~use_gmp_opt:false ~ctx:Nan ~profile t))
-        tlist;
-      c_int
-    | Pinitialized(_, t)
-    | Pfreeable(_, t)
-    | Pallocable(_, t)
-    | Pvalid(_, t)
-    | Pvalid_read(_, t)
-    | Pobject_pointer(_,t)
-    | Pvalid_function t ->
-      ignore (type_term ~use_gmp_opt:false ~ctx:Nan ~profile t);
-      c_int
-    | Pat(p, _) -> (type_predicate ~profile p).ty
-    | Pfresh _ -> Error.not_yet "\\fresh"
-  in
-  coerce ~arith_operand:false ~ctx:c_int ~op c_int
+          (fun x -> ignore (type_term ~use_gmp_opt: true ~profile x))
+          args;
+        let new_profile =
+          Profile.make
+            li.l_profile
+            (List.map (Interval.get_from_profile ~profile) args)
+        in
+        type_predicate ~profile:new_profile p;
+      | LBnone -> ()
+      | LBreads _ -> ()
+      | LBinductive _ -> ()
+      | LBterm _ ->
+        Options.fatal "unexpected logic definition"
+          Printer.pp_predicate p
+    end
+  | Pdangling _ -> Error.not_yet "\\dangling"
+  | Prel(_, t1, t2) ->
+    let ctx =
+      try
+        Some (ctx_relation ~profile t1 t2)
+      (* as before, we catch the exception Not_yet to ensure that [t1] and [t2]
+         get typed in all cases. *)
+      with Error.Not_yet _ ->
+        None
+    in
+    let on t () = ignore (type_term ~use_gmp_opt:true ?ctx ~profile t) in
+    do_both (on t1) (on t2);
+  | Pand(p1, p2)
+  | Por(p1, p2)
+  | Pxor(p1, p2)
+  | Pimplies(p1, p2)
+  | Piff(p1, p2) ->
+    let on p () = type_predicate ~profile p in
+    do_both (on p1) (on p2)
+  | Pnot p ->
+    type_predicate ~profile p
+  | Pif(t, p1, p2) ->
+    let ctx = mk_ctx ~use_gmp_opt:false c_int in
+    ignore (type_term ~use_gmp_opt:false ~ctx ~profile t);
+    let on p  () = type_predicate ~profile p in
+    do_both (on p1) (on p2)
+  | Plet(li, p) ->
+    let li_t = Misc.term_of_li li in
+    ignore (type_term ~use_gmp_opt:true ~profile li_t);
+    type_predicate ~profile p
+  | Pforall _
+  | Pexists _ ->
+    let guards, goal =
+      Error.retrieve_preprocessing
+        "preprocessing of quantified predicate"
+        Bound_variables.get_preprocessed_quantifier
+        p
+        Printer.pp_predicate
+    in
+    List.iter
+      (fun (t1, x, t2) -> type_bound_variables ~profile (t1, x, t2))
+      guards;
+    type_predicate ~profile goal
+  | Pseparated tlist ->
+    List.iter
+      (fun t -> ignore (type_term ~use_gmp_opt:false ~ctx:Nan ~profile t))
+      tlist
+  | Pinitialized(_, t)
+  | Pfreeable(_, t)
+  | Pallocable(_, t)
+  | Pvalid(_, t)
+  | Pvalid_read(_, t)
+  | Pobject_pointer(_,t)
+  | Pvalid_function t ->
+    ignore (type_term ~use_gmp_opt:false ~ctx:Nan ~profile t)
+  | Pat(p, _) -> type_predicate ~profile p
+  | Pfresh _ -> Error.not_yet "\\fresh"
 
 (** When typing a binary relation, generate the context in which the relation
     should be typed, to avoid spurious casts:
@@ -879,7 +878,7 @@ let type_named_predicate ~profile p =
 let unsafe_set t ?ctx ~logic_env ty =
   let profile = Logic_env.get_profile logic_env in
   let ctx = match ctx with None -> ty | Some ctx -> ctx in
-  let mk _ = coerce ~arith_operand:false ~ctx ~op:ty ty in
+  let mk _ = coerce ~arith_operand:false ~ctx ty in
   ignore (Memo.memo mk ~profile t)
 
 (******************************************************************************)
@@ -890,14 +889,6 @@ let get_number_ty ~logic_env t =
   let profile = Logic_env.get_profile logic_env in
   (Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term).ty
 
-let get_integer_op ~logic_env t =
-  let profile = Logic_env.get_profile logic_env in
-  (Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term).op
-
-let get_integer_op_of_predicate ~logic_env p =
-  let profile = Logic_env.get_profile logic_env in
-  (type_predicate ~profile p).op
-
 (* {!typ_of_integer}, but handle the not-integer cases. *)
 let extract_typ t ty =
   try typ_of_number_ty ty
@@ -911,29 +902,27 @@ let extract_typ t ty =
   | Larrow _ -> Error.not_yet "unsupported logic type: type arrow"
 
 let get_typ ~logic_env t =
-  let profile = Logic_env.get_profile logic_env in
-  let info =
-    Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term in
-  extract_typ t info.ty
-
-let get_op ~logic_env t =
-  let profile = Logic_env.get_profile logic_env in
-  let info =
-    Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term  in
-  extract_typ t info.op
+  extract_typ t (get_number_ty ~logic_env t)
 
 let get_cast ~logic_env t =
   let profile = Logic_env.get_profile logic_env in
   let info =
-    Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term in
+    Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term
+  in
   try Option.map typ_of_number_ty info.cast
   with Not_a_number -> None
 
-let get_cast_of_predicate ~logic_env p =
+let get_effective_ty ~logic_env t =
   let profile = Logic_env.get_profile logic_env in
-  let info = type_predicate ~profile p in
-  try Option.map typ_of_number_ty info.cast
-  with Not_a_number -> assert false
+  let info =
+    Error.retrieve_preprocessing "typing" (Memo.get ~profile) t Printer.pp_term
+  in
+  match info.cast with
+  | Some ty -> ty
+  | None -> info.ty
+
+let get_effective_typ ~logic_env t =
+  extract_typ t (get_effective_ty ~logic_env t)
 
 let clear = Memo.clear
 
diff --git a/src/plugins/e-acsl/src/analyses/typing.mli b/src/plugins/e-acsl/src/analyses/typing.mli
index 2fbf5e238a556a3b26055fbe8385b861392cd2c4..b33edd6fbb772638b342d9ff65206f0aef5e8bcc 100644
--- a/src/plugins/e-acsl/src/analyses/typing.mli
+++ b/src/plugins/e-acsl/src/analyses/typing.mli
@@ -101,29 +101,20 @@ val clear: unit -> unit
 val get_number_ty: logic_env:Logic_env.t -> term -> number_ty
 (** @return the infered type for the given term. *)
 
-val get_integer_op: logic_env:Logic_env.t -> term -> number_ty
-(** @return the infered type for the top operation of the given term.
-    It is meaningless to call this function over a non-arithmetical/logical
-    operator. *)
-
-val get_integer_op_of_predicate:
-  logic_env:Logic_env.t -> predicate -> number_ty
-(** @return the infered type for the top operation of the given predicate. *)
+val get_effective_ty: logic_env:Logic_env.t -> term -> number_ty
+(** @return the necessary cast infered by the type system if any, or the type
+    infered for the given term otherwise *)
 
 val get_typ: logic_env:Logic_env.t -> term -> typ
 (** Get the type which the given term must be generated to. *)
 
-val get_op: logic_env:Logic_env.t -> term -> typ
-(** Get the type which the operation on top of the given term must be generated
-    to. *)
+val get_effective_typ: logic_env:Logic_env.t -> term -> typ
+(** Get the type which the given term must be converted to if any, and the
+    translation type otherwise *)
 
 val get_cast: logic_env:Logic_env.t -> term -> typ option
 (** Get the type which the given term must be converted to (if any). *)
 
-val get_cast_of_predicate:
-  logic_env:Logic_env.t -> predicate -> typ option
-(** Like {!get_cast}, but for predicates. *)
-
 val unsafe_set:
   term ->
   ?ctx:number_ty ->
diff --git a/src/plugins/e-acsl/src/code_generator/loops.ml b/src/plugins/e-acsl/src/code_generator/loops.ml
index 0f25543b66d2f833927cb0c93e0cdb97abe0de7a..904f1c9fb591cb72f64869f322dd1d5f438134fd 100644
--- a/src/plugins/e-acsl/src/code_generator/loops.ml
+++ b/src/plugins/e-acsl/src/code_generator/loops.ml
@@ -374,6 +374,7 @@ let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars =
         guard :: body @ [ next ], env
       | Some p ->
         let adata, env = Assert.empty ~loc kf env in
+        Typing.preprocess_predicate ~logic_env p;
         let e, adata, env =
           (* Even though p is considered a RTE, it was generated while
              typing the loop, and was already typed at this moment. Thus
diff --git a/src/plugins/e-acsl/src/code_generator/translate_predicates.ml b/src/plugins/e-acsl/src/code_generator/translate_predicates.ml
index 1975623c8f965d0ccec1480f2ec94fad329d22e9..537ed90a85f324808f4a39e3ab7a498352902d8f 100644
--- a/src/plugins/e-acsl/src/code_generator/translate_predicates.ml
+++ b/src/plugins/e-acsl/src/code_generator/translate_predicates.ml
@@ -87,8 +87,12 @@ let rec predicate_content_to_exp ~adata ?(inplace=false) ?name kf env p =
   | Pobject_pointer _ -> Env.not_yet env "\\object_pointer"
   | Pvalid_function _ -> Env.not_yet env "\\valid_function"
   | Prel(rel, t1, t2) ->
+    let t1 = Logic_normalizer.get_term t1 in
+    let t2 = Logic_normalizer.get_term t2 in
     let ity =
-      Typing.get_integer_op_of_predicate ~logic_env p
+      Typing.join
+        (Typing.get_effective_ty ~logic_env t1)
+        (Typing.get_effective_ty ~logic_env t2)
     in
     Translate_utils.comparison_to_exp
       ~adata
@@ -321,11 +325,6 @@ and to_exp ~adata ?inplace ?name kf ?rte env p =
              predicate_content_to_exp ?inplace ~adata ?name kf env p
            in
            let env = if rte then !translate_rte_exp_ref kf env e else env in
-           let cast =
-             Typing.get_cast_of_predicate
-               ~logic_env:(Env.Logic_env.get env)
-               p
-           in
            let env = Assert.do_pending_register_data env in
            Extlib.nest
              adata
@@ -334,7 +333,7 @@ and to_exp ~adata ?inplace ?name kf ?rte env p =
                 ?name
                 env
                 kf
-                cast
+                None
                 Typed_number.C_number
                 None
                 e)
diff --git a/src/plugins/e-acsl/src/code_generator/translate_terms.ml b/src/plugins/e-acsl/src/code_generator/translate_terms.ml
index 12965127c73a69a7c0140e0ccaddfe33b2b57ded..456a28bc9882b25a38b8be0b9d4130f628135fea 100644
--- a/src/plugins/e-acsl/src/code_generator/translate_terms.ml
+++ b/src/plugins/e-acsl/src/code_generator/translate_terms.ml
@@ -318,7 +318,8 @@ and context_insensitive_term_to_exp ~adata ?(inplace=false) kf env t =
     else
       Cil.new_exp ~loc (UnOp(op, e, ty)), adata, env, Typed_number.C_number, ""
   | TUnOp(LNot, t) ->
-    let ty = Typing.get_op ~logic_env t in
+    let t = Logic_normalizer.get_term t in
+    let ty = Typing.get_effective_typ ~logic_env t in
     if Gmp_types.Z.is_t ty then
       (* [!t] is converted into [t == 0] *)
       let zero = Logic_const.tinteger 0 in
@@ -438,7 +439,13 @@ and context_insensitive_term_to_exp ~adata ?(inplace=false) kf env t =
     end
   | TBinOp(Lt | Gt | Le | Ge | Eq | Ne as bop, t1, t2) ->
     (* comparison operators *)
-    let ity = Typing.get_integer_op ~logic_env t in
+    let ity =
+      let t1 = Logic_normalizer.get_term t1 in
+      let t2 = Logic_normalizer.get_term t2 in
+      Typing.join
+        (Typing.get_effective_ty ~logic_env t1)
+        (Typing.get_effective_ty ~logic_env t2)
+    in
     let e, adata, env =
       Translate_utils.comparison_to_exp
         ~adata
diff --git a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
index e7a99a994e20892384a9ac2fb492aa4eaa82dbc4..81d4fa06f45a8688ea85ac8c638930365601d0c3 100644
--- a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
@@ -42,11 +42,9 @@
   E-ACSL construct `predicates with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:176: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
-  Ignoring annotation.
+  E-ACSL construct `datacons' is not yet supported. Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:183: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
-  Ignoring annotation.
+  E-ACSL construct `datacons' is not yet supported. Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:173: Warning: 
   Some assumes clauses could not be translated.
   Ignoring complete and disjoint behaviors annotations.
diff --git a/src/plugins/e-acsl/tests/libc/oracle/mem.res.oracle b/src/plugins/e-acsl/tests/libc/oracle/mem.res.oracle
index 4d889a0aa24b4f727ecbf30a7fd9869bc29ec18f..009670d149431e5e85ab761f5e00bc24266578b2 100644
--- a/src/plugins/e-acsl/tests/libc/oracle/mem.res.oracle
+++ b/src/plugins/e-acsl/tests/libc/oracle/mem.res.oracle
@@ -6,8 +6,7 @@
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:134: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
-  Ignoring annotation.
+  E-ACSL construct `datacons' is not yet supported. Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:120: Warning: 
   E-ACSL construct `predicates with labels' is not yet supported.
   Ignoring annotation.
diff --git a/src/plugins/e-acsl/tests/temporal/oracle/t_memcpy.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle/t_memcpy.res.oracle
index 2dfc948020964a7bff4201173e52df3ee35c838c..d7c3cd0d2e1d9b317764e8d378e42554002fb2dd 100644
--- a/src/plugins/e-acsl/tests/temporal/oracle/t_memcpy.res.oracle
+++ b/src/plugins/e-acsl/tests/temporal/oracle/t_memcpy.res.oracle
@@ -6,8 +6,7 @@
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:134: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
-  Ignoring annotation.
+  E-ACSL construct `datacons' is not yet supported. Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:95: Warning: 
   E-ACSL construct `predicates with labels' is not yet supported.
   Ignoring annotation.