diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in
index c366ab4588b3466bc5ebd711bc779af46c8a88e7..fc9b5349f30bd57b7b4b40dc4845a32b7051612b 100644
--- a/src/plugins/e-acsl/Makefile.in
+++ b/src/plugins/e-acsl/Makefile.in
@@ -79,6 +79,7 @@ PLUGIN_CMO:= local_config \
 	quantif \
 	at_with_lscope \
 	mmodel_translate \
+	logic_functions \
 	translate \
 	temporal \
 	prepare_ast \
diff --git a/src/plugins/e-acsl/at_with_lscope.ml b/src/plugins/e-acsl/at_with_lscope.ml
index c4981badab3bdf0f309f841e3b22eebd0a2e1ccc..9602bb5b61445e8aeb7051612f5faf469314052a 100644
--- a/src/plugins/e-acsl/at_with_lscope.ml
+++ b/src/plugins/e-acsl/at_with_lscope.ml
@@ -237,46 +237,47 @@ let to_exp ~loc kf env pot label =
     end
   in
   let ty_ptr = TPtr(ty, []) in
-  let vi_at, e_at, env = Env.new_var
-    ~loc
-    ~name:"at"
-    ~scope:Env.Function
-    env
-    None
-    ty_ptr
-    (fun vi e ->
-      (* Handle [malloc] and [free] stmts *)
-      let lty_sizeof = Ctype Cil.(theMachine.typeOfSizeOf) in
-      let t_sizeof = Logic_const.term ~loc (TSizeOf ty) lty_sizeof in
-      let t_size = size_from_sizes_and_shifts ~loc sizes_and_shifts in
-      let t_size =
-        Logic_const.term ~loc (TBinOp(Mult, t_sizeof, t_size)) lty_sizeof
-      in
-      Typing.type_term ~use_gmp_opt:false t_size;
-      let malloc_stmt = match Typing.get_integer_ty t_size with
-      | Typing.C_type IInt ->
-        let e_size, _ = term_to_exp kf env t_size in
-        let e_size = Cil.constFold false e_size in
-        let malloc_stmt =
-          Misc.mk_call ~loc ~result:(Cil.var vi) "malloc" [e_size]
-        in
-        malloc_stmt
-      | Typing.C_type _ | Typing.Gmp ->
-        Error.not_yet
-          "\\at on purely logic variables that needs to allocate \
-            too much memory (bigger than int_max bytes)"
-      | Typing.Other ->
-        Options.fatal
-          "quantification over non-integer type is not part of E-ACSL"
-      in
-      let free_stmt = Misc.mk_call ~loc "free" [e] in
-      (* The list of stmts returned by the current closure are inserted
-        LOCALLY to the block where the new var is FIRST used, whatever scope
-        is indicated to [Env.new_var].
-        Thus we need to add [malloc] and [free] through dedicated functions. *)
-      Malloc.add kf malloc_stmt;
-      Free.add kf free_stmt;
-      [])
+  let vi_at, e_at, env =
+    Env.new_var
+      ~loc
+      ~name:"at"
+      ~scope:Env.Function
+      env
+      None
+      ty_ptr
+      (fun vi e ->
+         (* Handle [malloc] and [free] stmts *)
+         let lty_sizeof = Ctype Cil.(theMachine.typeOfSizeOf) in
+         let t_sizeof = Logic_const.term ~loc (TSizeOf ty) lty_sizeof in
+         let t_size = size_from_sizes_and_shifts ~loc sizes_and_shifts in
+         let t_size =
+           Logic_const.term ~loc (TBinOp(Mult, t_sizeof, t_size)) lty_sizeof
+         in
+         Typing.type_term ~use_gmp_opt:false t_size;
+         let malloc_stmt = match Typing.get_integer_ty t_size with
+           | Typing.C_type IInt ->
+             let e_size, _ = term_to_exp kf env t_size in
+             let e_size = Cil.constFold false e_size in
+             let malloc_stmt =
+               Misc.mk_call ~loc ~result:(Cil.var vi) "malloc" [e_size]
+             in
+             malloc_stmt
+           | Typing.C_type _ | Typing.Gmp ->
+             Error.not_yet
+               "\\at on purely logic variables that needs to allocate \
+                too much memory (bigger than int_max bytes)"
+           | Typing.Other ->
+             Options.fatal
+               "quantification over non-integer type is not part of E-ACSL"
+         in
+         let free_stmt = Misc.mk_call ~loc "free" [e] in
+         (* The list of stmts returned by the current closure are inserted
+            LOCALLY to the block where the new var is FIRST used, whatever scope
+            is indicated to [Env.new_var]. Thus we need to add [malloc] and
+            [free] through dedicated functions. *)
+         Malloc.add kf malloc_stmt;
+         Free.add kf free_stmt;
+         [])
   in
   (* Index *)
   let t_index = index_from_sizes_and_shifts ~loc sizes_and_shifts in
@@ -337,4 +338,4 @@ let to_exp ~loc kf env pot label =
   (* Returning *)
   let lval_at_index, env = lval_at_index ~loc kf env (e_at, vi_at, t_index) in
   let e = Cil.new_exp ~loc (Lval lval_at_index) in
-  e, env
\ No newline at end of file
+  e, env
diff --git a/src/plugins/e-acsl/builtins.ml b/src/plugins/e-acsl/builtins.ml
index 45467db85bc2a5a59e5355efcff42e380860567a..ca591dc3496d098ac6e933a0f56a7bfbfa891b4c 100644
--- a/src/plugins/e-acsl/builtins.ml
+++ b/src/plugins/e-acsl/builtins.ml
@@ -39,7 +39,7 @@ let update s vi =
   with Not_found ->
     ()
 
-(* add [vi] in the built-in table if it is an E-ACSL built-in which is not
+(* add [vi] in the built-in table if it is an E-ACSL built-in that is not
    [already] registered. *)
 let add_builtin vi already =
   if not already then
diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index d47f3ef037ef8ffb6449bd85bac690a6436b9582..d548c07e389d43c27bb25ef058a5b39c69fd5ab5 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -19,6 +19,8 @@
 #   configure	configure
 ###############################################################################
 
+-  E-ACSL       [2019/04/29] Support for logic functions and predicates
+	        without labels.
 -  runtime      [2019/02/26] The behavior of __e_acsl_assert now depends on the
 	        runtime value of the global variable __e_acsl_sound_verdict:
 	        if 0, it means that its verdict is possibly incorrect.
diff --git a/src/plugins/e-acsl/dup_functions.ml b/src/plugins/e-acsl/dup_functions.ml
index 1e4b879d31923d8124661ae2f523674c8dc9f98d..0deac191f99cfd33e930bb3e9e19085a1e490fc3 100644
--- a/src/plugins/e-acsl/dup_functions.ml
+++ b/src/plugins/e-acsl/dup_functions.ml
@@ -123,7 +123,8 @@ let dup_fundec loc spec bhv sound_verdict_vi kf vi new_vi =
       if vi.vname = "" then
         (* unnamed formal parameter: must generate a fresh name since a fundec
            cannot have unnamed formals (see bts #2303). *)
-        Env.Varname.get ~scope:Env.Function
+        Env.Varname.get
+          ~scope:Env.Function
           (Functions.RTL.mk_gen_name "unamed_formal")
       else
         vi.vname
diff --git a/src/plugins/e-acsl/env.ml b/src/plugins/e-acsl/env.ml
index c571fb5333ace122ff9f20d5fac8f1a0ad1fa5d8..fd2e6d3b2083e1f32fb6a0f4d16d27e8b803f49f 100644
--- a/src/plugins/e-acsl/env.ml
+++ b/src/plugins/e-acsl/env.ml
@@ -24,6 +24,11 @@ module E_acsl_label = Label
 open Cil_types
 open Cil_datatype
 
+type localized_scope =
+  | LGlobal
+  | LFunction of kernel_function
+  | LLocal_block of kernel_function
+
 type scope =
   | Global
   | Function
@@ -55,7 +60,7 @@ type t =
       lscope: Lscope.t;
       lscope_reset: bool;
       annotation_kind: Misc.annotation_kind;
-      new_global_vars: (varinfo * scope) list;
+      new_global_vars: (varinfo * localized_scope) list;
       (* generated variables. The scope indicates the level where the variable
          should be added. *)
       global_mpz_tbl: mpz_tbl;
@@ -141,6 +146,19 @@ let has_no_new_stmt env =
   let local, _ = top env in
   local.block_info = empty_block
 
+let current_kf env =
+  let v = env.visitor in
+  match v#current_kf with
+  | None -> None
+  | Some kf -> Some (Cil.get_kernel_function v#behavior kf)
+
+let set_current_kf env kf =
+  let v = env.visitor in
+  v#set_current_kf kf
+
+let get_visitor env = env.visitor
+let get_behavior env = env.visitor#behavior
+
 (* ************************************************************************** *)
 (** {2 Loop invariants} *)
 (* ************************************************************************** *)
@@ -189,6 +207,11 @@ let do_new_var ~loc ?(scope=Local_block) ?(name="") env t ty mk_stmts =
       ty
   in
   v.vreferenced <- true;
+  let lscope = match scope with
+    | Global -> LGlobal
+    | Function -> LFunction (Extlib.the (current_kf env))
+    | Local_block -> LLocal_block (Extlib.the (current_kf env))
+  in
 (*  Options.feedback "new variable %a (global? %b)" Varinfo.pretty v global;*)
   let e = Cil.evar v in
   let stmts = mk_stmts v e in
@@ -222,7 +245,7 @@ let do_new_var ~loc ?(scope=Local_block) ?(name="") env t ty mk_stmts =
       (* also memoize the new variable, but must never be used *)
       { env with
 	cpt = n;
-        new_global_vars = (v, scope) :: env.new_global_vars;
+        new_global_vars = (v, lscope) :: env.new_global_vars;
 	global_mpz_tbl = extend_tbl env.global_mpz_tbl;
 	env_stack = local_env :: tl_env }
     | Local_block ->
@@ -234,9 +257,9 @@ let do_new_var ~loc ?(scope=Local_block) ?(name="") env t ty mk_stmts =
       { env with 
 	cpt = n; 
 	env_stack = local_env :: tl_env;
-        new_global_vars = (v, scope) :: env.new_global_vars }
+        new_global_vars = (v, lscope) :: env.new_global_vars }
   end else
-    let new_global_vars = (v, scope) :: env.new_global_vars in
+    let new_global_vars = (v, lscope) :: env.new_global_vars in
     let local_env = 
       { local_env with 
 	block_info = new_block; 
@@ -262,10 +285,8 @@ let new_var ~loc ?(scope=Local_block) ?name env t ty mk_stmts =
       do_new_var ~loc ~scope ?name env t ty mk_stmts
   in
   match scope with
-  | Global | Function ->
-    memo env.global_mpz_tbl
-  | Local_block ->
-    memo local_env.mpz_tbl
+  | Global | Function -> memo env.global_mpz_tbl
+  | Local_block -> memo local_env.mpz_tbl
 
 let new_var_and_mpz_init ~loc ?scope ?name env t mk_stmts =
   new_var
@@ -279,19 +300,29 @@ let new_var_and_mpz_init ~loc ?scope ?name env t mk_stmts =
 
 module Logic_binding = struct
 
+  let add_binding env logic_v vi =
+    try
+      let varinfos = Logic_var.Map.find logic_v env.var_mapping in
+      Stack.push vi varinfos;
+      env
+    with Not_found | Stack.Empty ->
+      let varinfos = Stack.create () in
+      Stack.push vi varinfos;
+      let var_mapping = Logic_var.Map.add logic_v varinfos env.var_mapping in
+      { env with var_mapping = var_mapping }
+
   let add ?ty env logic_v =
     let ty = match ty with
       | Some ty -> ty
       | None -> match logic_v.lv_type with
-	| Ctype ty -> ty
-	| Linteger -> Gmpz.t ()
-	| Ltype _ as ty when Logic_const.is_boolean_type ty -> Cil.charType
-	| Ltype _ | Lvar _ | Lreal | Larrow _ as lty ->
-	  let msg =
-	    Format.asprintf
-	      "logic variable of type %a" Logic_type.pretty lty
-	  in
-	  Error.not_yet msg
+        | Ctype ty -> ty
+        | Linteger -> Gmpz.t ()
+        | Ltype _ as ty when Logic_const.is_boolean_type ty -> Cil.charType
+        | Ltype _ | Lvar _ | Lreal | Larrow _ as lty ->
+          let msg =
+            Format.asprintf "logic variable of type %a" Logic_type.pretty lty
+          in
+          Error.not_yet msg
     in
     let v, e, env = new_var
       ~loc:Location.unknown
@@ -301,18 +332,7 @@ module Logic_binding = struct
       ty
       (fun _ _ -> [])
     in
-    let env =
-      try
-        let varinfos = Logic_var.Map.find logic_v env.var_mapping in
-        Stack.push v varinfos;
-        env
-      with Not_found ->
-        let varinfos = Stack.create () in
-        Stack.push v varinfos;
-        let var_mapping = Logic_var.Map.add logic_v varinfos env.var_mapping in
-        { env with var_mapping = var_mapping }
-    in
-    v, e, env
+    v, e, add_binding env logic_v v
 
   let get env logic_v =
     try
@@ -324,22 +344,12 @@ module Logic_binding = struct
   let remove env logic_v =
     try
       let varinfos = Logic_var.Map.find logic_v env.var_mapping in
-      ignore (Stack.pop varinfos);
-      env
+      ignore (Stack.pop varinfos)
     with Not_found | Stack.Empty ->
       assert false
 
 end
 
-let current_kf env = 
-  let v = env.visitor in
-  match v#current_kf with
-  | None -> None
-  | Some kf -> Some (Cil.get_kernel_function v#behavior kf)
-
-let get_visitor env = env.visitor
-let get_behavior env = env.visitor#behavior
-
 module Logic_scope = struct
   let get env = env.lscope
   let extend env lvs = { env with lscope = Lscope.add lvs env.lscope }
@@ -508,7 +518,9 @@ module Context = struct
 	{ env with new_global_vars = 
 	    List.filter
               (fun (v, scope) ->
-                (scope = Global || scope = Function)
+                (match scope with
+                | LGlobal | LFunction _ -> true
+                | LLocal_block _ -> false)
                 && List.for_all (fun (v', _) -> v != v') vars)
 	      !ctx 
 	      @ vars }
diff --git a/src/plugins/e-acsl/env.mli b/src/plugins/e-acsl/env.mli
index 7fe184e3d026caead108691fab9f09660331006b..d3d408eb20d64a8accff900abab575376c981060 100644
--- a/src/plugins/e-acsl/env.mli
+++ b/src/plugins/e-acsl/env.mli
@@ -36,6 +36,11 @@ val has_no_new_stmt: t -> bool
 (** Assume that a local context has been previously pushed.
     @return true iff the given env does not contain any new statement. *)
 
+type localized_scope =
+  | LGlobal
+  | LFunction of kernel_function
+  | LLocal_block of kernel_function
+
 type scope =
   | Global
   | Function
@@ -68,11 +73,16 @@ module Logic_binding: sig
   val add: ?ty:typ -> t -> logic_var -> varinfo * exp * t
   (* Add a new C binding to the list of bindings for the logic variable. *)
 
+  val add_binding: t -> logic_var -> varinfo -> t
+  (* [add_binding env lv vi] defines [vi] as the latest C binding for
+     [lv]. *)
+
   val get: t -> logic_var -> varinfo
   (* Return the latest C binding. *)
 
-  val remove: t -> logic_var -> t
+  val remove: t -> logic_var -> unit
   (* Remove the latest C binding. *)
+
 end
 
 val add_assert: t -> stmt -> predicate -> unit
@@ -111,10 +121,8 @@ val pop: t -> t
 val transfer: from:t -> t -> t
 (** Pop the last local context of [from] and push it into the other env. *)
 
-val get_generated_variables: t -> (varinfo * scope) list
-(** All the new variables local to the visited function. 
-    The boolean indicates whether the varinfo must be added to the outermost
-    function block. *)
+val get_generated_variables: t -> (varinfo * localized_scope) list
+(** All the new variables local to the visited function. *)
 
 val get_visitor: t -> Visitor.generic_frama_c_visitor
 val get_behavior: t -> Cil.visitor_behavior
@@ -142,6 +150,9 @@ module Logic_scope: sig
     reset at next call to [reset]. *)
 end
 
+val set_current_kf: t -> kernel_function -> unit
+(* Set current kf of the environment *)
+
 (* ************************************************************************** *)
 (** {2 Current annotation kind} *)
 (* ************************************************************************** *)
diff --git a/src/plugins/e-acsl/gmpz.ml b/src/plugins/e-acsl/gmpz.ml
index ea9e81f9486f8b67d9f192df29f8b2ff47bbeade..54e5597f325b579cfd69968fdf0d4ee063b2fc64 100644
--- a/src/plugins/e-acsl/gmpz.ml
+++ b/src/plugins/e-acsl/gmpz.ml
@@ -28,13 +28,34 @@ let t_torig_ref =
       tname = "";
       ttype = TVoid [];
       treferenced = false }
+let t_struct_torig_ref =
+  ref
+    { torig_name = "";
+      tname = "";
+      ttype = TVoid [];
+      treferenced = false }
 
 let set_t ty = t_torig_ref := ty
+let set_t_struct ty = t_struct_torig_ref := ty
 
 let is_now_referenced () = !t_torig_ref.treferenced <- true
 
 let t () = TNamed(!t_torig_ref, [])
-let is_t ty = Cil_datatype.Typ.equal ty (t ())
+let t_ptr () = TNamed(
+  {
+    torig_name = "";
+    tname = "__e_acsl_mpz_struct *";
+    ttype = TArray(
+      TNamed(!t_struct_torig_ref, []),
+      Some (Cil.one ~loc:Cil_datatype.Location.unknown),
+      {scache = Not_Computed},
+      []);
+    treferenced = true;
+  },
+[])
+
+let is_t ty =
+  Cil_datatype.Typ.equal ty (t ()) || Cil_datatype.Typ.equal ty (t_ptr ())
 
 let apply_on_var ~loc funname e = Misc.mk_call ~loc ("__gmpz_" ^ funname) [ e ]
 let init ~loc e = apply_on_var "init" ~loc e
@@ -106,6 +127,9 @@ let init_t () =
     | GType({ torig_name = s } as info, _) when s = "__e_acsl_mpz_t" ->
       set_t info;
       Cil.SkipChildren
+    | GType({ torig_name = s } as info, _) when s = "__e_acsl_mpz_struct" ->
+      set_t_struct info;
+      Cil.SkipChildren
     | _ -> 
       Cil.SkipChildren
   end in
diff --git a/src/plugins/e-acsl/gmpz.mli b/src/plugins/e-acsl/gmpz.mli
index 503d9887391538af619d68add5c8f95da59f680f..4f1f25f47e3ff9378a89c8a3f03097b220e68c54 100644
--- a/src/plugins/e-acsl/gmpz.mli
+++ b/src/plugins/e-acsl/gmpz.mli
@@ -31,6 +31,8 @@ val set_t: typeinfo -> unit
 
 val t: unit -> typ 
   (** type "mpz_t" *)
+val t_ptr: unit -> typ
+  (** type "_mpz_struct *" *)
   
 val is_now_referenced: unit -> unit 
   (** Should be called once one variable of type "mpz_t" exists *)
diff --git a/src/plugins/e-acsl/headers/header_spec.txt b/src/plugins/e-acsl/headers/header_spec.txt
index f6631bcaad981754bfeeb152348a57f562f71451..d1e50bebe74c088da2b7f6050b02021d859661b0 100644
--- a/src/plugins/e-acsl/headers/header_spec.txt
+++ b/src/plugins/e-acsl/headers/header_spec.txt
@@ -39,6 +39,8 @@ literal_strings.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL
 literal_strings.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL
 local_config.ml: .ignore
 local_config.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL
+logic_functions.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL
+logic_functions.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL
 loops.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL
 loops.mli: CEA_LGPL_OR_PROPRIETARY.E_ACSL
 lscope.ml: CEA_LGPL_OR_PROPRIETARY.E_ACSL
diff --git a/src/plugins/e-acsl/interval.ml b/src/plugins/e-acsl/interval.ml
index e2186708be58fcaa74693a8db9bbf956aaeafbca..0332ee10c8f66dd52fed572a6260a86dcc72ddd5 100644
--- a/src/plugins/e-acsl/interval.ml
+++ b/src/plugins/e-acsl/interval.ml
@@ -25,16 +25,24 @@ open Cil_types
 (* Implement Figure 3 of J. Signoles' JFLA'15 paper "Rester statique pour
    devenir plus rapide, plus précis et plus mince". *)
 
-exception Not_an_integer
-
 (* ********************************************************************* *)
 (* Basic datatypes and operations *)
 (* ********************************************************************* *)
 
+exception Not_an_integer
+
 (* constructors *)
 
 let singleton_of_int n = Ival.inject_singleton (Integer.of_int n)
 
+let interv_of_unknown_block =
+  (* since we have no idea of the size of this block, we take the largest
+     possible one which is unfortunately quite large *)
+  lazy
+    (Ival.inject_range
+       (Some Integer.zero)
+       (Some (Bit_utils.max_byte_address ())))
+
 let rec interv_of_typ ty = match Cil.unrollType ty with
   | TInt (k,_) as ty ->
     let n = Cil.bitsSizeOf ty in
@@ -47,22 +55,118 @@ let rec interv_of_typ ty = match Cil.unrollType ty with
   | _ ->
     raise Not_an_integer
 
-let interv_of_unknown_block =
-  (* since we have no idea of the size of this block, we take the largest
-     possible one which is unfortunately quite large *)
-  lazy
-    (Ival.inject_range (Some Integer.zero) (Some (Bit_utils.max_byte_address ())))
+let interv_of_logic_typ = function
+  | Ctype ty -> interv_of_typ ty
+  | Linteger -> Ival.inject_range None None
+  | Ltype _ -> Error.not_yet "user-defined logic type"
+  | Lvar _ -> Error.not_yet "type variable"
+  | Lreal -> Error.not_yet "real number"
+  | Larrow _ -> Error.not_yet "functional type"
 
-(* imperative environments *)
+let ikind_of_interv i =
+  if Ival.is_bottom i then IInt
+  else match Ival.min_and_max i with
+    | Some l, Some u ->
+      let is_pos = Integer.ge l Integer.zero in
+      let lkind = Cil.intKindForValue l is_pos in
+      let ukind = Cil.intKindForValue u is_pos in
+      (* kind corresponding to the interval *)
+      let kind = if Cil.intTypeIncluded lkind ukind then ukind else lkind in
+      (* convert the kind to [IInt] whenever smaller. *)
+      if Cil.intTypeIncluded kind IInt then IInt else kind
+    | None, None -> raise Cil.Not_representable (* GMP *)
+    | None, Some _ | Some _, None ->
+      Kernel.fatal ~current:true "ival: %a" Ival.pretty i
 
-module Env = struct
+(* Imperative environments *)
+module rec Env: sig
+  val clear: unit -> unit
+  val add: Cil_types.logic_var -> Ival.t -> unit
+  val find: Cil_types.logic_var -> Ival.t
+  val remove: Cil_types.logic_var -> unit
+  val replace: Cil_types.logic_var -> Ival.t -> unit
+end = struct
   open Cil_datatype
   let tbl: Ival.t Logic_var.Hashtbl.t = Logic_var.Hashtbl.create 7
-  let clear () = Logic_var.Hashtbl.clear tbl
+
   let add = Logic_var.Hashtbl.add tbl
   let remove = Logic_var.Hashtbl.remove tbl
   let replace = Logic_var.Hashtbl.replace tbl
   let find = Logic_var.Hashtbl.find tbl
+
+  let clear () =
+    Logic_var.Hashtbl.clear tbl;
+    Logic_function_env.clear ()
+
+end
+
+(* Environment for handling recursive logic functions *)
+and Logic_function_env: sig
+  val widen: infer:(term -> Ival.t) -> term -> Ival.t -> bool * Ival.t
+  val clear: unit -> unit
+end = struct
+
+  module Profile =
+    Datatype.List_with_collections
+      (Ival)
+      (struct
+        let module_name = "E_ACSL.Interval.Logic_function_env.Profile"
+      end)
+
+  module LF =
+    Datatype.Pair_with_collections
+      (Datatype.String)
+      (Profile)
+      (struct
+        let module_name = "E_ACSL.Interval.Logic_function_env.LF"
+      end)
+
+  let tbl = LF.Hashtbl.create 7
+
+  let clear () = LF.Hashtbl.clear tbl
+
+  let interv_of_typ_containing_interv i =
+    try
+      let kind = ikind_of_interv i in
+      interv_of_typ (TInt(kind, []))
+    with Cil.Not_representable ->
+      (* infinity *)
+      Ival.inject_range None None
+
+  let extract_profile ~infer t = match t.term_node with
+    | Tapp(li, _, args) ->
+      li.l_var_info.lv_name,
+      List.map2
+        (fun param arg ->
+           try
+             let i = infer arg in
+             (* over-approximation of the interval to reach the fixpoint
+                faster, and to generate fewer specialized functions *)
+             let larger_i = interv_of_typ_containing_interv i in
+             Env.add param larger_i;
+             larger_i
+           with Not_an_integer ->
+             (* no need to add [param] to the environment *)
+             Ival.bottom)
+        li.l_profile
+        args
+    | _ ->
+      assert false
+
+  let widen ~infer t i =
+    let p = extract_profile ~infer t in
+    try
+      let old_i = LF.Hashtbl.find tbl p in
+      if Ival.is_included i old_i then true, old_i
+      else begin
+        let j = Ival.join i old_i in
+        LF.Hashtbl.replace tbl p j;
+        false, j
+      end
+    with Not_found ->
+      LF.Hashtbl.add tbl p i;
+      false, i
+
 end
 
 (* ********************************************************************* *)
@@ -183,11 +287,28 @@ let rec infer t =
     Ival.meet i1 i2
 
   | Tapp (li, _, _args) ->
-    (match li.l_type with
-    | None -> assert false (* [None] only possible for predicates *)
-    | Some Linteger -> Error.not_yet "logic function returning an integer"
-    | Some (Ctype ty) -> interv_of_typ ty
-    | Some _ -> raise Not_an_integer)
+    (match li.l_body with
+     | LBpred _ ->
+       Ival.zero_or_one
+     | LBterm t' ->
+       let rec fixpoint i =
+         let is_included, new_i = Logic_function_env.widen ~infer t i in
+         if is_included then begin
+           List.iter (fun lv -> Env.remove lv) li.l_profile;
+           new_i
+         end else
+           let i = infer t' in
+           List.iter (fun lv -> Env.remove lv) li.l_profile;
+           fixpoint i
+       in
+       fixpoint Ival.bottom
+     | LBnone
+     | LBreads _ ->
+       (match li.l_type with
+       | None -> assert false
+       | Some ret_type -> interv_of_logic_typ ret_type)
+     | LBinductive _ ->
+       Error.not_yet "logic functions inductively defined")
   | Tunion _ -> Error.not_yet "tset union"
   | Tinter _ -> Error.not_yet "tset intersection"
   | Tcomprehension (_,_,_) -> Error.not_yet "tset comprehension"
@@ -230,7 +351,18 @@ and infer_term_lval (host, offset as tlv) =
 and infer_term_host = function
   | TVar v ->
     (try Env.find v
-     with Not_found -> interv_of_typ (Logic_utils.logicCType v.lv_type))
+     with Not_found ->
+     match v.lv_type with
+     | Linteger ->
+       Ival.inject_range None None
+     | Ctype (TFloat _) -> (* TODO: handle in MR !226 *)
+       raise Not_an_integer
+     | Lreal ->
+       Error.not_yet "real numbers"
+     | Ctype _ ->
+       interv_of_typ (Logic_utils.logicCType v.lv_type)
+     | Ltype _ | Lvar _ | Larrow _ ->
+       Options.fatal "unexpected logic type")
   | TResult ty -> interv_of_typ ty
   | TMem t ->
     let ty = Logic_utils.logicCType t.term_type in
diff --git a/src/plugins/e-acsl/interval.mli b/src/plugins/e-acsl/interval.mli
index 0a1e07d7b7845b5cb3305271bd22b74c452e3ffe..79ed83499b5327cba1d3e522657666de819079a7 100644
--- a/src/plugins/e-acsl/interval.mli
+++ b/src/plugins/e-acsl/interval.mli
@@ -52,6 +52,11 @@
 
 exception Not_an_integer
 
+val ikind_of_interv: Ival.t -> Cil_types.ikind
+(** @return the smallest ikind that contains the given interval.
+    @raise Cil.Not_representable if the given interval does not fit into any C
+    integral type. *)
+
 val interv_of_typ: Cil_types.typ -> Ival.t
 (** @return the smallest interval which contains the given C type.
     @raise Not_an_integer if the given type is not an integral type. *)
diff --git a/src/plugins/e-acsl/keep_status.ml b/src/plugins/e-acsl/keep_status.ml
index 69da42233489b929b8025a7f71693ced59b58002..cb76ec3fcc5a2f673d3a6b2a63ca37dca8ab2635 100644
--- a/src/plugins/e-acsl/keep_status.ml
+++ b/src/plugins/e-acsl/keep_status.ml
@@ -131,6 +131,7 @@ let must_translate kf kind =
        duplicate by [Dup_function] but they are still associated to the original
        function here *)
     let name = Functions.RTL.get_original_name kf in
+    try
     let info =
       try Datatype.String.Hashtbl.find keep_status name
       with Not_found ->
@@ -148,3 +149,4 @@ let must_translate kf kind =
         pretty_kind kind
         pretty_kind kind';
     keep
+    with Not_found -> true
diff --git a/src/plugins/e-acsl/logic_functions.ml b/src/plugins/e-acsl/logic_functions.ml
new file mode 100644
index 0000000000000000000000000000000000000000..8955a154b2531cbb01d60aacf7ddb4b1dacdaf82
--- /dev/null
+++ b/src/plugins/e-acsl/logic_functions.ml
@@ -0,0 +1,344 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+open Cil_datatype
+
+(**************************************************************************)
+(********************** Forward references ********************************)
+(**************************************************************************)
+
+let named_predicate_to_exp_ref
+  : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref
+  = Extlib.mk_fun "named_predicate_to_exp_ref"
+
+let term_to_exp_ref
+  : (kernel_function -> Env.t -> term -> exp * Env.t) ref
+  = Extlib.mk_fun "term_to_exp_ref"
+
+(*****************************************************************************)
+(************************** Auxiliary  functions* ****************************)
+(*****************************************************************************)
+
+(* @return true iff the result of the function is provided by reference as the
+   first extra argument at each call *)
+let result_as_extra_argument = Gmpz.is_t
+(* TODO: to be extended to any compound type? E.g. returning a struct is not
+   good practice... *)
+
+(*****************************************************************************)
+(****************** Generation of function bodies ****************************)
+(*****************************************************************************)
+
+(* Generate the block of code containing the statement assigning [e] to [ret_vi]
+   (the result). *)
+let generate_return_block ~loc env ret_vi e = match e.enode with
+  | Lval (Var _, NoOffset) ->
+    (* the returned value is a variable: Cil invariant preserved;
+       no need of [ret_vi] *)
+    let return_retres = Cil.mkStmt ~valid_sid:true (Return (Some e, loc)) in
+    let b, env =
+      Env.pop_and_get env return_retres ~global_clear:false Env.After
+    in
+    b.blocals <- b.blocals;
+    b.bscoping <- true;
+    b, env
+  | _ ->
+    (* the returned value is _not_ a variable: restore the invariant *)
+    let init = AssignInit (SingleInit e) in
+    let set =
+      Cil.mkStmtOneInstr ~valid_sid:true (Local_init (ret_vi, init, loc))
+    in
+    let return =
+      Cil.mkStmt ~valid_sid:true (Return (Some (Cil.evar ~loc ret_vi), loc))
+    in
+    let b, env = Env.pop_and_get env set ~global_clear:false Env.Middle in
+    ret_vi.vdefined <- true;
+    b.blocals <- ret_vi :: b.blocals;
+    b.bstmts <- b.bstmts @ [ return ];
+    b.bscoping <- true;
+    b, env
+
+(* Generate the function's body for predicates. *)
+let pred_to_block ~loc kf env ret_vi p =
+  Typing.type_named_predicate ~must_clear:false p;
+  let e, env = !named_predicate_to_exp_ref kf env p in
+  (* for predicate, since the result is either 0 or 1, return it directly (it
+     cannot be provided as extra argument *)
+  generate_return_block ~loc env ret_vi e
+
+(* Generate the function's body for terms. *)
+let term_to_block ~loc kf env ret_ty ret_vi t =
+  Typing.type_term ~use_gmp_opt:false ~ctx:(Typing.integer_ty_of_typ ret_ty) t;
+  let e, env = !term_to_exp_ref kf env t in
+  if Cil.isVoidType ret_ty then
+    (* if the function's result is a GMP, it is the first parameter of the
+       function (by reference). *)
+    let set =
+      let lv_star_ret = Cil.mkMem ~addr:(Cil.evar ~loc ret_vi) ~off:NoOffset in
+      let star_ret = Cil.new_exp ~loc (Lval lv_star_ret) in
+      Gmpz.init_set ~loc lv_star_ret star_ret e
+    in
+    let return_void = Cil.mkStmt ~valid_sid:true (Return (None, loc)) in
+    let b, env = Env.pop_and_get env set ~global_clear:false Env.Middle in
+    b.bstmts <- b.bstmts @ [ return_void ];
+    b.bscoping <- true;
+    b, env
+  else
+    generate_return_block ~loc env ret_vi e
+
+let generate_body ~loc kf env ret_ty ret_vi = function
+  | LBnone | LBreads _ ->
+    Options.abort
+      "logic function or predicate without explicit definition are not part of \
+       E-ACSL"
+  | LBterm t -> term_to_block ~loc kf env ret_ty ret_vi t
+  | LBpred p -> pred_to_block ~loc kf env ret_vi p
+  | LBinductive _ -> Error.not_yet "inductive definition"
+
+(* Generate a kernel function from a given logic info [li] *)
+let generate_kf ~loc fname env ret_ty params_ty li =
+  (* build the formal parameters *)
+  let params, params_ty =
+    List.fold_right2
+      (fun lvi pty (params, params_ty) ->
+        let ty = match pty with
+          | Typing.Gmp ->
+            (* GMP's integer are arrays: consider them as pointers in function's
+               parameters *)
+            Gmpz.t_ptr ()
+          | Typing.C_type ik -> TInt(ik, [])
+          | Typing.Other -> Typing.typ_of_lty lvi.lv_type
+        in
+        (* build the formals: cannot use [Cil.makeFormal] since the function
+           does not yet exist *)
+        let vi = Cil.makeVarinfo false true lvi.lv_name ty in
+        vi :: params, (lvi.lv_name, ty, []) :: params_ty)
+      li.l_profile
+      params_ty
+      ([], [])
+  in
+  (* build the varinfo storing the result *)
+  let ret_vi, ret_ty, params_with_ret, params_ty_with_ret =
+    let vname = "__retres" in
+    if result_as_extra_argument ret_ty then
+      let ret_ty_ptr = TPtr(ret_ty, []) (* call by reference *) in
+      let vname = vname ^ "_arg" in
+      let vi = Cil.makeVarinfo false true vname ret_ty_ptr in
+      vi, Cil.voidType, vi :: params, (vname, ret_ty_ptr, []) :: params_ty
+    else
+      Cil.makeVarinfo false false vname ret_ty, ret_ty, params, params_ty
+  in
+  (* build the function's varinfo *)
+  let vi =
+    Cil.makeGlobalVar
+      fname
+      (TFun
+         (ret_ty,
+          Some params_ty_with_ret,
+          false,
+          li.l_var_info.lv_attr))
+  in
+  vi.vdefined <- true;
+  (* create the fundec *)
+  let fundec =
+    { svar = vi;
+      sformals = params_with_ret;
+      slocals = []; (* filled later to break mutual dependencies between
+                       creating this list and creating the kf *)
+      smaxid = 0;
+      sbody = Cil.mkBlock []; (* filled later; same as above *)
+      smaxstmtid = None;
+      sallstmts = [];
+      sspec = Cil.empty_funspec () }
+  in
+  Cil.setMaxId fundec;
+  let spec = Cil.empty_funspec () in
+  Queue.add
+    (fun () -> Globals.Functions.replace_by_definition spec fundec loc)
+    (Env.get_visitor env)#get_filling_actions;
+  (* create the kernel function itself *)
+  let kf = { fundec = Definition(fundec, loc); spec } in
+  (* closure generating the function's body.
+     Delay its generation after filling the memoisation table (for termination
+     of recursive function calls) *)
+  let gen_body () =
+    let env = Env.push env in
+    let old_kf = Extlib.the (Env.current_kf env) in
+    Env.set_current_kf env kf;
+    (* fill the typing environment with the function's parameters
+       before generating the code (code generation invokes typing) *)
+    let env =
+      let add env lvi vi =
+        (match vi.vtype with
+        | TInt _ as ty -> Interval.Env.add lvi (Interval.interv_of_typ ty)
+        | ty ->
+          if Gmpz.is_t ty then
+            Interval.Env.add lvi (Ival.inject_range None None));
+        Env.Logic_binding.add_binding env lvi vi
+      in
+      List.fold_left2 add env li.l_profile params
+    in
+    let b, env = generate_body ~loc kf env ret_ty ret_vi li.l_body in
+    fundec.sbody <- b;
+    (* add the generated variables in the necessary lists *)
+    (* TODO: factorized the code below that add the generated vars with method
+       [add_generated_variables_in_function] in the main visitor *)
+    let vars =
+      let l = Env.get_generated_variables env in
+      if ret_vi.vdefined then (ret_vi, Env.LFunction kf) :: l else l
+    in
+    let locals, blocks =
+      List.fold_left
+        (fun (local_vars, block_vars as acc) (v, scope) -> match scope with
+        | Env.LFunction kf' when Kernel_function.equal kf kf' ->
+          v :: local_vars, block_vars
+        | Env.LLocal_block kf' when Kernel_function.equal kf kf' ->
+          v :: local_vars, block_vars
+        | _ -> acc)
+        (fundec.slocals, fundec.sbody.blocals)
+        vars
+    in
+    fundec.slocals <- locals;
+    fundec.sbody.blocals <- blocks;
+    List.iter
+      (fun lvi ->
+         Interval.Env.remove lvi;
+         ignore (Env.Logic_binding.remove env lvi))
+      li.l_profile;
+    Env.set_current_kf
+      env
+      (Cil.get_original_kernel_function (Env.get_behavior env) old_kf)
+  in
+  vi, kf, gen_body
+
+(**************************************************************************)
+(***************************** Memoization ********************************)
+(**************************************************************************)
+
+module Params_ty =
+  Datatype.List_with_collections
+    (Typing.Datatype)
+    (struct let module_name = "E_ACSL.Logic_functions.Params_ty" end)
+
+(* for each logic_info, associate its possible profiles, i.e. the types of its
+   parameters + the generated varinfo for the function *)
+let memo_tbl:
+    kernel_function Params_ty.Hashtbl.t Logic_info.Hashtbl.t
+  = Logic_info.Hashtbl.create 7
+
+let reset () = Logic_info.Hashtbl.clear memo_tbl
+
+let add_generated_functions globals =
+  let rec aux acc = function
+    | [] ->
+      acc
+    | GAnnot(Dfun_or_pred(li, loc), _) as g :: l ->
+      let acc = g :: acc in
+      (try
+         (* add the declarations close to its corresponding logic function or
+            predicate *)
+         let params = Logic_info.Hashtbl.find memo_tbl li in
+         let add_fundecl kf acc =
+           GFunDecl(Cil.empty_funspec (), Kernel_function.get_vi kf, loc)
+           :: acc
+         in
+         aux (Params_ty.Hashtbl.fold (fun _ -> add_fundecl) params acc) l
+       with Not_found ->
+         aux acc l)
+    | g :: l ->
+      aux (g :: acc) l
+  in
+  let rev_globals = aux [] globals in
+  (* add the definitions at the end of [globals] *)
+  let add_fundec kf globals =
+    let fundec =
+      try Kernel_function.get_definition kf
+      with Kernel_function.No_Definition -> assert false
+    in
+    GFun(fundec, Location.unknown) :: globals
+  in
+  let rev_globals =
+    Logic_info.Hashtbl.fold
+      (fun _ -> Params_ty.Hashtbl.fold (fun _ -> add_fundec))
+      memo_tbl
+      rev_globals
+  in
+  List.rev rev_globals
+
+let tapp_to_exp ~loc fname env t li params_ty args =
+  let ret_ty = Typing.get_typ t in
+  let gen tbl =
+    let vi, kf, gen_body = generate_kf fname ~loc env ret_ty params_ty li in
+    Params_ty.Hashtbl.add tbl params_ty kf;
+    vi, gen_body
+  in
+  (* memoise the function's varinfo *)
+  let fvi, gen_body =
+    try
+      let h = Logic_info.Hashtbl.find memo_tbl li in
+      try
+        let kf = Params_ty.Hashtbl.find h params_ty in
+        Kernel_function.get_vi kf,
+        (fun () -> ()) (* body generation already planified *)
+      with Not_found -> gen h
+    with Not_found ->
+      let h = Params_ty.Hashtbl.create 7 in
+      Logic_info.Hashtbl.add memo_tbl li h;
+      gen h
+  in
+  (* the generation of the function body must be performed after memoizing the
+     kernel function in order to handle recursive calls in finite time :-) *)
+  gen_body ();
+  (* create the function call for the tapp *)
+  let mkcall vi =
+    let mk_args types args =
+      match types (* generated by E-ACSL: no need to unroll *) with
+      | TFun(_, Some params, _, _) ->
+        (* additional casts are necessary whenever the argument is GMP and the
+           parameter is a (small) integralType: after handling the context in
+           [Translate] through [add_cast], the GMP has been translated into a
+           [long] (that is what provided the GMP API). This [long] must now be
+           translated to the parameter's type. It cannot be done before since
+           the exact type of the parameter is only computed when the function is
+           generated *)
+        List.map2
+          (fun (_, newt, _) e -> Cil.mkCast ~force:false ~newt ~e)
+          params
+          args
+      | _ -> assert false
+    in
+    if result_as_extra_argument ret_ty then
+      let args = mk_args fvi.vtype (Cil.mkAddrOf ~loc (Cil.var vi) :: args) in
+      Call(None, Cil.evar fvi, args, loc)
+    else
+      let args = mk_args fvi.vtype args in
+      Call(Some (Cil.var vi), Cil.evar fvi, args, loc)
+  in
+  (* generate the varinfo storing the result of the call *)
+  Env.new_var
+    ~loc
+    ~name:li.l_var_info.lv_name
+    env
+    (Some t)
+    ret_ty
+    (fun vi _ -> [ Cil.mkStmtOneInstr ~valid_sid:true (mkcall vi) ])
diff --git a/src/plugins/e-acsl/logic_functions.mli b/src/plugins/e-acsl/logic_functions.mli
new file mode 100644
index 0000000000000000000000000000000000000000..3e2c0d25c90e0714ad4fa660be492725c12359c8
--- /dev/null
+++ b/src/plugins/e-acsl/logic_functions.mli
@@ -0,0 +1,56 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2018                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+
+(** Generate C implementations of user-defined logic functions.
+    A logic function can have multiple C implementations depending on
+    the types computed for its arguments.
+    Eg: Consider the following definition: [integer g(integer x) = x]
+      with the following calls: [g(5)] and [g(10*INT_MAX)]
+      They will respectively generate the C prototypes [int g_1(int)]
+      and [long g_2(long)] *)
+
+(**************************************************************************)
+(************** Logic functions without labels ****************************)
+(**************************************************************************)
+
+val reset: unit -> unit
+
+val tapp_to_exp:
+  loc:location ->
+  string -> Env.t -> term -> logic_info -> Typing.integer_ty list -> exp list ->
+  varinfo * exp * Env.t
+
+val add_generated_functions: global list -> global list
+(* @return the input list of globals in which the generated functions have been
+   inserted at the right places (both their declaration and their definition) *)
+
+(**************************************************************************)
+(********************** Forward references ********************************)
+(**************************************************************************)
+
+val named_predicate_to_exp_ref:
+  (kernel_function -> Env.t -> predicate -> exp * Env.t) ref
+
+val term_to_exp_ref:
+  (kernel_function -> Env.t -> term -> exp * Env.t) ref
diff --git a/src/plugins/e-acsl/loops.ml b/src/plugins/e-acsl/loops.ml
index ea01ce00c635171832c265e10c6286b52b686d36..a6da567257aefb138decb63d0fcbdd37cf3ded15 100644
--- a/src/plugins/e-acsl/loops.ml
+++ b/src/plugins/e-acsl/loops.ml
@@ -297,7 +297,7 @@ let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars =
         Some break_stmt))
     in
     (* remove logic binding before returning *)
-    let env = Env.Logic_binding.remove env logic_x in
+    Env.Logic_binding.remove env logic_x;
     [ start ;  stmt ], env
   | Lscope.Lvs_let(lv, t) :: lscope_vars' ->
     let ty = Typing.get_typ t in
@@ -308,7 +308,7 @@ let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars =
       mk_nested_loops ~loc mk_innermost_block kf env lscope_vars'
     in
     (* remove logic binding now that the block is constructed *)
-    let env = Env.Logic_binding.remove env lv in
+    Env.Logic_binding.remove env lv;
     (* return *)
     let_stmt :: stmts, env
   | Lscope.Lvs_formal _ :: _ ->
diff --git a/src/plugins/e-acsl/misc.mli b/src/plugins/e-acsl/misc.mli
index 8f12597aa044599b664b993210e6b3d46b9bc53a..3fd7f4c409ccb25804d2f907a0c080be88d81673 100644
--- a/src/plugins/e-acsl/misc.mli
+++ b/src/plugins/e-acsl/misc.mli
@@ -93,7 +93,7 @@ val reorder_ast: unit -> unit
  * the very top of the file. *)
 
 val cty: logic_type -> typ
-(* Assume that the logic type is indeed a C type. Just return it. *)
+(** Assume that the logic type is indeed a C type. Just return it. *)
 
 val ptr_index: ?loc:location -> ?index:exp -> exp
   -> Cil_types.exp * Cil_types.exp
@@ -101,31 +101,31 @@ val ptr_index: ?loc:location -> ?index:exp -> exp
 pointer and integer parts. *)
 
 val term_of_li: logic_info -> term
-(* [term_of_li li] assumes that [li.l_body] matches [LBterm t]
+(** [term_of_li li] assumes that [li.l_body] matches [LBterm t]
    and returns [t]. *)
 
 val is_set_of_ptr_or_array: logic_type -> bool
-(* Checks whether the given logic type is a set of pointers. *)
+(** Checks whether the given logic type is a set of pointers. *)
 
 val is_range_free: term -> bool
-(* Returns [true] iff the given term does not contain any range. *)
+(** Returns [true] iff the given term does not contain any range. *)
 
 val is_bitfield_pointers: logic_type -> bool
-(* Returns [true] iff the given logic type is a bitfield pointer or a
+(** Returns [true] iff the given logic type is a bitfield pointer or a
    set of bitfield pointers. *)
 
 val term_has_lv_from_vi: term -> bool
-(* Return [true] iff the given term contains a variables that originates from
+(** Return [true] iff the given term contains a variables that originates from
   a C varinfo, that is a non-purely logic variable. *)
 
 type pred_or_term = PoT_pred of predicate | PoT_term of term
 
 val mk_ptr_sizeof: typ -> location -> exp
-(* [mk_ptr_sizeof ptr_typ loc] takes the pointer typ [ptr_typ] that points
+(** [mk_ptr_sizeof ptr_typ loc] takes the pointer typ [ptr_typ] that points
    to a [typ] typ and returns [sizeof(typ)]. *)
 
 val finite_min_and_max: Ival.t -> Integer.t * Integer.t
-(* [finite_min_and_max i] takes the finite ival [i] and returns its bounds *)
+(** [finite_min_and_max i] takes the finite ival [i] and returns its bounds *)
 
 (*
 Local Variables:
diff --git a/src/plugins/e-acsl/tests/bts/oracle/bts1307.res.oracle b/src/plugins/e-acsl/tests/bts/oracle/bts1307.res.oracle
index 15637955c83af4061c768c1c2e6d89f38d503997..827a26321492b61e202620b8b9a693ee43c628ba 100644
--- a/src/plugins/e-acsl/tests/bts/oracle/bts1307.res.oracle
+++ b/src/plugins/e-acsl/tests/bts/oracle/bts1307.res.oracle
@@ -4,23 +4,29 @@
 [e-acsl] beginning translation.
 [e-acsl] tests/bts/bts1307.i:23: Warning: approximating a real number by a float
 [e-acsl] tests/bts/bts1307.i:23: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/bts/bts1307.i:23: Warning: approximating a real number by a float
 [e-acsl] tests/bts/bts1307.i:23: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/bts/bts1307.i:11: Warning: approximating a real number by a float
 [e-acsl] tests/bts/bts1307.i:11: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/bts/bts1307.i:11: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/bts/bts1307.i:11: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/bts/bts1307.i:11: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
diff --git a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
index bfc158802d840c137876975f13346e34b5a2db15..79a76e5072ff36d4a82c3117a1502245997c1ce1 100644
--- a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle
@@ -28,7 +28,8 @@
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/stdio.h:82: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with no definition nor reads clause'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/stdio.h:82: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
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 72731f940f00df5cf7fccaa6f458428c7b854c64..61c88433a84b1f2c0017dcf6b44e3cf8e7a45164 100644
--- a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
+++ b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle
@@ -18,7 +18,7 @@
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
 [e-acsl] FRAMAC_SHARE/libc/string.h:327: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:328: Warning: 
   E-ACSL construct `logic function returning an integer' is not yet supported.
@@ -29,31 +29,36 @@
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:333: Warning: 
-  E-ACSL construct `logic function returning an integer' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:143: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:157: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:146: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:146: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:153: Warning: 
-  E-ACSL construct `user-defined logic type' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:111: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:111: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:113: Warning: 
-  E-ACSL construct `logic function returning an integer' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:113: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
diff --git a/src/plugins/e-acsl/tests/gmp/functions.c b/src/plugins/e-acsl/tests/gmp/functions.c
new file mode 100644
index 0000000000000000000000000000000000000000..80f796bad6a411b8a1b6a62cec3b07e2d481e244
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/functions.c
@@ -0,0 +1,72 @@
+/* run.config
+   COMMENT: logic functions without labels
+*/
+
+/*@ predicate p1(int x, int y) = x + y > 0; */
+/*@ predicate p2(integer x, integer y) = x + y > 0; */
+
+/*@ logic integer f1(integer x, integer y) = x + y; */
+
+// E-ACSL integer typing:
+// types less than int are considered as int
+/*@ logic char h_char(char c) = c; */
+/*@ logic short h_short(short s) = s; */
+
+/*@ logic int g_hidden(int x) = x; */
+/*@ logic int g(int x) = g_hidden(x); */
+
+struct mystruct { int k, l; };
+typedef struct mystruct mystruct;
+/*@ logic mystruct t1(mystruct m) = m; */
+/*@ logic integer t2(mystruct m) = m.k + m.l; */
+
+// To test function call in other clauses than assert:
+/*@ predicate k_pred(integer x) = x > 0; */
+/*@ requires k_pred(x); */
+void k(int x) {}
+
+// To test non-interference with global inits:
+int glob = 5;
+
+// To test that functions that are never called are not generated:
+/*@ predicate never_called(int x) = x == x; */
+
+/*@ logic double f2(double x) = (double)(1/x); */ /* handle in MR !226 */
+
+// To test not_yet:
+/*@ predicate p_notyet{L}(integer x) = x > 0; */
+/*@ logic integer f_notyet{L}(integer x) = x; */
+
+int main (void) {
+  int x = 1, y = 2;
+  /*@ assert p1(x, y); */ ;
+  /*@ assert p2(3, 4); */ ;
+  /*@ assert p2(5, 99999999999999999999999999999); */ ;
+
+  /*@ assert f1(x, y) == 3; */ ;
+  /*@ assert p2(x, f1(3, 4)); */ ;
+  /*@ assert f1(9, 99999999999999999999999999999) > 0; */ ;
+  /*@ assert f1(99999999999999999999999999999,
+                 99999999999999999999999999999) ==
+                 199999999999999999999999999998; */ ;
+
+  /*@ assert g(x) == x; */ ;
+
+  char c = 'c';
+  /*@ assert h_char(c) == c; */ ;
+  short s = 1;
+  /*@ assert h_short(s) == s; */ ;
+
+  mystruct m;
+  m.k = 8;
+  m.l = 9;
+  /*@ assert t2(t1(m)) == 17; */ ;
+
+  k(9);
+
+  // not yet supported
+  /* double d = 2.0; */
+  /* /\*@ assert f2(d) > 0; *\/ ; */
+  /* /\*@ assert p_notyet(27); *\/ ; */
+  /* /\*@ assert f_notyet(27) == 27; *\/ ; */
+}
diff --git a/src/plugins/e-acsl/tests/gmp/functions_contiki.c b/src/plugins/e-acsl/tests/gmp/functions_contiki.c
new file mode 100644
index 0000000000000000000000000000000000000000..382a1a64b9ef6fd97bc358a2ca031e1238d32935
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/functions_contiki.c
@@ -0,0 +1,28 @@
+/* run.config
+   COMMENT: functions used in Contiki
+*/
+
+#include <stdlib.h>
+#include <limits.h>
+
+struct list {
+  struct list *next;
+  int value;
+};
+
+/*@
+  logic integer length_aux(struct list *l, integer n) =
+    n < 0 ? -1 :
+      l == NULL ? n :
+        n < INT_MAX ? length_aux(l->next, n+1) :
+          -1;
+  logic integer length(struct list *l) = length_aux(l, 0);
+*/
+
+int main (void) {
+  struct list node1, node2, node3;
+  node1.next = &node2;
+  node2.next = &node3;
+  struct list *l = &node1;
+  /*@ assert length(l) == 3; */ ;
+}
\ No newline at end of file
diff --git a/src/plugins/e-acsl/tests/gmp/functions_rec.c b/src/plugins/e-acsl/tests/gmp/functions_rec.c
new file mode 100644
index 0000000000000000000000000000000000000000..76c60912194b4481bc8e6f06bb94b8f522b6a2d4
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/functions_rec.c
@@ -0,0 +1,31 @@
+/* run.config
+   COMMENT: recursive logic functions
+   STDOPT: +"-eva-ignore-recursive-calls"
+*/
+
+/*@ logic integer f1(integer n) =
+    n <= 0 ? 0 : f1(n - 1) + n; */
+
+/*@ logic integer f2(integer n) =
+    n < 0 ? 1 : f2(n - 1)*f2(n - 2)/f2(n - 3); */
+
+/*@ logic integer g(integer n) = 0; */
+/*@ logic integer f3(integer n) =
+    n > 0 ? g(n)*f3(n - 1) - 5 : g(n + 1); */
+
+/*@ logic integer f4(integer n) =
+    n < 100 ? f4(n + 1) :
+    n < 0x7fffffffffffffffL ? 0x7fffffffffffffffL :
+    6; */
+
+int main (void) {
+  //  /*@ assert f1(0) == 0; */ ;
+  //  /*@ assert f1(1) == 1; */ ;
+  //  /*@ assert f1(100) == 5050; */ ;
+
+   /*@ assert f2(7) == 1; */ ;
+
+  /*@ assert f3(6) == -5; */ ;
+
+  /*@ assert f4(9) > 0; */ ;
+}
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/functions.0.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/functions.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..b922d39b016f315e1b7441fce2762b8fc579c1b4
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/functions.0.res.oracle
@@ -0,0 +1,31 @@
+[e-acsl] beginning translation.
+[e-acsl] translation done in project "e-acsl".
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  __e_acsl_init ∈ [--..--]
+  __e_acsl_heap_allocation_size ∈ [--..--]
+  __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  glob ∈ {5}
+  __e_acsl_sound_verdict ∈ [--..--]
+[eva] using specification for function __e_acsl_memory_init
+[eva] using specification for function __e_acsl_assert
+[eva] using specification for function __gmpz_init_set_str
+[eva] using specification for function __gmpz_init_set_si
+[eva] using specification for function __gmpz_init
+[eva] using specification for function __gmpz_add
+[eva] using specification for function __gmpz_cmp
+[eva] using specification for function __gmpz_clear
+[eva:alarm] tests/gmp/functions.c:44: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:47: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] using specification for function __gmpz_init_set
+[eva:alarm] tests/gmp/functions.c:48: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:49: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/functions.1.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/functions.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6a88f942fbca56a062bb6516e4b0a01940d1817c
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/functions.1.res.oracle
@@ -0,0 +1,50 @@
+[e-acsl] beginning translation.
+[e-acsl] translation done in project "e-acsl".
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  __e_acsl_init ∈ [--..--]
+  __e_acsl_heap_allocation_size ∈ [--..--]
+  __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  glob ∈ {5}
+  __e_acsl_sound_verdict ∈ [--..--]
+[eva] using specification for function __e_acsl_memory_init
+[eva] using specification for function __gmpz_init_set_si
+[eva] using specification for function __gmpz_init
+[eva] using specification for function __gmpz_add
+[eva] using specification for function __gmpz_cmp
+[eva] using specification for function __gmpz_clear
+[eva] using specification for function __e_acsl_assert
+[eva:alarm] tests/gmp/functions.c:42: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:43: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] using specification for function __gmpz_init_set_str
+[eva:alarm] tests/gmp/functions.c:44: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] using specification for function __gmpz_init_set
+[eva:alarm] tests/gmp/functions.c:46: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:47: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_f1_4);
+[eva:alarm] tests/gmp/functions.c:47: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:48: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:49: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:53: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:56: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:58: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:63: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions.c:25: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/functions_contiki.0.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/functions_contiki.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c46fcfd437fbe80229820a34f46cab9345c29b1e
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/functions_contiki.0.res.oracle
@@ -0,0 +1,25 @@
+[e-acsl] beginning translation.
+[e-acsl] tests/gmp/functions_contiki.c:27: Warning: 
+  E-ACSL construct `logic functions with labels' is not yet supported.
+  Ignoring annotation.
+[e-acsl] translation done in project "e-acsl".
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  __e_acsl_init ∈ [--..--]
+  __e_acsl_heap_allocation_size ∈ [--..--]
+  __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+[eva] using specification for function __e_acsl_memory_init
+[eva] using specification for function __e_acsl_store_block
+[eva] using specification for function __e_acsl_initialize
+[eva] using specification for function __e_acsl_full_init
+[eva] tests/gmp/functions_contiki.c:27: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function length
+[eva:alarm] tests/gmp/functions_contiki.c:27: Warning: 
+  assertion got status unknown.
+[eva] using specification for function __e_acsl_delete_block
+[eva] using specification for function __e_acsl_memory_clean
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/functions_contiki.1.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/functions_contiki.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c46fcfd437fbe80229820a34f46cab9345c29b1e
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/functions_contiki.1.res.oracle
@@ -0,0 +1,25 @@
+[e-acsl] beginning translation.
+[e-acsl] tests/gmp/functions_contiki.c:27: Warning: 
+  E-ACSL construct `logic functions with labels' is not yet supported.
+  Ignoring annotation.
+[e-acsl] translation done in project "e-acsl".
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  __e_acsl_init ∈ [--..--]
+  __e_acsl_heap_allocation_size ∈ [--..--]
+  __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+[eva] using specification for function __e_acsl_memory_init
+[eva] using specification for function __e_acsl_store_block
+[eva] using specification for function __e_acsl_initialize
+[eva] using specification for function __e_acsl_full_init
+[eva] tests/gmp/functions_contiki.c:27: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function length
+[eva:alarm] tests/gmp/functions_contiki.c:27: Warning: 
+  assertion got status unknown.
+[eva] using specification for function __e_acsl_delete_block
+[eva] using specification for function __e_acsl_memory_clean
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/functions_rec.0.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/functions_rec.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..cbf74d13ac79e1568bba0f82bc91e82493871cf4
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/functions_rec.0.res.oracle
@@ -0,0 +1,87 @@
+[e-acsl] beginning translation.
+[e-acsl] translation done in project "e-acsl".
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  __e_acsl_init ∈ [--..--]
+  __e_acsl_heap_allocation_size ∈ [--..--]
+  __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+[eva] using specification for function __e_acsl_memory_init
+[eva] tests/gmp/functions_rec.c:26: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f2
+[eva:alarm] tests/gmp/functions_rec.c:26: Warning: assertion got status unknown.
+[eva] tests/gmp/functions_rec.c:10: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/gmp/functions_rec.c:10 <-
+                                             __gen_e_acsl_f2 :: tests/gmp/functions_rec.c:26 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva] using specification for function __gen_e_acsl_f2_2
+[eva] tests/gmp/functions_rec.c:10: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/gmp/functions_rec.c:10 <-
+                                             __gen_e_acsl_f2 :: tests/gmp/functions_rec.c:26 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva] tests/gmp/functions_rec.c:10: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/gmp/functions_rec.c:10 <-
+                                             __gen_e_acsl_f2 :: tests/gmp/functions_rec.c:26 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva] using specification for function __e_acsl_assert
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  division by zero. assert __gen_e_acsl_f2_8 ≢ 0;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  signed overflow.
+  assert -2147483648 ≤ __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  signed overflow. assert __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6 ≤ 2147483647;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  signed overflow.
+  assert
+  (int)(__gen_e_acsl_f2_4 * __gen_e_acsl_f2_6) / __gen_e_acsl_f2_8 ≤
+  2147483647;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  division by zero. assert __gen_e_acsl_f2_13 ≢ 0;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  signed overflow.
+  assert -2147483648 ≤ __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  signed overflow.
+  assert __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11 ≤ 2147483647;
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  signed overflow.
+  assert
+  (int)(__gen_e_acsl_f2_9 * __gen_e_acsl_f2_11) / __gen_e_acsl_f2_13 ≤
+  2147483647;
+[eva:alarm] tests/gmp/functions_rec.c:26: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] tests/gmp/functions_rec.c:28: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f3
+[eva:alarm] tests/gmp/functions_rec.c:28: Warning: assertion got status unknown.
+[eva] tests/gmp/functions_rec.c:14: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f3_2 (__gen_e_acsl_f3_2 <- __gen_e_acsl_f3_2 :: tests/gmp/functions_rec.c:14 <-
+                                             __gen_e_acsl_f3 :: tests/gmp/functions_rec.c:28 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva] using specification for function __gen_e_acsl_f3_2
+[eva] tests/gmp/functions_rec.c:30: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f4
+[eva:alarm] tests/gmp/functions_rec.c:30: Warning: assertion got status unknown.
+[eva] tests/gmp/functions_rec.c:17: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f4_2 (__gen_e_acsl_f4_2 <- __gen_e_acsl_f4_2 :: tests/gmp/functions_rec.c:17 <-
+                                             __gen_e_acsl_f4 :: tests/gmp/functions_rec.c:30 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva] using specification for function __gen_e_acsl_f4_2
+[eva:alarm] tests/gmp/functions_rec.c:30: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/functions_rec.1.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/functions_rec.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..ad15ac476ccad3eb4c1c7c322456de28b5dc3c3f
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/functions_rec.1.res.oracle
@@ -0,0 +1,116 @@
+[e-acsl] beginning translation.
+[e-acsl] translation done in project "e-acsl".
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  __e_acsl_init ∈ [--..--]
+  __e_acsl_heap_allocation_size ∈ [--..--]
+  __e_acsl_math_HUGE_VAL ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+  __e_acsl_math_HUGE_VALF ∈ [-3.40282346639e+38 .. 3.40282346639e+38]
+  __e_acsl_math_INFINITY ∈ [-1.79769313486e+308 .. 1.79769313486e+308]
+[eva] using specification for function __e_acsl_memory_init
+[eva] tests/gmp/functions_rec.c:26: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f2
+[eva:alarm] tests/gmp/functions_rec.c:26: Warning: assertion got status unknown.
+[eva] using specification for function __gmpz_init_set_si
+[eva] using specification for function __gmpz_cmp
+[eva] using specification for function __gmpz_init_set
+[eva] using specification for function __gmpz_clear
+[eva] using specification for function __gmpz_init
+[eva] using specification for function __gmpz_sub
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub);
+[eva] tests/gmp/functions_rec.c:10: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/gmp/functions_rec.c:10 <-
+                                             __gen_e_acsl_f2 :: tests/gmp/functions_rec.c:26 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_2);
+[eva] using specification for function __gen_e_acsl_f2_2
+[eva] tests/gmp/functions_rec.c:10: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/gmp/functions_rec.c:10 <-
+                                             __gen_e_acsl_f2 :: tests/gmp/functions_rec.c:26 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_3);
+[eva] using specification for function __gmpz_mul
+[eva] tests/gmp/functions_rec.c:10: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f2_2 (__gen_e_acsl_f2_2 <- __gen_e_acsl_f2_2 :: tests/gmp/functions_rec.c:10 <-
+                                             __gen_e_acsl_f2 :: tests/gmp/functions_rec.c:26 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_4);
+[eva] :0: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f2
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  assertion 'E_ACSL' got status unknown.
+[eva] using specification for function __e_acsl_assert
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] using specification for function __gmpz_tdiv_q
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_5);
+[eva:alarm] tests/gmp/functions_rec.c:10: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_6);
+[eva:alarm] tests/gmp/functions_rec.c:26: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] tests/gmp/functions_rec.c:28: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f3
+[eva:alarm] tests/gmp/functions_rec.c:28: Warning: assertion got status unknown.
+[eva:alarm] tests/gmp/functions_rec.c:14: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_7);
+[eva] using specification for function __gmpz_get_si
+[eva] tests/gmp/functions_rec.c:14: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f3_2 (__gen_e_acsl_f3_2 <- __gen_e_acsl_f3_2 :: tests/gmp/functions_rec.c:14 <-
+                                             __gen_e_acsl_f3 :: tests/gmp/functions_rec.c:28 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva:alarm] tests/gmp/functions_rec.c:14: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_8);
+[eva] using specification for function __gen_e_acsl_f3_2
+[eva] using specification for function __gmpz_add
+[eva:alarm] tests/gmp/functions_rec.c:14: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add);
+[eva:alarm] tests/gmp/functions_rec.c:14: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add_2);
+[eva] using specification for function __gmpz_neg
+[eva:alarm] tests/gmp/functions_rec.c:28: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] tests/gmp/functions_rec.c:30: 
+  cannot evaluate ACSL term, unsupported ACSL construct: logic function f4
+[eva:alarm] tests/gmp/functions_rec.c:30: Warning: assertion got status unknown.
+[eva:alarm] tests/gmp/functions_rec.c:17: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add_3);
+[eva] tests/gmp/functions_rec.c:17: Warning: 
+  recursive call during value analysis
+  of __gen_e_acsl_f4_2 (__gen_e_acsl_f4_2 <- __gen_e_acsl_f4_2 :: tests/gmp/functions_rec.c:17 <-
+                                             __gen_e_acsl_f4 :: tests/gmp/functions_rec.c:30 <-
+                                             main).
+  Assuming the call has no effect. The analysis will be unsound.
+[eva:alarm] tests/gmp/functions_rec.c:17: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add_4);
+[eva] using specification for function __gen_e_acsl_f4_2
+[eva] using specification for function __gmpz_init_set_ui
+[eva:alarm] tests/gmp/functions_rec.c:30: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_functions.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bf6931b3419cd8216a32e4081f39286c417a3f3
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions.c
@@ -0,0 +1,357 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+extern int __e_acsl_sound_verdict;
+
+struct mystruct {
+   int k ;
+   int l ;
+};
+typedef struct mystruct mystruct;
+/*@ predicate p1(int x, int y) = x + y > 0;
+ */
+int __gen_e_acsl_p1(int x, int y);
+
+/*@ predicate p2(ℤ x, ℤ y) = x + y > 0;
+
+*/
+int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y);
+
+int __gen_e_acsl_p2_5(int x, long y);
+
+int __gen_e_acsl_p2(int x, int y);
+
+/*@ logic ℤ f1(ℤ x, ℤ y) = x + y;
+
+*/
+void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x,
+                       __e_acsl_mpz_struct * y);
+
+void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x,
+                       __e_acsl_mpz_struct * y);
+
+long __gen_e_acsl_f1(int x, int y);
+
+/*@ logic char h_char(char c) = c;
+ */
+char __gen_e_acsl_h_char(int c);
+
+/*@ logic short h_short(short s) = s;
+ */
+short __gen_e_acsl_h_short(int s);
+
+/*@ logic int g_hidden(int x) = x;
+ */
+int __gen_e_acsl_g_hidden(int x);
+
+/*@ logic int g(int x) = g_hidden(x);
+ */
+int __gen_e_acsl_g(int x);
+
+/*@ logic mystruct t1(mystruct m) = m;
+ */
+mystruct __gen_e_acsl_t1(mystruct m);
+
+/*@ logic ℤ t2(mystruct m) = m.k + m.l;
+ */
+long __gen_e_acsl_t2(mystruct m);
+
+/*@ predicate k_pred(ℤ x) = x > 0;
+
+*/
+int __gen_e_acsl_k_pred(int x);
+
+/*@ requires k_pred(x); */
+void __gen_e_acsl_k(int x);
+
+void k(int x)
+{
+  return;
+}
+
+int glob = 5;
+/*@ predicate never_called(int x) = x ≡ x;
+ */
+/*@ logic double f2(double x) = (double)(1 / x);
+ */
+/*@ predicate p_notyet{L}(ℤ x) = x > 0;
+ */
+/*@ logic ℤ f_notyet{L}(ℤ x) = x;
+
+*/
+int main(void)
+{
+  int __retres;
+  mystruct m;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  int x = 1;
+  int y = 2;
+  /*@ assert p1(x, y); */
+  {
+    int __gen_e_acsl_p1_2;
+    __gen_e_acsl_p1_2 = __gen_e_acsl_p1(x,y);
+    __e_acsl_assert(__gen_e_acsl_p1_2,(char *)"Assertion",(char *)"main",
+                    (char *)"p1(x, y)",42);
+  }
+  /*@ assert p2(3, 4); */
+  {
+    int __gen_e_acsl_p2_2;
+    __gen_e_acsl_p2_2 = __gen_e_acsl_p2(3,4);
+    __e_acsl_assert(__gen_e_acsl_p2_2,(char *)"Assertion",(char *)"main",
+                    (char *)"p2(3, 4)",43);
+  }
+  /*@ assert p2(5, 99999999999999999999999999999); */
+  {
+    __e_acsl_mpz_t __gen_e_acsl_;
+    int __gen_e_acsl_p2_4;
+    __gmpz_init_set_str(__gen_e_acsl_,"99999999999999999999999999999",10);
+    __gen_e_acsl_p2_4 = __gen_e_acsl_p2_3(5,
+                                          (__e_acsl_mpz_struct *)__gen_e_acsl_);
+    __e_acsl_assert(__gen_e_acsl_p2_4,(char *)"Assertion",(char *)"main",
+                    (char *)"p2(5, 99999999999999999999999999999)",44);
+    __gmpz_clear(__gen_e_acsl_);
+  }
+  /*@ assert f1(x, y) ≡ 3; */
+  {
+    long __gen_e_acsl_f1_2;
+    __gen_e_acsl_f1_2 = __gen_e_acsl_f1(x,y);
+    __e_acsl_assert(__gen_e_acsl_f1_2 == 3L,(char *)"Assertion",
+                    (char *)"main",(char *)"f1(x, y) == 3",46);
+  }
+  /*@ assert p2(x, f1(3, 4)); */
+  {
+    long __gen_e_acsl_f1_4;
+    int __gen_e_acsl_p2_6;
+    __gen_e_acsl_f1_4 = __gen_e_acsl_f1(3,4);
+    __gen_e_acsl_p2_6 = __gen_e_acsl_p2_5(x,__gen_e_acsl_f1_4);
+    __e_acsl_assert(__gen_e_acsl_p2_6,(char *)"Assertion",(char *)"main",
+                    (char *)"p2(x, f1(3, 4))",47);
+  }
+  /*@ assert f1(9, 99999999999999999999999999999) > 0; */
+  {
+    __e_acsl_mpz_t __gen_e_acsl__4;
+    __e_acsl_mpz_t __gen_e_acsl_f1_6;
+    __e_acsl_mpz_t __gen_e_acsl__5;
+    int __gen_e_acsl_gt_3;
+    __gmpz_init_set_str(__gen_e_acsl__4,"99999999999999999999999999999",10);
+    __gen_e_acsl_f1_5(& __gen_e_acsl_f1_6,9,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl__4);
+    __gmpz_init_set_si(__gen_e_acsl__5,0L);
+    __gen_e_acsl_gt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_6),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__5));
+    __e_acsl_assert(__gen_e_acsl_gt_3 > 0,(char *)"Assertion",(char *)"main",
+                    (char *)"f1(9, 99999999999999999999999999999) > 0",48);
+    __gmpz_clear(__gen_e_acsl__4);
+    __gmpz_clear(__gen_e_acsl_f1_6);
+    __gmpz_clear(__gen_e_acsl__5);
+  }
+  /*@ assert
+      f1(99999999999999999999999999999, 99999999999999999999999999999) ≡
+      199999999999999999999999999998;
+  */
+  {
+    __e_acsl_mpz_t __gen_e_acsl__6;
+    __e_acsl_mpz_t __gen_e_acsl_f1_8;
+    __e_acsl_mpz_t __gen_e_acsl__7;
+    int __gen_e_acsl_eq;
+    __gmpz_init_set_str(__gen_e_acsl__6,"99999999999999999999999999999",10);
+    __gen_e_acsl_f1_7(& __gen_e_acsl_f1_8,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl__6,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl__6);
+    __gmpz_init_set_str(__gen_e_acsl__7,"199999999999999999999999999998",10);
+    __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_8),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__7));
+    __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main",
+                    (char *)"f1(99999999999999999999999999999, 99999999999999999999999999999) ==\n199999999999999999999999999998",
+                    49);
+    __gmpz_clear(__gen_e_acsl__6);
+    __gmpz_clear(__gen_e_acsl_f1_8);
+    __gmpz_clear(__gen_e_acsl__7);
+  }
+  /*@ assert g(x) ≡ x; */
+  {
+    int __gen_e_acsl_g_2;
+    __gen_e_acsl_g_2 = __gen_e_acsl_g(x);
+    __e_acsl_assert(__gen_e_acsl_g_2 == x,(char *)"Assertion",(char *)"main",
+                    (char *)"g(x) == x",53);
+  }
+  char c = (char)'c';
+  /*@ assert h_char(c) ≡ c; */
+  {
+    char __gen_e_acsl_h_char_2;
+    __gen_e_acsl_h_char_2 = __gen_e_acsl_h_char((int)c);
+    __e_acsl_assert((int)__gen_e_acsl_h_char_2 == (int)c,(char *)"Assertion",
+                    (char *)"main",(char *)"h_char(c) == c",56);
+  }
+  short s = (short)1;
+  /*@ assert h_short(s) ≡ s; */
+  {
+    short __gen_e_acsl_h_short_2;
+    __gen_e_acsl_h_short_2 = __gen_e_acsl_h_short((int)s);
+    __e_acsl_assert((int)__gen_e_acsl_h_short_2 == (int)s,
+                    (char *)"Assertion",(char *)"main",
+                    (char *)"h_short(s) == s",58);
+  }
+  m.k = 8;
+  m.l = 9;
+  /*@ assert t2(t1(m)) ≡ 17; */
+  {
+    mystruct __gen_e_acsl_t1_2;
+    long __gen_e_acsl_t2_2;
+    __gen_e_acsl_t1_2 = __gen_e_acsl_t1(m);
+    __gen_e_acsl_t2_2 = __gen_e_acsl_t2(__gen_e_acsl_t1_2);
+    __e_acsl_assert(__gen_e_acsl_t2_2 == 17L,(char *)"Assertion",
+                    (char *)"main",(char *)"t2(t1(m)) == 17",63);
+  }
+  __gen_e_acsl_k(9);
+  __retres = 0;
+  return __retres;
+}
+
+/*@ requires k_pred(x); */
+void __gen_e_acsl_k(int x)
+{
+  {
+    int __gen_e_acsl_k_pred_2;
+    __gen_e_acsl_k_pred_2 = __gen_e_acsl_k_pred(x);
+    __e_acsl_assert(__gen_e_acsl_k_pred_2,(char *)"Precondition",(char *)"k",
+                    (char *)"k_pred(x)",25);
+  }
+  k(x);
+  return;
+}
+
+char __gen_e_acsl_h_char(int c)
+{
+  char __retres = (char)c;
+  return __retres;
+}
+
+short __gen_e_acsl_h_short(int s)
+{
+  short __retres = (short)s;
+  return __retres;
+}
+
+int __gen_e_acsl_g_hidden(int x)
+{
+  return x;
+}
+
+int __gen_e_acsl_g(int x)
+{
+  int __gen_e_acsl_g_hidden_2;
+  __gen_e_acsl_g_hidden_2 = __gen_e_acsl_g_hidden(x);
+  return __gen_e_acsl_g_hidden_2;
+}
+
+mystruct __gen_e_acsl_t1(mystruct m)
+{
+  return m;
+}
+
+int __gen_e_acsl_p1(int x, int y)
+{
+  int __retres = x + (long)y > 0L;
+  return __retres;
+}
+
+long __gen_e_acsl_t2(mystruct m)
+{
+  long __retres = m.k + (long)m.l;
+  return __retres;
+}
+
+int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x;
+  __e_acsl_mpz_t __gen_e_acsl_add;
+  __e_acsl_mpz_t __gen_e_acsl__2;
+  int __gen_e_acsl_gt;
+  __gmpz_init_set_si(__gen_e_acsl_x,(long)x);
+  __gmpz_init(__gen_e_acsl_add);
+  __gmpz_add(__gen_e_acsl_add,(__e_acsl_mpz_struct const *)(__gen_e_acsl_x),
+             (__e_acsl_mpz_struct const *)(y));
+  __gmpz_init_set_si(__gen_e_acsl__2,0L);
+  __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add),
+                               (__e_acsl_mpz_struct const *)(__gen_e_acsl__2));
+  int __retres = __gen_e_acsl_gt > 0;
+  __gmpz_clear(__gen_e_acsl_x);
+  __gmpz_clear(__gen_e_acsl_add);
+  __gmpz_clear(__gen_e_acsl__2);
+  return __retres;
+}
+
+int __gen_e_acsl_p2_5(int x, long y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x_2;
+  __e_acsl_mpz_t __gen_e_acsl_y;
+  __e_acsl_mpz_t __gen_e_acsl_add_2;
+  __e_acsl_mpz_t __gen_e_acsl__3;
+  int __gen_e_acsl_gt_2;
+  __gmpz_init_set_si(__gen_e_acsl_x_2,(long)x);
+  __gmpz_init_set_si(__gen_e_acsl_y,y);
+  __gmpz_init(__gen_e_acsl_add_2);
+  __gmpz_add(__gen_e_acsl_add_2,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2),
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_y));
+  __gmpz_init_set_si(__gen_e_acsl__3,0L);
+  __gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__3));
+  int __retres = __gen_e_acsl_gt_2 > 0;
+  __gmpz_clear(__gen_e_acsl_x_2);
+  __gmpz_clear(__gen_e_acsl_y);
+  __gmpz_clear(__gen_e_acsl_add_2);
+  __gmpz_clear(__gen_e_acsl__3);
+  return __retres;
+}
+
+int __gen_e_acsl_p2(int x, int y)
+{
+  int __retres = x + (long)y > 0L;
+  return __retres;
+}
+
+int __gen_e_acsl_k_pred(int x)
+{
+  int __retres = x > 0;
+  return __retres;
+}
+
+void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x,
+                       __e_acsl_mpz_struct * y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_add_4;
+  __gmpz_init(__gen_e_acsl_add_4);
+  __gmpz_add(__gen_e_acsl_add_4,(__e_acsl_mpz_struct const *)(x),
+             (__e_acsl_mpz_struct const *)(y));
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_4));
+  __gmpz_clear(__gen_e_acsl_add_4);
+  return;
+}
+
+void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x,
+                       __e_acsl_mpz_struct * y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x_3;
+  __e_acsl_mpz_t __gen_e_acsl_add_3;
+  __gmpz_init_set_si(__gen_e_acsl_x_3,(long)x);
+  __gmpz_init(__gen_e_acsl_add_3);
+  __gmpz_add(__gen_e_acsl_add_3,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_3),
+             (__e_acsl_mpz_struct const *)(y));
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_3));
+  __gmpz_clear(__gen_e_acsl_x_3);
+  __gmpz_clear(__gen_e_acsl_add_3);
+  return;
+}
+
+long __gen_e_acsl_f1(int x, int y)
+{
+  long __retres = x + (long)y;
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_functions2.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions2.c
new file mode 100644
index 0000000000000000000000000000000000000000..9989adf5ca2bee1aad2ee77c8cb647276dbd3573
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions2.c
@@ -0,0 +1,449 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+extern int __e_acsl_sound_verdict;
+
+struct mystruct {
+   int k ;
+   int l ;
+};
+typedef struct mystruct mystruct;
+/*@ predicate p1(int x, int y) = x + y > 0;
+ */
+int __gen_e_acsl_p1(int x, int y);
+
+/*@ predicate p2(ℤ x, ℤ y) = x + y > 0;
+
+*/
+int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y);
+
+int __gen_e_acsl_p2(int x, int y);
+
+/*@ logic ℤ f1(ℤ x, ℤ y) = x + y;
+
+*/
+void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x,
+                       __e_acsl_mpz_struct * y);
+
+void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x,
+                       __e_acsl_mpz_struct * y);
+
+void __gen_e_acsl_f1(__e_acsl_mpz_t *__retres_arg, int x, int y);
+
+/*@ logic char h_char(char c) = c;
+ */
+char __gen_e_acsl_h_char(int c);
+
+/*@ logic short h_short(short s) = s;
+ */
+short __gen_e_acsl_h_short(int s);
+
+/*@ logic int g_hidden(int x) = x;
+ */
+int __gen_e_acsl_g_hidden(int x);
+
+/*@ logic int g(int x) = g_hidden(x);
+ */
+int __gen_e_acsl_g(int x);
+
+/*@ logic mystruct t1(mystruct m) = m;
+ */
+mystruct __gen_e_acsl_t1(mystruct m);
+
+/*@ logic ℤ t2(mystruct m) = m.k + m.l;
+ */
+void __gen_e_acsl_t2(__e_acsl_mpz_t *__retres_arg, mystruct m);
+
+/*@ predicate k_pred(ℤ x) = x > 0;
+
+*/
+int __gen_e_acsl_k_pred(int x);
+
+/*@ requires k_pred(x); */
+void __gen_e_acsl_k(int x);
+
+void k(int x)
+{
+  return;
+}
+
+int glob = 5;
+/*@ predicate never_called(int x) = x ≡ x;
+ */
+/*@ logic double f2(double x) = (double)(1 / x);
+ */
+/*@ predicate p_notyet{L}(ℤ x) = x > 0;
+ */
+/*@ logic ℤ f_notyet{L}(ℤ x) = x;
+
+*/
+int main(void)
+{
+  int __retres;
+  mystruct m;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  int x = 1;
+  int y = 2;
+  /*@ assert p1(x, y); */
+  {
+    int __gen_e_acsl_p1_2;
+    __gen_e_acsl_p1_2 = __gen_e_acsl_p1(x,y);
+    __e_acsl_assert(__gen_e_acsl_p1_2,(char *)"Assertion",(char *)"main",
+                    (char *)"p1(x, y)",42);
+  }
+  /*@ assert p2(3, 4); */
+  {
+    int __gen_e_acsl_p2_2;
+    __gen_e_acsl_p2_2 = __gen_e_acsl_p2(3,4);
+    __e_acsl_assert(__gen_e_acsl_p2_2,(char *)"Assertion",(char *)"main",
+                    (char *)"p2(3, 4)",43);
+  }
+  /*@ assert p2(5, 99999999999999999999999999999); */
+  {
+    __e_acsl_mpz_t __gen_e_acsl__3;
+    int __gen_e_acsl_p2_4;
+    __gmpz_init_set_str(__gen_e_acsl__3,"99999999999999999999999999999",10);
+    __gen_e_acsl_p2_4 = __gen_e_acsl_p2_3(5,
+                                          (__e_acsl_mpz_struct *)__gen_e_acsl__3);
+    __e_acsl_assert(__gen_e_acsl_p2_4,(char *)"Assertion",(char *)"main",
+                    (char *)"p2(5, 99999999999999999999999999999)",44);
+    __gmpz_clear(__gen_e_acsl__3);
+  }
+  /*@ assert f1(x, y) ≡ 3; */
+  {
+    __e_acsl_mpz_t __gen_e_acsl_f1_2;
+    __e_acsl_mpz_t __gen_e_acsl__5;
+    int __gen_e_acsl_eq;
+    __gen_e_acsl_f1(& __gen_e_acsl_f1_2,x,y);
+    __gmpz_init_set_si(__gen_e_acsl__5,3L);
+    __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_2),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__5));
+    __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main",
+                    (char *)"f1(x, y) == 3",46);
+    __gmpz_clear(__gen_e_acsl_f1_2);
+    __gmpz_clear(__gen_e_acsl__5);
+  }
+  /*@ assert p2(x, f1(3, 4)); */
+  {
+    __e_acsl_mpz_t __gen_e_acsl_f1_4;
+    int __gen_e_acsl_p2_6;
+    __gen_e_acsl_f1(& __gen_e_acsl_f1_4,3,4);
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_f1_4);
+    */
+    __gen_e_acsl_p2_6 = __gen_e_acsl_p2_3(x,
+                                          (__e_acsl_mpz_struct *)__gen_e_acsl_f1_4);
+    __e_acsl_assert(__gen_e_acsl_p2_6,(char *)"Assertion",(char *)"main",
+                    (char *)"p2(x, f1(3, 4))",47);
+    __gmpz_clear(__gen_e_acsl_f1_4);
+  }
+  /*@ assert f1(9, 99999999999999999999999999999) > 0; */
+  {
+    __e_acsl_mpz_t __gen_e_acsl__6;
+    __e_acsl_mpz_t __gen_e_acsl_f1_6;
+    __e_acsl_mpz_t __gen_e_acsl__7;
+    int __gen_e_acsl_gt_4;
+    __gmpz_init_set_str(__gen_e_acsl__6,"99999999999999999999999999999",10);
+    __gen_e_acsl_f1_5(& __gen_e_acsl_f1_6,9,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl__6);
+    __gmpz_init_set_si(__gen_e_acsl__7,0L);
+    __gen_e_acsl_gt_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_6),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__7));
+    __e_acsl_assert(__gen_e_acsl_gt_4 > 0,(char *)"Assertion",(char *)"main",
+                    (char *)"f1(9, 99999999999999999999999999999) > 0",48);
+    __gmpz_clear(__gen_e_acsl__6);
+    __gmpz_clear(__gen_e_acsl_f1_6);
+    __gmpz_clear(__gen_e_acsl__7);
+  }
+  /*@ assert
+      f1(99999999999999999999999999999, 99999999999999999999999999999) ≡
+      199999999999999999999999999998;
+  */
+  {
+    __e_acsl_mpz_t __gen_e_acsl__8;
+    __e_acsl_mpz_t __gen_e_acsl_f1_8;
+    __e_acsl_mpz_t __gen_e_acsl__9;
+    int __gen_e_acsl_eq_2;
+    __gmpz_init_set_str(__gen_e_acsl__8,"99999999999999999999999999999",10);
+    __gen_e_acsl_f1_7(& __gen_e_acsl_f1_8,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl__8,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl__8);
+    __gmpz_init_set_str(__gen_e_acsl__9,"199999999999999999999999999998",10);
+    __gen_e_acsl_eq_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f1_8),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__9));
+    __e_acsl_assert(__gen_e_acsl_eq_2 == 0,(char *)"Assertion",
+                    (char *)"main",
+                    (char *)"f1(99999999999999999999999999999, 99999999999999999999999999999) ==\n199999999999999999999999999998",
+                    49);
+    __gmpz_clear(__gen_e_acsl__8);
+    __gmpz_clear(__gen_e_acsl_f1_8);
+    __gmpz_clear(__gen_e_acsl__9);
+  }
+  /*@ assert g(x) ≡ x; */
+  {
+    int __gen_e_acsl_g_2;
+    __e_acsl_mpz_t __gen_e_acsl_app;
+    __e_acsl_mpz_t __gen_e_acsl_x_6;
+    int __gen_e_acsl_eq_3;
+    __gen_e_acsl_g_2 = __gen_e_acsl_g(x);
+    __gmpz_init_set_si(__gen_e_acsl_app,(long)__gen_e_acsl_g_2);
+    __gmpz_init_set_si(__gen_e_acsl_x_6,(long)x);
+    __gen_e_acsl_eq_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_app),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_6));
+    __e_acsl_assert(__gen_e_acsl_eq_3 == 0,(char *)"Assertion",
+                    (char *)"main",(char *)"g(x) == x",53);
+    __gmpz_clear(__gen_e_acsl_app);
+    __gmpz_clear(__gen_e_acsl_x_6);
+  }
+  char c = (char)'c';
+  /*@ assert h_char(c) ≡ c; */
+  {
+    char __gen_e_acsl_h_char_2;
+    __e_acsl_mpz_t __gen_e_acsl_app_2;
+    __e_acsl_mpz_t __gen_e_acsl_c;
+    int __gen_e_acsl_eq_4;
+    __gen_e_acsl_h_char_2 = __gen_e_acsl_h_char((int)c);
+    __gmpz_init_set_si(__gen_e_acsl_app_2,(long)__gen_e_acsl_h_char_2);
+    __gmpz_init_set_si(__gen_e_acsl_c,(long)c);
+    __gen_e_acsl_eq_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_app_2),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl_c));
+    __e_acsl_assert(__gen_e_acsl_eq_4 == 0,(char *)"Assertion",
+                    (char *)"main",(char *)"h_char(c) == c",56);
+    __gmpz_clear(__gen_e_acsl_app_2);
+    __gmpz_clear(__gen_e_acsl_c);
+  }
+  short s = (short)1;
+  /*@ assert h_short(s) ≡ s; */
+  {
+    short __gen_e_acsl_h_short_2;
+    __e_acsl_mpz_t __gen_e_acsl_app_3;
+    __e_acsl_mpz_t __gen_e_acsl_s;
+    int __gen_e_acsl_eq_5;
+    __gen_e_acsl_h_short_2 = __gen_e_acsl_h_short((int)s);
+    __gmpz_init_set_si(__gen_e_acsl_app_3,(long)__gen_e_acsl_h_short_2);
+    __gmpz_init_set_si(__gen_e_acsl_s,(long)s);
+    __gen_e_acsl_eq_5 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_app_3),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl_s));
+    __e_acsl_assert(__gen_e_acsl_eq_5 == 0,(char *)"Assertion",
+                    (char *)"main",(char *)"h_short(s) == s",58);
+    __gmpz_clear(__gen_e_acsl_app_3);
+    __gmpz_clear(__gen_e_acsl_s);
+  }
+  m.k = 8;
+  m.l = 9;
+  /*@ assert t2(t1(m)) ≡ 17; */
+  {
+    mystruct __gen_e_acsl_t1_2;
+    __e_acsl_mpz_t __gen_e_acsl_t2_2;
+    __e_acsl_mpz_t __gen_e_acsl__12;
+    int __gen_e_acsl_eq_6;
+    __gen_e_acsl_t1_2 = __gen_e_acsl_t1(m);
+    __gen_e_acsl_t2(& __gen_e_acsl_t2_2,__gen_e_acsl_t1_2);
+    __gmpz_init_set_si(__gen_e_acsl__12,17L);
+    __gen_e_acsl_eq_6 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_t2_2),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__12));
+    __e_acsl_assert(__gen_e_acsl_eq_6 == 0,(char *)"Assertion",
+                    (char *)"main",(char *)"t2(t1(m)) == 17",63);
+    __gmpz_clear(__gen_e_acsl_t2_2);
+    __gmpz_clear(__gen_e_acsl__12);
+  }
+  __gen_e_acsl_k(9);
+  __retres = 0;
+  return __retres;
+}
+
+/*@ requires k_pred(x); */
+void __gen_e_acsl_k(int x)
+{
+  {
+    int __gen_e_acsl_k_pred_2;
+    __gen_e_acsl_k_pred_2 = __gen_e_acsl_k_pred(x);
+    __e_acsl_assert(__gen_e_acsl_k_pred_2,(char *)"Precondition",(char *)"k",
+                    (char *)"k_pred(x)",25);
+  }
+  k(x);
+  return;
+}
+
+char __gen_e_acsl_h_char(int c)
+{
+  char __retres = (char)c;
+  return __retres;
+}
+
+short __gen_e_acsl_h_short(int s)
+{
+  short __retres = (short)s;
+  return __retres;
+}
+
+int __gen_e_acsl_g_hidden(int x)
+{
+  return x;
+}
+
+int __gen_e_acsl_g(int x)
+{
+  int __gen_e_acsl_g_hidden_2;
+  __gen_e_acsl_g_hidden_2 = __gen_e_acsl_g_hidden(x);
+  return __gen_e_acsl_g_hidden_2;
+}
+
+mystruct __gen_e_acsl_t1(mystruct m)
+{
+  return m;
+}
+
+int __gen_e_acsl_p1(int x, int y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x;
+  __e_acsl_mpz_t __gen_e_acsl_y;
+  __e_acsl_mpz_t __gen_e_acsl_add;
+  __e_acsl_mpz_t __gen_e_acsl_;
+  int __gen_e_acsl_gt;
+  __gmpz_init_set_si(__gen_e_acsl_x,(long)x);
+  __gmpz_init_set_si(__gen_e_acsl_y,(long)y);
+  __gmpz_init(__gen_e_acsl_add);
+  __gmpz_add(__gen_e_acsl_add,(__e_acsl_mpz_struct const *)(__gen_e_acsl_x),
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_y));
+  __gmpz_init_set_si(__gen_e_acsl_,0L);
+  __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add),
+                               (__e_acsl_mpz_struct const *)(__gen_e_acsl_));
+  int __retres = __gen_e_acsl_gt > 0;
+  __gmpz_clear(__gen_e_acsl_x);
+  __gmpz_clear(__gen_e_acsl_y);
+  __gmpz_clear(__gen_e_acsl_add);
+  __gmpz_clear(__gen_e_acsl_);
+  return __retres;
+}
+
+void __gen_e_acsl_t2(__e_acsl_mpz_t *__retres_arg, mystruct m)
+{
+  __e_acsl_mpz_t __gen_e_acsl__10;
+  __e_acsl_mpz_t __gen_e_acsl__11;
+  __e_acsl_mpz_t __gen_e_acsl_add_7;
+  __gmpz_init_set_si(__gen_e_acsl__10,(long)m.k);
+  __gmpz_init_set_si(__gen_e_acsl__11,(long)m.l);
+  __gmpz_init(__gen_e_acsl_add_7);
+  __gmpz_add(__gen_e_acsl_add_7,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl__10),
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl__11));
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_7));
+  __gmpz_clear(__gen_e_acsl__10);
+  __gmpz_clear(__gen_e_acsl__11);
+  __gmpz_clear(__gen_e_acsl_add_7);
+  return;
+}
+
+int __gen_e_acsl_p2_3(int x, __e_acsl_mpz_struct * y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x_3;
+  __e_acsl_mpz_t __gen_e_acsl_add_3;
+  __e_acsl_mpz_t __gen_e_acsl__4;
+  int __gen_e_acsl_gt_3;
+  __gmpz_init_set_si(__gen_e_acsl_x_3,(long)x);
+  __gmpz_init(__gen_e_acsl_add_3);
+  __gmpz_add(__gen_e_acsl_add_3,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_3),
+             (__e_acsl_mpz_struct const *)(y));
+  __gmpz_init_set_si(__gen_e_acsl__4,0L);
+  __gen_e_acsl_gt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_3),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__4));
+  int __retres = __gen_e_acsl_gt_3 > 0;
+  __gmpz_clear(__gen_e_acsl_x_3);
+  __gmpz_clear(__gen_e_acsl_add_3);
+  __gmpz_clear(__gen_e_acsl__4);
+  return __retres;
+}
+
+int __gen_e_acsl_p2(int x, int y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x_2;
+  __e_acsl_mpz_t __gen_e_acsl_y_2;
+  __e_acsl_mpz_t __gen_e_acsl_add_2;
+  __e_acsl_mpz_t __gen_e_acsl__2;
+  int __gen_e_acsl_gt_2;
+  __gmpz_init_set_si(__gen_e_acsl_x_2,(long)x);
+  __gmpz_init_set_si(__gen_e_acsl_y_2,(long)y);
+  __gmpz_init(__gen_e_acsl_add_2);
+  __gmpz_add(__gen_e_acsl_add_2,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_2),
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_y_2));
+  __gmpz_init_set_si(__gen_e_acsl__2,0L);
+  __gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_add_2),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__2));
+  int __retres = __gen_e_acsl_gt_2 > 0;
+  __gmpz_clear(__gen_e_acsl_x_2);
+  __gmpz_clear(__gen_e_acsl_y_2);
+  __gmpz_clear(__gen_e_acsl_add_2);
+  __gmpz_clear(__gen_e_acsl__2);
+  return __retres;
+}
+
+int __gen_e_acsl_k_pred(int x)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x;
+  __e_acsl_mpz_t __gen_e_acsl_;
+  int __gen_e_acsl_gt;
+  __gmpz_init_set_si(__gen_e_acsl_x,(long)x);
+  __gmpz_init_set_si(__gen_e_acsl_,0L);
+  __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_x),
+                               (__e_acsl_mpz_struct const *)(__gen_e_acsl_));
+  int __retres = __gen_e_acsl_gt > 0;
+  __gmpz_clear(__gen_e_acsl_x);
+  __gmpz_clear(__gen_e_acsl_);
+  return __retres;
+}
+
+void __gen_e_acsl_f1_7(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * x,
+                       __e_acsl_mpz_struct * y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_add_6;
+  __gmpz_init(__gen_e_acsl_add_6);
+  __gmpz_add(__gen_e_acsl_add_6,(__e_acsl_mpz_struct const *)(x),
+             (__e_acsl_mpz_struct const *)(y));
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_6));
+  __gmpz_clear(__gen_e_acsl_add_6);
+  return;
+}
+
+void __gen_e_acsl_f1_5(__e_acsl_mpz_t *__retres_arg, int x,
+                       __e_acsl_mpz_struct * y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x_5;
+  __e_acsl_mpz_t __gen_e_acsl_add_5;
+  __gmpz_init_set_si(__gen_e_acsl_x_5,(long)x);
+  __gmpz_init(__gen_e_acsl_add_5);
+  __gmpz_add(__gen_e_acsl_add_5,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_5),
+             (__e_acsl_mpz_struct const *)(y));
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_5));
+  __gmpz_clear(__gen_e_acsl_x_5);
+  __gmpz_clear(__gen_e_acsl_add_5);
+  return;
+}
+
+void __gen_e_acsl_f1(__e_acsl_mpz_t *__retres_arg, int x, int y)
+{
+  __e_acsl_mpz_t __gen_e_acsl_x_4;
+  __e_acsl_mpz_t __gen_e_acsl_y_3;
+  __e_acsl_mpz_t __gen_e_acsl_add_4;
+  __gmpz_init_set_si(__gen_e_acsl_x_4,(long)x);
+  __gmpz_init_set_si(__gen_e_acsl_y_3,(long)y);
+  __gmpz_init(__gen_e_acsl_add_4);
+  __gmpz_add(__gen_e_acsl_add_4,
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_4),
+             (__e_acsl_mpz_struct const *)(__gen_e_acsl_y_3));
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_4));
+  __gmpz_clear(__gen_e_acsl_x_4);
+  __gmpz_clear(__gen_e_acsl_y_3);
+  __gmpz_clear(__gen_e_acsl_add_4);
+  return;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_contiki.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_contiki.c
new file mode 100644
index 0000000000000000000000000000000000000000..259afb2e7cf7aff685e3f821c94a0a230968a678
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_contiki.c
@@ -0,0 +1,45 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+struct list {
+   struct list *next ;
+   int value ;
+};
+/*@
+logic ℤ length_aux{L}(struct list *l, ℤ n) =
+  \at(n < 0? -1:
+        (l ≡ (struct list *)((void *)0)? n:
+           (n < 2147483647? length_aux(l->next, n + 1): -1)),
+      L);
+ */
+/*@ logic ℤ length{L}(struct list *l) = \at(length_aux(l, 0),L);
+
+*/
+int main(void)
+{
+  int __retres;
+  struct list node1;
+  struct list node2;
+  struct list node3;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __e_acsl_store_block((void *)(& node3),(size_t)16);
+  __e_acsl_store_block((void *)(& node2),(size_t)16);
+  __e_acsl_store_block((void *)(& node1),(size_t)16);
+  __e_acsl_initialize((void *)(& node1.next),sizeof(struct list *));
+  node1.next = & node2;
+  __e_acsl_initialize((void *)(& node2.next),sizeof(struct list *));
+  node2.next = & node3;
+  struct list *l = & node1;
+  __e_acsl_store_block((void *)(& l),(size_t)8);
+  __e_acsl_full_init((void *)(& l));
+  /*@ assert length(l) ≡ 3; */ ;
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& l));
+  __e_acsl_delete_block((void *)(& node3));
+  __e_acsl_delete_block((void *)(& node2));
+  __e_acsl_delete_block((void *)(& node1));
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_contiki2.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_contiki2.c
new file mode 100644
index 0000000000000000000000000000000000000000..259afb2e7cf7aff685e3f821c94a0a230968a678
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_contiki2.c
@@ -0,0 +1,45 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+struct list {
+   struct list *next ;
+   int value ;
+};
+/*@
+logic ℤ length_aux{L}(struct list *l, ℤ n) =
+  \at(n < 0? -1:
+        (l ≡ (struct list *)((void *)0)? n:
+           (n < 2147483647? length_aux(l->next, n + 1): -1)),
+      L);
+ */
+/*@ logic ℤ length{L}(struct list *l) = \at(length_aux(l, 0),L);
+
+*/
+int main(void)
+{
+  int __retres;
+  struct list node1;
+  struct list node2;
+  struct list node3;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __e_acsl_store_block((void *)(& node3),(size_t)16);
+  __e_acsl_store_block((void *)(& node2),(size_t)16);
+  __e_acsl_store_block((void *)(& node1),(size_t)16);
+  __e_acsl_initialize((void *)(& node1.next),sizeof(struct list *));
+  node1.next = & node2;
+  __e_acsl_initialize((void *)(& node2.next),sizeof(struct list *));
+  node2.next = & node3;
+  struct list *l = & node1;
+  __e_acsl_store_block((void *)(& l),(size_t)8);
+  __e_acsl_full_init((void *)(& l));
+  /*@ assert length(l) ≡ 3; */ ;
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& l));
+  __e_acsl_delete_block((void *)(& node3));
+  __e_acsl_delete_block((void *)(& node2));
+  __e_acsl_delete_block((void *)(& node1));
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_rec.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_rec.c
new file mode 100644
index 0000000000000000000000000000000000000000..0fa4a22a630c4d80f8f44b38a7c561a6b5e93f13
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_rec.c
@@ -0,0 +1,208 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+/*@ logic ℤ f1(ℤ n) = n ≤ 0? 0: f1(n - 1) + n;
+ */
+/*@ logic ℤ f2(ℤ n) = n < 0? 1: (f2(n - 1) * f2(n - 2)) / f2(n - 3);
+ */
+int __gen_e_acsl_f2_2(long n);
+
+int __gen_e_acsl_f2(int n);
+
+/*@ logic ℤ g(ℤ n) = 0;
+ */
+int __gen_e_acsl_g_5(long n);
+
+int __gen_e_acsl_g(int n);
+
+/*@ logic ℤ f3(ℤ n) = n > 0? g(n) * f3(n - 1) - 5: g(n + 1);
+ */
+int __gen_e_acsl_f3_2(long n);
+
+int __gen_e_acsl_f3(int n);
+
+/*@
+logic ℤ f4(ℤ n) =
+  n < 100? f4(n + 1): (n < 0x7fffffffffffffffL? 0x7fffffffffffffffL: 6);
+
+*/
+unsigned long __gen_e_acsl_f4_2(long n);
+
+unsigned long __gen_e_acsl_f4(int n);
+
+int main(void)
+{
+  int __retres;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  /*@ assert f2(7) ≡ 1; */
+  {
+    int __gen_e_acsl_f2_14;
+    __gen_e_acsl_f2_14 = __gen_e_acsl_f2(7);
+    __e_acsl_assert(__gen_e_acsl_f2_14 == 1,(char *)"Assertion",
+                    (char *)"main",(char *)"f2(7) == 1",26);
+  }
+  /*@ assert f3(6) ≡ -5; */
+  {
+    int __gen_e_acsl_f3_6;
+    __gen_e_acsl_f3_6 = __gen_e_acsl_f3(6);
+    __e_acsl_assert(__gen_e_acsl_f3_6 == -5,(char *)"Assertion",
+                    (char *)"main",(char *)"f3(6) == -5",28);
+  }
+  /*@ assert f4(9) > 0; */
+  {
+    unsigned long __gen_e_acsl_f4_6;
+    __gen_e_acsl_f4_6 = __gen_e_acsl_f4(9);
+    __e_acsl_assert(__gen_e_acsl_f4_6 > 0UL,(char *)"Assertion",
+                    (char *)"main",(char *)"f4(9) > 0",30);
+  }
+  __retres = 0;
+  return __retres;
+}
+
+unsigned long __gen_e_acsl_f4_2(long n)
+{
+  unsigned long __gen_e_acsl_if_6;
+  if (n < 100L) {
+    unsigned long __gen_e_acsl_f4_4;
+    __gen_e_acsl_f4_4 = __gen_e_acsl_f4_2(n + 1L);
+    __gen_e_acsl_if_6 = __gen_e_acsl_f4_4;
+  }
+  else {
+    unsigned long __gen_e_acsl_if_5;
+    if (n < 9223372036854775807L) __gen_e_acsl_if_5 = 9223372036854775807UL;
+    else __gen_e_acsl_if_5 = 6UL;
+    __gen_e_acsl_if_6 = __gen_e_acsl_if_5;
+  }
+  return __gen_e_acsl_if_6;
+}
+
+unsigned long __gen_e_acsl_f4(int n)
+{
+  unsigned long __gen_e_acsl_if_8;
+  if (n < 100) {
+    unsigned long __gen_e_acsl_f4_5;
+    __gen_e_acsl_f4_5 = __gen_e_acsl_f4_2(n + 1L);
+    __gen_e_acsl_if_8 = __gen_e_acsl_f4_5;
+  }
+  else {
+    unsigned long __gen_e_acsl_if_7;
+    if ((long)n < 9223372036854775807L) __gen_e_acsl_if_7 = 9223372036854775807UL;
+    else __gen_e_acsl_if_7 = 6UL;
+    __gen_e_acsl_if_8 = __gen_e_acsl_if_7;
+  }
+  return __gen_e_acsl_if_8;
+}
+
+int __gen_e_acsl_f2_2(long n)
+{
+  int __gen_e_acsl_if;
+  if (n < 0L) __gen_e_acsl_if = 1;
+  else {
+    int __gen_e_acsl_f2_4;
+    int __gen_e_acsl_f2_6;
+    int __gen_e_acsl_f2_8;
+    __gen_e_acsl_f2_4 = __gen_e_acsl_f2_2(n - 1L);
+    __gen_e_acsl_f2_6 = __gen_e_acsl_f2_2(n - 2L);
+    __gen_e_acsl_f2_8 = __gen_e_acsl_f2_2(n - 3L);
+    __e_acsl_assert(__gen_e_acsl_f2_8 != 0,(char *)"RTE",(char *)"f2_2",
+                    (char *)"division_by_zero: __gen_e_acsl_f2_8 != 0",10);
+    /*@ assert Eva: division_by_zero: __gen_e_acsl_f2_8 ≢ 0; */
+    /*@ assert
+        Eva: signed_overflow:
+          -2147483648 ≤ __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6;
+    */
+    /*@ assert
+        Eva: signed_overflow:
+          __gen_e_acsl_f2_4 * __gen_e_acsl_f2_6 ≤ 2147483647;
+    */
+    /*@ assert
+        Eva: signed_overflow:
+          (int)(__gen_e_acsl_f2_4 * __gen_e_acsl_f2_6) / __gen_e_acsl_f2_8
+          ≤ 2147483647;
+    */
+    __gen_e_acsl_if = (__gen_e_acsl_f2_4 * __gen_e_acsl_f2_6) / __gen_e_acsl_f2_8;
+  }
+  return __gen_e_acsl_if;
+}
+
+int __gen_e_acsl_f2(int n)
+{
+  int __gen_e_acsl_if_2;
+  if (n < 0) __gen_e_acsl_if_2 = 1;
+  else {
+    int __gen_e_acsl_f2_9;
+    int __gen_e_acsl_f2_11;
+    int __gen_e_acsl_f2_13;
+    __gen_e_acsl_f2_9 = __gen_e_acsl_f2_2(n - 1L);
+    __gen_e_acsl_f2_11 = __gen_e_acsl_f2_2(n - 2L);
+    __gen_e_acsl_f2_13 = __gen_e_acsl_f2_2(n - 3L);
+    __e_acsl_assert(__gen_e_acsl_f2_13 != 0,(char *)"RTE",(char *)"f2",
+                    (char *)"division_by_zero: __gen_e_acsl_f2_13 != 0",10);
+    /*@ assert Eva: division_by_zero: __gen_e_acsl_f2_13 ≢ 0; */
+    /*@ assert
+        Eva: signed_overflow:
+          -2147483648 ≤ __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11;
+    */
+    /*@ assert
+        Eva: signed_overflow:
+          __gen_e_acsl_f2_9 * __gen_e_acsl_f2_11 ≤ 2147483647;
+    */
+    /*@ assert
+        Eva: signed_overflow:
+          (int)(__gen_e_acsl_f2_9 * __gen_e_acsl_f2_11) / __gen_e_acsl_f2_13
+          ≤ 2147483647;
+    */
+    __gen_e_acsl_if_2 = (__gen_e_acsl_f2_9 * __gen_e_acsl_f2_11) / __gen_e_acsl_f2_13;
+  }
+  return __gen_e_acsl_if_2;
+}
+
+int __gen_e_acsl_g_5(long n)
+{
+  int __retres = 0;
+  return __retres;
+}
+
+int __gen_e_acsl_g(int n)
+{
+  int __retres = 0;
+  return __retres;
+}
+
+int __gen_e_acsl_f3_2(long n)
+{
+  int __gen_e_acsl_if_3;
+  if (n > 0L) {
+    int __gen_e_acsl_g_4;
+    int __gen_e_acsl_f3_4;
+    __gen_e_acsl_g_4 = __gen_e_acsl_g((int)n);
+    __gen_e_acsl_f3_4 = __gen_e_acsl_f3_2(n - 1L);
+    __gen_e_acsl_if_3 = __gen_e_acsl_g_4 * __gen_e_acsl_f3_4 - 5;
+  }
+  else {
+    int __gen_e_acsl_g_6;
+    __gen_e_acsl_g_6 = __gen_e_acsl_g_5(n + 1L);
+    __gen_e_acsl_if_3 = __gen_e_acsl_g_6;
+  }
+  return __gen_e_acsl_if_3;
+}
+
+int __gen_e_acsl_f3(int n)
+{
+  int __gen_e_acsl_if_4;
+  if (n > 0) {
+    int __gen_e_acsl_g_2;
+    int __gen_e_acsl_f3_5;
+    __gen_e_acsl_g_2 = __gen_e_acsl_g(n);
+    __gen_e_acsl_f3_5 = __gen_e_acsl_f3_2(n - 1L);
+    __gen_e_acsl_if_4 = __gen_e_acsl_g_2 * __gen_e_acsl_f3_5 - 5;
+  }
+  else {
+    int __gen_e_acsl_g_8;
+    __gen_e_acsl_g_8 = __gen_e_acsl_g_5(n + 1L);
+    __gen_e_acsl_if_4 = __gen_e_acsl_g_8;
+  }
+  return __gen_e_acsl_if_4;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_rec2.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_rec2.c
new file mode 100644
index 0000000000000000000000000000000000000000..c13d6d1e49b1ef2fae4f1c8c5fb0922a23127c3f
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_functions_rec2.c
@@ -0,0 +1,593 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+/*@ logic ℤ f1(ℤ n) = n ≤ 0? 0: f1(n - 1) + n;
+ */
+/*@ logic ℤ f2(ℤ n) = n < 0? 1: (f2(n - 1) * f2(n - 2)) / f2(n - 3);
+
+*/
+void __gen_e_acsl_f2_2(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n);
+
+void __gen_e_acsl_f2(__e_acsl_mpz_t *__retres_arg, int n);
+
+/*@ logic ℤ g(ℤ n) = 0;
+
+*/
+void __gen_e_acsl_g_5(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n);
+
+void __gen_e_acsl_g(__e_acsl_mpz_t *__retres_arg, int n);
+
+/*@ logic ℤ f3(ℤ n) = n > 0? g(n) * f3(n - 1) - 5: g(n + 1);
+
+*/
+void __gen_e_acsl_f3_2(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n);
+
+void __gen_e_acsl_f3(__e_acsl_mpz_t *__retres_arg, int n);
+
+/*@
+logic ℤ f4(ℤ n) =
+  n < 100? f4(n + 1): (n < 0x7fffffffffffffffL? 0x7fffffffffffffffL: 6);
+
+*/
+void __gen_e_acsl_f4_2(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n);
+
+void __gen_e_acsl_f4(__e_acsl_mpz_t *__retres_arg, int n);
+
+int main(void)
+{
+  int __retres;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  /*@ assert f2(7) ≡ 1; */
+  {
+    __e_acsl_mpz_t __gen_e_acsl_f2_14;
+    __e_acsl_mpz_t __gen_e_acsl__13;
+    int __gen_e_acsl_eq;
+    __gen_e_acsl_f2(& __gen_e_acsl_f2_14,7);
+    __gmpz_init_set_si(__gen_e_acsl__13,1L);
+    __gen_e_acsl_eq = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_14),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__13));
+    __e_acsl_assert(__gen_e_acsl_eq == 0,(char *)"Assertion",(char *)"main",
+                    (char *)"f2(7) == 1",26);
+    __gmpz_clear(__gen_e_acsl_f2_14);
+    __gmpz_clear(__gen_e_acsl__13);
+  }
+  /*@ assert f3(6) ≡ -5; */
+  {
+    __e_acsl_mpz_t __gen_e_acsl_f3_6;
+    __e_acsl_mpz_t __gen_e_acsl__23;
+    __e_acsl_mpz_t __gen_e_acsl_neg;
+    int __gen_e_acsl_eq_2;
+    __gen_e_acsl_f3(& __gen_e_acsl_f3_6,6);
+    __gmpz_init_set_si(__gen_e_acsl__23,5L);
+    __gmpz_init(__gen_e_acsl_neg);
+    __gmpz_neg(__gen_e_acsl_neg,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__23));
+    __gen_e_acsl_eq_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f3_6),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg));
+    __e_acsl_assert(__gen_e_acsl_eq_2 == 0,(char *)"Assertion",
+                    (char *)"main",(char *)"f3(6) == -5",28);
+    __gmpz_clear(__gen_e_acsl_f3_6);
+    __gmpz_clear(__gen_e_acsl__23);
+    __gmpz_clear(__gen_e_acsl_neg);
+  }
+  /*@ assert f4(9) > 0; */
+  {
+    __e_acsl_mpz_t __gen_e_acsl_f4_6;
+    __e_acsl_mpz_t __gen_e_acsl__34;
+    int __gen_e_acsl_gt_3;
+    __gen_e_acsl_f4(& __gen_e_acsl_f4_6,9);
+    __gmpz_init_set_si(__gen_e_acsl__34,0L);
+    __gen_e_acsl_gt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f4_6),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__34));
+    __e_acsl_assert(__gen_e_acsl_gt_3 > 0,(char *)"Assertion",(char *)"main",
+                    (char *)"f4(9) > 0",30);
+    __gmpz_clear(__gen_e_acsl_f4_6);
+    __gmpz_clear(__gen_e_acsl__34);
+  }
+  __retres = 0;
+  return __retres;
+}
+
+void __gen_e_acsl_f4_2(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n)
+{
+  __e_acsl_mpz_t __gen_e_acsl__26;
+  int __gen_e_acsl_lt_4;
+  __e_acsl_mpz_t __gen_e_acsl_if_6;
+  __gmpz_init_set_si(__gen_e_acsl__26,100L);
+  __gen_e_acsl_lt_4 = __gmpz_cmp((__e_acsl_mpz_struct const *)(n),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__26));
+  if (__gen_e_acsl_lt_4 < 0) {
+    __e_acsl_mpz_t __gen_e_acsl__27;
+    __e_acsl_mpz_t __gen_e_acsl_add_4;
+    __e_acsl_mpz_t __gen_e_acsl_f4_4;
+    __gmpz_init_set_si(__gen_e_acsl__27,1L);
+    __gmpz_init(__gen_e_acsl_add_4);
+    __gmpz_add(__gen_e_acsl_add_4,(__e_acsl_mpz_struct const *)(n),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__27));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add_4);
+    */
+    __gen_e_acsl_f4_2(& __gen_e_acsl_f4_4,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_add_4);
+    __gmpz_init_set(__gen_e_acsl_if_6,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_f4_4));
+    __gmpz_clear(__gen_e_acsl__27);
+    __gmpz_clear(__gen_e_acsl_add_4);
+    __gmpz_clear(__gen_e_acsl_f4_4);
+  }
+  else {
+    __e_acsl_mpz_t __gen_e_acsl__28;
+    int __gen_e_acsl_lt_5;
+    __e_acsl_mpz_t __gen_e_acsl_if_5;
+    __gmpz_init_set_ui(__gen_e_acsl__28,9223372036854775807UL);
+    __gen_e_acsl_lt_5 = __gmpz_cmp((__e_acsl_mpz_struct const *)(n),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__28));
+    if (__gen_e_acsl_lt_5 < 0) {
+      __e_acsl_mpz_t __gen_e_acsl__29;
+      __gmpz_init_set_ui(__gen_e_acsl__29,9223372036854775807UL);
+      __gmpz_init_set(__gen_e_acsl_if_5,
+                      (__e_acsl_mpz_struct const *)(__gen_e_acsl__29));
+      __gmpz_clear(__gen_e_acsl__29);
+    }
+    else {
+      __e_acsl_mpz_t __gen_e_acsl__30;
+      __gmpz_init_set_si(__gen_e_acsl__30,6L);
+      __gmpz_init_set(__gen_e_acsl_if_5,
+                      (__e_acsl_mpz_struct const *)(__gen_e_acsl__30));
+      __gmpz_clear(__gen_e_acsl__30);
+    }
+    __gmpz_init_set(__gen_e_acsl_if_6,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_5));
+    __gmpz_clear(__gen_e_acsl__28);
+    __gmpz_clear(__gen_e_acsl_if_5);
+  }
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_6));
+  __gmpz_clear(__gen_e_acsl__26);
+  __gmpz_clear(__gen_e_acsl_if_6);
+  return;
+}
+
+void __gen_e_acsl_f4(__e_acsl_mpz_t *__retres_arg, int n)
+{
+  __e_acsl_mpz_t __gen_e_acsl_n_6;
+  __e_acsl_mpz_t __gen_e_acsl__24;
+  int __gen_e_acsl_lt_3;
+  __e_acsl_mpz_t __gen_e_acsl_if_8;
+  __gmpz_init_set_si(__gen_e_acsl_n_6,(long)n);
+  __gmpz_init_set_si(__gen_e_acsl__24,100L);
+  __gen_e_acsl_lt_3 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_n_6),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__24));
+  if (__gen_e_acsl_lt_3 < 0) {
+    __e_acsl_mpz_t __gen_e_acsl_n_7;
+    __e_acsl_mpz_t __gen_e_acsl__25;
+    __e_acsl_mpz_t __gen_e_acsl_add_3;
+    __e_acsl_mpz_t __gen_e_acsl_f4_5;
+    __gmpz_init_set_si(__gen_e_acsl_n_7,(long)n);
+    __gmpz_init_set_si(__gen_e_acsl__25,1L);
+    __gmpz_init(__gen_e_acsl_add_3);
+    __gmpz_add(__gen_e_acsl_add_3,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_7),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__25));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add_3);
+    */
+    __gen_e_acsl_f4_2(& __gen_e_acsl_f4_5,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_add_3);
+    __gmpz_init_set(__gen_e_acsl_if_8,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_f4_5));
+    __gmpz_clear(__gen_e_acsl_n_7);
+    __gmpz_clear(__gen_e_acsl__25);
+    __gmpz_clear(__gen_e_acsl_add_3);
+    __gmpz_clear(__gen_e_acsl_f4_5);
+  }
+  else {
+    __e_acsl_mpz_t __gen_e_acsl_n_8;
+    __e_acsl_mpz_t __gen_e_acsl__31;
+    int __gen_e_acsl_lt_6;
+    __e_acsl_mpz_t __gen_e_acsl_if_7;
+    __gmpz_init_set_si(__gen_e_acsl_n_8,(long)n);
+    __gmpz_init_set_ui(__gen_e_acsl__31,9223372036854775807UL);
+    __gen_e_acsl_lt_6 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_n_8),
+                                   (__e_acsl_mpz_struct const *)(__gen_e_acsl__31));
+    if (__gen_e_acsl_lt_6 < 0) {
+      __e_acsl_mpz_t __gen_e_acsl__32;
+      __gmpz_init_set_ui(__gen_e_acsl__32,9223372036854775807UL);
+      __gmpz_init_set(__gen_e_acsl_if_7,
+                      (__e_acsl_mpz_struct const *)(__gen_e_acsl__32));
+      __gmpz_clear(__gen_e_acsl__32);
+    }
+    else {
+      __e_acsl_mpz_t __gen_e_acsl__33;
+      __gmpz_init_set_si(__gen_e_acsl__33,6L);
+      __gmpz_init_set(__gen_e_acsl_if_7,
+                      (__e_acsl_mpz_struct const *)(__gen_e_acsl__33));
+      __gmpz_clear(__gen_e_acsl__33);
+    }
+    __gmpz_init_set(__gen_e_acsl_if_8,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_7));
+    __gmpz_clear(__gen_e_acsl_n_8);
+    __gmpz_clear(__gen_e_acsl__31);
+    __gmpz_clear(__gen_e_acsl_if_7);
+  }
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_8));
+  __gmpz_clear(__gen_e_acsl_n_6);
+  __gmpz_clear(__gen_e_acsl__24);
+  __gmpz_clear(__gen_e_acsl_if_8);
+  return;
+}
+
+void __gen_e_acsl_f2_2(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n)
+{
+  __e_acsl_mpz_t __gen_e_acsl__4;
+  int __gen_e_acsl_lt_2;
+  __e_acsl_mpz_t __gen_e_acsl_if;
+  __gmpz_init_set_si(__gen_e_acsl__4,0L);
+  __gen_e_acsl_lt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(n),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__4));
+  if (__gen_e_acsl_lt_2 < 0) {
+    __e_acsl_mpz_t __gen_e_acsl__5;
+    __gmpz_init_set_si(__gen_e_acsl__5,1L);
+    __gmpz_init_set(__gen_e_acsl_if,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl__5));
+    __gmpz_clear(__gen_e_acsl__5);
+  }
+  else {
+    __e_acsl_mpz_t __gen_e_acsl__6;
+    __e_acsl_mpz_t __gen_e_acsl_sub_2;
+    __e_acsl_mpz_t __gen_e_acsl_f2_4;
+    __e_acsl_mpz_t __gen_e_acsl__7;
+    __e_acsl_mpz_t __gen_e_acsl_sub_3;
+    __e_acsl_mpz_t __gen_e_acsl_f2_6;
+    __e_acsl_mpz_t __gen_e_acsl_mul;
+    __e_acsl_mpz_t __gen_e_acsl__8;
+    __e_acsl_mpz_t __gen_e_acsl_sub_4;
+    __e_acsl_mpz_t __gen_e_acsl_f2_8;
+    __e_acsl_mpz_t __gen_e_acsl__9;
+    int __gen_e_acsl_div_guard;
+    __e_acsl_mpz_t __gen_e_acsl_div;
+    __gmpz_init_set_si(__gen_e_acsl__6,1L);
+    __gmpz_init(__gen_e_acsl_sub_2);
+    __gmpz_sub(__gen_e_acsl_sub_2,(__e_acsl_mpz_struct const *)(n),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__6));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_2);
+    */
+    __gen_e_acsl_f2_2(& __gen_e_acsl_f2_4,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_2);
+    __gmpz_init_set_si(__gen_e_acsl__7,2L);
+    __gmpz_init(__gen_e_acsl_sub_3);
+    __gmpz_sub(__gen_e_acsl_sub_3,(__e_acsl_mpz_struct const *)(n),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__7));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_3);
+    */
+    __gen_e_acsl_f2_2(& __gen_e_acsl_f2_6,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_3);
+    __gmpz_init(__gen_e_acsl_mul);
+    __gmpz_mul(__gen_e_acsl_mul,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_4),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_6));
+    __gmpz_init_set_si(__gen_e_acsl__8,3L);
+    __gmpz_init(__gen_e_acsl_sub_4);
+    __gmpz_sub(__gen_e_acsl_sub_4,(__e_acsl_mpz_struct const *)(n),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__8));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_4);
+    */
+    __gen_e_acsl_f2_2(& __gen_e_acsl_f2_8,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_4);
+    __gmpz_init_set_si(__gen_e_acsl__9,0L);
+    __gen_e_acsl_div_guard = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_8),
+                                        (__e_acsl_mpz_struct const *)(__gen_e_acsl__9));
+    __gmpz_init(__gen_e_acsl_div);
+    /*@ assert E_ACSL: f2(n - 3) ≢ 0; */
+    __e_acsl_assert(! (__gen_e_acsl_div_guard == 0),(char *)"Assertion",
+                    (char *)"f2_2",(char *)"f2(n - 3) == 0",10);
+    __gmpz_tdiv_q(__gen_e_acsl_div,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul),
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_8));
+    __gmpz_init_set(__gen_e_acsl_if,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_div));
+    __gmpz_clear(__gen_e_acsl__6);
+    __gmpz_clear(__gen_e_acsl_sub_2);
+    __gmpz_clear(__gen_e_acsl_f2_4);
+    __gmpz_clear(__gen_e_acsl__7);
+    __gmpz_clear(__gen_e_acsl_sub_3);
+    __gmpz_clear(__gen_e_acsl_f2_6);
+    __gmpz_clear(__gen_e_acsl_mul);
+    __gmpz_clear(__gen_e_acsl__8);
+    __gmpz_clear(__gen_e_acsl_sub_4);
+    __gmpz_clear(__gen_e_acsl_f2_8);
+    __gmpz_clear(__gen_e_acsl__9);
+    __gmpz_clear(__gen_e_acsl_div);
+  }
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_if));
+  __gmpz_clear(__gen_e_acsl__4);
+  __gmpz_clear(__gen_e_acsl_if);
+  return;
+}
+
+void __gen_e_acsl_f2(__e_acsl_mpz_t *__retres_arg, int n)
+{
+  __e_acsl_mpz_t __gen_e_acsl_n;
+  __e_acsl_mpz_t __gen_e_acsl_;
+  int __gen_e_acsl_lt;
+  __e_acsl_mpz_t __gen_e_acsl_if_2;
+  __gmpz_init_set_si(__gen_e_acsl_n,(long)n);
+  __gmpz_init_set_si(__gen_e_acsl_,0L);
+  __gen_e_acsl_lt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_n),
+                               (__e_acsl_mpz_struct const *)(__gen_e_acsl_));
+  if (__gen_e_acsl_lt < 0) {
+    __e_acsl_mpz_t __gen_e_acsl__2;
+    __gmpz_init_set_si(__gen_e_acsl__2,1L);
+    __gmpz_init_set(__gen_e_acsl_if_2,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl__2));
+    __gmpz_clear(__gen_e_acsl__2);
+  }
+  else {
+    __e_acsl_mpz_t __gen_e_acsl_n_2;
+    __e_acsl_mpz_t __gen_e_acsl__3;
+    __e_acsl_mpz_t __gen_e_acsl_sub;
+    __e_acsl_mpz_t __gen_e_acsl_f2_9;
+    __e_acsl_mpz_t __gen_e_acsl__10;
+    __e_acsl_mpz_t __gen_e_acsl_sub_5;
+    __e_acsl_mpz_t __gen_e_acsl_f2_11;
+    __e_acsl_mpz_t __gen_e_acsl_mul_2;
+    __e_acsl_mpz_t __gen_e_acsl__11;
+    __e_acsl_mpz_t __gen_e_acsl_sub_6;
+    __e_acsl_mpz_t __gen_e_acsl_f2_13;
+    __e_acsl_mpz_t __gen_e_acsl__12;
+    int __gen_e_acsl_div_guard_2;
+    __e_acsl_mpz_t __gen_e_acsl_div_2;
+    __gmpz_init_set_si(__gen_e_acsl_n_2,(long)n);
+    __gmpz_init_set_si(__gen_e_acsl__3,1L);
+    __gmpz_init(__gen_e_acsl_sub);
+    __gmpz_sub(__gen_e_acsl_sub,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_2),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__3));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub);
+    */
+    __gen_e_acsl_f2_2(& __gen_e_acsl_f2_9,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub);
+    __gmpz_init_set_si(__gen_e_acsl__10,2L);
+    __gmpz_init(__gen_e_acsl_sub_5);
+    __gmpz_sub(__gen_e_acsl_sub_5,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_2),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__10));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_5);
+    */
+    __gen_e_acsl_f2_2(& __gen_e_acsl_f2_11,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_5);
+    __gmpz_init(__gen_e_acsl_mul_2);
+    __gmpz_mul(__gen_e_acsl_mul_2,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_9),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_11));
+    __gmpz_init_set_si(__gen_e_acsl__11,3L);
+    __gmpz_init(__gen_e_acsl_sub_6);
+    __gmpz_sub(__gen_e_acsl_sub_6,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_2),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__11));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_6);
+    */
+    __gen_e_acsl_f2_2(& __gen_e_acsl_f2_13,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_6);
+    __gmpz_init_set_si(__gen_e_acsl__12,0L);
+    __gen_e_acsl_div_guard_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_13),
+                                          (__e_acsl_mpz_struct const *)(__gen_e_acsl__12));
+    __gmpz_init(__gen_e_acsl_div_2);
+    /*@ assert E_ACSL: f2(n - 3) ≢ 0; */
+    __e_acsl_assert(! (__gen_e_acsl_div_guard_2 == 0),(char *)"Assertion",
+                    (char *)"f2",(char *)"f2(n - 3) == 0",10);
+    __gmpz_tdiv_q(__gen_e_acsl_div_2,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_2),
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_f2_13));
+    __gmpz_init_set(__gen_e_acsl_if_2,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_div_2));
+    __gmpz_clear(__gen_e_acsl_n_2);
+    __gmpz_clear(__gen_e_acsl__3);
+    __gmpz_clear(__gen_e_acsl_sub);
+    __gmpz_clear(__gen_e_acsl_f2_9);
+    __gmpz_clear(__gen_e_acsl__10);
+    __gmpz_clear(__gen_e_acsl_sub_5);
+    __gmpz_clear(__gen_e_acsl_f2_11);
+    __gmpz_clear(__gen_e_acsl_mul_2);
+    __gmpz_clear(__gen_e_acsl__11);
+    __gmpz_clear(__gen_e_acsl_sub_6);
+    __gmpz_clear(__gen_e_acsl_f2_13);
+    __gmpz_clear(__gen_e_acsl__12);
+    __gmpz_clear(__gen_e_acsl_div_2);
+  }
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_2));
+  __gmpz_clear(__gen_e_acsl_n);
+  __gmpz_clear(__gen_e_acsl_);
+  __gmpz_clear(__gen_e_acsl_if_2);
+  return;
+}
+
+void __gen_e_acsl_g_5(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n)
+{
+  __gmpz_init_set_si(*__retres_arg,0L);
+  return;
+}
+
+void __gen_e_acsl_g(__e_acsl_mpz_t *__retres_arg, int n)
+{
+  __gmpz_init_set_si(*__retres_arg,0L);
+  return;
+}
+
+void __gen_e_acsl_f3_2(__e_acsl_mpz_t *__retres_arg, __e_acsl_mpz_struct * n)
+{
+  __e_acsl_mpz_t __gen_e_acsl__16;
+  int __gen_e_acsl_gt_2;
+  __e_acsl_mpz_t __gen_e_acsl_if_3;
+  __gmpz_init_set_si(__gen_e_acsl__16,0L);
+  __gen_e_acsl_gt_2 = __gmpz_cmp((__e_acsl_mpz_struct const *)(n),
+                                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__16));
+  if (__gen_e_acsl_gt_2 > 0) {
+    long __gen_e_acsl__17;
+    __e_acsl_mpz_t __gen_e_acsl_g_4;
+    __e_acsl_mpz_t __gen_e_acsl__18;
+    __e_acsl_mpz_t __gen_e_acsl_sub_8;
+    __e_acsl_mpz_t __gen_e_acsl_f3_4;
+    __e_acsl_mpz_t __gen_e_acsl_mul_3;
+    __e_acsl_mpz_t __gen_e_acsl__19;
+    __e_acsl_mpz_t __gen_e_acsl_sub_9;
+    __gen_e_acsl__17 = __gmpz_get_si((__e_acsl_mpz_struct const *)(n));
+    __gen_e_acsl_g(& __gen_e_acsl_g_4,(int)__gen_e_acsl__17);
+    __gmpz_init_set_si(__gen_e_acsl__18,1L);
+    __gmpz_init(__gen_e_acsl_sub_8);
+    __gmpz_sub(__gen_e_acsl_sub_8,(__e_acsl_mpz_struct const *)(n),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__18));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_8);
+    */
+    __gen_e_acsl_f3_2(& __gen_e_acsl_f3_4,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_8);
+    __gmpz_init(__gen_e_acsl_mul_3);
+    __gmpz_mul(__gen_e_acsl_mul_3,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_g_4),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_f3_4));
+    __gmpz_init_set_si(__gen_e_acsl__19,5L);
+    __gmpz_init(__gen_e_acsl_sub_9);
+    __gmpz_sub(__gen_e_acsl_sub_9,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_3),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__19));
+    __gmpz_init_set(__gen_e_acsl_if_3,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_9));
+    __gmpz_clear(__gen_e_acsl_g_4);
+    __gmpz_clear(__gen_e_acsl__18);
+    __gmpz_clear(__gen_e_acsl_sub_8);
+    __gmpz_clear(__gen_e_acsl_f3_4);
+    __gmpz_clear(__gen_e_acsl_mul_3);
+    __gmpz_clear(__gen_e_acsl__19);
+    __gmpz_clear(__gen_e_acsl_sub_9);
+  }
+  else {
+    __e_acsl_mpz_t __gen_e_acsl__20;
+    __e_acsl_mpz_t __gen_e_acsl_add;
+    __e_acsl_mpz_t __gen_e_acsl_g_6;
+    __gmpz_init_set_si(__gen_e_acsl__20,1L);
+    __gmpz_init(__gen_e_acsl_add);
+    __gmpz_add(__gen_e_acsl_add,(__e_acsl_mpz_struct const *)(n),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__20));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add);
+    */
+    __gen_e_acsl_g_5(& __gen_e_acsl_g_6,
+                     (__e_acsl_mpz_struct *)__gen_e_acsl_add);
+    __gmpz_init_set(__gen_e_acsl_if_3,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_g_6));
+    __gmpz_clear(__gen_e_acsl__20);
+    __gmpz_clear(__gen_e_acsl_add);
+    __gmpz_clear(__gen_e_acsl_g_6);
+  }
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_3));
+  __gmpz_clear(__gen_e_acsl__16);
+  __gmpz_clear(__gen_e_acsl_if_3);
+  return;
+}
+
+void __gen_e_acsl_f3(__e_acsl_mpz_t *__retres_arg, int n)
+{
+  __e_acsl_mpz_t __gen_e_acsl_n_3;
+  __e_acsl_mpz_t __gen_e_acsl__14;
+  int __gen_e_acsl_gt;
+  __e_acsl_mpz_t __gen_e_acsl_if_4;
+  __gmpz_init_set_si(__gen_e_acsl_n_3,(long)n);
+  __gmpz_init_set_si(__gen_e_acsl__14,0L);
+  __gen_e_acsl_gt = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_n_3),
+                               (__e_acsl_mpz_struct const *)(__gen_e_acsl__14));
+  if (__gen_e_acsl_gt > 0) {
+    __e_acsl_mpz_t __gen_e_acsl_g_2;
+    __e_acsl_mpz_t __gen_e_acsl_n_4;
+    __e_acsl_mpz_t __gen_e_acsl__15;
+    __e_acsl_mpz_t __gen_e_acsl_sub_7;
+    __e_acsl_mpz_t __gen_e_acsl_f3_5;
+    __e_acsl_mpz_t __gen_e_acsl_mul_4;
+    __e_acsl_mpz_t __gen_e_acsl__21;
+    __e_acsl_mpz_t __gen_e_acsl_sub_10;
+    __gen_e_acsl_g(& __gen_e_acsl_g_2,n);
+    __gmpz_init_set_si(__gen_e_acsl_n_4,(long)n);
+    __gmpz_init_set_si(__gen_e_acsl__15,1L);
+    __gmpz_init(__gen_e_acsl_sub_7);
+    __gmpz_sub(__gen_e_acsl_sub_7,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_4),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__15));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_sub_7);
+    */
+    __gen_e_acsl_f3_2(& __gen_e_acsl_f3_5,
+                      (__e_acsl_mpz_struct *)__gen_e_acsl_sub_7);
+    __gmpz_init(__gen_e_acsl_mul_4);
+    __gmpz_mul(__gen_e_acsl_mul_4,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_g_2),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_f3_5));
+    __gmpz_init_set_si(__gen_e_acsl__21,5L);
+    __gmpz_init(__gen_e_acsl_sub_10);
+    __gmpz_sub(__gen_e_acsl_sub_10,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_mul_4),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__21));
+    __gmpz_init_set(__gen_e_acsl_if_4,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_10));
+    __gmpz_clear(__gen_e_acsl_g_2);
+    __gmpz_clear(__gen_e_acsl_n_4);
+    __gmpz_clear(__gen_e_acsl__15);
+    __gmpz_clear(__gen_e_acsl_sub_7);
+    __gmpz_clear(__gen_e_acsl_f3_5);
+    __gmpz_clear(__gen_e_acsl_mul_4);
+    __gmpz_clear(__gen_e_acsl__21);
+    __gmpz_clear(__gen_e_acsl_sub_10);
+  }
+  else {
+    __e_acsl_mpz_t __gen_e_acsl_n_5;
+    __e_acsl_mpz_t __gen_e_acsl__22;
+    __e_acsl_mpz_t __gen_e_acsl_add_2;
+    __e_acsl_mpz_t __gen_e_acsl_g_8;
+    __gmpz_init_set_si(__gen_e_acsl_n_5,(long)n);
+    __gmpz_init_set_si(__gen_e_acsl__22,1L);
+    __gmpz_init(__gen_e_acsl_add_2);
+    __gmpz_add(__gen_e_acsl_add_2,
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl_n_5),
+               (__e_acsl_mpz_struct const *)(__gen_e_acsl__22));
+    /*@ assert
+        Eva: initialization:
+          \initialized((__e_acsl_mpz_struct *)__gen_e_acsl_add_2);
+    */
+    __gen_e_acsl_g_5(& __gen_e_acsl_g_8,
+                     (__e_acsl_mpz_struct *)__gen_e_acsl_add_2);
+    __gmpz_init_set(__gen_e_acsl_if_4,
+                    (__e_acsl_mpz_struct const *)(__gen_e_acsl_g_8));
+    __gmpz_clear(__gen_e_acsl_n_5);
+    __gmpz_clear(__gen_e_acsl__22);
+    __gmpz_clear(__gen_e_acsl_add_2);
+    __gmpz_clear(__gen_e_acsl_g_8);
+  }
+  __gmpz_init_set(*__retres_arg,
+                  (__e_acsl_mpz_struct const *)(__gen_e_acsl_if_4));
+  __gmpz_clear(__gen_e_acsl_n_3);
+  __gmpz_clear(__gen_e_acsl__14);
+  __gmpz_clear(__gen_e_acsl_if_4);
+  return;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/local_goto.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/local_goto.res.oracle
index bdfaabe9c323f09e3c163d96e851403d33d8eadd..a2e7e709cc1b03f77f747ddda9fc902b26666500 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/local_goto.res.oracle
+++ b/src/plugins/e-acsl/tests/runtime/oracle/local_goto.res.oracle
@@ -9,19 +9,19 @@
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
 [e-acsl] tests/runtime/local_goto.c:37: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/runtime/local_goto.c:37: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/runtime/local_goto.c:28: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/runtime/local_goto.c:28: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/runtime/local_goto.c:16: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/runtime/local_goto.c:16: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/mainargs.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/mainargs.res.oracle
index f0225cf73e6ea678bbedc61ba28b397db2e9c357..bb9147c4b0e9addaee53ab74367d4c34a7e0a0a4 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/mainargs.res.oracle
+++ b/src/plugins/e-acsl/tests/runtime/oracle/mainargs.res.oracle
@@ -3,13 +3,14 @@
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
 [e-acsl] FRAMAC_SHARE/libc/string.h:125: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:125: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:127: Warning: 
-  E-ACSL construct `logic function returning an integer' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
 [eva:alarm] tests/runtime/mainargs.c:12: Warning: assertion got status unknown.
diff --git a/src/plugins/e-acsl/tests/temporal/oracle/t_getenv.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle/t_getenv.res.oracle
index 1b9876f5a9b0ea065f5db53858f36cf1c2d406a1..da6d987808fe99b9e725f20de1b03ab078b3b785 100644
--- a/src/plugins/e-acsl/tests/temporal/oracle/t_getenv.res.oracle
+++ b/src/plugins/e-acsl/tests/temporal/oracle/t_getenv.res.oracle
@@ -3,7 +3,7 @@
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
 [e-acsl] FRAMAC_SHARE/libc/stdlib.h:482: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/stdlib.h:482: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
diff --git a/src/plugins/e-acsl/tests/temporal/oracle/t_malloc-asan.res.oracle b/src/plugins/e-acsl/tests/temporal/oracle/t_malloc-asan.res.oracle
index dfe484df046029c67a10781f25849678644e64e8..1b8c383a119177d8b45eac1037821eb6692704a7 100644
--- a/src/plugins/e-acsl/tests/temporal/oracle/t_malloc-asan.res.oracle
+++ b/src/plugins/e-acsl/tests/temporal/oracle/t_malloc-asan.res.oracle
@@ -3,7 +3,7 @@
   the generated program may miss memory instrumentation
   if there are memory-related annotations.
 [e-acsl] tests/temporal/t_malloc-asan.c:31: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] tests/temporal/t_malloc-asan.c:31: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
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 70f435a9631d2c926ac0ed8d94b3e1189c4b8a64..66c2b5ac9dd0f05ecc77980ee35731fba9263872 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
@@ -8,7 +8,7 @@
 [e-acsl] FRAMAC_SHARE/libc/string.h:92: Warning: 
   E-ACSL construct `\separated' is not yet supported. Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:115: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:115: Warning: 
   E-ACSL construct `assigns clause in behavior' is not yet supported.
@@ -17,10 +17,10 @@
   E-ACSL construct `user-defined logic type' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:92: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:93: Warning: 
-  E-ACSL construct `logic function application' is not yet supported.
+  E-ACSL construct `logic functions with labels' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:95: Warning: 
   E-ACSL construct `\separated' is not yet supported. Ignoring annotation.
@@ -28,6 +28,7 @@
   E-ACSL construct `assigns clause in behavior' is not yet supported.
   Ignoring annotation.
 [e-acsl] FRAMAC_SHARE/libc/string.h:98: Warning: 
-  E-ACSL construct `logic function returning an integer' is not yet supported.
+  E-ACSL construct `logic functions performing read accesses'
+  is not yet supported.
   Ignoring annotation.
 [e-acsl] translation done in project "e-acsl".
diff --git a/src/plugins/e-acsl/translate.ml b/src/plugins/e-acsl/translate.ml
index 60bc68beda0ca390195bc892aa0fa0b579b95a1a..11a872659cbee2627db6282016bae368b9f1651b 100644
--- a/src/plugins/e-acsl/translate.ml
+++ b/src/plugins/e-acsl/translate.ml
@@ -448,36 +448,60 @@ and context_insensitive_term_to_exp kf env t =
   | TStartOf lv ->
     let lv, env, _ = tlval_to_lval kf env lv in
     Cil.mkAddrOrStartOf ~loc lv, env, false, "startof"
-  | Tapp(li, [], args) when Builtins.mem li.l_var_info.lv_name ->
-    (* E-ACSL built-in function call *)
+  | Tapp(li, [], targs) ->
     let fname = li.l_var_info.lv_name in
-    let args, env = (* args computed in the reverse order *)
-      try
-        List.fold_left
-          (fun (l, env) a ->
-            let e, env = term_to_exp kf env a in
-            e :: l, env)
-          ([], env)
-          args
-      with Invalid_argument _ ->
-        Options.fatal "[Tapp] unexpected number of arguments when calling %s"
-          fname
-    in
     (* build the varinfo (as an expression) which stores the result of the
        function call. *)
     let _, e, env =
-      Env.new_var
-        ~loc
-        ~name:(fname ^ "_app")
-        env
-        (Some t)
-        (Misc.cty (Extlib.the li.l_type))
-        (fun vi _ ->
-          [ Misc.mk_call ~loc ~result:(Cil.var vi) fname (List.rev args) ])
+      if Builtins.mem li.l_var_info.lv_name then
+        (* E-ACSL built-in function call *)
+        let args, env =
+          try
+            List.fold_right
+              (fun targ (l, env) ->
+                 let e, env = term_to_exp kf env targ in
+                 e :: l, env)
+              targs
+              ([], env)
+          with Invalid_argument _ ->
+            Options.fatal
+              "[Tapp] unexpected number of arguments when calling %s"
+              fname
+        in
+        Env.new_var
+          ~loc
+          ~name:(fname ^ "_app")
+          env
+          (Some t)
+          (Misc.cty (Extlib.the li.l_type))
+          (fun vi _ ->
+             [ Misc.mk_call ~loc ~result:(Cil.var vi) fname args ])
+      else
+        (* build the arguments and compute the integer_ty of the parameters *)
+        let params_ty, args, env =
+          List.fold_right
+            (fun targ (params_ty, args, env) ->
+               let e, env = term_to_exp kf env targ in
+               let param_ty = Typing.get_integer_ty targ in
+               let e, env =
+                 try
+                   let ty = Typing.typ_of_integer_ty param_ty in
+                   add_cast loc env (Some ty) false (Some targ) e
+                 with Typing.Not_an_integer ->
+                   e, env
+               in
+               param_ty :: params_ty, e :: args, env)
+            targs
+            ([], [], env)
+        in
+        let gen_fname =
+          Env.Varname.get ~scope:Env.Global (Functions.RTL.mk_gen_name fname)
+        in
+        Logic_functions.tapp_to_exp ~loc gen_fname env t li params_ty args
     in
     e, env, false, "app"
-  | Tapp _ ->
-    not_yet env "applying logic function"
+  | Tapp(_, _ :: _, _) ->
+    not_yet env "logic functions with labels"
   | Tlambda _ -> not_yet env "functional"
   | TDataCons _ -> not_yet env "constructor"
   | Tif(t1, t2, t3) ->
@@ -648,7 +672,20 @@ and named_predicate_content_to_exp ?name kf env p =
   match p.pred_content with
   | Pfalse -> Cil.zero ~loc, env
   | Ptrue -> Cil.one ~loc, env
-  | Papp _ -> not_yet env "logic function application"
+  | Papp(li, labels, args) ->
+    (* Simply use the implementation of Tapp(li, labels, args).
+      To achieve this, we create a clone of [li] for which the type is
+      transformed from [None] (type of predicates) to
+      [Some int] (type as a term). *)
+    let prj = Project.current () in
+    let o = object inherit Visitor.frama_c_copy prj end in
+    let li = Visitor.visitFramacLogicInfo o li in
+    let lty = Ctype Cil.intType in
+    li.l_type <- Some lty;
+    let tapp = Logic_const.term ~loc (Tapp(li, labels, args)) lty in
+    Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int tapp;
+    let e, env = term_to_exp kf env tapp in
+    e, env
   | Pseparated _ -> not_yet env "\\separated"
   | Pdangling _ -> not_yet env "\\dangling"
   | Pvalid_function _ -> not_yet env "\\valid_function"
@@ -845,7 +882,9 @@ let () =
   At_with_lscope.term_to_exp_ref := term_to_exp;
   At_with_lscope.predicate_to_exp_ref := named_predicate_to_exp;
   Mmodel_translate.term_to_exp_ref := term_to_exp;
-  Mmodel_translate.predicate_to_exp_ref := named_predicate_to_exp
+  Mmodel_translate.predicate_to_exp_ref := named_predicate_to_exp;
+  Logic_functions.term_to_exp_ref := term_to_exp;
+  Logic_functions.named_predicate_to_exp_ref := named_predicate_to_exp
 
 (* This function is used by Guillaume.
    However, it is correct to use it only in specific contexts. *)
diff --git a/src/plugins/e-acsl/typing.ml b/src/plugins/e-acsl/typing.ml
index ee2dcb2ffe54c50e7911dd7d475c7a66052e2669..5c0d16ac021e9b832383fe90e34bf566afab555e 100644
--- a/src/plugins/e-acsl/typing.ml
+++ b/src/plugins/e-acsl/typing.ml
@@ -46,28 +46,34 @@ let c_int = C_type IInt
 let ikind ik = C_type ik
 let other = Other
 
-include Datatype.Make
-(struct
-  type t = integer_ty
-  let name = "E_ACSL.New_typing.t"
-  let reprs = [ Gmp; c_int ]
-  include Datatype.Undefined
-
-  let compare ty1 ty2 = match ty1, ty2 with
-    | C_type i1, C_type i2 ->
-      if i1 = i2 then 0
-      else if Cil.intTypeIncluded i1 i2 then -1 else 1
-    | (Other | C_type _), Gmp | Other, C_type _ -> -1
-    | Gmp, (C_type _ | Other) | C_type _, Other -> 1
-    | Gmp, Gmp | Other, Other -> 0
-
-  let equal = Datatype.from_compare
-
-  let pretty fmt = function
-    | Gmp -> Format.pp_print_string fmt "GMP"
-    | C_type k -> Printer.pp_ikind fmt k
-    | Other -> Format.pp_print_string fmt "OTHER"
- end)
+module D =
+  Datatype.Make_with_collections
+    (struct
+      type t = integer_ty
+      let name = "E_ACSL.New_typing.t"
+      let reprs = [ Gmp; c_int ]
+      include Datatype.Undefined
+
+      let compare ty1 ty2 = match ty1, ty2 with
+        | C_type i1, C_type i2 ->
+          if i1 = i2 then 0
+          else if Cil.intTypeIncluded i1 i2 then -1 else 1
+        | (Other | C_type _), Gmp | Other, C_type _ -> -1
+        | Gmp, (C_type _ | Other) | C_type _, Other -> 1
+        | Gmp, Gmp | Other, Other -> 0
+
+      let equal = Datatype.from_compare
+
+      let hash = function
+        | Gmp -> 787
+        | Other -> 1011
+        | C_type ik -> Hashtbl.hash ik
+
+      let pretty fmt = function
+        | Gmp -> Format.pp_print_string fmt "GMP"
+        | C_type k -> Printer.pp_ikind fmt k
+        | Other -> Format.pp_print_string fmt "OTHER"
+    end)
 
 (******************************************************************************)
 (** Basic operations *)
@@ -94,14 +100,20 @@ let typ_of_integer_ty = function
   | C_type ik -> TInt(ik, [])
   | Other -> raise Not_an_integer
 
+let typ_of_lty = function
+  | Ctype cty -> cty
+  | Linteger -> Gmpz.t ()
+  | Lreal -> Error.not_yet "real numbers"
+  | Ltype _ | Lvar _ | Larrow _ -> Options.fatal "unexpected logic type"
+
 (******************************************************************************)
 (** Memoization *)
 (******************************************************************************)
 
 type computed_info =
-    { ty: t;  (* type required for the term *)
-      op: t; (* type required for the operation *)
-      cast: t option; (* if not [None], type of the context which the term
+    { ty: D.t;  (* type required for the term *)
+      op: D.t; (* type required for the operation *)
+      cast: D.t option; (* if not [None], type of the context which the term
                          must be casted to. If [None], no cast needed. *)
     }
 
@@ -171,38 +183,24 @@ let integer_ty_of_typ ty = ty_of_logic_ty (Ctype ty)
    interval. It is the \theta operator of the JFLA's paper. *)
 let ty_of_interv ?ctx i =
   try
-    let itv_kind =
-      if Ival.is_bottom i then IInt
-      else match Ival.min_and_max i with
-        | Some l, Some u ->
-          let is_pos = Integer.ge l Integer.zero in
-          let lkind = Cil.intKindForValue l is_pos in
-          let ukind = Cil.intKindForValue u is_pos in
-          (* kind corresponding to the interval *)
-          if Cil.intTypeIncluded lkind ukind then ukind else lkind
-        | None, None -> raise Cil.Not_representable (* GMP *)
-        | None, Some _ | Some _, None ->
-          Kernel.fatal ~current:true "ival: %a" Ival.pretty i
-    in
-    (* convert the kind to [IInt] whenever smaller. *)
-    let kind = if Cil.intTypeIncluded itv_kind IInt then IInt else itv_kind in
+    let kind = Interval.ikind_of_interv i in
     (* ctx type whenever possible to prevent superfluous casts in the generated
        code *)
     (match ctx with
      | None | Some (Gmp | Other) -> C_type kind
      | Some (C_type ik as ctx) ->
-       if Cil.intTypeIncluded itv_kind ik then ctx else C_type kind)
+       if Cil.intTypeIncluded kind ik then ctx else C_type kind)
   with Cil.Not_representable ->
     Gmp
 
 (* 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 =
-  if compare ty ctx = 1 then begin
+  if D.compare ty ctx = 1 then
     (* type larger than the expected context,
        so we must introduce an explicit cast *)
     { ty; op; cast = Some ctx }
-  end else
+  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
@@ -356,7 +354,7 @@ let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t =
       dup ctx_res
 
     | TBinOp ((Lt | Gt | Le | Ge | Eq | Ne), t1, t2) ->
-      assert (match ctx with None -> true | Some c -> compare c c_int >= 0);
+      assert (match ctx with None -> true | Some c -> D.compare c c_int >= 0);
       let ctx =
         try
           let i1 = Interval.infer t1 in
@@ -462,14 +460,55 @@ let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t =
       dup Other
 
     | Tapp(li, _, args) ->
-      let typ_arg lvi arg =
-        let ctx = ty_of_logic_ty lvi.lv_type in
-        ignore (type_term ~use_gmp_opt:false ~ctx arg)
-      in
-      List.iter2 typ_arg li.l_profile args;
-      (* [li.l_type is [None] for predicate only: not possible here.
-         Thus using [Extlib.the] is fine *)
-      dup (ty_of_logic_ty (Extlib.the li.l_type))
+      if Builtins.mem li.l_var_info.lv_name then
+        let typ_arg lvi arg =
+          (* a built-in is a C function, so the context is necessarily a C
+             type. *)
+          let ctx = ty_of_logic_ty lvi.lv_type in
+          ignore (type_term ~use_gmp_opt:false ~ctx arg)
+        in
+        List.iter2 typ_arg li.l_profile args;
+        (* [li.l_type is [None] for predicate only: not possible here.
+           Thus using [Extlib.the] is fine *)
+        dup (ty_of_logic_ty (Extlib.the 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
+           statically and at runtime)... *)
+        List.iter (fun arg -> ignore (type_term ~use_gmp_opt:true arg)) args;
+        (* TODO: recursive call in arguments of function call *)
+        match li.l_body with
+        | LBpred _ ->
+          (* possible to have an [LBpred] here because we transformed
+             [Papp] into [Tapp] *)
+          dup c_int
+        | LBterm _ ->
+          begin match li.l_type with
+          | None ->
+            assert false
+          | Some lty ->
+            match lty with
+            | Linteger ->
+              let i = Interval.infer t in
+              if Options.Gmp_only.get () then dup Gmp else dup (ty_of_interv i)
+            | Ctype TInt(ik, _ ) ->
+              dup (C_type ik)
+            | Ctype TFloat _ -> (* TODO: handle in MR !226 *)
+              dup Other
+            | Lreal ->
+              Error.not_yet "real numbers"
+            | Ctype _ ->
+              dup Other
+            | Ltype _ | Lvar _ | Larrow _ ->
+              Options.fatal "unexpected type"
+          end
+        | LBnone ->
+          Error.not_yet "logic functions with no definition nor reads clause"
+        | LBreads _ ->
+          Error.not_yet "logic functions performing read accesses"
+        | LBinductive _ ->
+          Error.not_yet "logic functions inductively defined"
+      end
 
     | Tunion _ -> Error.not_yet "tset union"
     | Tinter _ -> Error.not_yet "tset intersection"
@@ -528,7 +567,18 @@ let rec type_predicate p =
   (* 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 _ -> Error.not_yet "logic function application"
+    | Papp(li, _, _) ->
+      begin match li.l_body with
+      | LBpred _ ->
+        (* No need to type subpredicates
+           since Papp will be transformed into Tapp in Translate:
+           a retyping is done there *)
+        c_int
+      | LBnone -> (* Eg: \is_finite *)
+        Error.not_yet "logic functions with no definition nor reads clause"
+      | LBreads _ | LBterm _ | LBinductive _ ->
+        Options.fatal "unexpected logic definition"
+      end
     | Pseparated _ -> Error.not_yet "\\separated"
     | Pdangling _ -> Error.not_yet "\\dangling"
     | Prel(_, t1, t2) ->
@@ -637,7 +687,7 @@ let rec type_predicate p =
 
 let type_term ~use_gmp_opt ?ctx t =
   Options.feedback ~dkey ~level:4 "typing term '%a' in ctx '%a'."
-    Printer.pp_term t (Pretty_utils.pp_opt pretty) ctx;
+    Printer.pp_term t (Pretty_utils.pp_opt D.pretty) ctx;
   ignore (type_term ~use_gmp_opt ?ctx t)
 
 let type_named_predicate ?(must_clear=true) p =
@@ -694,6 +744,8 @@ let get_cast_of_predicate p =
 
 let clear = Memo.clear
 
+module Datatype = D
+
 (*
 Local Variables:
 compile-command: "make"
diff --git a/src/plugins/e-acsl/typing.mli b/src/plugins/e-acsl/typing.mli
index 8182360e77e376bfb86627f152fc2e3377706b13..a6387e848d2822859c11a1c63f269b19890f3e0d 100644
--- a/src/plugins/e-acsl/typing.mli
+++ b/src/plugins/e-acsl/typing.mli
@@ -56,7 +56,7 @@ type integer_ty = private
   | C_type of ikind
   | Other (** Any non-integral type *)
 
-val pretty: Format.formatter -> integer_ty -> unit
+module Datatype: Datatype.S_with_collections with type t = integer_ty
 
 (** {3 Smart constructors} *)
 
@@ -76,6 +76,9 @@ val typ_of_integer_ty: integer_ty -> typ
 val integer_ty_of_typ: typ -> integer_ty
 (** Reverse of [typ_of_integer_ty] *)
 
+val ty_of_logic_ty: logic_type -> integer_ty
+(** @return the {!integer_ty} that correponds to the given logic type. *)
+
 val join: integer_ty -> integer_ty -> integer_ty
 (** {!integer_ty} is a join-semi-lattice if you do not consider [Other]. If
     there is no [Other] in argument, this function computes the join of this
@@ -88,8 +91,8 @@ val join: integer_ty -> integer_ty -> integer_ty
 
 val type_term: use_gmp_opt:bool -> ?ctx:integer_ty -> term -> unit
 (** Compute the type of each subterm of the given term in the given context. If
-    [use_gmp_opt] is false, then the conversion to the given context is done even if
-    -e-acsl-gmp-only is set. *)
+    [use_gmp_opt] is false, then the conversion to the given context is done
+    even if -e-acsl-gmp-only is set. *)
 
 val type_named_predicate: ?must_clear:bool -> predicate -> unit
 (** Compute the type of each term of the given predicate.
@@ -132,15 +135,17 @@ val unsafe_set: term -> ?ctx:integer_ty -> integer_ty -> unit
 (** Register that the given term has the given type in the given context (if
     any). No verification is done. *)
 
-
 (*****************************************************************************)
-(* Utils *)
+(** {2 Typing/types-related utils} *)
 (*****************************************************************************)
 
 val ty_of_interv: ?ctx:integer_ty -> Ival.t -> integer_ty
 (* Compute the smallest type (bigger than [int]) which can contain the whole
    interval. It is the \theta operator of the JFLA's paper. *)
 
+val typ_of_lty: logic_type -> typ
+(** @return the C type that correponds to the given logic type. *)
+
 (******************************************************************************)
 (** {2 Internal stuff} *)
 (******************************************************************************)
diff --git a/src/plugins/e-acsl/visit.ml b/src/plugins/e-acsl/visit.ml
index a512b5eb8e5a89bf17ffd6b3810e578e8cc625dc..077f9360eb9db2b22253a05fcfdac5907a7aedcb 100644
--- a/src/plugins/e-acsl/visit.ml
+++ b/src/plugins/e-acsl/visit.ml
@@ -453,7 +453,12 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
             in
             Extlib.may handle_main main_fct
           in
-          Project.on prj build_mmodel_initializer ();
+          Project.on
+            prj
+            (fun () ->
+               f.globals <- Logic_functions.add_generated_functions f.globals;
+               build_mmodel_initializer ())
+            ();
           (* reset copied states at the end to be observationally
               equivalent to a standard visitor. *)
           Project.clear ~selection ~project:prj ();
@@ -468,8 +473,9 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
       Cil.JustCopyPost
         (fun l ->
           let new_vi = Cil.get_varinfo self#behavior vi in
-          Misc.register_library_function new_vi;
-          Builtins.update vi.vname new_vi;
+          if Misc.is_library_loc vi.vdecl then
+            Misc.register_library_function new_vi;
+          if Builtins.mem vi.vname then Builtins.update vi.vname new_vi;
           l)
     else begin
       Misc.register_library_function vi;
@@ -561,9 +567,10 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
     let locals, blocks =
       List.fold_left
         (fun (local_vars, block_vars as acc) (v, scope) -> match scope with
-        | Env.Global -> acc
-        | Env.Function -> v :: local_vars, v :: block_vars
-        | Env.Local_block -> v :: local_vars, block_vars)
+        (* TODO: [kf] assumed to be consistent. Should be asserted. *)
+        | Env.LFunction _kf -> v :: local_vars, v :: block_vars
+        | Env.LLocal_block _kf -> v :: local_vars, block_vars
+        | _ -> acc)
         (f.slocals, f.sbody.blocals)
         vars
     in
@@ -1020,6 +1027,7 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
 
   initializer
     Misc.reset ();
+    Logic_functions.reset ();
     Literal_strings.reset ();
     Global_observer.reset ();
     Keep_status.before_translation ();