diff --git a/src/plugins/e-acsl/Makefile.in b/src/plugins/e-acsl/Makefile.in
index e040d56b4057e911318d689fca91beb857e3832a..67badd902929239d8d609c12369c336bd1f4779d 100644
--- a/src/plugins/e-acsl/Makefile.in
+++ b/src/plugins/e-acsl/Makefile.in
@@ -58,7 +58,9 @@ PLUGIN_CMO:= local_config \
 	gmpz \
 	literal_strings \
 	mmodel_analysis \
+	prepare_ast \
 	dup_functions \
+	exit_points \
 	label \
 	env \
 	interval \
diff --git a/src/plugins/e-acsl/exit_points.ml b/src/plugins/e-acsl/exit_points.ml
new file mode 100644
index 0000000000000000000000000000000000000000..2701b2be851f7e26cd08a315df3fb772adeb1f86
--- /dev/null
+++ b/src/plugins/e-acsl/exit_points.ml
@@ -0,0 +1,142 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2016                                               *)
+(*    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 license/LGPLv2.1).             *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+open Cil_datatype
+
+module Build_env(X: sig type t val name: string end): sig
+  val add: stmt -> X.t -> unit
+  val get: stmt -> X.t
+  val get_all: stmt -> X.t list
+  val is_empty: unit -> bool
+  val clear: unit -> unit
+end = struct
+
+  let tbl = Stmt.Hashtbl.create 17
+  let add = Stmt.Hashtbl.add tbl
+
+  let get stmt =
+    try Stmt.Hashtbl.find tbl stmt
+    with Not_found ->
+      Options.fatal "unknown stmt %a in %s" Printer.pp_stmt stmt X.name
+
+  let get_all = Stmt.Hashtbl.find_all tbl
+  let is_empty () = Stmt.Hashtbl.length tbl = 0
+  let clear () = Stmt.Hashtbl.clear tbl
+
+end
+
+(* Mapping of statements to local variables available within that statement's
+   scope. The mappings of this structure are used to determine variables which
+   need to be removed before goto jumps. Generally, if some goto (with
+   scope variables are given by set G') jumps to a labeled statement with
+   scope variables given by set L', then the goto exists the scopes of
+   variables given via set G' \ L'. Consequently, if those variables are
+   tracked, they need to be removed from tracking. *)
+module SLocals =
+  Build_env(struct type t = Varinfo.Set.t let name = "SLocals" end)
+
+(* Statement to statement mapping indicating source/destination of a jump.
+   For instance, break statements are mapped to switches or loops they jump
+   out from and goto statements are mapped to their labeled statements. Notably,
+   such information does not really be computed for gotos (since they already
+   capture references to labelled statements they jumps to). Nevertheless it is
+   done for consistency, so all required information is stored uniformly. *)
+module Exits =
+  Build_env(struct type t = stmt let name = "Exits" end)
+
+(* Map labelled statements back to gotos which lead to them *)
+module LJumps =
+  Build_env(struct type t = stmt let name = "LJumps" end)
+
+let clear () =
+  SLocals.clear ();
+  Exits.clear ();
+  LJumps.clear ()
+
+let is_empty () =
+  SLocals.is_empty () && Exits.is_empty () && LJumps.is_empty ()
+
+let delete_vars stmt =
+  match stmt.skind with
+  | Goto _ | Break _ | Continue _ ->
+    Varinfo.Set.diff (SLocals.get stmt) (SLocals.get (Exits.get stmt))
+  | _ ->
+    Varinfo.Set.empty
+
+let store_vars stmt =
+  let gotos = LJumps.get_all stmt in
+  List.fold_left
+    (fun acc goto ->
+      Varinfo.Set.union
+        acc
+        (Varinfo.Set.diff (SLocals.get stmt) (SLocals.get goto)))
+    Varinfo.Set.empty
+    gotos
+
+let list_flatten_to_set =
+  List.fold_left
+    (List.fold_left (fun acc v -> Varinfo.Set.add v acc))
+    Varinfo.Set.empty
+
+class jump_context = object (_)
+  inherit Visitor.frama_c_inplace
+
+  val mutable locals = [[]]
+  (* Maintained list of local variables within the scope of a currently
+     visited statement. Variables within a single scope are given by a
+     single list *)
+
+  val jumps = Stack.create ()
+  (* Stack of entered switches and loops *)
+
+  method !vblock blk =
+    locals <- [blk.blocals] @ locals;
+    Cil.DoChildrenPost
+    (fun blk -> locals <- List.tl locals; blk)
+
+  method !vstmt stmt =
+    match stmt.skind with
+    | Loop _ | Switch _ ->
+      SLocals.add stmt (list_flatten_to_set locals);
+      Stack.push stmt jumps;
+      Cil.DoChildrenPost (fun st -> ignore(Stack.pop jumps); st)
+    | Break _ | Continue _ ->
+      Exits.add stmt (Stack.top jumps);
+      SLocals.add stmt (list_flatten_to_set locals);
+      Cil.DoChildren
+    | Goto(sref, _)  ->
+      SLocals.add stmt (list_flatten_to_set locals);
+      Exits.add stmt !sref;
+      LJumps.add !sref stmt;
+      Cil.DoChildren
+    | Instr _ | Return _ | If _ | Block _ | UnspecifiedSequence _
+    | Throw _ | TryCatch _ | TryFinally _ | TryExcept _ ->
+      (match stmt.labels with
+      | [] -> ()
+      | _ :: _ -> SLocals.add stmt (list_flatten_to_set locals));
+      Cil.DoChildren
+end
+
+let generate fct =
+  assert (is_empty ());
+  ignore (Cil.visitCilFunction (new jump_context :> Cil.cilVisitor) fct)
diff --git a/src/plugins/e-acsl/exit_points.mli b/src/plugins/e-acsl/exit_points.mli
new file mode 100644
index 0000000000000000000000000000000000000000..57d6773a83858e89e1c9effce1dc9c6fa9d76642
--- /dev/null
+++ b/src/plugins/e-acsl/exit_points.mli
@@ -0,0 +1,48 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2016                                               *)
+(*    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 license/LGPLv2.1).             *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** E-ACSL tracks a local variable by injecting:
+   - a call to [__e_acsl_store_block] at the beginning of its scope, and
+   - a call to [__e_acsl_delete_block] at the end of the scope.
+   This is not always sufficient to track variables because execution
+   may exit a scope early (for instance via a goto or a break statement).
+   This module computes program points at which extra `delete_block` statements
+   need to be added to handle such early scope exits. *)
+
+open Cil_types
+open Cil_datatype
+
+val generate: fundec -> unit
+(** Visit a function and populate data structures used to compute exit points *)
+
+val clear: unit -> unit
+(** Clear all gathered data *)
+
+val delete_vars: stmt -> Varinfo.Set.t
+(** Given a statement which potentially leads to an early scope exit (such as
+   goto, break or continue) return the list of local variables which
+   need to be removed from tracking before that statement is executed.
+   Before calling this function [generate] need to be executed. *)
+
+val store_vars: stmt -> Varinfo.Set.t
+(** Compute variables that should be re-recorded before a labelled statement to
+   which some goto jumps *)
diff --git a/src/plugins/e-acsl/main.ml b/src/plugins/e-acsl/main.ml
index d8ea9eca1d94fb8eda2ca6fa2cd9cefbd8e89edf..3873ed15198e33e57d2d87e96413ec1a583957d8 100644
--- a/src/plugins/e-acsl/main.ml
+++ b/src/plugins/e-acsl/main.ml
@@ -25,7 +25,7 @@ let check () =
   let t = Error.nb_untypable () in
   let n = Error.nb_not_yet () in
   let print msg n =
-    Options.result "@[%d annotation%s %s ignored,@ being %s.@]" 
+    Options.result "@[%d annotation%s %s ignored,@ being %s.@]"
       n
       (if n > 1 then "s" else "")
       (if n > 1 then "were" else "was")
@@ -75,26 +75,26 @@ let unmemoized_extend_ast () =
     Options.feedback ~level:2 "AST already computed: \
 E-ACSL is going to work on a copy.";
     let name = Project.get_name (Project.current ()) in
-    let tmpfile = 
+    let tmpfile =
       Extlib.temp_file_cleanup_at_exit ("e_acsl_" ^ name) ".i" in
     let cout = open_out tmpfile in
     let fmt = Format.formatter_of_out_channel cout in
     File.pretty_ast ~fmt ();
-    let selection = 
+    let selection =
       State_selection.diff
-	State_selection.full
-	(State_selection.with_dependencies Ast.self)
+        State_selection.full
+        (State_selection.with_dependencies Ast.self)
     in
     let prj =
       Project.create_by_copy
         ~last:false
-	~selection
-	(Format.asprintf "%s for E-ACSL" name)
+        ~selection
+        (Format.asprintf "%s for E-ACSL" name)
     in
     Project.on prj
       (fun () ->
-	Kernel.Files.set [ tmpfile ];
-	extend ())
+        Kernel.Files.set [ tmpfile ];
+        extend ())
       ();
     Some prj
   end else begin
@@ -103,7 +103,7 @@ E-ACSL is going to work on a copy.";
   end
 
 let extend_ast () = match !extended_ast_project with
-  | To_be_extended -> 
+  | To_be_extended ->
     let prj = unmemoized_extend_ast () in
     extended_ast_project := Already_extended prj;
     (match prj with
@@ -147,31 +147,42 @@ let generate_code =
       apply_on_e_acsl_ast
         (fun () ->
           Options.feedback "beginning translation.";
-          let dup_prj = Dup_functions.dup () in
+          let prepared_prj = Prepare_ast.prepare () in
           let res =
-            Project.on
-              dup_prj
-              (fun () ->
-                Gmpz.init_t ();
-                Mmodel_analysis.reset ();
-                let visit prj = Visit.do_visit ~prj true in
-                let prj = File.create_project_from_visitor name visit in
-                Loops.apply_after_transformation prj;
-(* remove the RTE's results computed from E-ACSL: their are
-   partial and associated with the wrong kernel function (the
-   one of the old project). *)
-                Project.clear
-                  ~selection:(State_selection.with_dependencies !Db.RteGen.self)
-                  ~project:prj
-                  ();
-                Resulting_projects.mark_as_computed ();
-                Project.copy
-                  ~selection:(State_selection.singleton Kernel.Files.self)
-                  prj;
-                prj)
+            Project.on prepared_prj
+            (fun () ->
+              let dup_prj = Dup_functions.dup () in
+              let res =
+                Project.on
+                  dup_prj
+                  (fun () ->
+                    Gmpz.init_t ();
+                    Mmodel_analysis.reset ();
+                    let visit prj = Visit.do_visit ~prj true in
+                    let prj = File.create_project_from_visitor name visit in
+                    Loops.apply_after_transformation prj;
+                    (* remove the RTE's results computed from E-ACSL: their are
+                       partial and associated with the wrong kernel function
+                       (the one of the old project). *)
+                    let selection =
+                      State_selection.with_dependencies !Db.RteGen.self
+                    in
+                    Project.clear ~selection ~project:prj ();
+                    Resulting_projects.mark_as_computed ();
+                    Project.copy
+                      ~selection:(State_selection.singleton Kernel.Files.self)
+                      prj;
+                    prj)
+                ()
+              in
+              if Options.Debug.get () = 0 then
+                Project.remove ~project:dup_prj ();
+              res)
               ()
           in
-          if Options.Debug.get () = 0 then Project.remove ~project:dup_prj ();
+          if Options.Debug.get () = 0 then begin
+            Project.remove ~project:prepared_prj ();
+          end;
           Options.feedback "translation done in project \"%s\"."
             (Options.Project_name.get ());
           res)
@@ -194,7 +205,7 @@ let predicate_to_exp =
        Kernel_function.ty Cil_datatype.Predicate.ty Cil_datatype.Exp.ty)
     Translate.predicate_to_exp
 
-let add_e_acsl_library _files = 
+let add_e_acsl_library _files =
   if Options.must_visit () || Options.Prepare.get () then ignore (extend_ast ())
 
 (* extending the AST as soon as possible reduce the amount of time the AST is
diff --git a/src/plugins/e-acsl/misc.ml b/src/plugins/e-acsl/misc.ml
index 3cc48be66de6d8639af873f86664d0f600140633..a22b60a23e2e0d4c2954d45a3d9b757d2135754d 100644
--- a/src/plugins/e-acsl/misc.ml
+++ b/src/plugins/e-acsl/misc.ml
@@ -34,14 +34,14 @@ let library_files () =
       "e_acsl_gmp.h";
       "e_acsl_mmodel_api.h" ]
 
-let normalized_library_files = 
+let normalized_library_files =
   lazy (List.map Filepath.normalize (library_files ()))
 
-let is_library_loc (loc, _) = 
+let is_library_loc (loc, _) =
   List.mem loc.Lexing.pos_fname (Lazy.force normalized_library_files)
 
 let library_functions = Datatype.String.Hashtbl.create 17
-let register_library_function vi = 
+let register_library_function vi =
   Datatype.String.Hashtbl.add library_functions vi.vname vi
 
 let reset () = Datatype.String.Hashtbl.clear library_functions
@@ -69,7 +69,7 @@ let mk_call ~loc ?result fname args =
   in
   let args =
     List.map2
-      (fun (_, ty, _) arg -> 
+      (fun (_, ty, _) arg ->
 	let e =
 	  match ty, Cil.unrollType (Cil.typeOf arg), arg.enode with
 	  | TPtr _, TArray _, Lval lv -> Cil.new_exp ~loc (StartOf lv)
@@ -82,15 +82,15 @@ let mk_call ~loc ?result fname args =
   in
   Cil.mkStmtOneInstr ~valid_sid:true (Call(result, f, args, loc))
 
-type annotation_kind = 
+type annotation_kind =
   | Assertion
   | Precondition
   | Postcondition
   | Invariant
   | RTE
 
-let kind_to_string loc k = 
-  Cil.mkString 
+let kind_to_string loc k =
+  Cil.mkString
     ~loc
     (match k with
     | Assertion -> "Assertion"
@@ -143,44 +143,44 @@ let mk_api_name fname =
   e_acsl_api_prefix ^ fname
 
 let mk_gen_name name =
-  e_acsl_gen_prefix ^ name 
+  e_acsl_gen_prefix ^ name
 
 (* Build a C conditional doing a runtime assertion check. *)
 let mk_e_acsl_guard ?(reverse=false) kind kf e p =
   let loc = p.pred_loc in
-  let msg = 
+  let msg =
     Kernel.Unicode.without_unicode
-      (Format.asprintf "%a@?" Printer.pp_predicate) p 
+      (Format.asprintf "%a@?" Printer.pp_predicate) p
   in
   let line = (fst loc).Lexing.pos_lnum in
-  let e = 
-    if reverse then e else Cil.new_exp ~loc:e.eloc (UnOp(LNot, e, Cil.intType)) 
+  let e =
+    if reverse then e else Cil.new_exp ~loc:e.eloc (UnOp(LNot, e, Cil.intType))
   in
-  mk_call 
-    ~loc 
+  mk_call
+    ~loc
     (mk_api_name "assert")
-    [ e; 
-      kind_to_string loc kind; 
-      Cil.mkString ~loc (get_orig_name kf); 
-      Cil.mkString ~loc msg; 
-      Cil.integer loc line ] 
+    [ e;
+      kind_to_string loc kind;
+      Cil.mkString ~loc (get_orig_name kf);
+      Cil.mkString ~loc msg;
+      Cil.integer loc line ]
 
-let mk_block prj stmt b = 
+let mk_block prj stmt b =
   let mk b = match b.bstmts with
-    | [] -> 
+    | [] ->
       (match stmt.skind with
       | Instr(Skip _) -> stmt
       | _ -> assert false)
-    | [ s ] -> 
-      if Stmt.equal stmt s then s 
-      else 
+    | [ s ] ->
+      if Stmt.equal stmt s then s
+      else
 	(* [JS 2012/10/19] this case exactly corresponds to
 	   __e_acsl_assert(...) when the annotation is associated to a
 	   statement <skip>. Creating a block prevents the printer to add
 	   a stupid unintuitive block *)
 	Cil.mkStmt ~valid_sid:true (Block b)
     |  _ :: _ -> Cil.mkStmt ~valid_sid:true (Block b)
-  in	    
+  in
   Project.on prj mk b
 
 (* ************************************************************************** *)
@@ -188,8 +188,8 @@ let mk_block prj stmt b =
 (* ************************************************************************** *)
 
 let result_lhost kf =
-  let stmt = 
-    try Kernel_function.find_return kf 
+  let stmt =
+    try Kernel_function.find_return kf
     with Kernel_function.No_Statement -> assert false
   in
   match stmt.skind with
@@ -206,11 +206,11 @@ let result_vi kf = match result_lhost kf with
 
 let mk_debug_mmodel_stmt stmt =
   if Options.debug_atleast 1
-    && Options.is_debug_key_enabled Options.dkey_analysis 
+    && Options.is_debug_key_enabled Options.dkey_analysis
   then
     let debug = mk_call ~loc:(Stmt.loc stmt) (mk_api_name "memory_debug") [] in
     Cil.mkStmt ~valid_sid:true (Block (Cil.mkBlock [ stmt; debug]))
-  else 
+  else
     stmt
 
 let mk_full_init_stmt ?(addr=true) vi =
@@ -223,21 +223,21 @@ let mk_full_init_stmt ?(addr=true) vi =
   mk_debug_mmodel_stmt stmt
 
 let mk_initialize ~loc (host, offset as lv) = match host, offset with
-  | Var _, NoOffset -> mk_call ~loc 
+  | Var _, NoOffset -> mk_call ~loc
     (mk_api_name "full_init")
     [ Cil.mkAddrOf ~loc lv ]
-  | _ -> 
+  | _ ->
     let typ = Cil.typeOfLval lv in
-    mk_call ~loc 
+    mk_call ~loc
       (mk_api_name "initialize")
       [ Cil.mkAddrOf ~loc lv; Cil.new_exp loc (SizeOf typ) ]
 
-let mk_store_stmt ?str_size vi =
+let mk_named_store_stmt name ?str_size vi =
   let ty = Cil.unrollType vi.vtype in
   let loc = vi.vdecl in
-  let store = mk_call ~loc (mk_api_name "store_block") in
+  let store = mk_call ~loc (mk_api_name name) in
   let stmt = match ty, str_size with
-    | TArray(_, Some _,_,_), None -> 
+    | TArray(_, Some _,_,_), None ->
       store [ Cil.evar ~loc vi ; Cil.sizeOf ~loc ty ]
     | TPtr(TInt(IChar, _), _), Some size -> store [ Cil.evar ~loc vi ; size ]
     | _, None -> store [ Cil.mkAddrOfVi vi ; Cil.sizeOf ~loc ty ]
@@ -245,12 +245,17 @@ let mk_store_stmt ?str_size vi =
   in
   mk_debug_mmodel_stmt stmt
 
+let mk_store_stmt ?str_size vi =
+  mk_named_store_stmt "store_block" ?str_size vi
+
+let mk_duplicate_store_stmt ?str_size vi =
+  mk_named_store_stmt "store_block_duplicate" ?str_size vi
+
 let mk_delete_stmt vi =
   let loc = vi.vdecl in
   let stmt = match Cil.unrollType vi.vtype with
     | TArray(_, Some _, _, _) ->
       mk_call ~loc (mk_api_name "delete_block") [ Cil.evar ~loc vi ]
-      (*      | Tarray(_, None, _, _)*)
     | _ -> mk_call ~loc (mk_api_name "delete_block") [ Cil.mkAddrOfVi vi ]
   in
   mk_debug_mmodel_stmt stmt
diff --git a/src/plugins/e-acsl/misc.mli b/src/plugins/e-acsl/misc.mli
index e00746e146fcd696323dd285c77eeff15903f753..e9de1d3662c1aae4f9ea27c5e320add1ace87d82 100644
--- a/src/plugins/e-acsl/misc.mli
+++ b/src/plugins/e-acsl/misc.mli
@@ -38,15 +38,15 @@ val mk_call: loc:Location.t -> ?result:lval -> string -> exp list -> stmt
 
 val mk_debug_mmodel_stmt: stmt -> stmt
 
-type annotation_kind = 
+type annotation_kind =
   | Assertion
   | Precondition
   | Postcondition
   | Invariant
   | RTE
 
-val mk_e_acsl_guard: 
-  ?reverse:bool -> annotation_kind -> kernel_function -> exp -> predicate 
+val mk_e_acsl_guard:
+  ?reverse:bool -> annotation_kind -> kernel_function -> exp -> predicate
   -> stmt
 
 val mk_block: Project.t -> stmt -> block -> stmt
@@ -71,6 +71,7 @@ val register_library_function: varinfo -> unit
 val reset: unit -> unit
 
 val mk_store_stmt: ?str_size:exp -> varinfo -> stmt
+val mk_duplicate_store_stmt: ?str_size:exp -> varinfo -> stmt
 val mk_delete_stmt: varinfo -> stmt
 val mk_full_init_stmt: ?addr:bool -> varinfo -> stmt
 val mk_initialize: loc:location -> lval -> stmt
diff --git a/src/plugins/e-acsl/prepare_ast.ml b/src/plugins/e-acsl/prepare_ast.ml
new file mode 100644
index 0000000000000000000000000000000000000000..dbebc4ef421cd7f35c57bd48d3fdd2936788e4bd
--- /dev/null
+++ b/src/plugins/e-acsl/prepare_ast.ml
@@ -0,0 +1,47 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2016                                               *)
+(*    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 license/LGPLv2.1).             *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+
+class prepare_visitor prj = object (_)
+  inherit Visitor.frama_c_copy prj
+
+  method !vstmt_aux _ =
+    Cil.DoChildrenPost (fun stmt ->
+      match stmt.skind with
+      | Switch(_,sw_blk,_,_) ->
+        let new_blk = Cil.mkBlock [ stmt ] in
+        let new_stmt = Cil.mkStmt (Block new_blk) in
+        new_blk.blocals <- sw_blk.blocals;
+        sw_blk.blocals <- [];
+        new_stmt
+      | _ -> stmt)
+
+  initializer
+    Project.copy ~selection:(Parameter_state.get_selection ()) prj
+end
+
+let prepare () =
+  Options.feedback ~level:2 "prepare AST for E-ACSL transformations";
+  File.create_project_from_visitor
+    "e_acsl_prepare_ast"
+    (new prepare_visitor)
diff --git a/src/plugins/e-acsl/prepare_ast.mli b/src/plugins/e-acsl/prepare_ast.mli
new file mode 100644
index 0000000000000000000000000000000000000000..a8c4fed1ee6facfbd7229a4211a2d3477846c779
--- /dev/null
+++ b/src/plugins/e-acsl/prepare_ast.mli
@@ -0,0 +1,29 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C's E-ACSL plug-in.                    *)
+(*                                                                        *)
+(*  Copyright (C) 2012-2016                                               *)
+(*    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 license/LGPLv2.1).             *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Prepare AST for E-ACSL generation.
+ * So for this mudule performs the only task:
+ *  - Move declarations of variables declared in the bodies of switch
+ *    statements to upper scopes.
+*)
+
+val prepare: unit -> Project.t
diff --git a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
index 21985b94e1cd2eca4695e98af06be88476ce5e06..e62516c2fa143a86ea7cc919724857bfa3c95a7b 100644
--- a/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
+++ b/src/plugins/e-acsl/share/e-acsl/bittree_model/e_acsl_bittree_mmodel.c
@@ -314,6 +314,24 @@ static void delete_block(void* ptr) {
     }
   }
 }
+
+static void* store_block_duplicate(void* ptr, size_t size) {
+  bt_block * tmp = NULL;
+  if (ptr != NULL) {
+    bt_block * tmp = bt_lookup(ptr);
+    if (tmp) {
+#ifdef E_ACSL_DEBUG
+    /* Make sure that duplicate block, if so is of the same length */
+    if (tmp->size != size)
+      vabort("Attempt to store duplicate block of different length");
+#endif
+      delete_block(ptr);
+    }
+    store_block(ptr, size);
+  }
+  return tmp;
+}
+
 /* }}} */
 
 /* HEAP ALLOCATION {{{ */
@@ -566,6 +584,7 @@ strong_alias(bittree_aligned_alloc, aligned_alloc)
 /* Explicit tracking */
 public_alias(delete_block)
 public_alias(store_block)
+public_alias(store_block_duplicate)
 /* Predicates */
 public_alias(offset)
 public_alias(base_addr)
diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_mmodel_api.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_mmodel_api.h
index 46a375dc46cf7548137a3ad8ea58c50c09f5b0d8..f19c4294999fd8276c77caa25075c4e87785026a 100644
--- a/src/plugins/e-acsl/share/e-acsl/e_acsl_mmodel_api.h
+++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_mmodel_api.h
@@ -82,6 +82,16 @@ int posix_memalign(void **memptr, size_t alignment, size_t size)
 void * __e_acsl_store_block(void * ptr, size_t size)
   __attribute__((FC_BUILTIN));
 
+/*! \brief Same as `__e_acsl_store_block`, but first check
+ * checks whether a block with a base address given by `ptr` exists in the
+ * tracked allocation and remove it before storing a new block.
+ *
+ * \param ptr base address of the tracked memory block
+ * \param size size of the tracked block in bytes */
+/*@ assigns \result \from *(((char*)ptr)+(0..size-1)); */
+void * __e_acsl_store_block_duplicate(void * ptr, size_t size)
+  __attribute__((FC_BUILTIN));
+
 /*! \brief Remove a memory block which base address is \p ptr from tracking. */
 /*@ assigns \nothing; */
 void __e_acsl_delete_block(void * ptr)
diff --git a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
index a740e1e360c7fd0646467249027c2b6d61182a33..4699f2d81716064a64b8dc1578e6783eb36080dc 100644
--- a/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
+++ b/src/plugins/e-acsl/share/e-acsl/segment_model/e_acsl_segment_mmodel.c
@@ -31,6 +31,7 @@
 #include <sys/resource.h>
 
 static int valid(void * ptr, size_t size);
+static int valid_read(void * ptr, size_t size);
 
 #include "e_acsl_string.h"
 #include "e_acsl_bits.h"
@@ -57,6 +58,13 @@ static void delete_block(void * ptr) {
   shadow_freea(ptr);
 }
 
+static void * store_block_duplicate(void * ptr, size_t size) {
+  if (valid_read(ptr, size))
+    delete_block(ptr);
+  shadow_alloca(ptr, size);
+  return ptr;
+}
+
 static void full_init(void * ptr) {
   initialize(ptr, block_length(ptr));
 }
@@ -180,6 +188,7 @@ strong_alias(shadow_posix_memalign, posix_memalign)
 /* Explicit tracking */
 public_alias(delete_block)
 public_alias(store_block)
+public_alias(store_block_duplicate)
 /* Predicates */
 public_alias2(segment_offset, offset)
 public_alias2(segment_base_addr, base_addr)
diff --git a/src/plugins/e-acsl/tests/bts/bts1740.i b/src/plugins/e-acsl/tests/bts/bts1740.i
new file mode 100644
index 0000000000000000000000000000000000000000..98e99dc7358c69c4d66e322b75829050a4dacb71
--- /dev/null
+++ b/src/plugins/e-acsl/tests/bts/bts1740.i
@@ -0,0 +1,18 @@
+/* run.config
+   COMMENT: bts #1740, about failure to correctly track local variables
+            in presence of goto
+*/
+
+int main(void) {
+  int *p;
+  {
+    int a = 0;
+    p = &a;
+    /*@ assert \valid(p); */
+    goto L;
+  }
+
+ L:
+  /*@ assert ! \valid(p); */
+  return 0;
+}
diff --git a/src/plugins/e-acsl/tests/bts/oracle/bts1740.err.oracle b/src/plugins/e-acsl/tests/bts/oracle/bts1740.err.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/e-acsl/tests/bts/oracle/bts1740.res.oracle b/src/plugins/e-acsl/tests/bts/oracle/bts1740.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..845be00612efea9581746723802617b328a66215
--- /dev/null
+++ b/src/plugins/e-acsl/tests/bts/oracle/bts1740.res.oracle
@@ -0,0 +1,7 @@
+[e-acsl] beginning translation.
+FRAMAC_SHARE/libc/stdlib.h:277:[kernel] warning: No code nor implicit assigns clause for function calloc, generating default assigns from the prototype
+[e-acsl] translation done in project "e-acsl".
+FRAMAC_SHARE/e-acsl/e_acsl.h:43:[value] warning: function __e_acsl_assert: precondition got status unknown.
+tests/bts/bts1740.i:12:[value] warning: locals {a} escaping the scope of a block of main through p
+tests/bts/bts1740.i:16:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&p);
diff --git a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1307.c b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1307.c
index ccf51aabe3e61bb7666fba2f9d1f45dad23d3bdf..65b4060b695afdfc576b001f8caddb3c60b020cf 100644
--- a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1307.c
+++ b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1307.c
@@ -24,15 +24,15 @@ void __gen_e_acsl_foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out);
  */
 void foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out)
 {
-  __e_acsl_store_block((void *)(& Mtmax_in),(size_t)8);
-  __e_acsl_store_block((void *)(& Mwmax),(size_t)8);
   __e_acsl_store_block((void *)(& Mtmax_out),(size_t)8);
+  __e_acsl_store_block((void *)(& Mwmax),(size_t)8);
+  __e_acsl_store_block((void *)(& Mtmax_in),(size_t)8);
   __e_acsl_initialize((void *)Mtmax_out,sizeof(float));
   *Mtmax_out = (float)((double)*Mtmax_in + ((double)5 - (double)((float)(
                                                                  5 / 80) * *Mwmax) * 0.4));
-  __e_acsl_delete_block((void *)(& Mtmax_in));
-  __e_acsl_delete_block((void *)(& Mwmax));
   __e_acsl_delete_block((void *)(& Mtmax_out));
+  __e_acsl_delete_block((void *)(& Mwmax));
+  __e_acsl_delete_block((void *)(& Mtmax_in));
   return;
 }
 
@@ -62,14 +62,14 @@ void __gen_e_acsl_bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out);
  */
 void bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out)
 {
-  __e_acsl_store_block((void *)(& Mtmin_in),(size_t)8);
-  __e_acsl_store_block((void *)(& Mwmin),(size_t)8);
   __e_acsl_store_block((void *)(& Mtmin_out),(size_t)8);
+  __e_acsl_store_block((void *)(& Mwmin),(size_t)8);
+  __e_acsl_store_block((void *)(& Mtmin_in),(size_t)8);
   __e_acsl_initialize((void *)Mtmin_out,sizeof(float));
   *Mtmin_out = (float)(0.85 * (double)*Mwmin);
-  __e_acsl_delete_block((void *)(& Mtmin_in));
-  __e_acsl_delete_block((void *)(& Mwmin));
   __e_acsl_delete_block((void *)(& Mtmin_out));
+  __e_acsl_delete_block((void *)(& Mwmin));
+  __e_acsl_delete_block((void *)(& Mtmin_in));
   return;
 }
 
@@ -120,9 +120,9 @@ void __gen_e_acsl_bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out)
     int __gen_e_acsl_valid;
     int __gen_e_acsl_valid_2;
     int __gen_e_acsl_valid_3;
-    __e_acsl_store_block((void *)(& Mtmin_in),(size_t)8);
-    __e_acsl_store_block((void *)(& Mwmin),(size_t)8);
     __e_acsl_store_block((void *)(& Mtmin_out),(size_t)8);
+    __e_acsl_store_block((void *)(& Mwmin),(size_t)8);
+    __e_acsl_store_block((void *)(& Mtmin_in),(size_t)8);
     __gen_e_acsl_valid = __e_acsl_valid((void *)Mtmin_in,sizeof(float));
     __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"bar",
                     (char *)"\\valid(Mtmin_in)",17);
@@ -190,9 +190,9 @@ void __gen_e_acsl_bar(float *Mtmin_in, float *Mwmin, float *Mtmin_out)
     __e_acsl_assert(__gen_e_acsl_if,(char *)"Postcondition",(char *)"bar",
                     (char *)"*\\old(Mtmin_out) == *\\old(Mtmin_in) < 0.85 * *\\old(Mwmin)?\n  *\\old(Mtmin_in) != 0.:\n  0.85 * *\\old(Mwmin) != 0.",
                     23);
-    __e_acsl_delete_block((void *)(& Mtmin_in));
-    __e_acsl_delete_block((void *)(& Mwmin));
     __e_acsl_delete_block((void *)(& Mtmin_out));
+    __e_acsl_delete_block((void *)(& Mwmin));
+    __e_acsl_delete_block((void *)(& Mtmin_in));
     return;
   }
 }
@@ -216,9 +216,9 @@ void __gen_e_acsl_foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out)
     int __gen_e_acsl_valid;
     int __gen_e_acsl_valid_2;
     int __gen_e_acsl_valid_3;
-    __e_acsl_store_block((void *)(& Mtmax_in),(size_t)8);
-    __e_acsl_store_block((void *)(& Mwmax),(size_t)8);
     __e_acsl_store_block((void *)(& Mtmax_out),(size_t)8);
+    __e_acsl_store_block((void *)(& Mwmax),(size_t)8);
+    __e_acsl_store_block((void *)(& Mtmax_in),(size_t)8);
     __gen_e_acsl_valid = __e_acsl_valid((void *)Mtmax_in,sizeof(float));
     __e_acsl_assert(__gen_e_acsl_valid,(char *)"Precondition",(char *)"foo",
                     (char *)"\\valid(Mtmax_in)",5);
@@ -255,9 +255,9 @@ void __gen_e_acsl_foo(float *Mtmax_in, float *Mwmax, float *Mtmax_out)
                     (char *)"Postcondition",(char *)"foo",
                     (char *)"*\\old(Mtmax_out) == *\\old(Mtmax_in) + (5 - ((5 / 80) * *\\old(Mwmax)) * 0.4)",
                     11);
-    __e_acsl_delete_block((void *)(& Mtmax_in));
-    __e_acsl_delete_block((void *)(& Mwmax));
     __e_acsl_delete_block((void *)(& Mtmax_out));
+    __e_acsl_delete_block((void *)(& Mwmax));
+    __e_acsl_delete_block((void *)(& Mtmax_in));
     return;
   }
 }
diff --git a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c
index eb341729c74ff62536e0b0f39ef1e298608c6bd6..73fe45e9e4e369b1cffed17422d3cd9a3a402ed2 100644
--- a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c
+++ b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c
@@ -20,12 +20,12 @@ void __gen_e_acsl_atp_NORMAL_computeAverageAccel(ArrayInt *Accel,
  */
 void atp_NORMAL_computeAverageAccel(ArrayInt *Accel, int *AverageAccel)
 {
-  __e_acsl_store_block((void *)(& Accel),(size_t)8);
   __e_acsl_store_block((void *)(& AverageAccel),(size_t)8);
+  __e_acsl_store_block((void *)(& Accel),(size_t)8);
   __e_acsl_initialize((void *)AverageAccel,sizeof(int));
   *AverageAccel = (((((*Accel)[4] + (*Accel)[3]) + (*Accel)[2]) + (*Accel)[1]) + (*Accel)[0]) / 5;
-  __e_acsl_delete_block((void *)(& Accel));
   __e_acsl_delete_block((void *)(& AverageAccel));
+  __e_acsl_delete_block((void *)(& Accel));
   return;
 }
 
@@ -71,8 +71,8 @@ void __gen_e_acsl_atp_NORMAL_computeAverageAccel(ArrayInt *Accel,
   ArrayInt *__gen_e_acsl_at_3;
   ArrayInt *__gen_e_acsl_at_2;
   int *__gen_e_acsl_at;
-  __e_acsl_store_block((void *)(& Accel),(size_t)8);
   __e_acsl_store_block((void *)(& AverageAccel),(size_t)8);
+  __e_acsl_store_block((void *)(& Accel),(size_t)8);
   __gen_e_acsl_at_6 = Accel;
   __gen_e_acsl_at_5 = Accel;
   __gen_e_acsl_at_4 = Accel;
@@ -127,8 +127,8 @@ void __gen_e_acsl_atp_NORMAL_computeAverageAccel(ArrayInt *Accel,
                     (char *)"atp_NORMAL_computeAverageAccel",
                     (char *)"*\\old(AverageAccel) ==\n(((((*\\old(Accel))[4] + (*\\old(Accel))[3]) + (*\\old(Accel))[2]) +\n  (*\\old(Accel))[1])\n + (*\\old(Accel))[0])\n/ 5",
                     8);
-    __e_acsl_delete_block((void *)(& Accel));
     __e_acsl_delete_block((void *)(& AverageAccel));
+    __e_acsl_delete_block((void *)(& Accel));
     return;
   }
 }
diff --git a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1740.c b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1740.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d1822a0543584b1951eae377aca95cd6a931aa6
--- /dev/null
+++ b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1740.c
@@ -0,0 +1,62 @@
+/* Generated by Frama-C */
+#include "stdlib.h"
+int main(void)
+{
+  int __retres;
+  int *p;
+  __e_acsl_memory_init((int *)0,(char ***)0,(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
+  {
+    int a;
+    __e_acsl_store_block((void *)(& a),(size_t)4);
+    __e_acsl_full_init((void *)(& a));
+    a = 0;
+    __e_acsl_full_init((void *)(& p));
+    p = & a;
+    /*@ assert \valid(p); */
+    {
+      {
+        int __gen_e_acsl_initialized;
+        int __gen_e_acsl_and;
+        __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
+                                                        sizeof(int *));
+        if (__gen_e_acsl_initialized) {
+          int __gen_e_acsl_valid;
+          __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int));
+          __gen_e_acsl_and = __gen_e_acsl_valid;
+        }
+        else __gen_e_acsl_and = 0;
+        __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",(char *)"main",
+                        (char *)"\\valid(p)",11);
+      }
+    }
+    __e_acsl_delete_block((void *)(& a));
+    goto L;
+    __e_acsl_delete_block((void *)(& a));
+  }
+  L:
+    /*@ assert ¬\valid(p); */
+    {
+      {
+        int __gen_e_acsl_initialized_2;
+        int __gen_e_acsl_and_2;
+        __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_2) {
+          int __gen_e_acsl_valid_2;
+          /*@ assert Value: dangling_pointer: ¬\dangling(&p); */
+          __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(int));
+          __gen_e_acsl_and_2 = __gen_e_acsl_valid_2;
+        }
+        else __gen_e_acsl_and_2 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",
+                        (char *)"main",(char *)"!\\valid(p)",16);
+      }
+    }
+    __retres = 0;
+    __e_acsl_delete_block((void *)(& p));
+    __e_acsl_memory_clean();
+    return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c
index 51bb8fb04b67b3018b4835c3cd33d4a638b5fb4a..96372a88cdf6508baef976d8ab4a3b4ec3bbe0e5 100644
--- a/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c
@@ -38,8 +38,8 @@ void g(int *p, int *q)
   int __gen_e_acsl_at_3;
   int __gen_e_acsl_at_2;
   int __gen_e_acsl_at;
-  __e_acsl_store_block((void *)(& p),(size_t)8);
   __e_acsl_store_block((void *)(& q),(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
   __e_acsl_initialize((void *)p,sizeof(int));
   *p = 0;
   __e_acsl_initialize((void *)(p + 1),sizeof(int));
@@ -96,8 +96,8 @@ void g(int *p, int *q)
                         (char *)"\\at(*(p + \\at(*q,L1)),Here) == 2",28);
       }
     }
-    __e_acsl_delete_block((void *)(& p));
     __e_acsl_delete_block((void *)(& q));
+    __e_acsl_delete_block((void *)(& p));
     return;
 }
 
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_at2.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_at2.c
index 76f52e27256a09e59fb476dc2b3eb6112cd8a397..ad94a8884d509d8203ef082ce8d1bb452759004e 100644
--- a/src/plugins/e-acsl/tests/gmp/oracle/gen_at2.c
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_at2.c
@@ -103,8 +103,8 @@ void g(int *p, int *q)
   int __gen_e_acsl_at_3;
   __e_acsl_mpz_t __gen_e_acsl_at_2;
   int __gen_e_acsl_at;
-  __e_acsl_store_block((void *)(& p),(size_t)8);
   __e_acsl_store_block((void *)(& q),(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
   __e_acsl_initialize((void *)p,sizeof(int));
   *p = 0;
   __e_acsl_initialize((void *)(p + 1),sizeof(int));
@@ -178,8 +178,8 @@ void g(int *p, int *q)
         __gmpz_clear(__gen_e_acsl__4);
       }
     }
-    __e_acsl_delete_block((void *)(& p));
     __e_acsl_delete_block((void *)(& q));
+    __e_acsl_delete_block((void *)(& p));
     __gmpz_clear(__gen_e_acsl_at_2);
     return;
 }
diff --git a/src/plugins/e-acsl/tests/runtime/bypassed_var.c b/src/plugins/e-acsl/tests/runtime/bypassed_var.c
new file mode 100644
index 0000000000000000000000000000000000000000..5201ef5f9cd6a62ba688ec1779d9c91deb5de918
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/bypassed_var.c
@@ -0,0 +1,16 @@
+/* run.config
+   COMMENT: Variable, which declaration is bypassed by a goto jump
+*/
+
+int main(int argc, char const **argv) {
+  goto L;
+  {
+    int *p;
+    L:
+      p = &argc; /* Important to keep this statement here to make sure
+                   initialize is ran after store_block */
+
+    /*@ assert \valid(&p); */
+  }
+  return 0;
+}
diff --git a/src/plugins/e-acsl/tests/runtime/decl_in_switch.c b/src/plugins/e-acsl/tests/runtime/decl_in_switch.c
new file mode 100644
index 0000000000000000000000000000000000000000..4914dfe74a3f67fc2cf0914437a93c4ce020dbc1
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/decl_in_switch.c
@@ -0,0 +1,17 @@
+/* run.config
+   DONTRUN:
+   COMMENT: Variables declared in the body of switch statements so far cannot
+   COMMENT: be tracked
+*/
+
+int main(int argc, char **argv) {
+  switch(argc) {
+    int *p;
+    default: {
+      p = &argc;
+      /*! assert \valid(p); */
+      break;
+    }
+  }
+  return 0;
+}
diff --git a/src/plugins/e-acsl/tests/runtime/early_exit.c b/src/plugins/e-acsl/tests/runtime/early_exit.c
new file mode 100644
index 0000000000000000000000000000000000000000..8dd7631bf598e04a990f8b334eb37c3c641d0520
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/early_exit.c
@@ -0,0 +1,161 @@
+/* run.config
+   COMMENT: test that local variables within a scope are removed from tracking
+            even if the execution exists the scope early via goto, break or
+            continue.
+*/
+
+/* Simple test case from BTS (#1740) */
+int goto_bts() {
+  int *p;
+  {
+    int a = 0;
+    p = &a;
+    /*@ assert \valid(p); */
+    goto L;
+  }
+
+L:
+  /*@ assert ! \valid(p); */
+  return 0;
+}
+
+/* Make sure that when `goto` jumps over several scopes all locals
+ * from those scopes are removed. */
+int goto_valid() {
+  int a = 9;
+  int *p, *q, *r;
+  {
+    int a1 = 0;
+    p = &a1;
+    {
+      int a2 = 0;
+      q = &a2;
+      {
+        int a3 = 0;
+        r = &a3;
+
+        goto FIRST;
+        /* Dead code */
+        p = (void*)0;
+        r = q = &a;
+      }
+    }
+FIRST:
+    /* At this point `a1` is still in scope, while `a2` and `a3` are not, thus
+     * `q` and `r` become invalid, whereas `p` is still valid. */
+    /*@ assert   \valid(p); */
+    /*@ assert ! \valid(q); */
+    /*@ assert ! \valid(r); */
+    /* The following `goto` invalidates `p`. */
+    goto SECOND;
+    /* Dead code */
+    p = r = q = &a;
+  }
+
+SECOND:
+  /*@ assert ! \valid(p); */
+  /*@ assert ! \valid(q); */
+  /*@ assert ! \valid(r); */
+  return 0;
+}
+
+/* Make sure that when a break statement is executed within a switch statement
+ * then all local variables declared within that switch are removed. */
+int switch_valid() {
+  int i = 1;
+  int *p, *q, *s;
+  {
+    s = &i;
+    switch(i) {
+      default: {
+        int a1 = 0;
+        p = &a1;
+        {
+          int a2 = 0;
+          q = &a2;
+          /*@ assert \valid(p); */
+          /*@ assert \valid(q); */
+          /*@ assert \valid(s); */
+          break;
+        }
+        /* Dead code */
+        p = q = &i;
+        s = (void*)0;
+      }
+    }
+    /* Break invalidates `p` and `q` but `s` is still in scope. */
+    /*@ assert ! \valid(q); */
+    /*@ assert ! \valid(p); */
+    /*@ assert \valid(s); */
+  }
+  return 0;
+}
+
+/* Same as switch_valid but for a break statement in a body of a loop. */
+int while_valid() {
+  int *p, *q, *r;
+  int i = 5;
+  {
+    int a0 = 0;
+    r = &a0;
+    while (--i) {
+      {
+        int a1 = 0;
+        p = &a1;
+        {
+          int a2 = 0;
+          q = &a2;
+          /*@ assert \valid(p); */
+          /*@ assert \valid(q); */
+          /*@ assert \valid(r); */
+          if (!i)
+            break;
+        }
+      }
+    }
+    /*@ assert ! \valid(p); */
+    /*@ assert ! \valid(q); */
+    /*@ assert   \valid(r); */
+  }
+  return 0;
+}
+
+/* Make sure that when `continue` is executed then local variables in scope
+ * are not recorded twice. */
+void continue_valid() {
+  int i = 0;
+  int *p, *q, *r;
+
+  while (i++) {
+    /*@ assert ! \valid(p); */
+    /*@ assert ! \valid(q); */
+    int a1 = 1;
+    p = &a1;
+
+    /*@ assert \valid(p); */
+    /*@ assert ! \valid(q); */
+
+    {
+      int a2 = 1;
+      q = &a2;
+      /*@ assert \valid(p); */
+      /*@ assert \valid(q); */
+      continue;
+    }
+
+    if (i == 5)
+      break;
+  }
+
+  /*@ assert ! \valid(p); */
+  /*@ assert ! \valid(q); */
+}
+
+int main(int argc, const char *argv[]) {
+  goto_bts();
+  goto_valid();
+  switch_valid();
+  while_valid();
+  continue_valid();
+  return 0;
+}
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/bypassed_var.err.oracle b/src/plugins/e-acsl/tests/runtime/oracle/bypassed_var.err.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/bypassed_var.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/bypassed_var.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..a0a8836bb7a329fc53da2da239850fee8b952dde
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/bypassed_var.res.oracle
@@ -0,0 +1,4 @@
+[e-acsl] beginning translation.
+FRAMAC_SHARE/libc/stdlib.h:277:[kernel] warning: No code nor implicit assigns clause for function calloc, generating default assigns from the prototype
+[e-acsl] translation done in project "e-acsl".
+FRAMAC_SHARE/e-acsl/e_acsl.h:43:[value] warning: function __e_acsl_assert: precondition got status unknown.
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/decl_in_switch.err.oracle b/src/plugins/e-acsl/tests/runtime/oracle/decl_in_switch.err.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/decl_in_switch.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/decl_in_switch.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c33737e3cac6e74853111a99a2a4002b6a9d7094
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/decl_in_switch.res.oracle
@@ -0,0 +1,3 @@
+[e-acsl] beginning translation.
+FRAMAC_SHARE/libc/stdlib.h:276:[kernel] warning: No code nor implicit assigns clause for function calloc, generating default assigns from the prototype
+[e-acsl] translation done in project "e-acsl".
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/early_exit.err.oracle b/src/plugins/e-acsl/tests/runtime/oracle/early_exit.err.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/early_exit.res.oracle b/src/plugins/e-acsl/tests/runtime/oracle/early_exit.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..5c4f44cb7b170063e9201f3c9e7ecf22654ddd38
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/early_exit.res.oracle
@@ -0,0 +1,35 @@
+[e-acsl] beginning translation.
+FRAMAC_SHARE/libc/stdlib.h:277:[kernel] warning: No code nor implicit assigns clause for function calloc, generating default assigns from the prototype
+[e-acsl] translation done in project "e-acsl".
+FRAMAC_SHARE/e-acsl/e_acsl.h:43:[value] warning: function __e_acsl_assert: precondition got status unknown.
+tests/runtime/early_exit.c:14:[value] warning: locals {a} escaping the scope of a block of goto_bts through p
+tests/runtime/early_exit.c:18:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&p);
+tests/runtime/early_exit.c:37:[value] warning: locals {a2} escaping the scope of a block of goto_valid through q
+tests/runtime/early_exit.c:37:[value] warning: locals {a3} escaping the scope of a block of goto_valid through r
+tests/runtime/early_exit.c:47:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&q);
+tests/runtime/early_exit.c:48:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&r);
+tests/runtime/early_exit.c:50:[value] warning: locals {a1} escaping the scope of a block of goto_valid through p
+tests/runtime/early_exit.c:56:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&p);
+tests/runtime/early_exit.c:57:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&q);
+tests/runtime/early_exit.c:58:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&r);
+tests/runtime/early_exit.c:79:[value] warning: locals {a1} escaping the scope of a block of switch_valid through p
+tests/runtime/early_exit.c:79:[value] warning: locals {a2} escaping the scope of a block of switch_valid through q
+tests/runtime/early_exit.c:87:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&q);
+tests/runtime/early_exit.c:88:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&p);
+tests/runtime/early_exit.c:103:[value] warning: locals {a1} escaping the scope of a block of while_valid through p
+tests/runtime/early_exit.c:103:[value] warning: locals {a2} escaping the scope of a block of while_valid through q
+tests/runtime/early_exit.c:116:[value] warning: accessing uninitialized left-value. assert \initialized(&p);
+tests/runtime/early_exit.c:116:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&p);
+tests/runtime/early_exit.c:117:[value] warning: accessing uninitialized left-value. assert \initialized(&q);
+tests/runtime/early_exit.c:117:[value] warning: accessing left-value that contains escaping addresses.
+                 assert ¬\dangling(&q);
+tests/runtime/early_exit.c:99:[value] warning: locals {a0} escaping the scope of a block of while_valid through r
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e1c554bd6a8077d99a6847b795e72bf054eb0fe
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_bypassed_var.c
@@ -0,0 +1,32 @@
+/* Generated by Frama-C */
+#include "stdlib.h"
+int main(int argc, char const **argv)
+{
+  int __retres;
+  __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8);
+  __e_acsl_store_block((void *)(& argc),(size_t)4);
+  goto L;
+  {
+    int *p;
+    __e_acsl_store_block((void *)(& p),(size_t)8);
+    L: __e_acsl_store_block_duplicate((void *)(& p),(size_t)8);
+    __e_acsl_full_init((void *)(& p));
+    p = & argc;
+    /*@ assert \valid(&p); */
+    {
+      {
+        int __gen_e_acsl_valid;
+        __gen_e_acsl_valid = __e_acsl_valid((void *)(& p),sizeof(int *));
+        __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",
+                        (char *)"main",(char *)"\\valid(&p)",13);
+        __e_acsl_delete_block((void *)(& p));
+      }
+    }
+  }
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& argc));
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_decl_in_switch.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_decl_in_switch.c
new file mode 100644
index 0000000000000000000000000000000000000000..15d0281d5ae0b4dc878a687bc8131e19bc4aecae
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_decl_in_switch.c
@@ -0,0 +1,24 @@
+/* Generated by Frama-C */
+int main(int argc, char **argv)
+{
+  int __retres;
+  __e_acsl_memory_init(& argc,& argv,8UL);
+  __e_acsl_store_block((void *)(& argc),4UL);
+  {
+    int *p;
+    __e_acsl_store_block((void *)(& p),8UL);
+    switch (argc) {
+      default: ;
+      __e_acsl_full_init((void *)(& p));
+      p = & argc;
+      break;
+    }
+    __e_acsl_delete_block((void *)(& p));
+  }
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& argc));
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_early_exit.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_early_exit.c
new file mode 100644
index 0000000000000000000000000000000000000000..897f45cce1a73daec858774c05a5077571ab97e6
--- /dev/null
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_early_exit.c
@@ -0,0 +1,753 @@
+/* Generated by Frama-C */
+#include "stdlib.h"
+int goto_bts(void)
+{
+  int __retres;
+  int *p;
+  __e_acsl_store_block((void *)(& p),(size_t)8);
+  {
+    int a;
+    __e_acsl_store_block((void *)(& a),(size_t)4);
+    __e_acsl_full_init((void *)(& a));
+    a = 0;
+    __e_acsl_full_init((void *)(& p));
+    p = & a;
+    /*@ assert \valid(p); */
+    {
+      {
+        int __gen_e_acsl_initialized;
+        int __gen_e_acsl_and;
+        __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
+                                                        sizeof(int *));
+        if (__gen_e_acsl_initialized) {
+          int __gen_e_acsl_valid;
+          __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int));
+          __gen_e_acsl_and = __gen_e_acsl_valid;
+        }
+        else __gen_e_acsl_and = 0;
+        __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",
+                        (char *)"goto_bts",(char *)"\\valid(p)",13);
+      }
+    }
+    __e_acsl_delete_block((void *)(& a));
+    goto L;
+    __e_acsl_delete_block((void *)(& a));
+  }
+  L:
+    /*@ assert ¬\valid(p); */
+    {
+      {
+        int __gen_e_acsl_initialized_2;
+        int __gen_e_acsl_and_2;
+        __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& p),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_2) {
+          int __gen_e_acsl_valid_2;
+          /*@ assert Value: dangling_pointer: ¬\dangling(&p); */
+          __gen_e_acsl_valid_2 = __e_acsl_valid((void *)p,sizeof(int));
+          __gen_e_acsl_and_2 = __gen_e_acsl_valid_2;
+        }
+        else __gen_e_acsl_and_2 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",
+                        (char *)"goto_bts",(char *)"!\\valid(p)",18);
+      }
+    }
+    __retres = 0;
+    __e_acsl_delete_block((void *)(& p));
+    return __retres;
+}
+
+int goto_valid(void)
+{
+  int __retres;
+  int a;
+  int *p;
+  int *q;
+  int *r;
+  __e_acsl_store_block((void *)(& r),(size_t)8);
+  __e_acsl_store_block((void *)(& q),(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
+  a = 9;
+  {
+    int a1;
+    __e_acsl_store_block((void *)(& a1),(size_t)4);
+    __e_acsl_full_init((void *)(& a1));
+    a1 = 0;
+    __e_acsl_full_init((void *)(& p));
+    p = & a1;
+    {
+      int a2;
+      __e_acsl_store_block((void *)(& a2),(size_t)4);
+      __e_acsl_full_init((void *)(& a2));
+      a2 = 0;
+      __e_acsl_full_init((void *)(& q));
+      q = & a2;
+      {
+        int a3;
+        __e_acsl_store_block((void *)(& a3),(size_t)4);
+        __e_acsl_full_init((void *)(& a3));
+        a3 = 0;
+        __e_acsl_full_init((void *)(& r));
+        r = & a3;
+        __e_acsl_delete_block((void *)(& a2));
+        __e_acsl_delete_block((void *)(& a3));
+        goto FIRST;
+        __e_acsl_full_init((void *)(& p));
+        p = (int *)0;
+        { /* sequence */
+          __e_acsl_full_init((void *)(& q));
+          q = & a;
+          __e_acsl_full_init((void *)(& r));
+          r = q;
+        }
+        __e_acsl_delete_block((void *)(& a3));
+        __e_acsl_delete_block((void *)(& a2));
+      }
+    }
+    FIRST:
+      /*@ assert \valid(p); */
+      {
+        {
+          int __gen_e_acsl_initialized;
+          int __gen_e_acsl_and;
+          __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
+                                                          sizeof(int *));
+          if (__gen_e_acsl_initialized) {
+            int __gen_e_acsl_valid;
+            __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int));
+            __gen_e_acsl_and = __gen_e_acsl_valid;
+          }
+          else __gen_e_acsl_and = 0;
+          __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",
+                          (char *)"goto_valid",(char *)"\\valid(p)",46);
+        }
+      }
+      /*@ assert ¬\valid(q); */
+      {
+        {
+          int __gen_e_acsl_initialized_2;
+          int __gen_e_acsl_and_2;
+          __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q),
+                                                            sizeof(int *));
+          if (__gen_e_acsl_initialized_2) {
+            int __gen_e_acsl_valid_2;
+            /*@ assert Value: dangling_pointer: ¬\dangling(&q); */
+            __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int));
+            __gen_e_acsl_and_2 = __gen_e_acsl_valid_2;
+          }
+          else __gen_e_acsl_and_2 = 0;
+          __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",
+                          (char *)"goto_valid",(char *)"!\\valid(q)",47);
+        }
+      }
+      /*@ assert ¬\valid(r); */
+      {
+        {
+          int __gen_e_acsl_initialized_3;
+          int __gen_e_acsl_and_3;
+          __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& r),
+                                                            sizeof(int *));
+          if (__gen_e_acsl_initialized_3) {
+            int __gen_e_acsl_valid_3;
+            /*@ assert Value: dangling_pointer: ¬\dangling(&r); */
+            __gen_e_acsl_valid_3 = __e_acsl_valid((void *)r,sizeof(int));
+            __gen_e_acsl_and_3 = __gen_e_acsl_valid_3;
+          }
+          else __gen_e_acsl_and_3 = 0;
+          __e_acsl_assert(! __gen_e_acsl_and_3,(char *)"Assertion",
+                          (char *)"goto_valid",(char *)"!\\valid(r)",48);
+        }
+      }
+      __e_acsl_delete_block((void *)(& a1));
+      goto SECOND;
+    { /* sequence */
+      __e_acsl_full_init((void *)(& q));
+      q = & a;
+      __e_acsl_full_init((void *)(& r));
+      r = q;
+      __e_acsl_full_init((void *)(& p));
+      p = r;
+    }
+    __e_acsl_delete_block((void *)(& a1));
+  }
+  SECOND:
+    /*@ assert ¬\valid(p); */
+    {
+      {
+        int __gen_e_acsl_initialized_4;
+        int __gen_e_acsl_and_4;
+        __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& p),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_4) {
+          int __gen_e_acsl_valid_4;
+          /*@ assert Value: dangling_pointer: ¬\dangling(&p); */
+          __gen_e_acsl_valid_4 = __e_acsl_valid((void *)p,sizeof(int));
+          __gen_e_acsl_and_4 = __gen_e_acsl_valid_4;
+        }
+        else __gen_e_acsl_and_4 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion",
+                        (char *)"goto_valid",(char *)"!\\valid(p)",56);
+      }
+    }
+    /*@ assert ¬\valid(q); */
+    {
+      {
+        int __gen_e_acsl_initialized_5;
+        int __gen_e_acsl_and_5;
+        __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& q),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_5) {
+          int __gen_e_acsl_valid_5;
+          /*@ assert Value: dangling_pointer: ¬\dangling(&q); */
+          __gen_e_acsl_valid_5 = __e_acsl_valid((void *)q,sizeof(int));
+          __gen_e_acsl_and_5 = __gen_e_acsl_valid_5;
+        }
+        else __gen_e_acsl_and_5 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion",
+                        (char *)"goto_valid",(char *)"!\\valid(q)",57);
+      }
+    }
+    /*@ assert ¬\valid(r); */
+    {
+      {
+        int __gen_e_acsl_initialized_6;
+        int __gen_e_acsl_and_6;
+        __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& r),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_6) {
+          int __gen_e_acsl_valid_6;
+          /*@ assert Value: dangling_pointer: ¬\dangling(&r); */
+          __gen_e_acsl_valid_6 = __e_acsl_valid((void *)r,sizeof(int));
+          __gen_e_acsl_and_6 = __gen_e_acsl_valid_6;
+        }
+        else __gen_e_acsl_and_6 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_6,(char *)"Assertion",
+                        (char *)"goto_valid",(char *)"!\\valid(r)",58);
+      }
+    }
+    __retres = 0;
+    __e_acsl_delete_block((void *)(& r));
+    __e_acsl_delete_block((void *)(& q));
+    __e_acsl_delete_block((void *)(& p));
+    return __retres;
+}
+
+int switch_valid(void)
+{
+  int __retres;
+  int i;
+  int *p;
+  int *q;
+  int *s;
+  __e_acsl_store_block((void *)(& s),(size_t)8);
+  __e_acsl_store_block((void *)(& q),(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
+  __e_acsl_store_block((void *)(& i),(size_t)4);
+  __e_acsl_full_init((void *)(& i));
+  i = 1;
+  __e_acsl_full_init((void *)(& s));
+  s = & i;
+  switch (i) {
+    default: ;
+    {
+      int a1;
+      __e_acsl_store_block((void *)(& a1),(size_t)4);
+      __e_acsl_full_init((void *)(& a1));
+      a1 = 0;
+      __e_acsl_full_init((void *)(& p));
+      p = & a1;
+      {
+        int a2;
+        __e_acsl_store_block((void *)(& a2),(size_t)4);
+        __e_acsl_full_init((void *)(& a2));
+        a2 = 0;
+        __e_acsl_full_init((void *)(& q));
+        q = & a2;
+        /*@ assert \valid(p); */
+        {
+          {
+            int __gen_e_acsl_initialized;
+            int __gen_e_acsl_and;
+            __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
+                                                            sizeof(int *));
+            if (__gen_e_acsl_initialized) {
+              int __gen_e_acsl_valid;
+              __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int));
+              __gen_e_acsl_and = __gen_e_acsl_valid;
+            }
+            else __gen_e_acsl_and = 0;
+            __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",
+                            (char *)"switch_valid",(char *)"\\valid(p)",76);
+          }
+        }
+        /*@ assert \valid(q); */
+        {
+          {
+            int __gen_e_acsl_initialized_2;
+            int __gen_e_acsl_and_2;
+            __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q),
+                                                              sizeof(int *));
+            if (__gen_e_acsl_initialized_2) {
+              int __gen_e_acsl_valid_2;
+              __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int));
+              __gen_e_acsl_and_2 = __gen_e_acsl_valid_2;
+            }
+            else __gen_e_acsl_and_2 = 0;
+            __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",
+                            (char *)"switch_valid",(char *)"\\valid(q)",77);
+          }
+        }
+        /*@ assert \valid(s); */
+        {
+          {
+            int __gen_e_acsl_initialized_3;
+            int __gen_e_acsl_and_3;
+            __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& s),
+                                                              sizeof(int *));
+            if (__gen_e_acsl_initialized_3) {
+              int __gen_e_acsl_valid_3;
+              __gen_e_acsl_valid_3 = __e_acsl_valid((void *)s,sizeof(int));
+              __gen_e_acsl_and_3 = __gen_e_acsl_valid_3;
+            }
+            else __gen_e_acsl_and_3 = 0;
+            __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",
+                            (char *)"switch_valid",(char *)"\\valid(s)",78);
+          }
+        }
+        __e_acsl_delete_block((void *)(& a1));
+        __e_acsl_delete_block((void *)(& a2));
+        break;
+        __e_acsl_delete_block((void *)(& a2));
+      }
+      { /* sequence */
+        __e_acsl_full_init((void *)(& q));
+        q = & i;
+        __e_acsl_full_init((void *)(& p));
+        p = q;
+      }
+      __e_acsl_full_init((void *)(& s));
+      s = (int *)0;
+      __e_acsl_delete_block((void *)(& a1));
+    }
+  }
+  /*@ assert ¬\valid(q); */
+  {
+    {
+      int __gen_e_acsl_initialized_4;
+      int __gen_e_acsl_and_4;
+      __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& q),
+                                                        sizeof(int *));
+      if (__gen_e_acsl_initialized_4) {
+        int __gen_e_acsl_valid_4;
+        /*@ assert Value: dangling_pointer: ¬\dangling(&q); */
+        __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(int));
+        __gen_e_acsl_and_4 = __gen_e_acsl_valid_4;
+      }
+      else __gen_e_acsl_and_4 = 0;
+      __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion",
+                      (char *)"switch_valid",(char *)"!\\valid(q)",87);
+    }
+  }
+  /*@ assert ¬\valid(p); */
+  {
+    {
+      int __gen_e_acsl_initialized_5;
+      int __gen_e_acsl_and_5;
+      __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p),
+                                                        sizeof(int *));
+      if (__gen_e_acsl_initialized_5) {
+        int __gen_e_acsl_valid_5;
+        /*@ assert Value: dangling_pointer: ¬\dangling(&p); */
+        __gen_e_acsl_valid_5 = __e_acsl_valid((void *)p,sizeof(int));
+        __gen_e_acsl_and_5 = __gen_e_acsl_valid_5;
+      }
+      else __gen_e_acsl_and_5 = 0;
+      __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion",
+                      (char *)"switch_valid",(char *)"!\\valid(p)",88);
+    }
+  }
+  /*@ assert \valid(s); */
+  {
+    {
+      int __gen_e_acsl_initialized_6;
+      int __gen_e_acsl_and_6;
+      __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& s),
+                                                        sizeof(int *));
+      if (__gen_e_acsl_initialized_6) {
+        int __gen_e_acsl_valid_6;
+        __gen_e_acsl_valid_6 = __e_acsl_valid((void *)s,sizeof(int));
+        __gen_e_acsl_and_6 = __gen_e_acsl_valid_6;
+      }
+      else __gen_e_acsl_and_6 = 0;
+      __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",
+                      (char *)"switch_valid",(char *)"\\valid(s)",89);
+    }
+  }
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& s));
+  __e_acsl_delete_block((void *)(& q));
+  __e_acsl_delete_block((void *)(& p));
+  __e_acsl_delete_block((void *)(& i));
+  return __retres;
+}
+
+int while_valid(void)
+{
+  int __retres;
+  int *p;
+  int *q;
+  int *r;
+  int i;
+  __e_acsl_store_block((void *)(& r),(size_t)8);
+  __e_acsl_store_block((void *)(& q),(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
+  i = 5;
+  {
+    int a0;
+    __e_acsl_store_block((void *)(& a0),(size_t)4);
+    __e_acsl_full_init((void *)(& a0));
+    a0 = 0;
+    __e_acsl_full_init((void *)(& r));
+    r = & a0;
+    while (1) {
+      i --;
+      if (! i) break;
+      {
+        int a1;
+        __e_acsl_store_block((void *)(& a1),(size_t)4);
+        __e_acsl_full_init((void *)(& a1));
+        a1 = 0;
+        __e_acsl_full_init((void *)(& p));
+        p = & a1;
+        {
+          int a2;
+          __e_acsl_store_block((void *)(& a2),(size_t)4);
+          __e_acsl_full_init((void *)(& a2));
+          a2 = 0;
+          __e_acsl_full_init((void *)(& q));
+          q = & a2;
+          /*@ assert \valid(p); */
+          {
+            {
+              int __gen_e_acsl_initialized;
+              int __gen_e_acsl_and;
+              __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
+                                                              sizeof(int *));
+              if (__gen_e_acsl_initialized) {
+                int __gen_e_acsl_valid;
+                __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int));
+                __gen_e_acsl_and = __gen_e_acsl_valid;
+              }
+              else __gen_e_acsl_and = 0;
+              __e_acsl_assert(__gen_e_acsl_and,(char *)"Assertion",
+                              (char *)"while_valid",(char *)"\\valid(p)",108);
+            }
+          }
+          /*@ assert \valid(q); */
+          {
+            {
+              int __gen_e_acsl_initialized_2;
+              int __gen_e_acsl_and_2;
+              __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q),
+                                                                sizeof(int *));
+              if (__gen_e_acsl_initialized_2) {
+                int __gen_e_acsl_valid_2;
+                __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int));
+                __gen_e_acsl_and_2 = __gen_e_acsl_valid_2;
+              }
+              else __gen_e_acsl_and_2 = 0;
+              __e_acsl_assert(__gen_e_acsl_and_2,(char *)"Assertion",
+                              (char *)"while_valid",(char *)"\\valid(q)",109);
+            }
+          }
+          /*@ assert \valid(r); */
+          {
+            {
+              int __gen_e_acsl_initialized_3;
+              int __gen_e_acsl_and_3;
+              __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& r),
+                                                                sizeof(int *));
+              if (__gen_e_acsl_initialized_3) {
+                int __gen_e_acsl_valid_3;
+                __gen_e_acsl_valid_3 = __e_acsl_valid((void *)r,sizeof(int));
+                __gen_e_acsl_and_3 = __gen_e_acsl_valid_3;
+              }
+              else __gen_e_acsl_and_3 = 0;
+              __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",
+                              (char *)"while_valid",(char *)"\\valid(r)",110);
+            }
+          }
+          if (! i) {
+            __e_acsl_delete_block((void *)(& a1));
+            __e_acsl_delete_block((void *)(& a2));
+            break;
+          }
+          __e_acsl_delete_block((void *)(& a2));
+          __e_acsl_delete_block((void *)(& a1));
+        }
+      }
+    }
+    /*@ assert ¬\valid(p); */
+    {
+      {
+        int __gen_e_acsl_initialized_4;
+        int __gen_e_acsl_and_4;
+        __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& p),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_4) {
+          int __gen_e_acsl_valid_4;
+          /*@ assert Value: initialisation: \initialized(&p); */
+          /*@ assert Value: dangling_pointer: ¬\dangling(&p); */
+          __gen_e_acsl_valid_4 = __e_acsl_valid((void *)p,sizeof(int));
+          __gen_e_acsl_and_4 = __gen_e_acsl_valid_4;
+        }
+        else __gen_e_acsl_and_4 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion",
+                        (char *)"while_valid",(char *)"!\\valid(p)",116);
+      }
+    }
+    /*@ assert ¬\valid(q); */
+    {
+      {
+        int __gen_e_acsl_initialized_5;
+        int __gen_e_acsl_and_5;
+        __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& q),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_5) {
+          int __gen_e_acsl_valid_5;
+          /*@ assert Value: initialisation: \initialized(&q); */
+          /*@ assert Value: dangling_pointer: ¬\dangling(&q); */
+          __gen_e_acsl_valid_5 = __e_acsl_valid((void *)q,sizeof(int));
+          __gen_e_acsl_and_5 = __gen_e_acsl_valid_5;
+        }
+        else __gen_e_acsl_and_5 = 0;
+        __e_acsl_assert(! __gen_e_acsl_and_5,(char *)"Assertion",
+                        (char *)"while_valid",(char *)"!\\valid(q)",117);
+      }
+    }
+    /*@ assert \valid(r); */
+    {
+      {
+        int __gen_e_acsl_initialized_6;
+        int __gen_e_acsl_and_6;
+        __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& r),
+                                                          sizeof(int *));
+        if (__gen_e_acsl_initialized_6) {
+          int __gen_e_acsl_valid_6;
+          __gen_e_acsl_valid_6 = __e_acsl_valid((void *)r,sizeof(int));
+          __gen_e_acsl_and_6 = __gen_e_acsl_valid_6;
+        }
+        else __gen_e_acsl_and_6 = 0;
+        __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",
+                        (char *)"while_valid",(char *)"\\valid(r)",118);
+        __e_acsl_delete_block((void *)(& a0));
+      }
+    }
+  }
+  __retres = 0;
+  __e_acsl_delete_block((void *)(& r));
+  __e_acsl_delete_block((void *)(& q));
+  __e_acsl_delete_block((void *)(& p));
+  return __retres;
+}
+
+void continue_valid(void)
+{
+  int i;
+  int *p;
+  int *q;
+  __e_acsl_store_block((void *)(& q),(size_t)8);
+  __e_acsl_store_block((void *)(& p),(size_t)8);
+  i = 0;
+  while (1) {
+    int tmp;
+    { /* sequence */
+      tmp = i;
+      i ++;
+      ;
+    }
+    if (! tmp) break;
+    {
+      int a1;
+      __e_acsl_store_block((void *)(& a1),(size_t)4);
+      /*@ assert ¬\valid(p); */
+      {
+        {
+          int __gen_e_acsl_initialized;
+          int __gen_e_acsl_and;
+          __gen_e_acsl_initialized = __e_acsl_initialized((void *)(& p),
+                                                          sizeof(int *));
+          if (__gen_e_acsl_initialized) {
+            int __gen_e_acsl_valid;
+            __gen_e_acsl_valid = __e_acsl_valid((void *)p,sizeof(int));
+            __gen_e_acsl_and = __gen_e_acsl_valid;
+          }
+          else __gen_e_acsl_and = 0;
+          __e_acsl_assert(! __gen_e_acsl_and,(char *)"Assertion",
+                          (char *)"continue_valid",(char *)"!\\valid(p)",130);
+        }
+      }
+      /*@ assert ¬\valid(q); */
+      {
+        {
+          int __gen_e_acsl_initialized_2;
+          int __gen_e_acsl_and_2;
+          __gen_e_acsl_initialized_2 = __e_acsl_initialized((void *)(& q),
+                                                            sizeof(int *));
+          if (__gen_e_acsl_initialized_2) {
+            int __gen_e_acsl_valid_2;
+            __gen_e_acsl_valid_2 = __e_acsl_valid((void *)q,sizeof(int));
+            __gen_e_acsl_and_2 = __gen_e_acsl_valid_2;
+          }
+          else __gen_e_acsl_and_2 = 0;
+          __e_acsl_assert(! __gen_e_acsl_and_2,(char *)"Assertion",
+                          (char *)"continue_valid",(char *)"!\\valid(q)",131);
+        }
+      }
+      __e_acsl_full_init((void *)(& a1));
+      a1 = 1;
+      __e_acsl_full_init((void *)(& p));
+      p = & a1;
+      /*@ assert \valid(p); */
+      {
+        {
+          int __gen_e_acsl_initialized_3;
+          int __gen_e_acsl_and_3;
+          __gen_e_acsl_initialized_3 = __e_acsl_initialized((void *)(& p),
+                                                            sizeof(int *));
+          if (__gen_e_acsl_initialized_3) {
+            int __gen_e_acsl_valid_3;
+            __gen_e_acsl_valid_3 = __e_acsl_valid((void *)p,sizeof(int));
+            __gen_e_acsl_and_3 = __gen_e_acsl_valid_3;
+          }
+          else __gen_e_acsl_and_3 = 0;
+          __e_acsl_assert(__gen_e_acsl_and_3,(char *)"Assertion",
+                          (char *)"continue_valid",(char *)"\\valid(p)",135);
+        }
+      }
+      /*@ assert ¬\valid(q); */
+      {
+        {
+          int __gen_e_acsl_initialized_4;
+          int __gen_e_acsl_and_4;
+          __gen_e_acsl_initialized_4 = __e_acsl_initialized((void *)(& q),
+                                                            sizeof(int *));
+          if (__gen_e_acsl_initialized_4) {
+            int __gen_e_acsl_valid_4;
+            __gen_e_acsl_valid_4 = __e_acsl_valid((void *)q,sizeof(int));
+            __gen_e_acsl_and_4 = __gen_e_acsl_valid_4;
+          }
+          else __gen_e_acsl_and_4 = 0;
+          __e_acsl_assert(! __gen_e_acsl_and_4,(char *)"Assertion",
+                          (char *)"continue_valid",(char *)"!\\valid(q)",136);
+        }
+      }
+      {
+        int a2;
+        __e_acsl_store_block((void *)(& a2),(size_t)4);
+        __e_acsl_full_init((void *)(& a2));
+        a2 = 1;
+        __e_acsl_full_init((void *)(& q));
+        q = & a2;
+        /*@ assert \valid(p); */
+        {
+          {
+            int __gen_e_acsl_initialized_5;
+            int __gen_e_acsl_and_5;
+            __gen_e_acsl_initialized_5 = __e_acsl_initialized((void *)(& p),
+                                                              sizeof(int *));
+            if (__gen_e_acsl_initialized_5) {
+              int __gen_e_acsl_valid_5;
+              __gen_e_acsl_valid_5 = __e_acsl_valid((void *)p,sizeof(int));
+              __gen_e_acsl_and_5 = __gen_e_acsl_valid_5;
+            }
+            else __gen_e_acsl_and_5 = 0;
+            __e_acsl_assert(__gen_e_acsl_and_5,(char *)"Assertion",
+                            (char *)"continue_valid",(char *)"\\valid(p)",
+                            141);
+          }
+        }
+        /*@ assert \valid(q); */
+        {
+          {
+            int __gen_e_acsl_initialized_6;
+            int __gen_e_acsl_and_6;
+            __gen_e_acsl_initialized_6 = __e_acsl_initialized((void *)(& q),
+                                                              sizeof(int *));
+            if (__gen_e_acsl_initialized_6) {
+              int __gen_e_acsl_valid_6;
+              __gen_e_acsl_valid_6 = __e_acsl_valid((void *)q,sizeof(int));
+              __gen_e_acsl_and_6 = __gen_e_acsl_valid_6;
+            }
+            else __gen_e_acsl_and_6 = 0;
+            __e_acsl_assert(__gen_e_acsl_and_6,(char *)"Assertion",
+                            (char *)"continue_valid",(char *)"\\valid(q)",
+                            142);
+          }
+        }
+        __e_acsl_delete_block((void *)(& a1));
+        __e_acsl_delete_block((void *)(& a2));
+        continue;
+        __e_acsl_delete_block((void *)(& a2));
+      }
+      if (i == 5) {
+        __e_acsl_delete_block((void *)(& a1));
+        break;
+      }
+      __e_acsl_delete_block((void *)(& a1));
+    }
+  }
+  /*@ assert ¬\valid(p); */
+  {
+    {
+      int __gen_e_acsl_initialized_7;
+      int __gen_e_acsl_and_7;
+      __gen_e_acsl_initialized_7 = __e_acsl_initialized((void *)(& p),
+                                                        sizeof(int *));
+      if (__gen_e_acsl_initialized_7) {
+        int __gen_e_acsl_valid_7;
+        __gen_e_acsl_valid_7 = __e_acsl_valid((void *)p,sizeof(int));
+        __gen_e_acsl_and_7 = __gen_e_acsl_valid_7;
+      }
+      else __gen_e_acsl_and_7 = 0;
+      __e_acsl_assert(! __gen_e_acsl_and_7,(char *)"Assertion",
+                      (char *)"continue_valid",(char *)"!\\valid(p)",150);
+    }
+  }
+  /*@ assert ¬\valid(q); */
+  {
+    {
+      int __gen_e_acsl_initialized_8;
+      int __gen_e_acsl_and_8;
+      __gen_e_acsl_initialized_8 = __e_acsl_initialized((void *)(& q),
+                                                        sizeof(int *));
+      if (__gen_e_acsl_initialized_8) {
+        int __gen_e_acsl_valid_8;
+        __gen_e_acsl_valid_8 = __e_acsl_valid((void *)q,sizeof(int));
+        __gen_e_acsl_and_8 = __gen_e_acsl_valid_8;
+      }
+      else __gen_e_acsl_and_8 = 0;
+      __e_acsl_assert(! __gen_e_acsl_and_8,(char *)"Assertion",
+                      (char *)"continue_valid",(char *)"!\\valid(q)",151);
+    }
+  }
+  __e_acsl_delete_block((void *)(& q));
+  __e_acsl_delete_block((void *)(& p));
+  return;
+}
+
+int main(int argc, char const **argv)
+{
+  int __retres;
+  __e_acsl_memory_init(& argc,(char ***)(& argv),(size_t)8);
+  goto_bts();
+  goto_valid();
+  switch_valid();
+  while_valid();
+  continue_valid();
+  __retres = 0;
+  __e_acsl_memory_clean();
+  return __retres;
+}
+
+
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c
index 765047ff16e0e909eb56009920a832a684b0e1c1..3e2f38a1e00738a66d4de878512397bbfb618c57 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_mainargs.c
@@ -10,8 +10,8 @@ int main(int argc, char **argv)
   {
     {
       int __gen_e_acsl_valid;
-      __e_acsl_store_block((void *)(& argc),(size_t)4);
       __e_acsl_store_block((void *)(& argv),(size_t)8);
+      __e_acsl_store_block((void *)(& argc),(size_t)4);
       __gen_e_acsl_valid = __e_acsl_valid((void *)(& argc),sizeof(int));
       __e_acsl_assert(__gen_e_acsl_valid,(char *)"Assertion",(char *)"main",
                       (char *)"\\valid(&argc)",10);
@@ -185,8 +185,8 @@ int main(int argc, char **argv)
     i ++;
   }
   __retres = 0;
-  __e_acsl_delete_block((void *)(& argc));
   __e_acsl_delete_block((void *)(& argv));
+  __e_acsl_delete_block((void *)(& argc));
   __e_acsl_memory_clean();
   return __retres;
 }
diff --git a/src/plugins/e-acsl/visit.ml b/src/plugins/e-acsl/visit.ml
index dc9997ed37d194ff5427f6819e16a43de98bdcec..3924bdcb7e46c82bd90df9458537622d5468fb95 100644
--- a/src/plugins/e-acsl/visit.ml
+++ b/src/plugins/e-acsl/visit.ml
@@ -26,28 +26,6 @@ open Cil_datatype
 
 let dkey = Options.dkey_translation
 
-let allocate_function env kf =
-  List.fold_left
-    (fun env vi -> 
-      if Mmodel_analysis.must_model_vi ~kf vi then
-        let vi = Cil.get_varinfo (Env.get_behavior env) vi in
-        Env.add_stmt env (Misc.mk_store_stmt vi)
-      else
-        env)
-    env
-    (Kernel_function.get_formals kf)
-
-let deallocate_function env kf  = 
-  List.fold_left
-    (fun env vi -> 
-      if Mmodel_analysis.must_model_vi ~kf vi then 
-        let vi = Cil.get_varinfo (Env.get_behavior env) vi in
-        Env.add_stmt env (Misc.mk_delete_stmt vi)
-      else
-        env)
-    env
-    (Kernel_function.get_formals kf)
-
 (* ************************************************************************** *)
 (* Visitor *)
 (* ************************************************************************** *)
@@ -57,10 +35,71 @@ let function_env = ref Env.dummy
 let dft_funspec = Cil.empty_funspec ()
 let funspec = ref dft_funspec
 
+(* extend the environment with statements which allocate/deallocate memory
+   blocks *)
+module Memory: sig
+  val store: ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t
+  val duplicate_store:
+    ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t
+  val delete_from_list:
+    ?before:stmt -> Env.t -> kernel_function -> varinfo list -> Env.t
+  val delete_from_set:
+    ?before:stmt -> Env.t -> kernel_function -> Varinfo.Set.t -> Env.t
+end = struct
+
+  let tracking_stmt ?before fold mk_stmt env kf vars =
+    fold
+      (fun vi env ->
+        if Mmodel_analysis.must_model_vi ~kf vi then
+          let vi = Cil.get_varinfo (Env.get_behavior env) vi in
+          Env.add_stmt ?before env (mk_stmt vi)
+        else
+          env)
+      vars
+      env
+
+  let store ?before env kf vars =
+    tracking_stmt
+      ?before
+      List.fold_right (* small list *)
+      Misc.mk_store_stmt
+      env
+      kf
+      vars
+
+  let duplicate_store ?before env kf vars =
+    tracking_stmt
+      ?before
+      Varinfo.Set.fold
+      Misc.mk_duplicate_store_stmt
+      env
+      kf
+      vars
+
+  let delete_from_list ?before env kf vars =
+    tracking_stmt
+      ?before
+      List.fold_right (* small list *)
+      Misc.mk_delete_stmt
+      env
+      kf
+      vars
+
+  let delete_from_set ?before env kf vars =
+    tracking_stmt
+      ?before
+      Varinfo.Set.fold
+      Misc.mk_delete_stmt
+      env
+      kf
+      vars
+
+end
+
 (* the main visitor performing e-acsl checking and C code generator *)
 class e_acsl_visitor prj generate = object (self)
 
-  inherit Visitor.generic_frama_c_visitor 
+  inherit Visitor.generic_frama_c_visitor
     (if generate then Cil.copy_visit prj else Cil.inplace_visit ())
 
   val mutable main_fct = None
@@ -246,7 +285,8 @@ class e_acsl_visitor prj generate = object (self)
                   f.globals <- new_globals
                 | None ->
                   Kernel.warning "@[no entry point specified:@ \
-you must call function `__e_acsl_memory_init` by yourself.@]";
+you must call function `%s' and `__e_acsl_memory_clean by yourself.@]"
+                    fname;
                   f.globals <- f.globals @ [ cil_fct ]
             in
             Project.on prj build_initializer ()
@@ -327,7 +367,7 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
            see bts #1392 *)
         if vi.vstorage <> Extern then
           vi.vghost <- false
-      | _ -> 
+      | _ ->
         ()
     in
     (match g with
@@ -391,33 +431,35 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
     f.sbody.blocals <- blocks
 
   method !vfunc f =
-    if generate then
+    if generate then begin
+      Exit_points.generate f;
       let kf = Extlib.the self#current_kf in
-      Options.feedback ~dkey ~level:2 "entering in function %a." 
+      Options.feedback ~dkey ~level:2 "entering in function %a."
         Kernel_function.pretty kf;
       List.iter (fun vi -> vi.vghost <- false) f.slocals;
-      Cil.DoChildrenPost 
-        (fun f -> 
-          self#add_generated_variables_in_function f; 
+      Cil.DoChildrenPost
+        (fun f ->
+          Exit_points.clear ();
+          self#add_generated_variables_in_function f;
           Options.feedback ~dkey ~level:2 "function %a done."
             Kernel_function.pretty kf;
           f)
-    else
+    end else
       Cil.DoChildren
 
-  method private is_return old_kf stmt = 
-    let old_ret = 
+  method private is_return old_kf stmt =
+    let old_ret =
       try Kernel_function.find_return old_kf
       with Kernel_function.No_Statement -> assert false
     in
     Stmt.equal stmt (Cil.get_stmt self#behavior old_ret)
 
   method private is_first_stmt old_kf stmt =
-    try 
+    try
       Stmt.equal
-        (Cil.get_original_stmt self#behavior stmt) 
+        (Cil.get_original_stmt self#behavior stmt)
         (Kernel_function.find_first_stmt old_kf)
-    with Kernel_function.No_Statement -> 
+    with Kernel_function.No_Statement ->
       assert false
 
   method private is_main old_kf =
@@ -427,7 +469,7 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
     with Globals.No_such_entry_point _s ->
       (* [JS 2013/05/21] already a warning in pre-analysis *)
       (*      Options.warning ~once:true "%s@ \
-              @[The generated program may be incomplete.@]" 
+              @[The generated program may be incomplete.@]"
               s;*)
       false
 
@@ -462,14 +504,14 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
            Literal_strings.add s vi;
            env_ref := env;
            Cil.ChangeTo exp)
-      | _ -> 
+      | _ ->
         Cil.DoChildren
     end in
     let e = Cil.visitCilExpr o e in
     e, !env_ref
 
   method !vstmt_aux stmt =
-    Options.debug ~level:4 "proceeding stmt (sid %d) %a@." 
+    Options.debug ~level:4 "proceeding stmt (sid %d) %a@."
       stmt.sid Stmt.pretty stmt;
     let kf = Extlib.the self#current_kf in
     let is_main = self#is_main kf in
@@ -478,10 +520,13 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
       | Loop _ -> Env.push_loop env
       | _ -> env
     in
-    let env = 
+    let env =
       if self#is_first_stmt kf stmt then
         (* JS: should be done in the new project? *)
-        let env = if generate then allocate_function env kf else env in
+        let env =
+          if generate then Memory.store env kf (Kernel_function.get_formals kf)
+          else env
+        in
         (* translate the precondition of the function *)
         if Dup_functions.is_generated (Extlib.the self#current_kf) then
           Project.on prj (Translate.translate_pre_spec kf Kglobal env) !funspec
@@ -490,25 +535,37 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
       else
         env
     in
+
     let env, new_annots =
       Annotations.fold_code_annot
-        (fun _ old_a (env, new_annots) -> 
+        (fun _ old_a (env, new_annots) ->
           let a =
             (* [VP] Don't use Visitor here, as it will fill the queue in the
                middle of the computation... *)
             Cil.visitCilCodeAnnotation (self :> Cil.cilVisitor) old_a
           in
-          let env = 
+          let env =
             Project.on
               prj
               (Translate.translate_pre_code_annotation kf stmt env)
-              a 
+              a
           in
           env, a :: new_annots)
         (Cil.get_original_stmt self#behavior stmt)
         (env, [])
     in
+
+    (* Add [__e_acsl_store_duplicate] calls for local variables which
+     * declarations are bypassed by gotos. Note: should be done before
+     * [vinst] method (which adds initializers) is executed, otherwise
+     * init calls appear before store calls. *)
+    let duplicates = Exit_points.store_vars stmt in
+    let env =
+      if generate then Memory.duplicate_store ~before:stmt env kf duplicates
+      else env
+    in
     function_env := env;
+
     let mk_block stmt =
       (* be careful: since this function is called in a post action, [env] has
          been modified from the time where pre actions have been executed.
@@ -524,39 +581,50 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
           env
       in
       let mk_post_env env =
-        (* [fold_right] to preserve order of generation of pre_conditions *) 
+        (* [fold_right] to preserve order of generation of pre_conditions *)
         Project.on
           prj
           (List.fold_right
-             (fun a env -> 
+             (fun a env ->
                Translate.translate_post_code_annotation kf stmt env a)
              new_annots)
           env
       in
       (* handle loop invariants *)
       let new_stmt, env, must_mv = Loops.preserve_invariant prj env kf stmt in
-      let new_stmt, env = 
-        if self#is_return kf stmt then 
+      let new_stmt, env =
+        (* Remove local variables which scopes ended via goto/break/continue. *)
+        let del_vars = Exit_points.delete_vars stmt in
+        let env =
+          if generate then Memory.delete_from_set ~before:stmt env kf del_vars
+          else env
+        in
+        if self#is_return kf stmt then
           (* must generate the post_block before including [stmt] (the 'return')
              since no code is executed after it. However, since this statement
              is pure (Cil invariant), that is semantically correct. *)
           let env = mk_post_env env in
           (* also handle the postcondition of the function and clear the env *)
-          let env = 
+          let env =
             if Dup_functions.is_generated (Extlib.the self#current_kf) then
               Project.on
                 prj
-                (Translate.translate_post_spec kf Kglobal env) 
-                !funspec 
+                (Translate.translate_post_spec kf Kglobal env)
+                !funspec
             else
               env
           in
           (* de-allocating memory previously allocating by the kf *)
           (* JS: should be done in the new project? *)
           if generate then
-            let env = deallocate_function env kf in
-            let b, env = 
-              Env.pop_and_get env new_stmt ~global_clear:true Env.After 
+            (* Remove recorded function arguments *)
+            let fargs = Kernel_function.get_formals kf in
+            let env =
+              if generate then Memory.delete_from_list env kf fargs
+              else env
+            in
+            let b, env =
+              Env.pop_and_get env new_stmt ~global_clear:true Env.After
             in
             if is_main && Mmodel_analysis.use_model () then begin
               let stmts = b.bstmts in
@@ -627,8 +695,8 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
       | Var vi, NoOffset -> vi.vglob || vi.vformal
       | _ -> false
     in
-(*    Options.feedback "%a? %a (%b && %b)" 
-      Printer.pp_lval assigned_lv 
+(*    Options.feedback "%a? %a (%b && %b)"
+      Printer.pp_lval assigned_lv
       Printer.pp_lval checked_lv
       (not (may_safely_ignore assigned_lv))
       (Pre_analysis.must_model_lval ~kf ~stmt checked_lv);*)
@@ -649,10 +717,10 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
   method !vinst = function
   | Set(old_lv, _, _) ->
     if generate then
-      Cil.DoChildrenPost 
-        (function 
-        | [ Set(new_lv, _, loc) ] as l -> 
-          self#add_initializer loc old_lv new_lv; 
+      Cil.DoChildrenPost
+        (function
+        | [ Set(new_lv, _, loc) ] as l ->
+          self#add_initializer loc old_lv new_lv;
           l
         | _ -> assert false)
     else
@@ -661,9 +729,9 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
     if not generate || Misc.is_generated_kf (Extlib.the self#current_kf) then
       Cil.DoChildren
     else
-      Cil.DoChildrenPost 
-        (function 
-        | [ Call(Some new_ret, _, _, loc) ] as l -> 
+      Cil.DoChildrenPost
+        (function
+        | [ Call(Some new_ret, _, _, loc) ] as l ->
           self#add_initializer loc old_ret new_ret;
           l
         | _ -> assert false)
@@ -671,7 +739,7 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
     Cil.DoChildren
 
   method !vblock blk =
-    let handle_memory new_blk = 
+    let handle_memory new_blk =
       match new_blk.blocals with
       | [] -> new_blk
       | _ :: _ ->
@@ -690,7 +758,7 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
           | { skind = Return _ } as ret :: ((potential_clean :: tl) as l) ->
             (* keep the return (enclosed in a generated block) at the end;
                preceded by clean if any *)
-            let init, tl = 
+            let init, tl =
               if self#is_main kf && Mmodel_analysis.use_model () then
                 [ potential_clean; ret ], tl
               else
@@ -698,15 +766,15 @@ you must call function `__e_acsl_memory_init` by yourself.@]";
             in
             blk.bstmts <-
               List.fold_left (fun acc v -> v :: acc) (add_locals init) tl
-          | { skind = Block b } :: _ -> 
+          | { skind = Block b } :: _ ->
             insert_in_innermost_last_block b (List.rev b.bstmts)
-          | l -> blk.bstmts <- 
+          | l -> blk.bstmts <-
             List.fold_left (fun acc v -> v :: acc) (add_locals []) l
         in
         insert_in_innermost_last_block new_blk (List.rev new_blk.bstmts);
         new_blk.bstmts <-
           List.fold_left
-          (fun acc vi -> 
+          (fun acc vi ->
             if Mmodel_analysis.must_model_vi vi then
               let vi = Cil.get_varinfo self#behavior vi in
               Misc.mk_store_stmt vi :: acc
@@ -764,11 +832,11 @@ end
 let do_visit ?(prj=Project.current ()) generate =
   (* The main visitor proceeds by tracking declarations belonging to the
      E-ACSL runtime library and then using these declarations to generate
-     statements used in instrumentation. The following code reorders AST 
-     so declarations belonging to E-ACSL library appear atop of any location 
+     statements used in instrumentation. The following code reorders AST
+     so declarations belonging to E-ACSL library appear atop of any location
      requiring instrumentation. *)
-  Misc.reorder_ast ();  
-  Options.feedback ~level:2 "%s annotations in %a." 
+  Misc.reorder_ast ();
+  Options.feedback ~level:2 "%s annotations in %a."
     (if generate then "translating" else "checking")
     Project.pretty prj;
   let vis =