diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in
index e12228f3c5541e1458ef4f9d0861b658d36101d8..13768e6bfbc325d7a77691443608f60bb05c4c78 100644
--- a/src/plugins/e-acsl/Makefile.in
+++ b/src/plugins/e-acsl/Makefile.in
@@ -69,16 +69,18 @@ PLUGIN_CMO:= local_config \
 	mmodel_analysis \
 	exit_points \
 	label \
+	lscope \
 	env \
 	keep_status \
 	dup_functions \
 	interval \
 	typing \
+	loops \
 	quantif \
+	at_with_lscope \
 	translate \
 	temporal \
 	prepare_ast \
-	loops \
 	visit \
 	main
 
diff --git a/src/plugins/e-acsl/at_with_lscope.ml b/src/plugins/e-acsl/at_with_lscope.ml
new file mode 100644
index 0000000000000000000000000000000000000000..b266dff47c569425190f3ba6912993c39d50e996
--- /dev/null
+++ b/src/plugins/e-acsl/at_with_lscope.ml
@@ -0,0 +1,340 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-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
+
+(**************************************************************************)
+(********************** Forward references ********************************)
+(**************************************************************************)
+
+let 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"
+
+(*****************************************************************************)
+(**************************** Handling memory ********************************)
+(*****************************************************************************)
+
+(* Remove all the bindings for [kf]. [Cil_datatype.Kf.Hashtbl] does not
+  provide the [remove_all] function. Thus we need to keep calling [remove]
+  until all entries are removed. *)
+let rec remove_all tbl kf =
+  if Cil_datatype.Kf.Hashtbl.mem tbl kf then begin
+    Cil_datatype.Kf.Hashtbl.remove tbl kf;
+    remove_all tbl kf
+  end
+
+module Malloc = struct
+  let tbl = Cil_datatype.Kf.Hashtbl.create 7
+  let add kf stmt = Cil_datatype.Kf.Hashtbl.add tbl kf stmt
+  let find_all kf = Cil_datatype.Kf.Hashtbl.find_all tbl kf
+  let remove_all kf = remove_all tbl kf
+end
+
+module Free = struct
+  let tbl = Cil_datatype.Kf.Hashtbl.create 7
+  let add kf stmt = Cil_datatype.Kf.Hashtbl.add tbl kf stmt
+  let find_all kf = Cil_datatype.Kf.Hashtbl.find_all tbl kf
+  let remove_all kf = remove_all tbl kf
+end
+
+(**************************************************************************)
+(*************************** Translation **********************************)
+(**************************************************************************)
+
+(* Builds the terms [t_size] and [t_shifted] from each
+  [Lvs_quantif(tmin, lv, tmax)] from [lscope]
+  where [t_size = tmax - tmin + (-1|0|1)] depending on whether the
+                                          inequalities are strict or large
+  and [t_shifted = lv - tmin + (-1|0)] (so that we start indexing at 0) *)
+let rec sizes_and_shifts_from_quantifs ~loc kf lscope sizes_and_shifts =
+  match lscope with
+  | [] ->
+    sizes_and_shifts
+  | Lscope.Lvs_quantif(tmin, _, _,  _, tmax) ::_
+    when Misc.term_has_lv_from_vi tmin || Misc.term_has_lv_from_vi tmax ->
+    Error.not_yet "\\at with logic variable linked to C variable"
+  | Lscope.Lvs_quantif(tmin, rel1, lv, rel2, tmax) :: lscope' ->
+    let t_size = Logic_const.term ~loc (TBinOp(MinusA, tmax, tmin)) Linteger in
+    let t_size = match rel1, rel2 with
+      | Rle, Rle ->
+        Logic_const.term
+          ~loc
+          (TBinOp(PlusA, t_size, Cil.lone ~loc ()))
+          Linteger
+      | Rlt, Rle | Rle, Rlt ->
+        t_size
+      | Rlt, Rlt ->
+        Logic_const.term
+          ~loc
+          (TBinOp(MinusA, t_size, Cil.lone ~loc ()))
+          Linteger
+      | _ ->
+        Options.fatal "Unexpected comparison operator"
+    in
+    let i = Interval.infer t_size in
+    (* The EXACT amount of memory that is needed can be known at runtime. This
+      is because the tightest bounds for the variables can be known at runtime.
+      Example: In the following predicate
+        [\exists integer u; 9 <= u <= 13 &&
+         \forall integer v; -5 < v <= (u <= 11 ? u + 6 : u - 9) ==>
+           \at(u + v > 0, K)]
+        the upper bound [M] for [v] depends on [u].
+        In chronological order, [M] equals to 15, 16, 17, 3 and 4.
+        Thus the tightest upper bound for [v] is [max(M)=17].
+      HOWEVER, computing that exact information requires extra nested loops,
+      prior to the [malloc] stmts, that will try all the possible values of the
+      variables involved in the bounds.
+      Instead of sacrificing time over memory (by performing these extra
+      computations), we consider that sacrificing memory over time is more
+      beneficial. In particular, though we may allocate more memory than
+      needed, the number of reads/writes into it is the same in both cases.
+      Conclusion: over-approximate [t_size] *)
+    let t_size = match Ival.min_and_max i with
+      | _, Some max ->
+        Logic_const.tint ~loc max
+      | _, None ->
+        Error.not_yet
+          "\\at on purely logic variables and with quantifier that uses \
+            too complex bound (E-ACSL cannot infer a finite upper bound to it)"
+    in
+    (* Index *)
+    let t_lv = Logic_const.tvar ~loc lv in
+    let t_shifted = match rel1 with
+      | Rle ->
+        Logic_const.term ~loc (TBinOp(MinusA, t_lv, tmin)) Linteger
+      | Rlt ->
+        let t =  Logic_const.term ~loc (TBinOp(MinusA, t_lv, tmin)) Linteger in
+        Logic_const.term ~loc (TBinOp(MinusA, t, Cil.lone ~loc())) Linteger
+      | _ ->
+        Options.fatal "Unexpected comparison operator"
+    in
+    (* Returning *)
+    let sizes_and_shifts = (t_size, t_shifted) :: sizes_and_shifts in
+    sizes_and_shifts_from_quantifs ~loc kf lscope' sizes_and_shifts
+  | (Lscope.Lvs_let(_, t) | Lscope.Lvs_global(_, t)) :: _
+    when Misc.term_has_lv_from_vi t ->
+    Error.not_yet "\\at with logic variable linked to C variable"
+  | Lscope.Lvs_let _ :: lscope' ->
+    sizes_and_shifts_from_quantifs ~loc kf lscope' sizes_and_shifts
+  | Lscope.Lvs_formal _ :: _ ->
+    Error.not_yet "\\at using formal variable of a logic function"
+  | Lscope.Lvs_global _ :: _ ->
+    Error.not_yet "\\at using global logic variable"
+
+let size_from_sizes_and_shifts ~loc = function
+  | [] ->
+    (* No quantified variable. But still need to allocate [1*sizeof(_)] amount
+      of memory to store purely logic variables that are NOT quantified
+      (example: from \let). *)
+    Cil.lone ~loc ()
+  | (size, _) :: sizes_and_shifts ->
+    List.fold_left
+      (fun t_size (t_s, _) ->
+        Logic_const.term ~loc (TBinOp(Mult, t_size, t_s)) Linteger)
+      size
+      sizes_and_shifts
+
+(* Build the left-value corresponding to [*(at + index)]. *)
+let lval_at_index ~loc kf env (e_at, vi_at, t_index) =
+  Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int t_index;
+  let term_to_exp = !term_to_exp_ref in
+  let e_index, env = term_to_exp kf env t_index in
+  let e_index = Cil.constFold false e_index in
+  let e_addr =
+    Cil.new_exp ~loc (BinOp(PlusPI, e_at, e_index, vi_at.vtype))
+  in
+  let lval_at_index = Mem e_addr, NoOffset in
+  lval_at_index, env
+
+(* Associate to each possible tuple of quantifiers
+  a unique index from the set {n | 0 <= n < n_max}.
+  That index will serve to identify the memory location where the evaluation
+  of the term/predicate is stored for the given tuple of quantifier.
+  The following gives the smallest set of such indexes (hence we use the
+  smallest amount of memory in some respect):
+  To (t_shifted_n, t_shifted_n-1, ..., t_shifted_1)
+  where 0 <= t_shifted_i < beta_i
+  corresponds: \sum_{i=1}^n( t_shifted_i * \pi_{j=1}^{i-1}(beta_j) ) *)
+let index_from_sizes_and_shifts ~loc sizes_and_shifts =
+  let product terms = List.fold_left
+    (fun product t ->
+      Logic_const.term ~loc (TBinOp(Mult, product, t)) Linteger)
+    (Cil.lone ~loc ())
+    terms
+  in
+  let sum, _ = List.fold_left
+    (fun (index, sizes) (t_size, t_shifted) ->
+      let pi_beta_j = product sizes in
+      let bi_mult_pi_beta_j =
+        Logic_const.term ~loc (TBinOp(Mult, t_shifted, pi_beta_j)) Linteger
+      in
+      let sum = Logic_const.term
+        ~loc
+        (TBinOp(PlusA, bi_mult_pi_beta_j, index))
+        Linteger
+      in
+      sum, t_size :: sizes)
+    (Cil.lzero ~loc (), [])
+    sizes_and_shifts
+  in
+  sum
+
+let put_block_at_label env block label =
+  let stmt = Label.get_stmt (Env.get_visitor env) label in
+  let env_ref = ref env in
+  let o = object
+    inherit Visitor.frama_c_inplace
+    method !vstmt_aux stmt =
+      assert (!env_ref == env);
+      env_ref := Env.extend_stmt_in_place env stmt ~label block;
+      Cil.ChangeTo stmt
+  end
+  in
+  let bhv = Env.get_behavior env in
+  ignore(Visitor.visitFramacStmt o (Cil.get_stmt bhv stmt));
+  !env_ref
+
+let to_exp ~loc kf env pot label =
+  let term_to_exp = !term_to_exp_ref in
+  let lscope_vars = Lscope.get_all (Env.Logic_scope.get env) in
+  let sizes_and_shifts =
+    sizes_and_shifts_from_quantifs ~loc kf lscope_vars []
+  in
+  (* Creating the pointer *)
+  let ty = match pot with
+  | Misc.PoT_pred _ ->
+    Cil.intType
+  | Misc.PoT_term t ->
+    begin match Typing.get_integer_ty t with
+    | Typing.C_type _ | Typing.Other ->
+      Typing.get_typ t
+    | Typing.Gmp ->
+      Error.not_yet "\\at on purely logic variables and over gmp type"
+    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;
+      [])
+  in
+  (* Index *)
+  let t_index = index_from_sizes_and_shifts ~loc sizes_and_shifts in
+  (* Innermost block *)
+  let mk_innermost_block env =
+    let term_to_exp = !term_to_exp_ref in
+    let named_predicate_to_exp = !predicate_to_exp_ref in
+    match pot with
+    | Misc.PoT_pred p ->
+      let env = Env.push env in
+      let lval, env = lval_at_index ~loc kf env (e_at, vi_at, t_index) in
+      let e, env = named_predicate_to_exp kf env p in
+      let e = Cil.constFold false e in
+      let storing_stmt =
+        Cil.mkStmtOneInstr ~valid_sid:true (Set(lval, e, loc))
+      in
+      let block, env =
+        Env.pop_and_get env storing_stmt ~global_clear:false Env.After
+      in
+      (* We CANNOT return [block.bstmts] because it does NOT contain
+        variable declarations. *)
+      [ Cil.mkStmt ~valid_sid:true (Block block) ], env
+    | Misc.PoT_term t ->
+      begin match Typing.get_integer_ty t with
+      | Typing.C_type _ | Typing.Other ->
+        let env = Env.push env in
+        let lval, env = lval_at_index ~loc kf env (e_at, vi_at, t_index) in
+        let e, env = term_to_exp kf env t in
+        let e = Cil.constFold false e in
+        let storing_stmt =
+          Cil.mkStmtOneInstr ~valid_sid:true (Set(lval, e, loc))
+        in
+        let block, env =
+          Env.pop_and_get env storing_stmt ~global_clear:false Env.After
+        in
+        (* We CANNOT return [block.bstmts] because it does NOT contain
+          variable declarations. *)
+        [ Cil.mkStmt ~valid_sid:true (Block block) ], env
+      | Typing.Gmp ->
+        Error.not_yet "\\at on purely logic variables and over gmp type"
+      end
+  in
+  (* Storing loops *)
+  let lscope_vars = Lscope.get_all (Env.Logic_scope.get env) in
+  let env = Env.push env in
+  let storing_loops_stmts, env =
+    Loops.mk_nested_loops ~loc mk_innermost_block kf env lscope_vars
+  in
+  let storing_loops_block = Cil.mkBlock storing_loops_stmts in
+  let storing_loops_block, env = Env.pop_and_get
+    env
+    (Cil.mkStmt ~valid_sid:true (Block storing_loops_block))
+    ~global_clear:false
+    Env.After
+  in
+  (* Put at label *)
+  let env = put_block_at_label env storing_loops_block label in
+  (* 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
diff --git a/src/plugins/e-acsl/at_with_lscope.mli b/src/plugins/e-acsl/at_with_lscope.mli
new file mode 100644
index 0000000000000000000000000000000000000000..40eeb55fd3c1c9b3625c16eb9ddcea102495b06f
--- /dev/null
+++ b/src/plugins/e-acsl/at_with_lscope.mli
@@ -0,0 +1,69 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-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
+
+(* Convert \at on terms or predicates in which we can find purely
+  logic variable. *)
+
+(**************************************************************************)
+(*************************** Translation **********************************)
+(**************************************************************************)
+
+val to_exp:
+  loc:Location.t -> kernel_function -> Env.t ->
+  Misc.pred_or_term -> logic_label -> exp * Env.t
+
+(*****************************************************************************)
+(**************************** Handling memory ********************************)
+(*****************************************************************************)
+
+(* The different possible evaluations of the [\at] under study are
+  stored in a memory location that needs to be alloted then freed.
+  This part is designed for that purpose. *)
+
+module Malloc: sig
+  val find_all: kernel_function -> stmt list
+  (* Return the list of [malloc] stmts that need to be inserted into [kf]. *)
+
+  val remove_all: kernel_function -> unit
+  (* Remove all [malloc] stmts for [kf] from the internal table. *)
+end
+
+module Free: sig
+  val find_all: kernel_function -> stmt list
+  (* Return the list of [free] stmts that need to be inserted into [kf]. *)
+
+  val remove_all: kernel_function -> unit
+  (* Remove all [free] stmts for [kf] from the internal table. *)
+end
+
+(**************************************************************************)
+(********************** Forward references ********************************)
+(**************************************************************************)
+
+val 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
\ No newline at end of file
diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index 21e6f60037087fe70025dc22e78128b9040885f2..4adf3772d04bbd70aff6198441d842f4e4728849 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -19,6 +19,8 @@
 #   configure	configure
 ###############################################################################
 
+-* E-ACSL       [2018/10/04] Support for \at on purely logic variables.
+                Fix bug #1762 about out-of-scope variables when using \old.
 *  E-ACSL       [2018/10/02] Fix bug #2305 about taking the address of a
                 bitfield.
 -  E-ACSL       [2018/09/18] Support for ranges in memory builtins
diff --git a/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables.c b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables.c
new file mode 100644
index 0000000000000000000000000000000000000000..88bbc974a191e189a3fdaa7e88047b65abf6387f
--- /dev/null
+++ b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables.c
@@ -0,0 +1,12 @@
+main(void) {
+  int m = 2;
+  int n = 7;;
+  K: ;
+  n = 875;
+  /*@ assert
+      \let k = 3;
+      \exists integer u; 9 <= u < 21 &&
+      \forall integer v; -5 < v <= (u < 15 ? u + 6 : k) ==>
+        \at(n + u + v > 0, K); */ ;
+  return 0;
+}
diff --git a/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables_not-yet.c b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables_not-yet.c
new file mode 100644
index 0000000000000000000000000000000000000000..dff4da97bd3e5b3fa986023c89a94a7307563cd5
--- /dev/null
+++ b/src/plugins/e-acsl/doc/refman/at_on-purely-logic-variables_not-yet.c
@@ -0,0 +1,2 @@
+/*@ ensures \forall int i; 0 <= i < n-1 ==> \old(t[i]) == t[i+1]; */
+void reverse(int *t, int n) { }
diff --git a/src/plugins/e-acsl/doc/refman/changes_modern.tex b/src/plugins/e-acsl/doc/refman/changes_modern.tex
index 99a5c9360d647dc13f05eebf515b6ff6fa296016..bbcf78dedebb7f60052f788e1606d485795cd53e 100644
--- a/src/plugins/e-acsl/doc/refman/changes_modern.tex
+++ b/src/plugins/e-acsl/doc/refman/changes_modern.tex
@@ -119,6 +119,8 @@ in \lstinline|\\at|}
 \subsection*{Version \eacslversion}
 
 \begin{itemize}
+\item \changeinsection{at}{support of \lstinline|\\at| on purely
+logic variables}
 \item \changeinsection{locations}{support of ranges in memory built-ins
   (e.g. \lstinline|\\valid| or \lstinline|\\initialized|)}
 \end{itemize}
diff --git a/src/plugins/e-acsl/doc/refman/speclang_modern.tex b/src/plugins/e-acsl/doc/refman/speclang_modern.tex
index 2b4fa7dec498ee36d6c79fa6a84e1a43bfe71fd0..3adb89eb13dd0ba7731bb2be8fd24caf64fc863e 100644
--- a/src/plugins/e-acsl/doc/refman/speclang_modern.tex
+++ b/src/plugins/e-acsl/doc/refman/speclang_modern.tex
@@ -512,6 +512,30 @@ only the first one is accepted and valid in \eacsl since evaluating the term
 
 \end{example}
 
+For the time being, \verb|\at| can be applied to any term or predicate that uses
+quantified variables, let-binded variables and C variables.
+
+\begin{example}
+The \verb|\at| construct of the following example is supported.
+\cinput{at_on-purely-logic-variables.c}
+
+\end{example}
+
+
+\begin{notimplementedenv}
+However, quantified variables that use C variables in their bounds and
+let-binded variables that use C variables in their definition
+are not yet supported.
+
+\begin{example}
+The \verb|\at| construct of the following example is \emph{not yet} supported
+since the quantified variable \verb|i| uses the C variable \verb|n| in the
+definition of its upper bound.
+\cinput{at_on-purely-logic-variables_not-yet.c}
+
+\end{example}
+\end{notimplementedenv}
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 \subsection{Statement contracts}
diff --git a/src/plugins/e-acsl/env.ml b/src/plugins/e-acsl/env.ml
index 6cbc310cb12e66d4da8067836bca1bb4733c2bee..aeb9cc143e247a31d4abaf5747dd76a4e2ce4708 100644
--- a/src/plugins/e-acsl/env.ml
+++ b/src/plugins/e-acsl/env.ml
@@ -51,7 +51,9 @@ type local_env =
       rte: bool }
 
 type t = 
-    { visitor: Visitor.frama_c_visitor; 
+    { visitor: Visitor.frama_c_visitor;
+      lscope: Lscope.t;
+      lscope_reset: bool;
       annotation_kind: Misc.annotation_kind;
       new_global_vars: (varinfo * scope) list;
       (* generated variables. The scope indicates the level where the variable
@@ -59,7 +61,8 @@ type t =
       global_mpz_tbl: mpz_tbl;
       env_stack: local_env list;
       init_env: local_env;
-      var_mapping: Varinfo.t Logic_var.Map.t; (* bind logic var to C var *)
+      var_mapping: Varinfo.t Stack.t Logic_var.Map.t;
+      (* records of C bindings for logic vars *)
       loop_invariants: predicate list list;
       (* list of loop invariants for each currently visited loops *) 
       cpt: int; (* counter used when generating variables *) }
@@ -108,7 +111,9 @@ let empty_local_env =
     rte = true }
 
 let dummy = 
-  { visitor = new Visitor.generic_frama_c_visitor (Cil.inplace_visit ()); 
+  { visitor = new Visitor.generic_frama_c_visitor (Cil.inplace_visit ());
+    lscope = Lscope.empty;
+    lscope_reset = true;
     annotation_kind = Misc.Assertion;
     new_global_vars = [];
     global_mpz_tbl = empty_mpz_tbl; 
@@ -119,7 +124,9 @@ let dummy =
     cpt = 0; }
 
 let empty v =
-  { visitor = v; 
+  { visitor = v;
+    lscope = Lscope.empty;
+    lscope_reset = true;
     annotation_kind = Misc.Assertion;
     new_global_vars = [];
     global_mpz_tbl = empty_mpz_tbl; 
@@ -280,29 +287,48 @@ module Logic_binding = struct
 	| 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 = 
+	| 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 env ~name:logic_v.lv_name None ty (fun _ _ -> []) 
+    let v, e, env = new_var
+      ~loc:Location.unknown
+      env
+      ~name:logic_v.lv_name
+      None
+      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 with var_mapping = Logic_var.Map.add logic_v v env.var_mapping }
+    v, e, env
 
-  let get env logic_v = 
-    try Logic_var.Map.find logic_v env.var_mapping
-    with Not_found -> assert false
+  let get env logic_v =
+    try
+      let varinfos = Logic_var.Map.find logic_v env.var_mapping in
+      Stack.top varinfos
+    with Not_found | Stack.Empty ->
+      assert false
 
-  let remove env v = 
-    let map = env.var_mapping in
-    assert (Logic_var.Map.mem v map);
-    { env with var_mapping = Logic_var.Map.remove v map }
+  let remove env logic_v =
+    try
+      let varinfos = Logic_var.Map.find logic_v env.var_mapping in
+      ignore (Stack.pop varinfos);
+      env
+    with Not_found | Stack.Empty ->
+      assert false
 
 end
 
@@ -315,6 +341,16 @@ let current_kf env =
 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 }
+  let set_reset env bool = { env with lscope_reset = bool }
+  let get_reset env = env.lscope_reset
+  let reset env =
+    if env.lscope_reset then { env with lscope = Lscope.empty }
+    else env
+end
+
 let emitter = 
   Emitter.create
     "E_ACSL" 
@@ -345,12 +381,17 @@ let add_stmt ?(post=false) ?(init=false) ?before env stmt =
     init_env = if init then local_env else env.init_env;
     env_stack = if init then env.env_stack else local_env :: tl }
 
-let extend_stmt_in_place env stmt ~pre block =
+let extend_stmt_in_place env stmt ~label block =
   let new_stmt = Cil.mkStmt ~valid_sid:true (Block block) in
   let sk = stmt.skind in
-  stmt.skind <- 
+  stmt.skind <-
     Block (Cil.mkBlock [ new_stmt; Cil.mkStmt ~valid_sid:true sk ]);
-  if pre then 
+    let pre = match label with
+    | BuiltinLabel(Here | Post) -> true
+    | BuiltinLabel(Old | Pre | LoopEntry | LoopCurrent | Init)
+    | FormalLabel _ | StmtLabel _ -> false
+    in
+    if pre then
     let local_env, tl_env = top false env in
     let b_info = local_env.block_info in
     let b_info = { b_info with pre_stmts = new_stmt :: b_info.pre_stmts } in
diff --git a/src/plugins/e-acsl/env.mli b/src/plugins/e-acsl/env.mli
index bb32297e32dd877b7127bb645f1f44047b191224..b56fe807cd817458a57e3b58a3004f0d89bb42dc 100644
--- a/src/plugins/e-acsl/env.mli
+++ b/src/plugins/e-acsl/env.mli
@@ -66,8 +66,13 @@ val new_var_and_mpz_init:
 
 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 get: t -> logic_var -> varinfo
+  (* Return the latest C binding. *)
+
   val remove: t -> logic_var -> t
+  (* Remove the latest C binding. *)
 end
 
 val add_assert: t -> stmt -> predicate -> unit
@@ -80,11 +85,11 @@ val add_stmt: ?post:bool -> ?init:bool -> ?before:stmt -> t -> stmt -> t
     say that any labels attached to [before] are moved to [stmt]. [post]
     indicates that [stmt] should be added after the target statement. *)
 
-val extend_stmt_in_place: t -> stmt -> pre:bool -> block -> t
-(**  [extend_stmt_in_place env stmt ~pre b] modifies [stmt] in place in order to
-     add the given [block]. If [pre] is [true], then this block is guaranteed
-     to be at the first place of the resulting [stmt] whatever modification
-     will be done by the visitor later. *)
+val extend_stmt_in_place: t -> stmt -> label:logic_label -> block -> t
+(** [extend_stmt_in_place env stmt ~label b] modifies [stmt] in place in
+    order to add the given [block]. If [label] is [Here] or [Post],
+    then this block is guaranteed to be at the first place of the resulting
+    [stmt] whatever modification will be done by the visitor later. *)
 
 val push: t -> t
 (** Push a new local context in the environment *)
@@ -116,6 +121,27 @@ val get_behavior: t -> Cil.visitor_behavior
 val current_kf: t -> kernel_function option
 (** Kernel function currently visited in the new project. *)
 
+module Logic_scope: sig
+  val get: t -> Lscope.t
+  (** Return the logic scope associated to the environment. *)
+
+  val extend: t -> Lscope.lscope_var -> t
+  (** Add a new logic variable with its associated information in the
+    logic scope of the environment. *)
+
+  val reset: t -> t
+  (** Return a new environment in which the logic scope is reset
+    iff [set_reset _ true] has been called beforehand. Do nothing otherwise. *)
+
+  val set_reset: t -> bool -> t
+  (** Setter of the information indicating whether the logic scope should be
+    reset at next call to [reset]. *)
+
+  val get_reset: t -> bool
+  (** Getter of the information indicating whether the logic scope should be
+    reset at next call to [reset]. *)
+end
+
 (* ************************************************************************** *)
 (** {2 Current annotation kind} *)
 (* ************************************************************************** *)
diff --git a/src/plugins/e-acsl/loops.ml b/src/plugins/e-acsl/loops.ml
index 3997c2c9ef324672d9aea532bfc8b0380a7e0a7b..b359b7beb1d82d9b23977ef0977a608a08ab8379 100644
--- a/src/plugins/e-acsl/loops.ml
+++ b/src/plugins/e-acsl/loops.ml
@@ -20,27 +20,44 @@
 (*                                                                        *)
 (**************************************************************************)
 
+open Cil
 open Cil_types
 
+(**************************************************************************)
+(********************** Forward references ********************************)
+(**************************************************************************)
+
+let translate_named_predicate_ref
+  : (kernel_function -> Env.t -> predicate -> Env.t) ref
+  = Extlib.mk_fun "translate_named_predicate_ref"
+
+let term_to_exp_ref
+  : (kernel_function -> Env.t -> term -> exp * Env.t) ref
+  = Extlib.mk_fun "term_to_exp_ref"
+
+(**************************************************************************)
+(************************* Loop invariants ********************************)
+(**************************************************************************)
+
 module Loop_invariants_actions = Hook.Make(struct end)
 
 let apply_after_transformation prj =
   Project.on prj Loop_invariants_actions.apply ()
 
-let mv_invariants env ~old stmt = 
+let mv_invariants env ~old stmt =
   Options.feedback ~current:true ~level:3
     "keep loop invariants attached to its loop";
   match Env.current_kf env with
   | None -> assert false
   | Some kf ->
-    let filter _ ca = match ca.annot_content with 
+    let filter _ ca = match ca.annot_content with
       | AInvariant(_, b, _) -> b
       | _ -> false
     in
     let l = Annotations.code_annot_emitter ~filter stmt in
     if l != [] then
       Loop_invariants_actions.extend
-	(fun () -> 
+	(fun () ->
 	  List.iter
 	    (fun (ca, e) ->
 	      Annotations.remove_code_annot e ~kf old ca;
@@ -48,21 +65,22 @@ let mv_invariants env ~old stmt =
 	    l)
 
 let preserve_invariant prj env kf stmt = match stmt.skind with
-  | Loop(_, ({ bstmts = stmts } as blk), loc, cont, break) -> 
+  | Loop(_, ({ bstmts = stmts } as blk), loc, cont, break) ->
     let rec handle_invariants (stmts, env, _ as acc) = function
-      | [] -> 
+      | [] ->
 	(* empty loop body: no need to verify the invariant twice *)
 	acc
-      | [ last ] -> 
+      | [ last ] ->
 	let invariants, env = Env.pop_loop env in
 	let env = Env.push env in
-	let env = 
+	let env =
+    let translate_named_predicate = !translate_named_predicate_ref in
 	  Project.on
 	    prj
-	    (List.fold_left (Translate.translate_named_predicate kf) env)
-	    invariants 
+	    (List.fold_left (translate_named_predicate kf) env)
+	    invariants
 	in
-	let blk, env = 
+	let blk, env =
 	  Env.pop_and_get env last ~global_clear:false Env.Before
 	in
 	Misc.mk_block prj last blk :: stmts, env, invariants != []
@@ -71,11 +89,160 @@ let preserve_invariant prj env kf stmt = match stmt.skind with
     let env = Env.set_annotation_kind env Misc.Invariant in
     let stmts, env, has_loop = handle_invariants ([], env, false) stmts in
     let new_blk = { blk with bstmts = List.rev stmts } in
-    { stmt with skind = Loop([], new_blk, loc, cont, break) }, 
-    env, 
+    { stmt with skind = Loop([], new_blk, loc, cont, break) },
+    env,
     has_loop
   | _ -> stmt, env, false
 
+(**************************************************************************)
+(**************************** Nested loops ********************************)
+(**************************************************************************)
+
+let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars =
+  let term_to_exp = !term_to_exp_ref in
+  match lscope_vars with
+  | [] ->
+    mk_innermost_block env
+  | Lscope.Lvs_quantif(t1, rel1, logic_x, rel2, t2) :: lscope_vars' ->
+    let ctx =
+      let ty1 = Typing.get_integer_ty t1 in
+      let ty2 = Typing.get_integer_ty t2 in
+      Typing.join ty1 ty2
+    in
+    let t_plus_one ?ty t =
+      (* whenever provided, [ty] is known to be the type of the result *)
+      let tone = Cil.lone ~loc () in
+      let res = Logic_const.term ~loc (TBinOp(PlusA, t, tone)) Linteger in
+      Extlib.may
+        (fun ty ->
+          Typing.unsafe_set tone ~ctx:ty ctx;
+          Typing.unsafe_set t ~ctx:ty ctx;
+          Typing.unsafe_set res ty)
+        ty;
+      res
+    in
+    let t1 = match rel1 with
+      | Rlt ->
+        let t = t_plus_one t1 in
+        Typing.type_term ~use_gmp_opt:false ~ctx t;
+        t
+      | Rle ->
+        t1
+      | Rgt | Rge | Req | Rneq ->
+        assert false
+      in
+    let t2_one, bop2 = match rel2 with
+      | Rlt ->
+        t2, Lt
+      | Rle ->
+        (* we increment the loop counter one more time (at the end of the
+          loop). Thus to prevent overflow, check the type of [t2+1]
+          instead of [t2]. *)
+        t_plus_one t2, Le
+      | Rgt | Rge | Req | Rneq ->
+        assert false
+    in
+    Typing.type_term ~use_gmp_opt:false ~ctx t2_one;
+    let ctx_one =
+      let ty1 = Typing.get_integer_ty t1 in
+      let ty2 = Typing.get_integer_ty t2_one in
+      Typing.join ty1 ty2
+    in
+    let ty =
+      try Typing.typ_of_integer_ty ctx_one
+      with Typing.Not_an_integer -> assert false
+    in
+    (* loop counter corresponding to the quantified variable *)
+    let var_x, x, env = Env.Logic_binding.add ~ty env logic_x in
+    let lv_x = var var_x in
+    let env = match ctx_one with
+      | Typing.C_type _ -> env
+      | Typing.Gmp -> Env.add_stmt env (Gmpz.init ~loc x)
+      | Typing.Other -> assert false
+    in
+    (* build the inner loops and loop body *)
+    let body, env =
+      mk_nested_loops ~loc mk_innermost_block kf env lscope_vars'
+    in
+    (* initialize the loop counter to [t1] *)
+    let e1, env = term_to_exp kf (Env.push env) t1 in
+    let init_blk, env = Env.pop_and_get
+      env
+      (Gmpz.affect ~loc:e1.eloc lv_x x e1)
+      ~global_clear:false
+      Env.Middle
+    in
+    (* generate the guard [x bop t2] *)
+    let block_to_stmt b = mkStmt ~valid_sid:true (Block b) in
+    let tlv = Logic_const.tvar ~loc logic_x in
+    let guard =
+      (* must copy [t2] to force being typed again *)
+      Logic_const.term ~loc
+        (TBinOp(bop2, tlv, { t2 with term_node = t2.term_node } )) Linteger
+    in
+    Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int guard;
+    let guard_exp, env = term_to_exp kf (Env.push env) guard in
+    let break_stmt = mkStmt ~valid_sid:true (Break guard_exp.eloc) in
+    let guard_blk, env = Env.pop_and_get
+      env
+      (mkStmt
+        ~valid_sid:true
+        (If(
+          guard_exp,
+          mkBlock [ mkEmptyStmt ~loc () ],
+          mkBlock [ break_stmt ],
+          guard_exp.eloc)))
+      ~global_clear:false
+      Env.Middle
+    in
+    let guard = block_to_stmt guard_blk in
+    (* increment the loop counter [x++];
+       previous typing ensures that [x++] fits type [ty] *)
+    (* TODO: should check that it does not overflow in the case of the type
+       of the loop variable is __declared__ too small. *)
+    let tlv_one = t_plus_one ~ty:ctx_one tlv in
+    let incr, env = term_to_exp kf (Env.push env) tlv_one in
+    let next_blk, env = Env.pop_and_get
+      env
+      (Gmpz.affect ~loc:incr.eloc lv_x x incr)
+      ~global_clear:false
+      Env.Middle
+    in
+    (* remove logic binding now that the block is constructed *)
+    let env = Env.Logic_binding.remove env logic_x in
+    (* generate the whole loop *)
+    let start = block_to_stmt init_blk in
+    let next = block_to_stmt next_blk in
+    let stmt = mkStmt
+      ~valid_sid:true
+      (Loop(
+        [],
+        mkBlock (guard :: body @ [ next ]),
+        loc,
+        None,
+        Some break_stmt))
+    in
+    [ start ;  stmt ], env
+  | Lscope.Lvs_let(lv, t) :: lscope_vars' ->
+    let ty = Typing.get_typ t in
+    let vi_of_lv, exp_of_lv, env = Env.Logic_binding.add ~ty env lv in
+    let e, env = term_to_exp kf env t in
+    let let_stmt = Gmpz.init_set ~loc (Cil.var vi_of_lv) exp_of_lv  e in
+    let stmts, env =
+      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
+    (* return *)
+    let_stmt :: stmts, env
+  | Lscope.Lvs_formal _ :: _ ->
+    Error.not_yet
+      "creating nested loops from formal variable of a logic function"
+  | Lscope.Lvs_global _ :: _ ->
+    Error.not_yet
+      "creating nested loops from global logic variable"
+
+
 (*
 Local Variables:
 compile-command: "make"
diff --git a/src/plugins/e-acsl/loops.mli b/src/plugins/e-acsl/loops.mli
index ba56d942004fc4383a949448eba3bf5883f25562..1f2d658a8e25528cc3367cbb4906ba003e331271 100644
--- a/src/plugins/e-acsl/loops.mli
+++ b/src/plugins/e-acsl/loops.mli
@@ -24,19 +24,47 @@
 
 open Cil_types
 
+(**************************************************************************)
+(************************* Loop invariants ********************************)
+(**************************************************************************)
+
 val apply_after_transformation: Project.t -> unit
 
 val mv_invariants: Env.t -> old:stmt -> stmt -> unit
 (** Transfer the loop invariants from the [old] loop to the new one.
     Both statements must be loops. *)
 
-val preserve_invariant: 
+val preserve_invariant:
   Project.t -> Env.t -> Kernel_function.t -> stmt -> stmt * Env.t * bool
 (** modify the given stmt loop to insert the code which preserves its loop
     invarariants. Also return the modify environment and a boolean which
     indicates whether the annotations corresponding to the loop invariant must
     be moved from the new statement to the old one. *)
 
+(**************************************************************************)
+(**************************** Nested loops ********************************)
+(**************************************************************************)
+
+val mk_nested_loops:
+  loc:location -> (Env.t -> stmt list * Env.t) -> kernel_function -> Env.t ->
+  Lscope.lscope_var list -> stmt list * Env.t
+(** [mk_nested_loops ~loc mk_innermost_block kf env lvars] creates nested
+    loops (with the proper statements for initializing the loop counters)
+    from the list of logic variables [lvars]. Quantified variables create
+    loops while let-bindings simply create new variables.
+    The [mk_innermost_block] closure creates the statements of the innermost
+    block. *)
+
+(**************************************************************************)
+(********************** Forward references ********************************)
+(**************************************************************************)
+
+val translate_named_predicate_ref:
+  (kernel_function -> Env.t -> predicate -> Env.t) ref
+
+val term_to_exp_ref:
+  (kernel_function -> Env.t -> term -> exp * Env.t) ref
+
 (*
 Local Variables:
 compile-command: "make"
diff --git a/src/plugins/e-acsl/lscope.ml b/src/plugins/e-acsl/lscope.ml
new file mode 100644
index 0000000000000000000000000000000000000000..e3c50676d35aa7e0f3c9aea1ecbc1ccd8aac5e50
--- /dev/null
+++ b/src/plugins/e-acsl/lscope.ml
@@ -0,0 +1,64 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-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
+
+type lscope_var =
+  | Lvs_let of logic_var * term
+  | Lvs_quantif of term * relation * logic_var * relation * term
+  | Lvs_formal of logic_var * logic_info
+  | Lvs_global of logic_var * term
+
+type t = lscope_var list
+(* The logic scope is usually small, so a list is fine instead of a Map *)
+
+let empty = []
+
+let is_empty = function [] -> true | _ :: _ -> false
+
+let add lscope_var t = lscope_var :: t
+
+let get_all t = List.rev t
+
+let exists lv t =
+  let is_lv = function
+  | Lvs_let(lv', _) | Lvs_quantif(_, _, lv', _, _) | Lvs_formal(lv', _)
+  | Lvs_global(lv', _) ->
+    Cil_datatype.Logic_var.equal lv lv'
+  in
+  List.exists is_lv t
+
+exception Lscope_used
+let is_used lscope pot =
+  let o = object inherit Visitor.frama_c_inplace
+    method !vlogic_var_use lv = match lv.lv_origin with
+    | Some _ -> Cil.SkipChildren
+    | None -> if exists lv lscope then raise Lscope_used else Cil.SkipChildren
+  end
+  in
+  try
+    (match pot with
+    | Misc.PoT_pred p -> ignore (Visitor.visitFramacPredicate o p)
+    | Misc.PoT_term t -> ignore (Visitor.visitFramacTerm o t));
+    false
+  with Lscope_used ->
+    true
\ No newline at end of file
diff --git a/src/plugins/e-acsl/lscope.mli b/src/plugins/e-acsl/lscope.mli
new file mode 100644
index 0000000000000000000000000000000000000000..d3c80d15fe87391bc9ec129f10fad2c0201bd5a6
--- /dev/null
+++ b/src/plugins/e-acsl/lscope.mli
@@ -0,0 +1,53 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of Frama-C.                                         *)
+(*                                                                        *)
+(*  Copyright (C) 2007-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
+
+(* Handle the logic scope of a term.
+  We define the logic scope of a term [t] to be the set of PURELY logic
+  variables that are visible by [t]. *)
+
+type lscope_var =
+  | Lvs_let of logic_var * term (* the expression to which the lv is binded *)
+  | Lvs_quantif of term * relation * logic_var * relation * term
+  | Lvs_formal of logic_var * logic_info (* the logic definition *)
+  | Lvs_global of logic_var * term (* same as Lvs_let *)
+
+type t
+
+val empty: t
+(* Create an empty logic scope. *)
+
+val is_empty: t -> bool
+(* Check whether the given logic scope is empty. *)
+
+val add: lscope_var -> t -> t
+(* Return a new logic scope in which the given [lscope_var] has been added. *)
+
+val get_all: t -> lscope_var list
+(* Return the list of [lscope_var] of the given logic scope.
+  The first element is the first [lscope_var] that was added to [t], the
+  second element is the second [lscope_var] that was added to [t], an so on. *)
+
+val is_used: t -> Misc.pred_or_term -> bool
+(* [is_used lscope pot] returns [true] iff [pot] uses a variable from
+  [lscope]. *)
\ No newline at end of file
diff --git a/src/plugins/e-acsl/misc.ml b/src/plugins/e-acsl/misc.ml
index 1b48696679d33a0787c9f6c037b71bfe04f58fc2..89ff5794ca4f86d4f852934c90980b13b402ce82 100644
--- a/src/plugins/e-acsl/misc.ml
+++ b/src/plugins/e-acsl/misc.ml
@@ -290,6 +290,22 @@ let is_bitfield_pointers lty =
   else
     is_bitfield_pointer lty
 
+exception Lv_from_vi_found
+let term_has_lv_from_vi t =
+  try
+    let o = object inherit Visitor.frama_c_inplace
+      method !vlogic_var_use lv = match lv.lv_origin with
+      | None -> Cil.DoChildren
+      | Some _ -> raise Lv_from_vi_found
+    end
+    in
+    ignore (Visitor.visitFramacTerm o t);
+    false
+  with Lv_from_vi_found ->
+    true
+
+type pred_or_term = PoT_pred of predicate | PoT_term of term
+
 (*
 Local Variables:
 compile-command: "make"
diff --git a/src/plugins/e-acsl/misc.mli b/src/plugins/e-acsl/misc.mli
index 9dbd86e33fb00aada379667e35a442dbe818dc59..006fa6d4383a0f783d87aa82d747c40d63861d08 100644
--- a/src/plugins/e-acsl/misc.mli
+++ b/src/plugins/e-acsl/misc.mli
@@ -114,6 +114,12 @@ val is_bitfield_pointers: logic_type -> bool
 (* 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
+  a C varinfo, that is a non-purely logic variable. *)
+
+type pred_or_term = PoT_pred of predicate | PoT_term of term
+
 (*
 Local Variables:
 compile-command: "make"
diff --git a/src/plugins/e-acsl/quantif.ml b/src/plugins/e-acsl/quantif.ml
index 1af799e81cb0016bd6acfbb8e252ab538c51aa2b..fa8fc69a5ef68fe8f93d9ae7f14cafd5a645804f 100644
--- a/src/plugins/e-acsl/quantif.ml
+++ b/src/plugins/e-acsl/quantif.ml
@@ -25,12 +25,8 @@ open Cil
 open Cil_datatype
 
 let 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"
+  : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref
+  = Extlib.mk_fun "named_predicate_to_exp_ref"
 
 let compute_quantif_guards quantif bounded_vars hyps =
   let error msg pp x =
@@ -92,13 +88,13 @@ let compute_quantif_guards quantif bounded_vars hyps =
   (match vars with
   | [] -> ()
   | _ :: _ ->
-    let msg = 
+    let msg =
       Format.asprintf
-	"@[unguarded variable%s %tin quantification@ %a@]" 
-	(if List.length vars = 1 then "" else "s") 
-	(fun fmt -> 
+	"@[unguarded variable%s %tin quantification@ %a@]"
+	(if List.length vars = 1 then "" else "s")
+	(fun fmt ->
 	  List.iter
-	    (fun v -> Format.fprintf fmt "@[%a @]" Printer.pp_logic_var v) 
+	    (fun v -> Format.fprintf fmt "@[%a @]" Printer.pp_logic_var v)
 	    vars)
 	Printer.pp_predicate quantif
     in
@@ -107,22 +103,30 @@ let compute_quantif_guards quantif bounded_vars hyps =
 
 let () = Typing.compute_quantif_guards_ref := compute_quantif_guards
 
-module Label_ids = 
+module Label_ids =
   State_builder.Counter(struct let name = "E_ACSL.Label_ids" end)
 
 let convert kf env loc is_forall p bounded_vars hyps goal =
-  (* part depending on the kind of quantifications 
+  (* part depending on the kind of quantifications
      (either universal or existential) *)
-  let init_val, found_val, mk_guard = 
+  let init_val, found_val, mk_guard =
     let z = zero ~loc in
     let o = one ~loc in
-    if is_forall then o, z, (fun x -> x) 
+    if is_forall then o, z, (fun x -> x)
     else z, o, (fun e -> new_exp ~loc:e.eloc (UnOp(LNot, e, intType)))
   in
-  let named_predicate_to_exp = !predicate_to_exp_ref in
-  let term_to_exp = !term_to_exp_ref in
   (* universal quantification over integers (or a subtype of integer) *)
   let guards = compute_quantif_guards p bounded_vars hyps in
+  (* transform [guards] into [lscope_var list],
+     and update logic scope in the process *)
+  let lvs_guards, env = List.fold_right
+    (fun (t1, rel1, lv, rel2, t2) (lvs_guards, env) ->
+      let lvs = Lscope.Lvs_quantif(t1, rel1, lv, rel2, t2) in
+      let env = Env.Logic_scope.extend env lvs in
+      lvs :: lvs_guards, env)
+    guards
+    ([], env)
+  in
   let var_res, res, env =
     (* variable storing the result of the quantifier *)
     let name = if is_forall then "forall" else "exists" in
@@ -133,149 +137,39 @@ let convert kf env loc is_forall p bounded_vars hyps goal =
       None
       intType
       (fun v _ ->
-	let lv = var v in
-	[ mkStmtOneInstr ~valid_sid:true (Set(lv, init_val, loc)) ])
+        let lv = var v in
+        [ mkStmtOneInstr ~valid_sid:true (Set(lv, init_val, loc)) ])
   in
   let end_loop_ref = ref dummyStmt in
-  let rec mk_for_loop env = function
-    | [] -> 
-      (* innermost loop body: store the result in [res] and go out according
-	 to evaluation of the goal *)
-      let test, env = named_predicate_to_exp kf (Env.push env) goal in
-      let then_block = mkBlock [ mkEmptyStmt ~loc () ] in
-      let else_block = 
-	(* use a 'goto', not a simple 'break' in order to handle 'forall' with
-	   multiple binders (leading to imbricated loops) *)
-	mkBlock
-	  [ mkStmtOneInstr
-	       ~valid_sid:true (Set(var var_res, found_val, loc));
-	    mkStmt ~valid_sid:true (Goto(end_loop_ref, loc)) ]
-      in
-      let blk, env = 
-	Env.pop_and_get
-	  env
-	  (mkStmt ~valid_sid:true
-	     (If(mk_guard test, then_block, else_block, loc)))
-	  ~global_clear:false
-	  Env.After
-      in
-      let blk = Cil.flatten_transient_sub_blocks blk in
-      [ mkStmt ~valid_sid:true (Block blk) ], env
-    | (t1, rel1, logic_x, rel2, t2) :: tl ->
-      let ctx =
-        let ty1 = Typing.get_integer_ty t1 in
-        let ty2 = Typing.get_integer_ty t2 in
-        Typing.join ty1 ty2
-      in
-      let t_plus_one ?ty t =
-        (* whenever provided, [ty] is known to be the type of the result *)
-        let tone = Logic_const.tinteger ~loc 1 in
-        let res = Logic_const.term ~loc (TBinOp(PlusA, t, tone)) Linteger in
-        Extlib.may
-          (fun ty ->
-            Typing.unsafe_set tone ~ctx:ty ctx;
-            Typing.unsafe_set t ~ctx:ty ctx;
-            Typing.unsafe_set res ty)
-          ty;
-        res
-      in
-      let t1 = match rel1 with
-        | Rlt ->
-          let t = t_plus_one t1 in
-          Typing.type_term ~use_gmp_opt:false ~ctx t;
-          t
-        | Rle -> t1
-        | Rgt | Rge | Req | Rneq -> assert false
-      in
-      let t2_one, bop2 = match rel2 with
-        | Rlt -> t2, Lt
-        | Rle ->
-          (* we increment the loop counter one more time (at the end of the
-             loop). Thus to prevent overflow, check the type of [t2+1]
-             instead of [t2]. *)
-          t_plus_one t2, Le
-        | Rgt | Rge | Req | Rneq -> assert false
-      in
-      Typing.type_term ~use_gmp_opt:false ~ctx t2_one;
-      let ctx_one =
-        let ty1 = Typing.get_integer_ty t1 in
-        let ty2 = Typing.get_integer_ty t2_one in
-        Typing.join ty1 ty2
-      in
-      let ty =
-        try Typing.typ_of_integer_ty ctx_one
-        with Typing.Not_an_integer -> assert false
-      in
-      (* loop counter corresponding to the quantified variable *)
-      let var_x, x, env = Env.Logic_binding.add ~ty env logic_x in
-      let lv_x = var var_x in
-      let env = match ctx_one with
-        | Typing.C_type _ -> env
-        | Typing.Gmp -> Env.add_stmt env (Gmpz.init ~loc x)
-        | Typing.Other -> assert false
-      in
-      (* build the inner loops and loop body *)
-      let body, env = mk_for_loop env tl in
-      (* initialize the loop counter to [t1] *)
-      let e1, env = term_to_exp kf (Env.push env) t1 in
-      let init_blk, env =
-        Env.pop_and_get
-          env
-          (Gmpz.affect ~loc:e1.eloc lv_x x e1)
-          ~global_clear:false
-          Env.Middle
-      in
-      (* generate the guard [x bop t2] *)
-      let stmts_block b = [ mkStmt ~valid_sid:true (Block b) ] in
-      let tlv = Logic_const.tvar ~loc logic_x in
-      let guard =
-        (* must copy [t2] to force being typed again *)
-        Logic_const.term ~loc
-          (TBinOp(bop2, tlv, { t2 with term_node = t2.term_node } )) Linteger
-      in
-      Typing.type_term ~use_gmp_opt:false ~ctx:Typing.c_int guard;
-      let guard_exp, env = term_to_exp kf (Env.push env) guard in
-      let break_stmt = mkStmt ~valid_sid:true (Break guard_exp.eloc) in
-      let guard_blk, env =
-	Env.pop_and_get
-	  env
-	  (mkStmt ~valid_sid:true
-	     (If(guard_exp,
-		 mkBlock [ mkEmptyStmt ~loc () ],
-		 mkBlock [ break_stmt ], 
-		 guard_exp.eloc)))
-	  ~global_clear:false
-	  Env.Middle
-      in
-      let guard = stmts_block guard_blk in
-      (* increment the loop counter [x++];
-         previous typing ensures that [x++] fits type [ty] *)
-      (* TODO: should check that it does not overflow in the case of the type
-         of the loop variable is __declared__ too small. *)
-      let tlv_one = t_plus_one ~ty:ctx_one tlv in
-      let incr, env = term_to_exp kf (Env.push env) tlv_one in
-      let next_blk, env = 
-	Env.pop_and_get
-	  env
-	  (Gmpz.affect ~loc:incr.eloc lv_x x incr)
-	  ~global_clear:false
-	  Env.Middle
-      in
-      (* generate the whole loop *)
-      let start = stmts_block init_blk in
-      let next = stmts_block next_blk in
-      start @
-	[ mkStmt ~valid_sid:true
-	    (Loop ([],
-		   mkBlock (guard @ body @ next),
-		   loc, 
-		   None, 
-		   Some break_stmt)) ], 
+  (* innermost block *)
+  let mk_innermost_block env =
+    (* innermost loop body: store the result in [res] and go out according
+       to evaluation of the goal *)
+    let named_predicate_to_exp = !predicate_to_exp_ref in
+    let test, env = named_predicate_to_exp kf (Env.push env) goal in
+    let then_block = mkBlock [ mkEmptyStmt ~loc () ] in
+    let else_block =
+    (* use a 'goto', not a simple 'break' in order to handle 'forall' with
+       multiple binders (leading to imbricated loops) *)
+    mkBlock
+      [ mkStmtOneInstr ~valid_sid:true (Set(var var_res, found_val, loc));
+        mkStmt ~valid_sid:true (Goto(end_loop_ref, loc)) ]
+    in
+    let blk, env = Env.pop_and_get
       env
+      (mkStmt ~valid_sid:true
+        (If(mk_guard test, then_block, else_block, loc)))
+      ~global_clear:false
+      Env.After
+    in
+    let blk = Cil.flatten_transient_sub_blocks blk in
+    [ mkStmt ~valid_sid:true (Block blk) ], env
+  in
+  let stmts, env =
+    Loops.mk_nested_loops ~loc mk_innermost_block kf env lvs_guards
   in
-  let stmts, env = mk_for_loop env guards in
-  let env = 
-    Env.add_stmt env (mkStmt ~valid_sid:true (Block (mkBlock stmts))) 
+  let env =
+    Env.add_stmt env (mkStmt ~valid_sid:true (Block (mkBlock stmts)))
   in
   (* where to jump to go out of the loop *)
   let end_loop = mkEmptyStmt ~loc () in
@@ -284,16 +178,15 @@ let convert kf env loc is_forall p bounded_vars hyps goal =
   end_loop.labels <- label :: end_loop.labels;
   end_loop_ref := end_loop;
   let env = Env.add_stmt env end_loop in
-  let env = List.fold_left Env.Logic_binding.remove env bounded_vars in
   res, env
 
-let quantif_to_exp kf env p = 
+let quantif_to_exp kf env p =
   let loc = p.pred_loc in
   match p.pred_content with
-  | Pforall(bounded_vars, { pred_content = Pimplies(hyps, goal) }) -> 
+  | Pforall(bounded_vars, { pred_content = Pimplies(hyps, goal) }) ->
     convert kf env loc true p bounded_vars hyps goal
   | Pforall _ -> Error.not_yet "unguarded \\forall quantification"
-  | Pexists(bounded_vars, { pred_content = Pand(hyps, goal) }) -> 
+  | Pexists(bounded_vars, { pred_content = Pand(hyps, goal) }) ->
     convert kf env loc false p bounded_vars hyps goal
   | Pexists _ -> Error.not_yet "unguarded \\exists quantification"
   | _ -> assert false
diff --git a/src/plugins/e-acsl/quantif.mli b/src/plugins/e-acsl/quantif.mli
index 5e67e747265d04f8e59d363a103d6bab672d3a26..d8e8b9819c91d418be5d6f9b207e7f7dd8f2f58e 100644
--- a/src/plugins/e-acsl/quantif.mli
+++ b/src/plugins/e-acsl/quantif.mli
@@ -24,19 +24,17 @@
 
 open Cil_types
 
-val quantif_to_exp: kernel_function -> Env.t -> predicate -> exp * Env.t
+val quantif_to_exp:
+  kernel_function -> Env.t -> predicate -> exp * Env.t
 (** The given predicate must be a quantification. *)
 
 (* ***********************************************************************)
 (** {2 Forward references} *)
 (* ***********************************************************************)
 
-val predicate_to_exp_ref: 
+val 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
-
 (*
 Local Variables:
 compile-command: "make"
diff --git a/src/plugins/e-acsl/tests/gmp/at_on-purely-logic-variables.c b/src/plugins/e-acsl/tests/gmp/at_on-purely-logic-variables.c
new file mode 100644
index 0000000000000000000000000000000000000000..a289de1d5a1c02e97bd12f1f5205a24c93639039
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/at_on-purely-logic-variables.c
@@ -0,0 +1,69 @@
+/* run.config
+  COMMENT: \at on purely logic variables
+  COMMENT:
+*/
+
+/*@ ensures \forall integer n; 1 < n <= 3 ==>
+      \old(t[n] == 12) && \old(t[n - 1] > 5);
+    ensures \let m = 4; \old(t[m] == -4) && \old(t[m - 4]) == 9; */
+void f(int *t) {}
+
+void g() {
+  int m;
+  m = 8;
+  Q: ;
+  m = 10;
+  /*@ assert \exists integer w; 3 <= w < 6 && \at(m + w == 12, Q); */ ;
+}
+
+int main(void) {
+  int n;
+  n = 7;
+  L: ;
+  n = 9;
+  K: ;
+  n = 666;
+
+  // Predicates:
+  /*@ assert \let i = 3; \at(n + i == 10, L); */ ;
+  /*@ assert \exists integer j; 2 <= j < 5 && \at(n + j == 11, L); */ ;
+  /*@ assert
+      \let k = -7;
+      \exists integer u; 9 <= u < 21 &&
+      \forall integer v; -5 < v <= 6 ==>
+        \at((u > 0 ? n + k : u + v) > 0, K); */ ;
+
+  // Terms:
+  /*@ assert \let i = 3; \at(n + i, L) == 10; */ ;
+  unsigned int m = 3;
+  G: ;
+  m = -3;
+  /*@ assert \exists integer k; -9 < k < 0 && \at(m + k, G) == 0; */ ;
+  /*@ assert
+      \exists integer u; 9 <= u < 21 &&
+      \forall integer v; -5 < v <= (u < 15 ? u + 6 : 3) ==>
+        \at(n + u + v > 0, K); */ ;
+
+  // Function calls:
+  int t[5] = {9, 12, 12, 12, -4};
+  f(t);
+  g();
+
+  // Name capturing
+  /*@ assert
+         \exists integer u; 10 <= u < 20
+      && \exists integer v; -10 < v <= -5  + (\let u = -2; u) // another u
+      && \exists integer w; 100 < w <= 200
+      && \at(n - u +
+          (\let u = 42; u) // yet another u
+          + v + w > 0, K); */ ;
+
+  // Not yet:
+  /*@ assert
+        \exists integer j; 2 <= j < 10000000000000000 // too big => not_yet
+        && \at(n + j == 11, L); */ ;
+  /*@ assert \let i = n; // lv defined with C var => not_yet
+        \at(n + i == 10, L); */ ;
+
+  return 0;
+}
\ No newline at end of file
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/at_on-purely-logic-variables.0.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/at_on-purely-logic-variables.0.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..5170b1fe4ba40ee38526fcf4da7a7232988f4b14
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/at_on-purely-logic-variables.0.res.oracle
@@ -0,0 +1,163 @@
+[e-acsl] beginning translation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:64: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:65: Warning: 
+  E-ACSL construct `\at with logic variable linked to C variable'
+  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] tests/gmp/at_on-purely-logic-variables.c:57: 
+  allocating variable __malloc_main_l57
+[eva] tests/gmp/at_on-purely-logic-variables.c:45: 
+  allocating variable __malloc_main_l45
+[eva] tests/gmp/at_on-purely-logic-variables.c:41: 
+  allocating variable __malloc_main_l41
+[eva] tests/gmp/at_on-purely-logic-variables.c:37: 
+  allocating variable __malloc_main_l37
+[eva] tests/gmp/at_on-purely-logic-variables.c:34: 
+  allocating variable __malloc_main_l34
+[eva] tests/gmp/at_on-purely-logic-variables.c:29: 
+  allocating variable __malloc_main_l29
+[eva] tests/gmp/at_on-purely-logic-variables.c:28: 
+  allocating variable __malloc_main_l28
+[eva] using specification for function __e_acsl_store_block
+[eva] using specification for function __e_acsl_full_init
+[eva] tests/gmp/at_on-purely-logic-variables.c:29: 
+  starting to merge loop iterations
+[eva] tests/gmp/at_on-purely-logic-variables.c:57: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:57: Warning: 
+  out of bounds write.
+  assert
+  \valid(__gen_e_acsl_at_7 +
+         (int)((int)((int)(__gen_e_acsl_u_6 - 10) * 300) +
+               (int)((int)((int)((int)(__gen_e_acsl_v_6 - -10) - 1) * 100) +
+                     (int)((int)(__gen_e_acsl_w_2 - 100) - 1))));
+[eva] tests/gmp/at_on-purely-logic-variables.c:45: 
+  starting to merge loop iterations
+[eva] tests/gmp/at_on-purely-logic-variables.c:34: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:28: Warning: 
+  assertion got status unknown.
+[eva] using specification for function __e_acsl_valid_read
+[eva] using specification for function __e_acsl_assert
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:29: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:29: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized(__gen_e_acsl_at_2 + (__gen_e_acsl_j - 2));
+[eva] tests/gmp/at_on-purely-logic-variables.c:29: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:29: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:29: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:31: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:33: Warning: 
+  accessing uninitialized left-value.
+  assert
+  \initialized(__gen_e_acsl_at_3 +
+               ((__gen_e_acsl_u - 9) * 11 + ((__gen_e_acsl_v - -5) - 1)));
+[eva] tests/gmp/at_on-purely-logic-variables.c:33: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:34: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:37: Warning: 
+  assertion got status unknown.
+[eva] tests/gmp/at_on-purely-logic-variables.c:41: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:41: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:41: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_3 - -9) - 1));
+[eva] tests/gmp/at_on-purely-logic-variables.c:41: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:41: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:41: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:43: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:44: Warning: 
+  accessing uninitialized left-value.
+  assert
+  \initialized(__gen_e_acsl_at_6 +
+               ((__gen_e_acsl_u_3 - 9) * 32 + ((__gen_e_acsl_v_3 - -5) - 1)));
+[eva] tests/gmp/at_on-purely-logic-variables.c:44: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:45: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva] tests/gmp/at_on-purely-logic-variables.c:8: 
+  allocating variable __malloc___gen_e_acsl_f_l8
+[eva] tests/gmp/at_on-purely-logic-variables.c:8: 
+  allocating variable __malloc___gen_e_acsl_f_l8_0
+[eva] tests/gmp/at_on-purely-logic-variables.c:7: 
+  allocating variable __malloc___gen_e_acsl_f_l7
+[eva] tests/gmp/at_on-purely-logic-variables.c:7: 
+  allocating variable __malloc___gen_e_acsl_f_l7_0
+[eva] tests/gmp/at_on-purely-logic-variables.c:7: 
+  starting to merge loop iterations
+[eva] tests/gmp/at_on-purely-logic-variables.c:7: 
+  starting to merge loop iterations
+[eva] using specification for function __e_acsl_delete_block
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:7: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized(__gen_e_acsl_at + ((__gen_e_acsl_n - 1) - 1));
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:7: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized(__gen_e_acsl_at_2 + ((__gen_e_acsl_n - 1) - 1));
+[eva] tests/gmp/at_on-purely-logic-variables.c:6: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:7: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:7: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:6: Warning: 
+  function __gen_e_acsl_f: postcondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:8: Warning: 
+  function __gen_e_acsl_f: postcondition got status unknown.
+[eva] tests/gmp/at_on-purely-logic-variables.c:16: 
+  allocating variable __malloc_g_l16
+[eva] tests/gmp/at_on-purely-logic-variables.c:16: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:16: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:16: Warning: 
+  accessing uninitialized left-value.
+  assert \initialized(__gen_e_acsl_at + (__gen_e_acsl_w - 3));
+[eva] tests/gmp/at_on-purely-logic-variables.c:16: 
+  starting to merge loop iterations
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:16: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:16: Warning: 
+  function __e_acsl_assert: precondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:54: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:56: Warning: 
+  accessing uninitialized left-value.
+  assert
+  \initialized(__gen_e_acsl_at_7 +
+               ((__gen_e_acsl_u_5 - 10) * 300 +
+                (((__gen_e_acsl_v_5 - -10) - 1) * 100 +
+                 ((__gen_e_acsl_w - 100) - 1))));
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:63: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:65: Warning: 
+  assertion got status unknown.
+[eva] using specification for function __e_acsl_memory_clean
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/at_on-purely-logic-variables.1.res.oracle b/src/plugins/e-acsl/tests/gmp/oracle/at_on-purely-logic-variables.1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..1e6a8533f45e6676b9d6c5b3062032e0c04185bd
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/at_on-purely-logic-variables.1.res.oracle
@@ -0,0 +1,98 @@
+[e-acsl] beginning translation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:16: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:28: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:29: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:34: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:37: Warning: 
+  E-ACSL construct `\at on purely logic variables and over gmp type'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:41: Warning: 
+  E-ACSL construct `\at on purely logic variables and over gmp type'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:45: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables and with quantifier that uses too complex bound (E-ACSL cannot infer a finite upper bound to it)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:57: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:64: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:65: Warning: 
+  E-ACSL construct `\at with logic variable linked to C variable'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:7: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  is not yet supported.
+  Ignoring annotation.
+[e-acsl] tests/gmp/at_on-purely-logic-variables.c:8: Warning: 
+  E-ACSL construct
+  `\at on purely logic variables that needs to allocate too much memory (bigger than int_max bytes)'
+  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_full_init
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:28: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:29: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:31: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:37: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:41: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:43: Warning: 
+  assertion got status unknown.
+[eva] using specification for function __e_acsl_delete_block
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:6: Warning: 
+  function __gen_e_acsl_f: postcondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:8: Warning: 
+  function __gen_e_acsl_f: postcondition got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:16: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:54: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:63: Warning: 
+  assertion got status unknown.
+[eva:alarm] tests/gmp/at_on-purely-logic-variables.c:65: Warning: 
+  assertion got status unknown.
+[eva] using specification for function __e_acsl_memory_clean
+[eva] done for function main
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_at_on-purely-logic-variables.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_at_on-purely-logic-variables.c
new file mode 100644
index 0000000000000000000000000000000000000000..c6f65b06f7c80ea452bdd467b56a65ec502f71f2
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_at_on-purely-logic-variables.c
@@ -0,0 +1,726 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+/*@ ensures
+      ∀ ℤ n;
+        1 < n ≤ 3 ⇒ \old(*(t + n) ≡ 12) ∧ \old(*(t + (n - 1)) > 5);
+    ensures \let m = 4; \old(*(t + m) ≡ -4) ∧ \old(*(t + (m - 4))) ≡ 9;
+ */
+void __gen_e_acsl_f(int *t);
+
+void f(int *t)
+{
+  __e_acsl_store_block((void *)(& t),(size_t)8);
+  __e_acsl_delete_block((void *)(& t));
+  return;
+}
+
+void g(void)
+{
+  int *__gen_e_acsl_at;
+  int m;
+  __gen_e_acsl_at = (int *)malloc((size_t)12);
+  m = 8;
+  Q:
+  {
+    {
+      int __gen_e_acsl_w_2;
+      __gen_e_acsl_w_2 = 3;
+      while (1) {
+        if (__gen_e_acsl_w_2 < 6) ; else break;
+        *(__gen_e_acsl_at + (__gen_e_acsl_w_2 - 3)) = m + (long)__gen_e_acsl_w_2 == 12L;
+        __gen_e_acsl_w_2 ++;
+      }
+    }
+    ;
+  }
+  m = 10;
+  /*@ assert ∃ ℤ w; 3 ≤ w < 6 ∧ \at(m + w ≡ 12,Q); */
+  {
+    int __gen_e_acsl_exists;
+    int __gen_e_acsl_w;
+    __gen_e_acsl_exists = 0;
+    __gen_e_acsl_w = 3;
+    while (1) {
+      if (__gen_e_acsl_w < 6) ; else break;
+      {
+        int __gen_e_acsl_valid_read;
+        __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(__gen_e_acsl_at + (int)(
+                                                               __gen_e_acsl_w - 3L)),
+                                                      sizeof(int),
+                                                      (void *)__gen_e_acsl_at,
+                                                      (void *)(& __gen_e_acsl_at));
+        __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"g",
+                        (char *)"mem_access: \\valid_read(__gen_e_acsl_at + (int)(__gen_e_acsl_w - 3))",
+                        16);
+        /*@ assert
+            Value: initialization:
+              \initialized(__gen_e_acsl_at + (__gen_e_acsl_w - 3));
+        */
+        if (! *(__gen_e_acsl_at + (__gen_e_acsl_w - 3))) ;
+        else {
+          __gen_e_acsl_exists = 1;
+          goto e_acsl_end_loop1;
+        }
+      }
+      __gen_e_acsl_w ++;
+    }
+    e_acsl_end_loop1: ;
+    __e_acsl_assert(__gen_e_acsl_exists,(char *)"Assertion",(char *)"g",
+                    (char *)"\\exists integer w; 3 <= w < 6 && \\at(m + w == 12,Q)",
+                    16);
+  }
+  free((void *)__gen_e_acsl_at);
+  return;
+}
+
+int main(void)
+{
+  int *__gen_e_acsl_at_7;
+  int *__gen_e_acsl_at_6;
+  long *__gen_e_acsl_at_5;
+  long *__gen_e_acsl_at_4;
+  int *__gen_e_acsl_at_3;
+  int *__gen_e_acsl_at_2;
+  int *__gen_e_acsl_at;
+  int __retres;
+  int n;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __gen_e_acsl_at_7 = (int *)malloc((size_t)12000);
+  __gen_e_acsl_at_6 = (int *)malloc((size_t)1536);
+  __gen_e_acsl_at_5 = (long *)malloc((size_t)64);
+  __gen_e_acsl_at_4 = (long *)malloc((size_t)8);
+  __gen_e_acsl_at_3 = (int *)malloc((size_t)528);
+  __gen_e_acsl_at_2 = (int *)malloc((size_t)12);
+  __gen_e_acsl_at = (int *)malloc((size_t)4);
+  __e_acsl_store_block((void *)(& n),(size_t)4);
+  __e_acsl_full_init((void *)(& n));
+  n = 7;
+  L:
+  {
+    {
+      int __gen_e_acsl_i_4;
+      __gen_e_acsl_i_4 = 3;
+      *(__gen_e_acsl_at_4 + 0) = n + (long)__gen_e_acsl_i_4;
+    }
+    {
+      int __gen_e_acsl_j_2;
+      __gen_e_acsl_j_2 = 2;
+      while (1) {
+        if (__gen_e_acsl_j_2 < 5) ; else break;
+        *(__gen_e_acsl_at_2 + (__gen_e_acsl_j_2 - 2)) = n + (long)__gen_e_acsl_j_2 == 11L;
+        __gen_e_acsl_j_2 ++;
+      }
+    }
+    {
+      int __gen_e_acsl_i_2;
+      __gen_e_acsl_i_2 = 3;
+      *(__gen_e_acsl_at + 0) = n + (long)__gen_e_acsl_i_2 == 10L;
+    }
+    ;
+  }
+  __e_acsl_full_init((void *)(& n));
+  n = 9;
+  K:
+  {
+    {
+      int __gen_e_acsl_u_6;
+      int __gen_e_acsl_v_6;
+      int __gen_e_acsl_w_2;
+      __gen_e_acsl_u_6 = 10;
+      while (1) {
+        if (__gen_e_acsl_u_6 < 20) ; else break;
+        __gen_e_acsl_v_6 = -10 + 1;
+        while (1) {
+          {
+            int __gen_e_acsl_u_8;
+            __gen_e_acsl_u_8 = -2;
+            if (__gen_e_acsl_v_6 <= -5 + __gen_e_acsl_u_8) ; else break;
+          }
+          __gen_e_acsl_w_2 = 100 + 1;
+          while (1) {
+            if (__gen_e_acsl_w_2 <= 200) ; else break;
+            {
+              int __gen_e_acsl_u_7;
+              __gen_e_acsl_u_7 = 42;
+              /*@ assert
+                  Value: mem_access:
+                    \valid(__gen_e_acsl_at_7 +
+                           (int)((int)((int)(__gen_e_acsl_u_6 - 10) * 300) +
+                                 (int)((int)((int)((int)(__gen_e_acsl_v_6 -
+                                                         -10)
+                                                   - 1)
+                                             * 100)
+                                       +
+                                       (int)((int)(__gen_e_acsl_w_2 - 100) -
+                                             1))));
+              */
+              *(__gen_e_acsl_at_7 + ((__gen_e_acsl_u_6 - 10) * 300 + (
+                                     ((__gen_e_acsl_v_6 - -10) - 1) * 100 + (
+                                     (__gen_e_acsl_w_2 - 100) - 1)))) = 
+              (((n - (long)__gen_e_acsl_u_6) + __gen_e_acsl_u_7) + __gen_e_acsl_v_6) + __gen_e_acsl_w_2 > 0L;
+            }
+            __gen_e_acsl_w_2 ++;
+          }
+          __gen_e_acsl_v_6 ++;
+        }
+        __gen_e_acsl_u_6 ++;
+      }
+    }
+    {
+      int __gen_e_acsl_u_4;
+      int __gen_e_acsl_v_4;
+      __gen_e_acsl_u_4 = 9;
+      while (1) {
+        if (__gen_e_acsl_u_4 < 21) ; else break;
+        __gen_e_acsl_v_4 = -5 + 1;
+        while (1) {
+          {
+            int __gen_e_acsl_if_2;
+            if (__gen_e_acsl_u_4 < 15) __gen_e_acsl_if_2 = __gen_e_acsl_u_4 + 6;
+            else __gen_e_acsl_if_2 = 3;
+            if (__gen_e_acsl_v_4 <= __gen_e_acsl_if_2) ; else break;
+          }
+          *(__gen_e_acsl_at_6 + ((__gen_e_acsl_u_4 - 9) * 32 + ((__gen_e_acsl_v_4 - -5) - 1))) = 
+          (n + (long)__gen_e_acsl_u_4) + __gen_e_acsl_v_4 > 0L;
+          __gen_e_acsl_v_4 ++;
+        }
+        __gen_e_acsl_u_4 ++;
+      }
+    }
+    {
+      int __gen_e_acsl_k_2;
+      int __gen_e_acsl_u_2;
+      int __gen_e_acsl_v_2;
+      __gen_e_acsl_k_2 = -7;
+      __gen_e_acsl_u_2 = 9;
+      while (1) {
+        if (__gen_e_acsl_u_2 < 21) ; else break;
+        __gen_e_acsl_v_2 = -5 + 1;
+        while (1) {
+          if (__gen_e_acsl_v_2 <= 6) ; else break;
+          {
+            long __gen_e_acsl_if;
+            if (__gen_e_acsl_u_2 > 0) __gen_e_acsl_if = n + (long)__gen_e_acsl_k_2;
+            else __gen_e_acsl_if = __gen_e_acsl_u_2 + __gen_e_acsl_v_2;
+            *(__gen_e_acsl_at_3 + ((__gen_e_acsl_u_2 - 9) * 11 + ((__gen_e_acsl_v_2 - -5) - 1))) = 
+            __gen_e_acsl_if > 0L;
+          }
+          __gen_e_acsl_v_2 ++;
+        }
+        __gen_e_acsl_u_2 ++;
+      }
+    }
+    ;
+  }
+  __e_acsl_full_init((void *)(& n));
+  n = 666;
+  /*@ assert \let i = 3; \at(n + i ≡ 10,L); */
+  {
+    int __gen_e_acsl_i;
+    int __gen_e_acsl_valid_read;
+    __gen_e_acsl_i = 3;
+    __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(__gen_e_acsl_at + 0),
+                                                  sizeof(int),
+                                                  (void *)__gen_e_acsl_at,
+                                                  (void *)(& __gen_e_acsl_at));
+    __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"main",
+                    (char *)"mem_access: \\valid_read(__gen_e_acsl_at + 0)",
+                    28);
+    __e_acsl_assert(*(__gen_e_acsl_at + 0),(char *)"Assertion",
+                    (char *)"main",
+                    (char *)"\\let i = 3; \\at(n + i == 10,L)",28);
+  }
+  /*@ assert ∃ ℤ j; 2 ≤ j < 5 ∧ \at(n + j ≡ 11,L); */
+  {
+    int __gen_e_acsl_exists;
+    int __gen_e_acsl_j;
+    __gen_e_acsl_exists = 0;
+    __gen_e_acsl_j = 2;
+    while (1) {
+      if (__gen_e_acsl_j < 5) ; else break;
+      {
+        int __gen_e_acsl_valid_read_2;
+        __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_2 + (int)(
+                                                                 __gen_e_acsl_j - 2L)),
+                                                        sizeof(int),
+                                                        (void *)__gen_e_acsl_at_2,
+                                                        (void *)(& __gen_e_acsl_at_2));
+        __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",
+                        (char *)"main",
+                        (char *)"mem_access: \\valid_read(__gen_e_acsl_at_2 + (int)(__gen_e_acsl_j - 2))",
+                        29);
+        /*@ assert
+            Value: initialization:
+              \initialized(__gen_e_acsl_at_2 + (__gen_e_acsl_j - 2));
+        */
+        if (! *(__gen_e_acsl_at_2 + (__gen_e_acsl_j - 2))) ;
+        else {
+          __gen_e_acsl_exists = 1;
+          goto e_acsl_end_loop2;
+        }
+      }
+      __gen_e_acsl_j ++;
+    }
+    e_acsl_end_loop2: ;
+    __e_acsl_assert(__gen_e_acsl_exists,(char *)"Assertion",(char *)"main",
+                    (char *)"\\exists integer j; 2 <= j < 5 && \\at(n + j == 11,L)",
+                    29);
+  }
+  /*@ assert \let k = -7;
+      ∃ ℤ u;
+        9 ≤ u < 21 ∧
+        (∀ ℤ v; -5 < v ≤ 6 ⇒ \at((u > 0? n + k: u + v) > 0,K));
+  */
+  {
+    int __gen_e_acsl_k;
+    int __gen_e_acsl_exists_2;
+    int __gen_e_acsl_u;
+    __gen_e_acsl_k = -7;
+    __gen_e_acsl_exists_2 = 0;
+    __gen_e_acsl_u = 9;
+    while (1) {
+      if (__gen_e_acsl_u < 21) ; else break;
+      {
+        int __gen_e_acsl_forall;
+        int __gen_e_acsl_v;
+        __gen_e_acsl_forall = 1;
+        __gen_e_acsl_v = -5 + 1;
+        while (1) {
+          if (__gen_e_acsl_v <= 6) ; else break;
+          {
+            int __gen_e_acsl_valid_read_3;
+            __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)(
+                                                            __gen_e_acsl_at_3 + (int)(
+                                                            (long)((int)(
+                                                            (long)((int)(
+                                                            __gen_e_acsl_u - 9L)) * 11L)) + (int)(
+                                                            (int)(__gen_e_acsl_v - -5L) - 1))),
+                                                            sizeof(int),
+                                                            (void *)__gen_e_acsl_at_3,
+                                                            (void *)(& __gen_e_acsl_at_3));
+            __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",
+                            (char *)"main",
+                            (char *)"mem_access:\n  \\valid_read(__gen_e_acsl_at_3 +\n              (int)((int)((int)(__gen_e_acsl_u - 9) * 11) +\n                    (int)((int)(__gen_e_acsl_v - -5) - 1)))",
+                            34);
+            /*@ assert
+                Value: initialization:
+                  \initialized(__gen_e_acsl_at_3 +
+                               ((__gen_e_acsl_u - 9) * 11 +
+                                ((__gen_e_acsl_v - -5) - 1)));
+            */
+            if (*(__gen_e_acsl_at_3 + ((__gen_e_acsl_u - 9) * 11 + ((
+                                                                    __gen_e_acsl_v - -5) - 1)))) 
+              ;
+            else {
+              __gen_e_acsl_forall = 0;
+              goto e_acsl_end_loop3;
+            }
+          }
+          __gen_e_acsl_v ++;
+        }
+        e_acsl_end_loop3: ;
+        if (! __gen_e_acsl_forall) ;
+        else {
+          __gen_e_acsl_exists_2 = 1;
+          goto e_acsl_end_loop4;
+        }
+      }
+      __gen_e_acsl_u ++;
+    }
+    e_acsl_end_loop4: ;
+    __e_acsl_assert(__gen_e_acsl_exists_2,(char *)"Assertion",(char *)"main",
+                    (char *)"\\let k = -7;\n\\exists integer u;\n  9 <= u < 21 &&\n  (\\forall integer v; -5 < v <= 6 ==> \\at((u > 0? n + k: u + v) > 0,K))",
+                    31);
+  }
+  /*@ assert \let i = 3; \at(n + i,L) ≡ 10; */
+  {
+    int __gen_e_acsl_i_3;
+    int __gen_e_acsl_valid_read_4;
+    __gen_e_acsl_i_3 = 3;
+    __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_4 + 0),
+                                                    sizeof(long),
+                                                    (void *)__gen_e_acsl_at_4,
+                                                    (void *)(& __gen_e_acsl_at_4));
+    __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"main",
+                    (char *)"mem_access: \\valid_read(__gen_e_acsl_at_4 + 0)",
+                    37);
+    __e_acsl_assert(*(__gen_e_acsl_at_4 + 0) == 10L,(char *)"Assertion",
+                    (char *)"main",
+                    (char *)"\\let i = 3; \\at(n + i,L) == 10",37);
+  }
+  unsigned int m = (unsigned int)3;
+  G:
+  {
+    {
+      int __gen_e_acsl_k_4;
+      __gen_e_acsl_k_4 = -9 + 1;
+      while (1) {
+        if (__gen_e_acsl_k_4 < 0) ; else break;
+        *(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_4 - -9) - 1)) = m + (long)__gen_e_acsl_k_4;
+        __gen_e_acsl_k_4 ++;
+      }
+    }
+    ;
+  }
+  m = (unsigned int)(-3);
+  /*@ assert ∃ ℤ k; -9 < k < 0 ∧ \at(m + k,G) ≡ 0; */
+  {
+    int __gen_e_acsl_exists_3;
+    int __gen_e_acsl_k_3;
+    __gen_e_acsl_exists_3 = 0;
+    __gen_e_acsl_k_3 = -9 + 1;
+    while (1) {
+      if (__gen_e_acsl_k_3 < 0) ; else break;
+      {
+        int __gen_e_acsl_valid_read_5;
+        __gen_e_acsl_valid_read_5 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_5 + (
+                                                                 (int)(
+                                                                 __gen_e_acsl_k_3 - -9L) - 1)),
+                                                        sizeof(long),
+                                                        (void *)__gen_e_acsl_at_5,
+                                                        (void *)(& __gen_e_acsl_at_5));
+        __e_acsl_assert(__gen_e_acsl_valid_read_5,(char *)"RTE",
+                        (char *)"main",
+                        (char *)"mem_access:\n  \\valid_read(__gen_e_acsl_at_5 + (int)((int)(__gen_e_acsl_k_3 - -9) - 1))",
+                        41);
+        /*@ assert
+            Value: initialization:
+              \initialized(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_3 - -9) - 1));
+        */
+        if (! (*(__gen_e_acsl_at_5 + ((__gen_e_acsl_k_3 - -9) - 1)) == 0L)) 
+          ;
+        else {
+          __gen_e_acsl_exists_3 = 1;
+          goto e_acsl_end_loop5;
+        }
+      }
+      __gen_e_acsl_k_3 ++;
+    }
+    e_acsl_end_loop5: ;
+    __e_acsl_assert(__gen_e_acsl_exists_3,(char *)"Assertion",(char *)"main",
+                    (char *)"\\exists integer k; -9 < k < 0 && \\at(m + k,G) == 0",
+                    41);
+  }
+  /*@ assert
+      ∃ ℤ u;
+        9 ≤ u < 21 ∧
+        (∀ ℤ v; -5 < v ≤ (u < 15? u + 6: 3) ⇒ \at((n + u) + v > 0,K));
+  */
+  {
+    int __gen_e_acsl_exists_4;
+    int __gen_e_acsl_u_3;
+    __gen_e_acsl_exists_4 = 0;
+    __gen_e_acsl_u_3 = 9;
+    while (1) {
+      if (__gen_e_acsl_u_3 < 21) ; else break;
+      {
+        int __gen_e_acsl_forall_2;
+        int __gen_e_acsl_v_3;
+        __gen_e_acsl_forall_2 = 1;
+        __gen_e_acsl_v_3 = -5 + 1;
+        while (1) {
+          {
+            int __gen_e_acsl_if_3;
+            if (__gen_e_acsl_u_3 < 15) __gen_e_acsl_if_3 = __gen_e_acsl_u_3 + 6;
+            else __gen_e_acsl_if_3 = 3;
+            if (__gen_e_acsl_v_3 <= __gen_e_acsl_if_3) ; else break;
+          }
+          {
+            int __gen_e_acsl_valid_read_6;
+            __gen_e_acsl_valid_read_6 = __e_acsl_valid_read((void *)(
+                                                            __gen_e_acsl_at_6 + (int)(
+                                                            (long)((int)(
+                                                            (long)((int)(
+                                                            __gen_e_acsl_u_3 - 9L)) * 32L)) + (int)(
+                                                            (int)(__gen_e_acsl_v_3 - -5L) - 1))),
+                                                            sizeof(int),
+                                                            (void *)__gen_e_acsl_at_6,
+                                                            (void *)(& __gen_e_acsl_at_6));
+            __e_acsl_assert(__gen_e_acsl_valid_read_6,(char *)"RTE",
+                            (char *)"main",
+                            (char *)"mem_access:\n  \\valid_read(__gen_e_acsl_at_6 +\n              (int)((int)((int)(__gen_e_acsl_u_3 - 9) * 32) +\n                    (int)((int)(__gen_e_acsl_v_3 - -5) - 1)))",
+                            45);
+            /*@ assert
+                Value: initialization:
+                  \initialized(__gen_e_acsl_at_6 +
+                               ((__gen_e_acsl_u_3 - 9) * 32 +
+                                ((__gen_e_acsl_v_3 - -5) - 1)));
+            */
+            if (*(__gen_e_acsl_at_6 + ((__gen_e_acsl_u_3 - 9) * 32 + (
+                                       (__gen_e_acsl_v_3 - -5) - 1)))) 
+              ;
+            else {
+              __gen_e_acsl_forall_2 = 0;
+              goto e_acsl_end_loop6;
+            }
+          }
+          __gen_e_acsl_v_3 ++;
+        }
+        e_acsl_end_loop6: ;
+        if (! __gen_e_acsl_forall_2) ;
+        else {
+          __gen_e_acsl_exists_4 = 1;
+          goto e_acsl_end_loop7;
+        }
+      }
+      __gen_e_acsl_u_3 ++;
+    }
+    e_acsl_end_loop7: ;
+    __e_acsl_assert(__gen_e_acsl_exists_4,(char *)"Assertion",(char *)"main",
+                    (char *)"\\exists integer u;\n  9 <= u < 21 &&\n  (\\forall integer v; -5 < v <= (u < 15? u + 6: 3) ==> \\at((n + u) + v > 0,K))",
+                    43);
+  }
+  int t[5] = {9, 12, 12, 12, -4};
+  __e_acsl_store_block((void *)(t),(size_t)20);
+  __e_acsl_full_init((void *)(& t));
+  __gen_e_acsl_f(t);
+  g();
+  /*@ assert
+      ∃ ℤ u;
+        10 ≤ u < 20 ∧
+        (∃ ℤ v;
+           -10 < v ≤ -5 + (\let u = -2; u) ∧
+           (∃ ℤ w;
+              100 < w ≤ 200 ∧
+              \at((((n - u) + (\let u = 42; u)) + v) + w > 0,K)));
+  */
+  {
+    int __gen_e_acsl_exists_5;
+    int __gen_e_acsl_u_5;
+    __gen_e_acsl_exists_5 = 0;
+    __gen_e_acsl_u_5 = 10;
+    while (1) {
+      if (__gen_e_acsl_u_5 < 20) ; else break;
+      {
+        int __gen_e_acsl_exists_6;
+        int __gen_e_acsl_v_5;
+        __gen_e_acsl_exists_6 = 0;
+        __gen_e_acsl_v_5 = -10 + 1;
+        while (1) {
+          {
+            int __gen_e_acsl_u_9;
+            __gen_e_acsl_u_9 = -2;
+            if (__gen_e_acsl_v_5 <= -5 + __gen_e_acsl_u_9) ; else break;
+          }
+          {
+            int __gen_e_acsl_exists_7;
+            int __gen_e_acsl_w;
+            __gen_e_acsl_exists_7 = 0;
+            __gen_e_acsl_w = 100 + 1;
+            while (1) {
+              if (__gen_e_acsl_w <= 200) ; else break;
+              {
+                int __gen_e_acsl_valid_read_7;
+                __gen_e_acsl_valid_read_7 = __e_acsl_valid_read((void *)(
+                                                                __gen_e_acsl_at_7 + (int)(
+                                                                (long)((int)(
+                                                                (long)((int)(
+                                                                __gen_e_acsl_u_5 - 10L)) * 300L)) + (int)(
+                                                                (long)((int)(
+                                                                (long)((int)(
+                                                                (int)(
+                                                                __gen_e_acsl_v_5 - -10L) - 1)) * 100L)) + (int)(
+                                                                (long)((int)(
+                                                                __gen_e_acsl_w - 100L)) - 1L)))),
+                                                                sizeof(int),
+                                                                (void *)__gen_e_acsl_at_7,
+                                                                (void *)(& __gen_e_acsl_at_7));
+                __e_acsl_assert(__gen_e_acsl_valid_read_7,(char *)"RTE",
+                                (char *)"main",
+                                (char *)"mem_access:\n  \\valid_read(__gen_e_acsl_at_7 +\n              (int)((int)((int)(__gen_e_acsl_u_5 - 10) * 300) +\n                    (int)((int)((int)((int)(__gen_e_acsl_v_5 - -10) - 1) *\n                                100)\n                          + (int)((int)(__gen_e_acsl_w - 100) - 1))))",
+                                57);
+                /*@ assert
+                    Value: initialization:
+                      \initialized(__gen_e_acsl_at_7 +
+                                   ((__gen_e_acsl_u_5 - 10) * 300 +
+                                    (((__gen_e_acsl_v_5 - -10) - 1) * 100 +
+                                     ((__gen_e_acsl_w - 100) - 1))));
+                */
+                if (! *(__gen_e_acsl_at_7 + ((__gen_e_acsl_u_5 - 10) * 300 + (
+                                             ((__gen_e_acsl_v_5 - -10) - 1) * 100 + (
+                                             (__gen_e_acsl_w - 100) - 1))))) 
+                  ;
+                else {
+                  __gen_e_acsl_exists_7 = 1;
+                  goto e_acsl_end_loop8;
+                }
+              }
+              __gen_e_acsl_w ++;
+            }
+            e_acsl_end_loop8: ;
+            if (! __gen_e_acsl_exists_7) ;
+            else {
+              __gen_e_acsl_exists_6 = 1;
+              goto e_acsl_end_loop9;
+            }
+          }
+          __gen_e_acsl_v_5 ++;
+        }
+        e_acsl_end_loop9: ;
+        if (! __gen_e_acsl_exists_6) ;
+        else {
+          __gen_e_acsl_exists_5 = 1;
+          goto e_acsl_end_loop10;
+        }
+      }
+      __gen_e_acsl_u_5 ++;
+    }
+    e_acsl_end_loop10: ;
+    __e_acsl_assert(__gen_e_acsl_exists_5,(char *)"Assertion",(char *)"main",
+                    (char *)"\\exists integer u;\n  10 <= u < 20 &&\n  (\\exists integer v;\n     -10 < v <= -5 + (\\let u = -2; u) &&\n     (\\exists integer w;\n        100 < w <= 200 && \\at((((n - u) + (\\let u = 42; u)) + v) + w > 0,K)))",
+                    54);
+  }
+  /*@ assert ∃ ℤ j; 2 ≤ j < 10000000000000000 ∧ \at(n + j ≡ 11,L);
+   */
+  ;
+  /*@ assert \let i = n; \at(n + i ≡ 10,L); */ ;
+  __retres = 0;
+  __e_acsl_delete_block((void *)(t));
+  __e_acsl_delete_block((void *)(& n));
+  free((void *)__gen_e_acsl_at_7);
+  free((void *)__gen_e_acsl_at_6);
+  free((void *)__gen_e_acsl_at_5);
+  free((void *)__gen_e_acsl_at_4);
+  free((void *)__gen_e_acsl_at_3);
+  free((void *)__gen_e_acsl_at_2);
+  free((void *)__gen_e_acsl_at);
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+/*@ ensures
+      ∀ ℤ n;
+        1 < n ≤ 3 ⇒ \old(*(t + n) ≡ 12) ∧ \old(*(t + (n - 1)) > 5);
+    ensures \let m = 4; \old(*(t + m) ≡ -4) ∧ \old(*(t + (m - 4))) ≡ 9;
+ */
+void __gen_e_acsl_f(int *t)
+{
+  int *__gen_e_acsl_at_4;
+  int *__gen_e_acsl_at_3;
+  int *__gen_e_acsl_at_2;
+  int *__gen_e_acsl_at;
+  __gen_e_acsl_at_4 = (int *)malloc((size_t)4);
+  __gen_e_acsl_at_3 = (int *)malloc((size_t)4);
+  __gen_e_acsl_at_2 = (int *)malloc((size_t)8);
+  __gen_e_acsl_at = (int *)malloc((size_t)8);
+  {
+    int __gen_e_acsl_m_3;
+    __gen_e_acsl_m_3 = 4;
+    *(__gen_e_acsl_at_4 + 0) = *(t + (__gen_e_acsl_m_3 - 4));
+  }
+  {
+    int __gen_e_acsl_m_2;
+    __gen_e_acsl_m_2 = 4;
+    *(__gen_e_acsl_at_3 + 0) = *(t + __gen_e_acsl_m_2) == -4;
+  }
+  {
+    int __gen_e_acsl_n_3;
+    __gen_e_acsl_n_3 = 1 + 1;
+    while (1) {
+      if (__gen_e_acsl_n_3 <= 3) ; else break;
+      *(__gen_e_acsl_at_2 + ((__gen_e_acsl_n_3 - 1) - 1)) = *(t + (__gen_e_acsl_n_3 - 1)) > 5;
+      __gen_e_acsl_n_3 ++;
+    }
+  }
+  {
+    int __gen_e_acsl_n_2;
+    __gen_e_acsl_n_2 = 1 + 1;
+    while (1) {
+      if (__gen_e_acsl_n_2 <= 3) ; else break;
+      *(__gen_e_acsl_at + ((__gen_e_acsl_n_2 - 1) - 1)) = *(t + __gen_e_acsl_n_2) == 12;
+      __gen_e_acsl_n_2 ++;
+    }
+  }
+  __e_acsl_store_block((void *)(& t),(size_t)8);
+  f(t);
+  {
+    int __gen_e_acsl_forall;
+    int __gen_e_acsl_n;
+    int __gen_e_acsl_m;
+    int __gen_e_acsl_valid_read_3;
+    int __gen_e_acsl_and_2;
+    __gen_e_acsl_forall = 1;
+    __gen_e_acsl_n = 1 + 1;
+    while (1) {
+      if (__gen_e_acsl_n <= 3) ; else break;
+      {
+        int __gen_e_acsl_valid_read;
+        int __gen_e_acsl_and;
+        __gen_e_acsl_valid_read = __e_acsl_valid_read((void *)(__gen_e_acsl_at + (int)(
+                                                               (long)((int)(
+                                                               __gen_e_acsl_n - 1L)) - 1L)),
+                                                      sizeof(int),
+                                                      (void *)__gen_e_acsl_at,
+                                                      (void *)(& __gen_e_acsl_at));
+        __e_acsl_assert(__gen_e_acsl_valid_read,(char *)"RTE",(char *)"f",
+                        (char *)"mem_access:\n  \\valid_read(__gen_e_acsl_at + (int)((int)(__gen_e_acsl_n - 1) - 1))",
+                        7);
+        /*@ assert
+            Value: initialization:
+              \initialized(__gen_e_acsl_at + ((__gen_e_acsl_n - 1) - 1));
+        */
+        if (*(__gen_e_acsl_at + ((__gen_e_acsl_n - 1) - 1))) {
+          int __gen_e_acsl_valid_read_2;
+          __gen_e_acsl_valid_read_2 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_2 + (int)(
+                                                                   (long)((int)(
+                                                                   __gen_e_acsl_n - 1L)) - 1L)),
+                                                          sizeof(int),
+                                                          (void *)__gen_e_acsl_at_2,
+                                                          (void *)(& __gen_e_acsl_at_2));
+          __e_acsl_assert(__gen_e_acsl_valid_read_2,(char *)"RTE",
+                          (char *)"f",
+                          (char *)"mem_access:\n  \\valid_read(__gen_e_acsl_at_2 + (int)((int)(__gen_e_acsl_n - 1) - 1))",
+                          7);
+          /*@ assert
+              Value: initialization:
+                \initialized(__gen_e_acsl_at_2 + ((__gen_e_acsl_n - 1) - 1));
+          */
+          __gen_e_acsl_and = *(__gen_e_acsl_at_2 + ((__gen_e_acsl_n - 1) - 1));
+        }
+        else __gen_e_acsl_and = 0;
+        if (__gen_e_acsl_and) ;
+        else {
+          __gen_e_acsl_forall = 0;
+          goto e_acsl_end_loop11;
+        }
+      }
+      __gen_e_acsl_n ++;
+    }
+    e_acsl_end_loop11: ;
+    __e_acsl_assert(__gen_e_acsl_forall,(char *)"Postcondition",(char *)"f",
+                    (char *)"\\forall integer n;\n  1 < n <= 3 ==> \\old(*(t + n) == 12) && \\old(*(t + (n - 1)) > 5)",
+                    6);
+    __gen_e_acsl_m = 4;
+    __gen_e_acsl_valid_read_3 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_3 + 0),
+                                                    sizeof(int),
+                                                    (void *)__gen_e_acsl_at_3,
+                                                    (void *)(& __gen_e_acsl_at_3));
+    __e_acsl_assert(__gen_e_acsl_valid_read_3,(char *)"RTE",(char *)"f",
+                    (char *)"mem_access: \\valid_read(__gen_e_acsl_at_3 + 0)",
+                    8);
+    if (*(__gen_e_acsl_at_3 + 0)) {
+      int __gen_e_acsl_valid_read_4;
+      __gen_e_acsl_valid_read_4 = __e_acsl_valid_read((void *)(__gen_e_acsl_at_4 + 0),
+                                                      sizeof(int),
+                                                      (void *)__gen_e_acsl_at_4,
+                                                      (void *)(& __gen_e_acsl_at_4));
+      __e_acsl_assert(__gen_e_acsl_valid_read_4,(char *)"RTE",(char *)"f",
+                      (char *)"mem_access: \\valid_read(__gen_e_acsl_at_4 + 0)",
+                      8);
+      __gen_e_acsl_and_2 = *(__gen_e_acsl_at_4 + 0) == 9;
+    }
+    else __gen_e_acsl_and_2 = 0;
+    __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Postcondition",(char *)"f",
+                    (char *)"\\let m = 4; \\old(*(t + m) == -4) && \\old(*(t + (m - 4))) == 9",
+                    8);
+    __e_acsl_delete_block((void *)(& t));
+    free((void *)__gen_e_acsl_at_4);
+    free((void *)__gen_e_acsl_at_3);
+    free((void *)__gen_e_acsl_at_2);
+    free((void *)__gen_e_acsl_at);
+    return;
+  }
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_at_on-purely-logic-variables2.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_at_on-purely-logic-variables2.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c6d212d7a8b887c51dd0afd90d6b03a8fe215c7
--- /dev/null
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_at_on-purely-logic-variables2.c
@@ -0,0 +1,103 @@
+/* Generated by Frama-C */
+#include "stdio.h"
+#include "stdlib.h"
+/*@ ensures
+      ∀ ℤ n;
+        1 < n ≤ 3 ⇒ \old(*(t + n) ≡ 12) ∧ \old(*(t + (n - 1)) > 5);
+    ensures \let m = 4; \old(*(t + m) ≡ -4) ∧ \old(*(t + (m - 4))) ≡ 9;
+ */
+void __gen_e_acsl_f(int *t);
+
+void f(int *t)
+{
+  __e_acsl_store_block((void *)(& t),(size_t)8);
+  __e_acsl_delete_block((void *)(& t));
+  return;
+}
+
+void g(void)
+{
+  int m;
+  m = 8;
+  Q: ;
+  m = 10;
+  /*@ assert ∃ ℤ w; 3 ≤ w < 6 ∧ \at(m + w ≡ 12,Q); */ ;
+  return;
+}
+
+int main(void)
+{
+  int __retres;
+  int n;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __e_acsl_store_block((void *)(& n),(size_t)4);
+  __e_acsl_full_init((void *)(& n));
+  n = 7;
+  L: ;
+  __e_acsl_full_init((void *)(& n));
+  n = 9;
+  K: ;
+  __e_acsl_full_init((void *)(& n));
+  n = 666;
+  /*@ assert \let i = 3; \at(n + i ≡ 10,L); */ ;
+  /*@ assert ∃ ℤ j; 2 ≤ j < 5 ∧ \at(n + j ≡ 11,L); */ ;
+  /*@
+  assert \let k = -7;
+  ∃ ℤ u;
+    9 ≤ u < 21 ∧
+    (∀ ℤ v; -5 < v ≤ 6 ⇒ \at((u > 0? n + k: u + v) > 0,K));
+   */
+  ;
+  /*@ assert \let i = 3; \at(n + i,L) ≡ 10; */ ;
+  unsigned int m = (unsigned int)3;
+  G: ;
+  m = (unsigned int)(-3);
+  /*@ assert ∃ ℤ k; -9 < k < 0 ∧ \at(m + k,G) ≡ 0; */ ;
+  /*@
+  assert
+  ∃ ℤ u;
+    9 ≤ u < 21 ∧
+    (∀ ℤ v; -5 < v ≤ (u < 15? u + 6: 3) ⇒ \at((n + u) + v > 0,K));
+   */
+  ;
+  int t[5] = {9, 12, 12, 12, -4};
+  __e_acsl_store_block((void *)(t),(size_t)20);
+  __e_acsl_full_init((void *)(& t));
+  __gen_e_acsl_f(t);
+  g();
+  /*@
+  assert
+  ∃ ℤ u;
+    10 ≤ u < 20 ∧
+    (∃ ℤ v;
+       -10 < v ≤ -5 + (\let u = -2; u) ∧
+       (∃ ℤ w;
+          100 < w ≤ 200 ∧
+          \at((((n - u) + (\let u = 42; u)) + v) + w > 0,K)));
+   */
+  ;
+  /*@ assert ∃ ℤ j; 2 ≤ j < 10000000000000000 ∧ \at(n + j ≡ 11,L);
+   */
+  ;
+  /*@ assert \let i = n; \at(n + i ≡ 10,L); */ ;
+  __retres = 0;
+  __e_acsl_delete_block((void *)(t));
+  __e_acsl_delete_block((void *)(& n));
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+/*@ ensures
+      ∀ ℤ n;
+        1 < n ≤ 3 ⇒ \old(*(t + n) ≡ 12) ∧ \old(*(t + (n - 1)) > 5);
+    ensures \let m = 4; \old(*(t + m) ≡ -4) ∧ \old(*(t + (m - 4))) ≡ 9;
+ */
+void __gen_e_acsl_f(int *t)
+{
+  __e_acsl_store_block((void *)(& t),(size_t)8);
+  f(t);
+  __e_acsl_delete_block((void *)(& t));
+  return;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/test_config b/src/plugins/e-acsl/tests/gmp/test_config
index b51a18dcf2f95a90239b1a25a517a65a5e866834..645d2c1fa60b62e4c9c9223a7c2f6adf06608878 100644
--- a/src/plugins/e-acsl/tests/gmp/test_config
+++ b/src/plugins/e-acsl/tests/gmp/test_config
@@ -1,5 +1,5 @@
 LOG: gen_@PTEST_NAME@.c
-OPT: -machdep gcc_x86_64 -check -e-acsl -then-last -load-script tests/print.cmxs -print -ocode tests/gmp/result/gen_@PTEST_NAME@.c -kernel-verbose 0 -val -no-val-print -no-val-show-progress -no-results
+OPT: -machdep gcc_x86_64 -check -e-acsl -then-last -load-script tests/print.cmxs -print -ocode tests/gmp/result/gen_@PTEST_NAME@.c -kernel-verbose 0 -val -no-val-print -no-val-show-progress -no-results -eva-no-alloc-returns-null
 EXEC: ./scripts/testrun.sh @PTEST_NAME@ gmp "1" "--frama-c=@frama-c@"
 LOG: gen_@PTEST_NAME@2.c
-OPT: -machdep gcc_x86_64 -check -e-acsl -e-acsl-gmp-only -then-last -load-script tests/print.cmxs -print -ocode tests/gmp/result/gen_@PTEST_NAME@2.c -kernel-verbose 0 -val -no-val-print -no-val-show-progress -no-results
+OPT: -machdep gcc_x86_64 -check -e-acsl -e-acsl-gmp-only -then-last -load-script tests/print.cmxs -print -ocode tests/gmp/result/gen_@PTEST_NAME@2.c -kernel-verbose 0 -val -no-val-print -no-val-show-progress -no-results -eva-no-alloc-returns-null
diff --git a/src/plugins/e-acsl/translate.ml b/src/plugins/e-acsl/translate.ml
index 4510c8f3fdf32192a964c9ac49eec82aaf5b5c95..8afed8ab60fd26c4412c5a6d3b2fa3d27ac2deee 100644
--- a/src/plugins/e-acsl/translate.ml
+++ b/src/plugins/e-acsl/translate.ml
@@ -296,7 +296,7 @@ let cast_integer_to_float lty lty_t e =
   else
     e
 
-let rec thost_to_host kf env = function
+let rec thost_to_host kf env th = match th with
   | TVar { lv_origin = Some v } ->
     Var (Cil.get_varinfo (Env.get_behavior env) v), env, v.vname
   | TVar ({ lv_origin = None } as logic_v) ->
@@ -424,7 +424,8 @@ and context_insensitive_term_to_exp kf env t =
       (* do not generate [e2] from [t2] twice *)
       let guard, env =
         let name = name_of_binop bop ^ "_guard" in
-        comparison_to_exp ~loc kf env Typing.gmp ~e1:e2 ~name Eq t2 zero t
+        comparison_to_exp
+          ~loc kf env Typing.gmp ~e1:e2 ~name Eq t2 zero t
       in
       let mk_stmts _v e =
 	assert (Gmpz.is_t ty);
@@ -549,10 +550,15 @@ and context_insensitive_term_to_exp kf env t =
     let e, env = term_to_exp kf env t in
     e, env, false, ""
   | Tat(t', label) ->
-    (* convert [t'] to [e] in a separated local env *)
-    let e, env = term_to_exp kf (Env.push env) t' in
-    let e, env, is_mpz_string = at_to_exp env (Some t) label e in
-    e, env, is_mpz_string, ""
+    let lscope = Env.Logic_scope.get env in
+    let pot = Misc.PoT_term t' in
+    if Lscope.is_used lscope pot then
+      let e, env = At_with_lscope.to_exp ~loc kf env pot label in
+      e, env, false, ""
+    else
+      let e, env = term_to_exp kf (Env.push env) t' in
+      let e, env, is_mpz_string = at_to_exp_no_lscope env (Some t) label e in
+      e, env, is_mpz_string, ""
   | Tbase_addr(BuiltinLabel Here, t) ->
     mmodel_call ~loc kf "base_addr" Cil.voidPtrType env t
   | Tbase_addr _ -> not_yet env "labeled \\base_addr"
@@ -576,6 +582,8 @@ and context_insensitive_term_to_exp kf env t =
   | Tcomprehension _ -> not_yet env "tset comprehension"
   | Trange _ -> not_yet env "range"
   | Tlet(li, t) ->
+    let lvs = Lscope.Lvs_let(li.l_var_info, Misc.term_of_li li) in
+    let env = Env.Logic_scope.extend env lvs in
     let env = env_of_li li kf env loc in
     let e, env = term_to_exp kf env t in
     Interval.Env.remove li.l_var_info;
@@ -590,7 +598,9 @@ and term_to_exp kf env t =
     Printer.pp_term t generate_rte;
   let env = Env.rte env false in
   let t = match t.term_node with TLogic_coerce(_, t) -> t | _ -> t in
-  let e, env, is_mpz_string, name = context_insensitive_term_to_exp kf env t in
+  let e, env, is_mpz_string, name =
+    context_insensitive_term_to_exp kf env t
+  in
   let env = if generate_rte then translate_rte kf env e else env in
   let cast = Typing.get_cast t in
   let name = if name = "" then None else Some name in
@@ -675,7 +685,13 @@ and mmodel_call_with_size ~loc kf name ctx env t =
     res, env
   in
   mmodel_call_with_ranges
-    ~loc kf name ctx env t call_for_unsupported_constructs
+    ~loc
+    kf
+    name
+    ctx
+    env
+    t
+    call_for_unsupported_constructs
 
 and mmodel_call_valid ~loc kf name ctx env t =
   let call_for_unsupported_constructs ~loc kf name ctx env t =
@@ -703,7 +719,13 @@ and mmodel_call_valid ~loc kf name ctx env t =
     res, env
   in
   mmodel_call_with_ranges
-    ~loc kf name ctx env t call_for_unsupported_constructs
+    ~loc
+    kf
+    name
+    ctx
+    env
+    t
+    call_for_unsupported_constructs
 
 (* [mmodel_call_with_ranges] handles ranges in [t] when calling builtin [name].
   It only supports the following cases for the time being:
@@ -859,7 +881,7 @@ and mmodel_call_memory_block ~loc kf name ctx env p r =
   in
   e, env
 
-and at_to_exp env t_opt label e =
+and at_to_exp_no_lscope env t_opt label e =
   let stmt = E_acsl_label.get_stmt (Env.get_visitor env) label in
   (* generate a new variable denoting [\at(t',label)].
      That is this variable which is the resulting expression.
@@ -884,20 +906,15 @@ and at_to_exp env t_opt label e =
     inherit Visitor.frama_c_inplace
     method !vstmt_aux stmt =
       (* either a standard C affectation or an mpz one according to type of
-	 [e] *)
+        [e] *)
       let new_stmt = Gmpz.init_set ~loc (Cil.var res_v) res e in
       assert (!env_ref == new_env);
       (* generate the new block of code for the labeled statement and the
-	 corresponding environment *)
+        corresponding environment *)
       let block, new_env =
-	Env.pop_and_get new_env new_stmt ~global_clear:false Env.Middle
-      in
-      let pre = match label with
-        | BuiltinLabel(Here | Post) -> true
-        | BuiltinLabel(Old | Pre | LoopEntry | LoopCurrent | Init)
-        | FormalLabel _ | StmtLabel _ -> false
+       Env.pop_and_get new_env new_stmt ~global_clear:false Env.Middle
       in
-      env_ref := Env.extend_stmt_in_place new_env stmt ~pre block;
+      env_ref := Env.extend_stmt_in_place new_env stmt ~label block;
       Cil.ChangeTo stmt
   end
   in
@@ -936,7 +953,8 @@ and named_predicate_content_to_exp ?name kf env p =
   | Pand(p1, p2) ->
     (* p1 && p2 <==> if p1 then p2 else false *)
     let e1, env1 = named_predicate_to_exp kf (Env.rte env true) p1 in
-    let _, env2 as res2 = named_predicate_to_exp kf (Env.push env1) p2 in
+    let _, env2 as res2 =
+      named_predicate_to_exp kf (Env.push env1) p2 in
     let env3 = Env.push env2 in
     let name = match name with None -> "and" | Some n -> n in
     conditional_to_exp ~name loc None e1 res2 (Cil.zero loc, env3)
@@ -969,10 +987,13 @@ and named_predicate_content_to_exp ?name kf env p =
     Cil.new_exp ~loc (UnOp(LNot, e, Cil.intType)), env
   | Pif(t, p2, p3) ->
     let e1, env1 = term_to_exp kf (Env.rte env true) t in
-    let (_, env2 as res2) = named_predicate_to_exp kf (Env.push env1) p2 in
+    let (_, env2 as res2) =
+      named_predicate_to_exp kf (Env.push env1) p2 in
     let res3 = named_predicate_to_exp kf (Env.push env2) p3 in
     conditional_to_exp loc None e1 res2 res3
   | Plet(li, p) ->
+    let lvs = Lscope.Lvs_let(li.l_var_info, Misc.term_of_li li) in
+    let env = Env.Logic_scope.extend env lvs in
     let env = env_of_li li kf env loc in
     let e, env = named_predicate_to_exp kf env p in
     Interval.Env.remove li.l_var_info;
@@ -981,11 +1002,17 @@ and named_predicate_content_to_exp ?name kf env p =
   | Pat(p, BuiltinLabel Here) ->
     named_predicate_to_exp kf env p
   | Pat(p', label) ->
-    (* convert [t'] to [e] in a separated local env *)
-    let e, env = named_predicate_to_exp kf (Env.push env) p' in
-    let e, env, is_string = at_to_exp env None label e in
-    assert (not is_string);
-    e, env
+    let lscope = Env.Logic_scope.get env in
+    let pot = Misc.PoT_pred p' in
+    if Lscope.is_used lscope pot then
+      At_with_lscope.to_exp ~loc kf env pot label
+    else begin
+      (* convert [t'] to [e] in a separated local env *)
+      let e, env = named_predicate_to_exp kf (Env.push env) p' in
+      let e, env, is_string = at_to_exp_no_lscope env None label e in
+      assert (not is_string);
+      e, env
+    end
   | Pvalid_read(BuiltinLabel Here as llabel, t) as pc
   | (Pvalid(BuiltinLabel Here as llabel, t) as pc) ->
     let call_valid t =
@@ -1022,7 +1049,8 @@ and named_predicate_content_to_exp ?name kf env p =
     | TAddrOf (TVar { lv_origin = Some vi }, TNoOffset)
 	when vi.vformal || vi.vglob || Functions.RTL.is_generated_name vi.vname ->
       Cil.one ~loc, env
-    | _ -> mmodel_call_with_size ~loc kf "initialized" Cil.intType env t)
+    | _ ->
+      mmodel_call_with_size ~loc kf "initialized" Cil.intType env t)
   | Pinitialized _ -> not_yet env "labeled \\initialized"
   | Pallocable _ -> not_yet env "\\allocate"
   | Pfreeable(BuiltinLabel Here, t) ->
@@ -1061,7 +1089,13 @@ and translate_rte_annots:
 	  handle_error
 	    (fun env ->
 	      Options.feedback ~dkey ~level:4 "prevent RTE from %a" pp elt;
-	      translate_named_predicate kf (Env.rte env false) p)
+        (* The logic scope MUST NOT be reset here since we still might be
+          in the middle of the translation of the original predicate. *)
+        let lscope_reset_old = Env.Logic_scope.get_reset env in
+        let env = Env.Logic_scope.set_reset env false in
+        let env = translate_named_predicate kf (Env.rte env false) p in
+        let env = Env.Logic_scope.set_reset env lscope_reset_old in
+        env)
 	    env
         | _ -> assert false)
         env
@@ -1082,6 +1116,7 @@ and translate_named_predicate kf env p =
   Typing.type_named_predicate ~must_clear:rte p;
   let e, env = named_predicate_to_exp kf ~rte env p in
   assert (Typ.equal (Cil.typeOf e) Cil.intType);
+  let env = Env.Logic_scope.reset env in
   Env.add_stmt
     env
     (Misc.mk_e_acsl_guard ~reverse:true (Env.annotation_kind env) kf e p)
@@ -1090,8 +1125,11 @@ let named_predicate_to_exp ?name kf env p =
   named_predicate_to_exp ?name kf env p (* forget optional argument ?rte *)
 
 let () =
-  Quantif.term_to_exp_ref := term_to_exp;
-  Quantif.predicate_to_exp_ref := named_predicate_to_exp
+  Loops.term_to_exp_ref := term_to_exp;
+  Loops.translate_named_predicate_ref := translate_named_predicate;
+  Quantif.predicate_to_exp_ref := named_predicate_to_exp;
+  At_with_lscope.term_to_exp_ref := term_to_exp;
+  At_with_lscope.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/translate.mli b/src/plugins/e-acsl/translate.mli
index 77207f008721471b78209def6378a9df79deb60e..4f8540341fa2d6340d09325272825dbe46866080 100644
--- a/src/plugins/e-acsl/translate.mli
+++ b/src/plugins/e-acsl/translate.mli
@@ -32,14 +32,14 @@ val translate_pre_code_annotation:
   kernel_function -> Env.t -> code_annotation -> Env.t
 val translate_post_code_annotation:
   kernel_function -> Env.t -> code_annotation -> Env.t
-val translate_named_predicate: 
+val translate_named_predicate:
   kernel_function -> Env.t -> predicate -> Env.t
 
 val translate_rte_annots:
-  (Format.formatter -> 'a -> unit) -> 
+  (Format.formatter -> 'a -> unit) ->
   'a ->
-  kernel_function -> 
-  Env.t -> 
+  kernel_function ->
+  Env.t ->
   code_annotation list ->
   Env.t
 
diff --git a/src/plugins/e-acsl/typing.mli b/src/plugins/e-acsl/typing.mli
index 2319e9c37671cae5d175c52d98a31045472de96a..e8a74d55ae836bdb349a116b739b0607c80e43b2 100644
--- a/src/plugins/e-acsl/typing.mli
+++ b/src/plugins/e-acsl/typing.mli
@@ -132,6 +132,15 @@ 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 *)
+(*****************************************************************************)
+
+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. *)
+
 (******************************************************************************)
 (** {2 Internal stuff} *)
 (******************************************************************************)
diff --git a/src/plugins/e-acsl/visit.ml b/src/plugins/e-acsl/visit.ml
index 68fed7786520b3528633e2e3122779d6316e5e93..91933f67a107917c3db8381f5b77ad4c65eedad2 100644
--- a/src/plugins/e-acsl/visit.ml
+++ b/src/plugins/e-acsl/visit.ml
@@ -456,6 +456,17 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
     f.slocals <- locals;
     f.sbody.blocals <- blocks
 
+  (* Memory management for \at on purely logic variables:
+    Put [malloc] stmts at proper locations *)
+  method private insert_malloc_and_free_stmts kf f =
+    let malloc_stmts = At_with_lscope.Malloc.find_all kf in
+    let fstmts = malloc_stmts @ f.sbody.bstmts in
+    f.sbody.bstmts <- fstmts;
+    (* Now that [malloc] stmts for [kf] have been inserted,
+      there is no more need to keep the corresponding entries in the
+      table managing them. *)
+    At_with_lscope.Malloc.remove_all kf
+
   method !vfunc f =
     if generate then begin
       Exit_points.generate f;
@@ -467,6 +478,7 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
         (fun f ->
           Exit_points.clear ();
           self#add_generated_variables_in_function f;
+          self#insert_malloc_and_free_stmts kf f;
           Options.feedback ~dkey ~level:2 "function %a done."
             Kernel_function.pretty kf;
           f)
@@ -834,10 +846,12 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
 
   method !vblock blk =
     let handle_memory new_blk =
-      match new_blk.blocals with
-      | [] -> new_blk
-      | _ :: _ ->
-        let kf = Extlib.the self#current_kf in
+      let kf = Extlib.the self#current_kf in
+      let free_stmts = At_with_lscope.Free.find_all kf in
+      match new_blk.blocals, free_stmts with
+      | [], [] ->
+        new_blk
+      | [], _ :: _ | _ :: _, [] | _ :: _, _ :: _ ->
         let add_locals stmts =
           List.fold_left
             (fun acc vi ->
@@ -854,10 +868,14 @@ you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
                preceded by clean if any *)
             let init, tl =
               if self#is_main kf && Mmodel_analysis.use_model () then
-                [ potential_clean; ret ], tl
+                free_stmts @ [ potential_clean; ret ], tl
               else
-                [ ret ], l
+                free_stmts @ [ ret ], l
             in
+            (* Now that [free] stmts for [kf] have been inserted,
+              there is no more need to keep the corresponding entries in the
+              table managing them. *)
+            At_with_lscope.Free.remove_all kf;
             blk.bstmts <-
               List.fold_left (fun acc v -> v :: acc) (add_locals init) tl
           | { skind = Block b } :: _ ->