diff --git a/src/plugins/value/domains/abstract_domain.mli b/src/plugins/value/domains/abstract_domain.mli
index 8a05da1655898d95dbf049af9504cd5472e5206f..06dfe5a14d785e2beacf3e3c0cb524f5bca8ba6f 100644
--- a/src/plugins/value/domains/abstract_domain.mli
+++ b/src/plugins/value/domains/abstract_domain.mli
@@ -272,18 +272,23 @@ type 'state logic_environment = {
   result: varinfo option;
 }
 
+type variable_kind =
+  | Global                     (** Global variable. *)
+  | Formal of kernel_function  (** Formal parameter of a function. *)
+  | Local of kernel_function   (** Local variable of a function. *)
+  | Result of kernel_function  (** Special variable storing the return value
+                                   of a call. Assigned at the end of the called
+                                   function, and used at the call site. Also
+                                   used to model the ACSL \result construct. *)
+
 (** Value for the initialization of variables. Can be either zero or top. *)
 type init_value = Zero | Top
 
-(* Kind of variable being initialized by initialize_variable_using_type. *)
-type init_kind =
-    Main_Formal | Library_Global | Spec_Return of kernel_function
-
 (** MemExec is a global cache for the complete analysis of functions.
     It avoids repeating the analysis of a function in equivalent entry states.
     It uses an over-approximation of the locations possibly read and written
     by a function, and compare the entry states for these locations. *)
-module type Recycle = sig
+module type Reuse = sig
   type t (** Type of states. *)
 
   (** [relate kf bases state] returns the set of bases [bases] in relation with
@@ -371,31 +376,28 @@ module type S = sig
   val reduce_by_predicate:
     state logic_environment -> state -> predicate -> bool -> state or_bottom
 
-  (** {3 Miscellaneous } *)
+  (** {3 Scoping and initialization } *)
 
   (** Scoping: abstract transformers for entering and exiting blocks.
-      [kf] is the englobing function, and the variables of the list [vars]
-      should be added or removed from the abstract state here.
-      Note that the formals of a function enter the scope through the transfer
-      function {!Transfer.start_call}, but leave it through a
-      call to {!leave_scope}. *)
-  val enter_scope: kernel_function -> varinfo list -> t -> t
+      The variables should be added or removed from the abstract state here.
+      Note that the formals of a called function enter the scope through the
+      transfer function {!start_call}, and leave it through a call to
+      {!leave_scope}. *)
+
+  (** Introduces a list of variables in the state. At this point, the variables
+      are uninitialized. Globals and formals of the 'main' will be initialized
+      by {!initialize_variable} and {!initialize_variable_using_type}. Local
+      variables remain uninitialized until an assignment through {!assign}.
+      The formal parameters of a call enter the scope through {!start_call}. *)
+  val enter_scope: variable_kind -> varinfo list -> t -> t
+
+  (** Removes a list of local and formal variables from the state.
+      The first argument is the englobing function. *)
   val leave_scope: kernel_function -> varinfo list -> t -> t
 
-  val enter_loop: stmt -> state -> state
-  val incr_loop_counter: stmt -> state -> state
-  val leave_loop: stmt -> state -> state
-
-  (** Initialization *)
-
   (** The initial state with which the analysis start. *)
   val empty: unit -> t
 
-  (** Introduces the list of global variables in the state.  At this point,
-      these variables are uninitialized: they will be initialized through the
-      two functions below.*)
-  val introduce_globals: varinfo list -> t -> t
-
   (** [initialize_variable lval loc ~initialized init_value state] initializes
       the value of the location [loc] of lvalue [lval] in [state] with:
       – bits 0 if init_value = Zero;
@@ -405,11 +407,22 @@ module type S = sig
   val initialize_variable:
     lval -> location -> initialized:bool -> init_value -> t -> t
 
-  (** Initializes a variable according to its type. TODO: move some parts
-      of the cvalue implementation of this function in the generic engine. *)
-  val initialize_variable_using_type: init_kind -> varinfo -> t -> t
+  (** Initializes a variable according to its type.
+      The variable can be:
+      - a global variable on lib-entry mode.
+      - a formal parameter of the 'main' function.
+      - the return variable of a function specification. *)
+  (* TODO: move some parts of the cvalue implementation of this function
+     in the generic engine. *)
+  val initialize_variable_using_type: variable_kind -> varinfo -> t -> t
+
+  (** {3 Miscellaneous } *)
+
+  val enter_loop: stmt -> state -> state
+  val incr_loop_counter: stmt -> state -> state
+  val leave_loop: stmt -> state -> state
 
-  include Recycle with type t := t
+  include Reuse with type t := t
 
   (** Category for the messages about the domain.
       Must be created through {!Value_parameters.register_category}. *)
diff --git a/src/plugins/value/domains/apron/apron_domain.ml b/src/plugins/value/domains/apron/apron_domain.ml
index 09ecaf05ded71c5ed74445d1625d74915edc7081..228a52c2079280e1e86448bd7f2236ef208ce735 100644
--- a/src/plugins/value/domains/apron/apron_domain.ml
+++ b/src/plugins/value/domains/apron/apron_domain.ml
@@ -679,24 +679,12 @@ module Make (Man : Input) = struct
 
   let empty () = top
 
-  let introduce_globals vars state = enter_scope vars state
-
-  let enter_scope _kf vars state = enter_scope vars state
+  let enter_scope _kind vars state = enter_scope vars state
 
   let initialize_variable _lval _loc ~initialized:_ _init_value state = state
 
-  let initialize_variable_using_type _kind varinfo state =
-    try
-      let var = translate_varinfo varinfo in
-      let env = Abstract1.env state in
-      if Environment.mem_var env var
-      then state
-      else
-        let env = Environment.add env [|var|] [||] in
-        let state = Abstract1.change_environment man state env false in
-        constraint_to_typ env state [(var, varinfo)]
-    with
-    | Out_of_Scope _ -> state
+  (* TODO: use constraint_to_type? *)
+  let initialize_variable_using_type _kind _varinfo state = state
 
   let relate _ _ _ = Base.SetLattice.top
   let filter _ _ _ state = state
diff --git a/src/plugins/value/domains/cvalue/cvalue_domain.ml b/src/plugins/value/domains/cvalue/cvalue_domain.ml
index 13142d74dcbfad8306ad66a7e6189f9e81200f9f..67eab080499f68a2f4336a21b9a833b5279aab22 100644
--- a/src/plugins/value/domains/cvalue/cvalue_domain.ml
+++ b/src/plugins/value/domains/cvalue/cvalue_domain.ml
@@ -322,15 +322,6 @@ module State = struct
   (*                             Initialization                               *)
   (* ------------------------------------------------------------------------ *)
 
-  let introduce_globals vars (state, clob) =
-    let introduce state varinfo =
-      let base = Base.of_varinfo varinfo in
-      let loc = Locations.loc_of_base base in
-      let value = Cvalue.V_Or_Uninitialized.uninitialized in
-      Model.add_indeterminate_binding ~exact:true state loc value
-    in
-    List.fold_left introduce state vars, clob
-
   let initialize_variable  _lval loc ~initialized init_value (state, clob) =
     let value = match init_value with
       | Abstract_domain.Top  -> Cvalue.V.top_int
@@ -371,10 +362,9 @@ module State = struct
 
   let initialize_variable_using_type kind varinfo (state, clob) =
     match kind with
-    | Abstract_domain.Main_Formal
-    | Abstract_domain.Library_Global ->
+    | Abstract_domain.(Global | Formal _ | Local _) ->
       Cvalue_init.initialize_var_using_type varinfo state, clob
-    | Abstract_domain.Spec_Return kf ->
+    | Abstract_domain.Result kf ->
       let value = Library_functions.returned_value kf in
       let loc = Locations.loc_of_varinfo varinfo in
       Model.add_binding ~exact:true state loc value, clob
@@ -383,21 +373,32 @@ module State = struct
   (*                                  Misc                                    *)
   (* ------------------------------------------------------------------------ *)
 
-  let enter_scope _kf vars (state, clob) =
-    let bind_local state vi =
-      let b = Base.of_varinfo vi in
-      let offsm =
-        if Value_parameters.InitializedLocals.get () then
-          let v = Cvalue.(V_Or_Uninitialized.initialized V.top_int) in
-          match Cvalue.V_Offsetmap.size_from_validity (Base.validity b) with
-          | `Bottom -> assert false
-          | `Value size -> Cvalue.V_Offsetmap.create_isotropic ~size v
-        else
-          Bottom.non_bottom (Cvalue.Default_offsetmap.default_offsetmap b)
-      in
-      Model.add_base b offsm state
+  let bind_local state vi =
+    let b = Base.of_varinfo vi in
+    let offsm =
+      if Value_parameters.InitializedLocals.get () then
+        let v = Cvalue.(V_Or_Uninitialized.initialized V.top_int) in
+        match Cvalue.V_Offsetmap.size_from_validity (Base.validity b) with
+        | `Bottom -> assert false
+        | `Value size -> Cvalue.V_Offsetmap.create_isotropic ~size v
+      else
+        Bottom.non_bottom (Cvalue.Default_offsetmap.default_offsetmap b)
+    in
+    Model.add_base b offsm state
+
+  let bind_global state varinfo =
+    let base = Base.of_varinfo varinfo in
+    let loc = Locations.loc_of_base base in
+    let value = Cvalue.V_Or_Uninitialized.uninitialized in
+    Model.add_indeterminate_binding ~exact:true state loc value
+
+  let enter_scope kind vars (state, clob) =
+    let bind =
+      match kind with
+      | Abstract_domain.Global -> bind_global
+      | Abstract_domain.(Local _ | Formal _ | Result _)  -> bind_local
     in
-    List.fold_left bind_local state vars, clob
+    List.fold_left bind state vars, clob
 
   let leave_scope kf vars (state, clob) =
     let state = Model.remove_variables vars state in
diff --git a/src/plugins/value/domains/domain_builder.ml b/src/plugins/value/domains/domain_builder.ml
index ae604a6b2b0a9d2b111991a4b586d80df49f1115..ebeab1fb6a2a86043e77fe44a01ff9b1a27ef3cd 100644
--- a/src/plugins/value/domains/domain_builder.ml
+++ b/src/plugins/value/domains/domain_builder.ml
@@ -73,7 +73,7 @@ module Make_Minimal
   let extract_expr _oracle _state _expr = top_answer
   let extract_lval _oracle _state _lval _typ _location = top_answer
   let backward_location _state _lval _typ location value = `Value (location, value)
-  let reduce_further _sttae _expr _value = []
+  let reduce_further _state _expr _value = []
 
   let update _valuation state = `Value state
 
@@ -100,7 +100,6 @@ module Make_Minimal
 
   let initialize_variable_using_type _kind varinfo state =
     let lval = Cil.var varinfo in
-    let state = introduce_globals [varinfo] state in
     Domain.initialize_variable lval ~initialized:true Abstract_domain.Top state
 
   let logic_assign _assigns _location ~pre:_ _state = top
@@ -235,7 +234,6 @@ module Complete_Simple_Cvalue (Domain: Simpler_domains.Simple_Cvalue)
 
     let initialize_variable_using_type _kind varinfo state =
       let lval = Cil.var varinfo in
-      let state = introduce_globals [varinfo] state in
       Domain.initialize_variable lval ~initialized:true Abstract_domain.Top state
 
     let logic_assign _assigns _location ~pre:_ _state = top
diff --git a/src/plugins/value/domains/domain_lift.ml b/src/plugins/value/domains/domain_lift.ml
index 4aff78893455842c47ad75e696d3b179aaa77c1f..8d264722a108824d17a64ac725f3cecfc6bd7713 100644
--- a/src/plugins/value/domains/domain_lift.ml
+++ b/src/plugins/value/domains/domain_lift.ml
@@ -137,11 +137,9 @@ module Make
   let leave_loop = Domain.leave_loop
 
   let empty = Domain.empty
-  let introduce_globals = Domain.introduce_globals
   let initialize_variable lval loc ~initialized init_value state =
     let loc = Convert.restrict_loc loc in
     Domain.initialize_variable lval loc ~initialized init_value state
-
   let initialize_variable_using_type = Domain.initialize_variable_using_type
 
   let relate = Domain.relate
diff --git a/src/plugins/value/domains/domain_product.ml b/src/plugins/value/domains/domain_product.ml
index 5f9d14b4397089916514467667cdbe4bb1ef82b4..5dd265a91b888e10bb49749433674b65cef6de10 100644
--- a/src/plugins/value/domains/domain_product.ml
+++ b/src/plugins/value/domains/domain_product.ml
@@ -256,8 +256,8 @@ module Make
     Right.reduce_by_predicate right_env right pred positive >>-: fun right ->
     left, right
 
-  let enter_scope kf vars (left, right) =
-    Left.enter_scope kf vars left, Right.enter_scope kf vars right
+  let enter_scope kind vars (left, right) =
+    Left.enter_scope kind vars left, Right.enter_scope kind vars right
   let leave_scope kf vars (left, right) =
     Left.leave_scope kf vars left, Right.leave_scope kf vars right
 
@@ -269,8 +269,6 @@ module Make
     Left.leave_loop stmt left, Right.leave_loop stmt right
 
   let empty () = Left.empty (), Right.empty ()
-  let introduce_globals vars (left, right) =
-    Left.introduce_globals vars left, Right.introduce_globals vars right
   let initialize_variable lval loc ~initialized init_value (left, right) =
     Left.initialize_variable lval loc ~initialized init_value left,
     Right.initialize_variable lval loc ~initialized init_value right
diff --git a/src/plugins/value/domains/equality/equality_domain.ml b/src/plugins/value/domains/equality/equality_domain.ml
index 9407df3145acd07c7720396fd5201a2c27309a2f..c6d87d30f888e9c09609bb91ce39875369f9c145 100644
--- a/src/plugins/value/domains/equality/equality_domain.ml
+++ b/src/plugins/value/domains/equality/equality_domain.ml
@@ -511,7 +511,7 @@ module Make
   let evaluate_predicate _ _ _ = Alarmset.Unknown
   let reduce_by_predicate _ state _ _ = `Value state
 
-  let enter_scope _kf _vars state = state
+  let enter_scope _kind _vars state = state
   let leave_scope _kf vars state = unscope state vars
 
   let enter_loop _ state = state
@@ -519,7 +519,6 @@ module Make
   let leave_loop _ state = state
 
   let empty () = empty
-  let introduce_globals _vars state = state
   let initialize_variable _ _ ~initialized:_ _ state = state
   let initialize_variable_using_type _ _ state  = state
 
diff --git a/src/plugins/value/domains/gauges/gauges_domain.ml b/src/plugins/value/domains/gauges/gauges_domain.ml
index 5c892c9e22580ec5d8efe251d826e6637d599269..240fedb691b190bf53e2c2cc78a9c3e61d90a4df 100644
--- a/src/plugins/value/domains/gauges/gauges_domain.ml
+++ b/src/plugins/value/domains/gauges/gauges_domain.ml
@@ -1141,7 +1141,7 @@ module D_Impl : Abstract_domain.S
 
   let pretty = G.pretty
 
-  let enter_scope _kf _vars state =
+  let enter_scope _kind _vars state =
     state (* default is Top, nothing to do *)
 
   let remove_variables vars (state:state) =
@@ -1292,7 +1292,6 @@ module D_Impl : Abstract_domain.S
   let reuse _kf _bases ~current_input:_ ~previous_output = previous_output
 
   (* Initial state *)
-  let introduce_globals _ state = state
   let initialize_variable_using_type _ _ state = state
   let initialize_variable _ _ ~initialized:_ _ state = state
 
diff --git a/src/plugins/value/domains/inout_domain.ml b/src/plugins/value/domains/inout_domain.ml
index b34535306a3b0b05c5dba5bc892f52592547dac7..000941e666bddcacbdc13211447291196891a97d 100644
--- a/src/plugins/value/domains/inout_domain.ml
+++ b/src/plugins/value/domains/inout_domain.ml
@@ -223,7 +223,7 @@ module Internal
   let name = "inout"
   let log_category = Value_parameters.register_category "d-inout"
 
-  let enter_scope _kf _vars state = state
+  let enter_scope _kind _vars state = state
   let leave_scope _kf vars state = Transfer.remove_variables vars state
 
   let to_z valuation lv =
@@ -257,7 +257,6 @@ module Internal
 
   (* Initial state. Initializers are singletons, so we store nothing. *)
   let empty () = LatticeInout.empty
-  let introduce_globals _vars state = state
   let initialize_variable _ _ ~initialized:_ _ state = state
   let initialize_variable_using_type _ _ state  = state
 
diff --git a/src/plugins/value/domains/octagons.ml b/src/plugins/value/domains/octagons.ml
index fae7d982ebcea2eda03670255d94a9a0a03350ce..4249c66e0ef5230a97916246a43486dacd51c412 100644
--- a/src/plugins/value/domains/octagons.ml
+++ b/src/plugins/value/domains/octagons.ml
@@ -1244,7 +1244,7 @@ module Domain = struct
   let evaluate_predicate _env _state _pred = Alarmset.Unknown
   let reduce_by_predicate _env state _pred _positive = `Value state
 
-  let enter_scope _kf _varinfos state = state
+  let enter_scope _kind _varinfos state = state
   let leave_scope _kf varinfos state =
     let state = List.fold_left State.remove state varinfos in
     check "leave_scope" state
@@ -1253,7 +1253,6 @@ module Domain = struct
   let incr_loop_counter _stmt state = state
   let leave_loop _stmt state = state
 
-  let introduce_globals _varinfos state = state
   let initialize_variable _lval _location ~initialized:_ _value state = state
   let initialize_variable_using_type _kind _varinfo state = state
 
diff --git a/src/plugins/value/domains/offsm_domain.ml b/src/plugins/value/domains/offsm_domain.ml
index 2809ade3ffa86d3af14817a0de035bb7d6daeee0..c02f00d3972cb678cb6eb78cd18314198a57bb99 100644
--- a/src/plugins/value/domains/offsm_domain.ml
+++ b/src/plugins/value/domains/offsm_domain.ml
@@ -109,7 +109,7 @@ module Internal  : Domain_builder.InputDomain
 
   let empty _ = Memory.empty_map
 
-  let enter_scope _kf _vars state = state (* default is Top, nothing to do *)
+  let enter_scope _kind _vars state = state (* default is Top, nothing to do *)
   let leave_scope _kf vars state =
     Memory.remove_variables vars state
 
@@ -212,7 +212,6 @@ module Internal  : Domain_builder.InputDomain
     state
 
   (* Initial state *)
-  let introduce_globals _ state = state
   let initialize_variable_using_type _ _ state = state
   let initialize_variable _ _ ~initialized:_ _ state = state
 
diff --git a/src/plugins/value/domains/printer_domain.ml b/src/plugins/value/domains/printer_domain.ml
index 6e77dfe64e77dc709f991386cd8cbc65199cc2a1..330c4cde1a0ebb451c88ff227c3fe83242046f59 100644
--- a/src/plugins/value/domains/printer_domain.ml
+++ b/src/plugins/value/domains/printer_domain.ml
@@ -110,18 +110,14 @@ module Simple : Simpler_domains.Simple_Cvalue = struct
     feedback "empty";
     ()
 
-  let introduce_globals vi_list state =
-    feedback "introduce_globals %a" pp_vi_list vi_list;
-    state
-
   let initialize_variable lval ~initialized:_ init state =
     feedback "initialize_variable %a with %a"
       Printer.pp_lval lval
       pp_init_val init;
     state
 
-  let enter_scope _kf vi_list state =
-    feedback  "enter_scope %a" pp_vi_list vi_list;
+  let enter_scope _kind vi_list state =
+    feedback "enter_scope %a" pp_vi_list vi_list;
     state
 
   let leave_scope _kf vi_list state =
diff --git a/src/plugins/value/domains/simple_memory.ml b/src/plugins/value/domains/simple_memory.ml
index 97eed460437020f80b6cd893aabb6e68c3d22776..fe8be4136e0fecb4457121a826543da320027a45 100644
--- a/src/plugins/value/domains/simple_memory.ml
+++ b/src/plugins/value/domains/simple_memory.ml
@@ -293,7 +293,7 @@ module Make_Internal (Info: sig val name: string end) (Value: Value) = struct
       end
     | _ -> ()
 
-  let enter_scope _kf _vars state = state
+  let enter_scope _kind _vars state = state
   let leave_scope _kf vars state = remove_variables vars state
 
   let enter_loop _ state = state
@@ -305,7 +305,6 @@ module Make_Internal (Info: sig val name: string end) (Value: Value) = struct
   let reduce_by_predicate _ state _ _ = `Value state
 
   let empty () = top
-  let introduce_globals _varinfos state = state
   let initialize_variable _lval _location ~initialized:_ _value state = state
   let initialize_variable_using_type _kind _varinfo state = state
 
diff --git a/src/plugins/value/domains/simpler_domains.mli b/src/plugins/value/domains/simpler_domains.mli
index 2b4d654bdde07ef30011bb6c4a568da82dfa7c54..c8aa69e2c585df1d92dea213155ab484bda1c647 100644
--- a/src/plugins/value/domains/simpler_domains.mli
+++ b/src/plugins/value/domains/simpler_domains.mli
@@ -70,11 +70,10 @@ module type Minimal = sig
   (** Initialization of variables. *)
 
   val empty: unit -> t
-  val introduce_globals: varinfo list -> t -> t
   val initialize_variable:
     lval -> initialized:bool -> Abstract_domain.init_value -> t -> t
 
-  val enter_scope: kernel_function -> varinfo list -> t -> t
+  val enter_scope: Abstract_domain.variable_kind -> varinfo list -> t -> t
   val leave_scope: kernel_function -> varinfo list -> t -> t
 
   (** Pretty printers. *)
@@ -138,11 +137,10 @@ module type Simple_Cvalue = sig
   (** Initialization of variables. *)
 
   val empty: unit -> t
-  val introduce_globals: varinfo list -> t -> t
   val initialize_variable:
     lval -> initialized:bool -> Abstract_domain.init_value -> t -> t
 
-  val enter_scope: kernel_function -> varinfo list -> t -> t
+  val enter_scope: Abstract_domain.variable_kind -> varinfo list -> t -> t
   val leave_scope: kernel_function -> varinfo list -> t -> t
 
   (** Pretty printer. *)
diff --git a/src/plugins/value/domains/symbolic_locs.ml b/src/plugins/value/domains/symbolic_locs.ml
index f325e2a714866b4ff21fee35ef0222c04ffdc98a..98a56ef209dcf9cd50a8b76b57653c4054e316b0 100644
--- a/src/plugins/value/domains/symbolic_locs.ml
+++ b/src/plugins/value/domains/symbolic_locs.ml
@@ -478,7 +478,7 @@ module Internal : Domain_builder.InputDomain
 
   let empty _ = Memory.empty_map
 
-  let enter_scope _kf _vars state = state
+  let enter_scope _kind _vars state = state
   let leave_scope _kf vars state =
     (* removed variables revert implicitly to Top *)
     Memory.remove_variables vars state
@@ -627,7 +627,6 @@ module Internal : Domain_builder.InputDomain
       keys state
 
   (* Initial state. Initializers are singletons, so we store nothing. *)
-  let introduce_globals _ state = state
   let initialize_variable_using_type _ _ state = state
   let initialize_variable _ _ ~initialized:_ _ state = state
 
diff --git a/src/plugins/value/domains/traces_domain.ml b/src/plugins/value/domains/traces_domain.ml
index 771c2220a59d89cdc052d8fbf7efdb77c9377177..a2dffc08c938b4ed4b02626373dd70448e12d5e1 100644
--- a/src/plugins/value/domains/traces_domain.ml
+++ b/src/plugins/value/domains/traces_domain.ml
@@ -914,24 +914,19 @@ module Internal = struct
   let reuse _kf _bases ~current_input:_ ~previous_output:state = state
 
   let empty () = Traces.empty
-  let introduce_globals vars state =
-    {state with globals = vars @ state.globals}
   let initialize_variable lv _ ~initialized:_ _ state =
     Traces.add_trans state (Msg(Format.asprintf "initialize variable: %a" Printer.pp_lval lv ))
-  let initialize_variable_using_type init_kind varinfo state =
-    let state =
-      match init_kind with
-      | Abstract_domain.Main_Formal -> {state with main_formals = varinfo::state.main_formals}
-      | _ -> state
+  let initialize_variable_using_type var_kind varinfo state =
+    let kind_str =
+      match var_kind with
+      | Abstract_domain.Global   -> "global"
+      | Abstract_domain.Local _  -> "local"
+      | Abstract_domain.Formal _ -> "formal"
+      | Abstract_domain.Result _ -> "result"
     in
-    let msg = Format.asprintf "initialize@ variable@ using@ type@ %a@ %a"
-        (fun fmt init_kind ->
-           match init_kind with
-           | Abstract_domain.Main_Formal -> Format.pp_print_string fmt "Main_Formal"
-           | Abstract_domain.Library_Global -> Format.pp_print_string fmt "Library_Global"
-           | Abstract_domain.Spec_Return kf -> Format.fprintf fmt "Spec_Return(%s)" (Kernel_function.get_name kf))
-        init_kind
-        Varinfo.pretty varinfo
+    let msg =
+      Format.asprintf "initialize@ %s variable@ using@ type@ %a"
+        kind_str Varinfo.pretty varinfo
     in
     Traces.add_trans state (Msg msg)
 
@@ -1000,8 +995,19 @@ module Internal = struct
       Traces.add_trans state (Msg "leave_loop")
 
 
-  let enter_scope kf vars state = Traces.add_trans state (EnterScope (kf, vars))
-  let leave_scope kf vars state = Traces.add_trans state (LeaveScope (kf, vars))
+  let enter_scope kind vars state =
+    match kind with
+    | Abstract_domain.Global ->
+      { state with globals = vars @ state.globals }
+    | Abstract_domain.Formal kf ->
+      if Kernel_function.equal kf (fst (Globals.entry_point ()))
+      then { state with main_formals = vars @ state.main_formals }
+      else state
+    | Abstract_domain.(Local kf | Result kf) ->
+      Traces.add_trans state (EnterScope (kf, vars))
+
+  let leave_scope kf vars state =
+    Traces.add_trans state (LeaveScope (kf, vars))
 
   let reduce_further _state _expr _value = [] (*Nothing intelligent to suggest*)
 
diff --git a/src/plugins/value/domains/unit_domain.ml b/src/plugins/value/domains/unit_domain.ml
index 8fd5df76754bde4450ce50ccb1758000a2f44d84..cd989453aedf3ba7cf4e3246ece6543d49445b8b 100644
--- a/src/plugins/value/domains/unit_domain.ml
+++ b/src/plugins/value/domains/unit_domain.ml
@@ -79,7 +79,6 @@ module Make
   let leave_loop _ _ = ()
 
   let empty () = ()
-  let introduce_globals _ () = ()
   let initialize_variable _ _ ~initialized:_ _ _ = ()
   let initialize_variable_using_type _ _ _  = ()
 
diff --git a/src/plugins/value/engine/initialization.ml b/src/plugins/value/engine/initialization.ml
index fd124a687b6a27f5c823130697fcad9ca2042a7a..fb70a7e9ae9ad49c3a92d717cba3d342a3052d6c 100644
--- a/src/plugins/value/engine/initialization.ml
+++ b/src/plugins/value/engine/initialization.ml
@@ -234,7 +234,7 @@ module Make
             initialize_var_padding vi ~local:false ~lib_entry:true state
           in
           (* Then initialize non-padding bits according to the type. *)
-          let kind = Abstract_domain.Library_Global in
+          let kind = Abstract_domain.Global in
           Domain.initialize_variable_using_type kind vi state
       in
       (* If needed, initializes const fields according to the initializer
@@ -264,8 +264,9 @@ module Make
         Value_parameters.abort "Entry point %a has arguments"
           Kernel_function.pretty kf
       else
-        let kind = Abstract_domain.Main_Formal in
-        List.fold_right (Domain.initialize_variable_using_type kind) l state
+        let var_kind = Abstract_domain.Formal kf in
+        let state = Domain.enter_scope var_kind l state in
+        List.fold_right (Domain.initialize_variable_using_type var_kind) l state
 
   (* Use the values supplied in [actuals] for the formals of [kf], and
      bind them in [state] *)
@@ -305,7 +306,7 @@ module Make
 
   let initialize_global_variable ~lib_entry vi init state =
     Cil.CurrentLoc.set vi.vdecl;
-    let state = Domain.introduce_globals [vi] state in
+    let state = Domain.enter_scope Abstract_domain.Global [vi] state in
     if vi.vsource then
       let initialize =
         if lib_entry || (vi.vstorage = Extern)
diff --git a/src/plugins/value/engine/iterator.ml b/src/plugins/value/engine/iterator.ml
index cc122f92ae9f36e93fb5d47b4a370cabe8620dc2..83a22d27168133743da52eacbf4e5aa693e62158 100644
--- a/src/plugins/value/engine/iterator.ml
+++ b/src/plugins/value/engine/iterator.ml
@@ -281,18 +281,20 @@ module Make_Dataflow
   let transfer_instr (stmt : stmt) (instr : instr) : transfer_function =
     match instr with
     | Local_init (vi, AssignInit exp, _loc) ->
+      let kind = Abstract_domain.Local kf in
       let transfer state =
-        let state = Domain.enter_scope kf [vi] state in
+        let state = Domain.enter_scope kind [vi] state in
         Init.initialize_local_variable stmt vi exp state
       in
       lift' transfer
     | Local_init (vi, ConsInit (f, args, k), loc) ->
+      let kind = Abstract_domain.Local kf in
       let as_func dest callee args _loc state =
         (* This variable enters the scope too early, as it should
            be introduced after the call to [f] but before the assignment
            to [v]. This is currently not possible, at least without
            splitting Transfer.call in two. *)
-        let state = Domain.enter_scope kf [vi] state in
+        let state = Domain.enter_scope kind [vi] state in
         transfer_call stmt dest callee args state
       in
       Cil.treat_constructor_as_func as_func vi f args k loc
@@ -335,7 +337,8 @@ module Make_Dataflow
         let return_lval = Var vi_ret, NoOffset in
         let kstmt = Kstmt stmt in
         fun state ->
-          let state = Domain.enter_scope kf [vi_ret] state in
+          let kind = Abstract_domain.Result kf in
+          let state = Domain.enter_scope kind [vi_ret] state in
           let state' = Transfer.assign state kstmt return_lval return_exp in
           Bottom.to_list state'
     in
diff --git a/src/plugins/value/engine/mem_exec.ml b/src/plugins/value/engine/mem_exec.ml
index 83629ab5fc926f6d2d59ee2a77e93208b3df5d6a..4cd62fcbaaddebc8ee5bf8c7151d6dd134d26991 100644
--- a/src/plugins/value/engine/mem_exec.ml
+++ b/src/plugins/value/engine/mem_exec.ml
@@ -23,7 +23,7 @@
 
 module type Domain = sig
   include Datatype.S_with_collections
-  include Abstract_domain.Recycle with type t := t
+  include Abstract_domain.Reuse with type t := t
 end
 
 
diff --git a/src/plugins/value/engine/mem_exec.mli b/src/plugins/value/engine/mem_exec.mli
index 0b3fc959820db051608932a33d8a7d781b2850c9..9c288436038e2680f6aee33a1b04b14acd6c7d3c 100644
--- a/src/plugins/value/engine/mem_exec.mli
+++ b/src/plugins/value/engine/mem_exec.mli
@@ -25,7 +25,7 @@ open Eval
 
 module type Domain = sig
   include Datatype.S_with_collections
-  include Abstract_domain.Recycle with type t := t
+  include Abstract_domain.Reuse with type t := t
 end
 
 (** Counter that must be used each time a new call is analyzed, in order
diff --git a/src/plugins/value/engine/transfer_specification.ml b/src/plugins/value/engine/transfer_specification.ml
index b3be9e6f908aa569bd360e6f002cde811ecc29a5..331a5946cf1fbd37dd1080195da3cfa0f8961bce 100644
--- a/src/plugins/value/engine/transfer_specification.ml
+++ b/src/plugins/value/engine/transfer_specification.ml
@@ -546,9 +546,9 @@ module Make
         | Some retres_vi ->
           (* Notify the user about missing assigns \result. *)
           if warn then warn_on_missing_result_assigns kinstr call.kf spec;
-          let state = Domain.enter_scope call.kf [retres_vi] state in
-          let init_kind = Abstract_domain.Spec_Return call.kf  in
-          Domain.initialize_variable_using_type init_kind retres_vi state
+          let var_kind = Abstract_domain.Result call.kf in
+          let state = Domain.enter_scope var_kind [retres_vi] state in
+          Domain.initialize_variable_using_type var_kind retres_vi state
       in
       let states =
         compute_specification ~warn kinstr call.kf call.return spec state
diff --git a/src/plugins/value/engine/transfer_stmt.ml b/src/plugins/value/engine/transfer_stmt.ml
index d4ccb75c422925589acb2ffb2d016a802e16a24a..3e770b1c5ba1796ad72fe2ce66d12fce1825fa73 100644
--- a/src/plugins/value/engine/transfer_stmt.ml
+++ b/src/plugins/value/engine/transfer_stmt.ml
@@ -846,7 +846,8 @@ module Make (Abstract: Abstractions.Eva) = struct
   (* Makes the local variables [variables] enter the scope in [state].
      Also initializes volatile variable to top. *)
   let enter_scope kf variables state =
-    let state = Domain.enter_scope kf variables state in
+    let kind = Abstract_domain.Local kf in
+    let state = Domain.enter_scope kind variables state in
     let is_volatile varinfo =
       Cil.typeHasQualifier "volatile" varinfo.vtype
     in
diff --git a/tests/value/traces/oracle/test1.res.oracle b/tests/value/traces/oracle/test1.res.oracle
index 371a47f96c36e39e09c8da22b72a8cc9d95178cd..679625f40788362b3bb3910df23bb974d38a6738 100644
--- a/tests/value/traces/oracle/test1.res.oracle
+++ b/tests/value/traces/oracle/test1.res.oracle
@@ -14,11 +14,11 @@
 [eva:d-traces] Trace domains:
  start: 0; globals = g, entropy_source; main_formals = c;
  {[ 0 -> initialize variable: entropy_source -> 1
-    1 -> initialize variable using type Library_Global
+    1 -> initialize global variable using type
 entropy_source -> 2
     2 -> initialize variable: g -> 3
     3 -> Assign: g = 42 -> 4
-    4 -> initialize variable using type Main_Formal
+    4 -> initialize formal variable using type
 c -> 5
     5 -> EnterScope: tmp -> 6
     6 -> Assign: tmp = 0 -> 7
diff --git a/tests/value/traces/oracle/test2.res.oracle b/tests/value/traces/oracle/test2.res.oracle
index c936d8bb9b5ec7356b61cb874df09a8192438bd2..65c109933939b95fb5d020721e76de0b4dc550a6 100644
--- a/tests/value/traces/oracle/test2.res.oracle
+++ b/tests/value/traces/oracle/test2.res.oracle
@@ -21,7 +21,7 @@
   tmp ∈ {4; 5}
 [eva:d-traces] Trace domains:
  start: 0; globals = ; main_formals = c;
- {[ 0 -> initialize variable using type Main_Formal
+ {[ 0 -> initialize formal variable using type
 c -> 1
     1 -> EnterScope: tmp -> 2
     2 -> Assign: tmp = 0 -> 3
diff --git a/tests/value/traces/oracle/test3.res.oracle b/tests/value/traces/oracle/test3.res.oracle
index d99315838e92aad39c6e71fdddf12bbbf71b6085..94615aa1fd40d461d21b8914fbc9490ccf004a56 100644
--- a/tests/value/traces/oracle/test3.res.oracle
+++ b/tests/value/traces/oracle/test3.res.oracle
@@ -14,7 +14,7 @@
 [eva:d-traces] Trace domains:
  start: 0; globals = g; main_formals = c;
  {[ 0 -> initialize variable: g -> 1
-    1 -> initialize variable using type Main_Formal
+    1 -> initialize formal variable using type
 c -> 2
     2 -> EnterScope: __retres -> 3
     3 -> EnterScope: tmp -> 4
diff --git a/tests/value/traces/oracle/test4.res.oracle b/tests/value/traces/oracle/test4.res.oracle
index 62f44d1b1031d4d20500bb91b2d631300bead971..131cdfb303e054a35f2fc4f8e90c97fdbcaedb83 100644
--- a/tests/value/traces/oracle/test4.res.oracle
+++ b/tests/value/traces/oracle/test4.res.oracle
@@ -24,7 +24,7 @@
   tmp ∈ [46..2147483647]
 [eva:d-traces] Trace domains:
  start: 0; globals = ; main_formals = c;
- {[ 0 -> initialize variable using type Main_Formal
+ {[ 0 -> initialize formal variable using type
 c -> 1
     1 -> EnterScope: tmp -> 2
     2 -> initialize variable: tmp -> 3
diff --git a/tests/value/traces/oracle/test5.res.oracle b/tests/value/traces/oracle/test5.res.oracle
index 1f021acddb6043e4a0f2f980bb3d3fb69561792d..815b9a52bd370ee6179be96c05a8b4a23601ab60 100644
--- a/tests/value/traces/oracle/test5.res.oracle
+++ b/tests/value/traces/oracle/test5.res.oracle
@@ -107,7 +107,7 @@
   tmp ∈ [--..--]
 [eva:d-traces] Trace domains:
  start: 0; globals = ; main_formals = c;
- {[ 0 -> initialize variable using type Main_Formal
+ {[ 0 -> initialize formal variable using type
 c -> 1
     1 -> EnterScope: tmp -> 2
     2 -> initialize variable: tmp -> 3