diff --git a/src/plugins/e-acsl/src/analyses/bound_variables.ml b/src/plugins/e-acsl/src/analyses/bound_variables.ml
index eeb8edc7e90b78d38187ceba14d482937130a8d4..114c9183be103c8c010293411078dfeddb5c403b 100644
--- a/src/plugins/e-acsl/src/analyses/bound_variables.ml
+++ b/src/plugins/e-acsl/src/analyses/bound_variables.ml
@@ -31,3 +31,580 @@
     is an additional optional guard to intersect the first guard with the
     provided type for the variable v *)
 
+open Cil_types
+open Cil
+open Cil_datatype
+
+(** [error_msg quantif msg pp x] creates an error message from the string [msg]
+    containing the value [x] pretty-printed by [pp] and the predicate [quantif]
+    pretty-printed. *)
+let error_msg quantif msg pp x =
+  let msg1 = Format.asprintf msg pp x in
+  let msg2 =
+    Format.asprintf "@[ in quantification@ %a@]"
+      Printer.pp_predicate quantif
+  in
+  msg1 ^ msg2
+
+(** Helper module to process the constraints in the quantification and extract
+    guards for the quantified variables. *)
+module Constraints: sig
+  (** Context type manipulated by the functions of the module. *)
+  type t
+
+  (** [empty quantif bounded_vars] creates an empty context from a
+      quantification predicate and the list of bounded variables for the
+      predicate. *)
+  val empty: predicate -> logic_var list -> t
+
+  (** [get_bounded_var ctxt t] returns the logic var corresponding to the given
+      term if the term is a variable ([TLval(Tvar _, TNoOffset)]) that is a
+      bounded variable for the quantification being processed, or [None]
+      otherwise. *)
+  val get_bounded_var: term -> t -> logic_var option
+
+  (** [has_unguarded_bounded_vars ctxt] returns true iff some bounded variables
+      in [ctxt] do not have a guard extracted from the quantification
+      predicate. *)
+  val has_unguarded_bounded_vars: t -> bool
+
+  (** [add_lower_bound ctxt t r lv] adds the lower bound [t r lv] to the list
+      of guards for the quantification.
+      @raises Typing_error if a lower bound already exists for [lv]. *)
+  val add_lower_bound: term -> relation -> logic_var -> t -> t
+
+  (** [add_linked_upper_bound ctxt lv1 r lv2] adds a link between two bounded
+      variables with still incomplete guards. [lv1] should already have at least
+      a lower bound.
+      @raises Typing_error if [lv1] do not have an existing lower bound. *)
+  val add_linked_upper_bound: logic_var -> relation -> logic_var -> t -> t
+
+  (** [add_upper_bound ctxt lv r t] adds the upper bound [lv r t] to the list of
+      guards for the quantification.
+      For each existing linked relation [lv' r' lv], also adds the upper bound
+      [lv' r'' t] to the list of guards, with [r''] being the strictest relation
+      between [r] and [r'].
+      @raises Typing_error if either [lv] or [lv'] does not have an existing
+      lower bound. *)
+  val add_upper_bound: logic_var -> relation -> term -> t -> t
+
+  (** [check_validity ctxt] checks the validity of the quantification after
+      processing.
+      @raises Typing_error if some bound (lower or upper) cound not be extracted
+      from the quantification for each bounded variable. *)
+  val check_validity: t -> unit
+
+  (** [retrieve_guards ctxt] returns the list of guards for the bounded
+      variables of the quantification, in the order in which they must be
+      generated, ie. if [j] depends on [i] then the guard for [i] will be before
+      the guard for [j] in the list.
+      [check_validity ctxt] must have been called before calling
+      [retrieve_guards]. *)
+  val retrieve_guards: t -> (term * relation * logic_var * relation * term) list
+
+  (** [raise_error ctxt msg] raises a [Typing_error] exception with the given
+      message after appending the quantification from the context. *)
+  val raise_error: string -> t -> 'a
+
+  (** [error_invalid_pred ?warn_rel ctxt p] raises a [Typing_error] exception
+      with a message indicating that the predicate [p] is not valid in the
+      quantification. Depending on the state of [ctxt], more information about
+      missing bounds is added to the message. If [warn_rel] is [true], then a
+      reminder that only [Rle] and [Rlt] are allowed to guard quantified
+      variables is added to the message. *)
+  val raise_error_invalid_pred: ?warn_rel:bool -> predicate -> t -> 'a
+end = struct
+  type t = {
+    (** Quantification predicate being analyzed. *)
+    quantif: predicate;
+    (** Variables of the quantification that still need guards. *)
+    bounded_vars: Logic_var.Set.t;
+    (** Bounded variables list in reverse order in which they must be
+        generated. *)
+    rev_order: Logic_var.t list;
+    (** Table associating a bounded variable with its guard. *)
+    guards: (term * relation * (relation * term) option) Logic_var.Map.t;
+    (** Table associating a bounded variable with a relation with another
+        bounded variable. *)
+    linked_upper_bounds: (logic_var * relation) Logic_var.Map.t;
+  }
+
+  let empty quantif bounded_vars =
+    (* Check that the bounded vars have integer type and store them in a set. *)
+    let bounded_vars =
+      List.fold_left
+        (fun s v ->
+           let v =
+             match v.lv_type with
+             | Ctype ty when isIntegralType ty -> v
+             | Linteger -> v
+             | Ltype _ as ty when Logic_const.is_boolean_type ty -> v
+             | Ctype _ | Ltype _ | Lvar _ | Lreal | Larrow _ ->
+               Error.not_yet
+                 (error_msg
+                    quantif
+                    "@[non integer variable %a@]"
+                    Printer.pp_logic_var v)
+           in
+           Logic_var.Set.add v s
+        )
+        Logic_var.Set.empty
+        bounded_vars
+    in
+    {
+      quantif;
+      bounded_vars;
+      rev_order = [];
+      guards = Logic_var.Map.empty;
+      linked_upper_bounds = Logic_var.Map.empty;
+    }
+
+  let get_bounded_var t ctxt =
+    let rec aux t =
+      match t.term_node with
+      | TLogic_coerce(_, t) -> aux t
+      | TLval(TVar lv, TNoOffset) when Logic_var.Set.mem lv ctxt.bounded_vars ->
+        Some lv
+      | _ -> None
+    in
+    aux t
+
+  let has_unguarded_bounded_vars ctxt =
+    not (Logic_var.Set.is_empty ctxt.bounded_vars)
+
+  (** Pretty printer for a guard, represented by a tuple
+      [(term, relation, logic_var, relation, term)]. *)
+  let pp_guard fmt (t1, r1, lv, r2, t2) =
+    Format.fprintf
+      fmt
+      "@[%a %a %a %a %a@]"
+      Printer.pp_term t1
+      Printer.pp_relation r1
+      Printer.pp_logic_var lv
+      Printer.pp_relation r2
+      Printer.pp_term t2
+
+  (** Pretty printer for a lower bound, represented by the tuple
+      [(term, relation, logic_var)]. *)
+  let pp_lbound fmt (t, r, lv) =
+    Format.fprintf
+      fmt
+      "@[%a %a %a@]"
+      Printer.pp_term t
+      Printer.pp_relation r
+      Printer.pp_logic_var lv
+
+  (** Pretty printer for a bound between two quantified variables,
+      represented by the tuple [(logic_var, relation, logic_var)]. *)
+  let pp_linked_bound fmt (lv1, r, lv2) =
+    Format.fprintf
+      fmt
+      "@[%a %a %a@]"
+      Printer.pp_logic_var lv1
+      Printer.pp_relation r
+      Printer.pp_logic_var lv2
+
+  let add_lower_bound t r lv ctxt =
+    match Logic_var.Map.find_opt lv ctxt.guards with
+    | None ->
+      { ctxt with
+        guards = Logic_var.Map.add lv (t, r, None) ctxt.guards; }
+    | Some (t', r', None) ->
+      let msg =
+        Format.asprintf
+          "@[found existing lower bound %a@ when processing %a@ \
+           in quantification@ %a@]"
+          pp_lbound (t', r', lv)
+          pp_lbound (t, r, lv)
+          Printer.pp_predicate ctxt.quantif
+      in
+      Error.untypable msg
+    | Some (t1', r1', Some (r2', t2')) ->
+      let msg =
+        Format.asprintf
+          "@[found existing guard %a@ when processing %a@ \
+           in quantification@ %a@]"
+          pp_guard (t1', r1', lv, r2', t2')
+          pp_lbound (t, r, lv)
+          Printer.pp_predicate ctxt.quantif
+      in
+      Error.untypable msg
+
+  let add_linked_upper_bound lv1 r lv2 ctxt =
+    if Logic_var.Map.mem lv1 ctxt.guards then begin
+      { ctxt with
+        linked_upper_bounds =
+          Logic_var.Map.add lv2
+            (lv1, r)
+            ctxt.linked_upper_bounds; }
+    end else
+      let msg=
+        Format.asprintf
+          "@[missing lower bound for %a@ when processing the linked upper \
+           bound %a@ in quantification@ %a@]"
+          Printer.pp_logic_var lv1
+          pp_linked_bound (lv1, r, lv2)
+          Printer.pp_predicate ctxt.quantif
+      in
+      Error.untypable msg
+
+  let add_upper_bound lv r t ctxt =
+    (* Select the strictest relation between [r1] and [r2], with both relations
+       being either [Rlt] or [Rle]. *)
+    let strictest_relation r1 r2 =
+      match r1, r2 with
+      | (Rlt | Rle), Rlt | Rlt, Rle -> Rlt
+      | Rle, Rle -> Rle
+      | _, _ ->
+        Options.fatal
+          "invalid relations %a and %a in quantification %a"
+          Printer.pp_relation r1
+          Printer.pp_relation r2
+          Printer.pp_predicate ctxt.quantif
+    in
+    (* Replace the guard for [lv] to add the upper bound [lv r t], and
+       recursively walk the bounds linked to [lv] to also add upper bounds. *)
+    let rec replace_guard lv r t ctxt =
+      try
+        let lower_bound_t, lower_bound_r, _ =
+          Logic_var.Map.find lv ctxt.guards
+        in
+        let ctxt =
+          { ctxt with
+            guards =
+              Logic_var.Map.add
+                lv
+                (lower_bound_t, lower_bound_r, Some (r, t))
+                ctxt.guards; }
+        in
+        let ctxt =
+          { ctxt with
+            bounded_vars = Logic_var.Set.remove lv ctxt.bounded_vars; }
+        in
+        let need_upper_bound =
+          Logic_var.Map.find_opt lv ctxt.linked_upper_bounds
+        in
+        let ctxt =
+          match need_upper_bound with
+          | Some (lv', r') ->
+            let ctxt =
+              { ctxt with
+                linked_upper_bounds =
+                  Logic_var.Map.remove lv ctxt.linked_upper_bounds; }
+            in
+            replace_guard lv' (strictest_relation r r') t ctxt
+          | None -> ctxt
+        in
+        { ctxt with rev_order = lv :: ctxt.rev_order }
+      with Not_found ->
+        Error.untypable
+          (error_msg ctxt.quantif
+             "@[missing lower bound for %a@]"
+             Printer.pp_logic_var lv)
+    in
+    replace_guard lv r t ctxt
+
+  let check_validity ctxt =
+    if not (Logic_var.Map.is_empty ctxt.linked_upper_bounds) then
+      let msg =
+        let iter_keys f map_seq =
+          Seq.iter
+            (fun (key, _) -> f key)
+            map_seq
+        in
+        Format.asprintf
+          "@[missing upper bound%s for %a@ in quantification@ %a@]"
+          (if Logic_var.Map.cardinal ctxt.linked_upper_bounds = 1 then ""
+           else "s")
+          (Pretty_utils.pp_iter
+             ~sep:", "
+             iter_keys
+             Printer.pp_logic_var)
+          (Logic_var.Map.to_seq ctxt.linked_upper_bounds)
+          Printer.pp_predicate ctxt.quantif
+      in
+      Error.untypable msg
+    else if not (Logic_var.Set.is_empty ctxt.bounded_vars) then
+      let msg =
+        Format.asprintf
+          "@[missing lower bound%s for %a@ in quantification@ %a@]"
+          (if Logic_var.Set.cardinal ctxt.bounded_vars = 1 then "" else "s")
+          (Pretty_utils.pp_iter
+             ~sep:", "
+             Logic_var.Set.iter
+             Printer.pp_logic_var)
+          ctxt.bounded_vars
+          Printer.pp_predicate ctxt.quantif
+      in
+      Error.untypable msg
+
+  let retrieve_guards ctxt =
+    List.fold_left
+      (fun acc lv ->
+         match Logic_var.Map.find_opt lv ctxt.guards with
+         | Some (t1, r1, Some (r2, t2)) ->
+           (t1, r1, lv, r2, t2) :: acc
+
+         (* The error cases should not occur if the traversal of the
+            quantification was completed and [check_validity] was called
+            successfully. *)
+         | Some (_, _, None) ->
+           Options.fatal
+             "Missing upper bound when trying to retrieve the guard for %a"
+             Printer.pp_logic_var lv
+         | None -> Options.fatal "Missing guard for %a" Printer.pp_logic_var lv
+      )
+      []
+      ctxt.rev_order
+
+  let raise_error msg ctxt =
+    let msg2 =
+      Format.asprintf "@[ in quantification@ %a@]"
+        Printer.pp_predicate ctxt.quantif
+    in
+    Error.untypable (msg ^ msg2)
+
+  let raise_error_invalid_pred ?(warn_rel=false) p ctxt =
+    (* Extract the set of variables that have another variable for upper bound.
+       They will be considered valid for the purpose of the error message, ie.
+       if we have the relation [0 < i < j] with [0 < i] as an incomplete guard
+       and [i < j] as a linked upper bound, then the error is about [j] not
+       having an upper bound, not about [i]. *)
+    let linked_upper_bounds =
+      Logic_var.Map.fold
+        (fun _ (lv, _) acc -> Logic_var.Set.add lv acc)
+        ctxt.linked_upper_bounds
+        Logic_var.Set.empty
+    in
+
+    let missing_guards, missing_upper_bounds =
+      Logic_var.Set.fold
+        (fun lv (missing_guards, missing_upper_bounds) ->
+           match Logic_var.Map.find_opt lv ctxt.guards with
+           | Some (_, _, None)
+             when not (Logic_var.Set.mem lv linked_upper_bounds) ->
+             (* A variable with an incomplete constraint and without a linked
+                upper bound has a missing upper bound. *)
+             missing_guards, lv :: missing_upper_bounds
+           | None ->
+             (* A variable without a constraint has a missing guard. *)
+             lv :: missing_guards, missing_upper_bounds
+           | _ ->
+             (* Otherwise the variable either has a complete constraint, or an
+                incomplete constraint but with a linked upper bound. *)
+             missing_guards, missing_upper_bounds)
+        ctxt.bounded_vars
+        ([], [])
+    in
+
+    let msg =
+      Format.asprintf
+        "@[invalid guard %a@ in quantification@ %a.@ \
+         %a@,%a@ \
+         %t@]"
+        Printer.pp_predicate p Printer.pp_predicate ctxt.quantif
+        (Pretty_utils.pp_list
+           ~pre:"@[Missing guard for "
+           ~sep:",@ "
+           ~suf:".@]"
+           Printer.pp_logic_var)
+        (List.rev missing_guards)
+        (Pretty_utils.pp_list
+           ~pre:"@[Missing upper bound for "
+           ~sep:",@ "
+           ~suf:".@]"
+           Printer.pp_logic_var)
+        (List.rev missing_upper_bounds)
+        (fun fmt ->
+           if warn_rel then
+             Format.fprintf fmt
+               "@[Only %a and %a are allowed to guard quantifier variables@]"
+               Printer.pp_relation Rlt Printer.pp_relation Rle)
+    in
+    Error.untypable msg
+end
+
+(** [extract_constraint ctxt t1 r t2] populates the quantification context
+    [ctxt] with the constraint [t1 r t2], either adding a lower bound if [t2] is
+    a bounded variable or adding an upper bound if [t1] is a bounded variable.
+    @raises Typing_error if no constraint can be extracted or if the constraint
+    is invalid (no bounded variable in [t1] or [t2] for instance). *)
+let extract_constraint ctxt t1 r t2 =
+  (* Return the logic var corresponding to the given term or [None] if the term
+     is not a variable ([TLval(TVar _, TNoOffset)]). *)
+  let rec _get_logic_var_opt t =
+    match t.term_node with
+    | TLogic_coerce(_, t) -> _get_logic_var_opt t
+    | TLval(TVar x, TNoOffset) -> Some x
+    | _ -> None
+  in
+  (* Process the given relation *)
+  let lv1 = Constraints.get_bounded_var t1 ctxt in
+  let lv2 = Constraints.get_bounded_var t2 ctxt in
+  match lv1, lv2 with
+  | None, Some lv2 -> (* t1 value, t2 variable: store lower bound *)
+    Constraints.add_lower_bound t1 r lv2 ctxt
+  | Some lv1, None -> (* t1 variable, t2 value: store upper bound *)
+    Constraints.add_upper_bound lv1 r t2 ctxt
+  | Some lv1, Some lv2 ->
+    (* t1 variable, t2 variable: store link between t1 and t2 *)
+    let ctxt = Constraints.add_linked_upper_bound lv1 r lv2 ctxt in
+    Constraints.add_lower_bound t1 r lv2 ctxt
+  | None, None -> (* t1 value, t2 value: error *)
+    let msg =
+      Format.asprintf
+        "@[invalid constraint %a %a %a, both operands are constants or \
+         already bounded@]"
+        Printer.pp_term t1
+        Printer.pp_relation r
+        Printer.pp_term t2
+    in
+    Constraints.raise_error msg ctxt
+
+(** [visit_quantif_relations ~is_forall ctxt p] traverses the predicate [p] of
+    the quantification being analyzed in the context [ctxt] from left to right
+    as long as the predicate is [Pimplies], [Pand] or [Prel(Rlt | Rle)], and
+    calls [extract_constraint] on each relation [Rlt] or [Rle] it encounters
+    until all the guards of the quantification have been found or the predicate
+    is finished. If [is_forall] is [true] then the predicate being traversed is
+    a universal quantification, otherwise it is an existential quantification.
+    The function returns a tuple [ctxt, goal_opt] where [ctxt] is the
+    quantification context and [goal_opt] is either [None] if the goal of the
+    quantification has not been found yet or [Some goal] if [goal] is the
+    predicate corresponding to the goal of the quantification.
+    @raises Typing_error if the predicate contains something other than
+    [Pimplies], [Pand] or [Prel] with a relation that is neither [Rlt] nor
+    [Rle]. *)
+let rec visit_quantif_relations ~is_forall ctxt p =
+  match p.pred_content with
+  | Pimplies(lhs, rhs) ->
+    let ctxt, _ = visit_quantif_relations ~is_forall ctxt lhs in
+    if is_forall then begin
+      if Constraints.has_unguarded_bounded_vars ctxt then
+        visit_quantif_relations ~is_forall ctxt rhs
+      else
+        ctxt, Some rhs
+    end else
+      let msg =
+        Format.asprintf
+          "@[invalid quantification guard, expecting '%s' to continue@ \
+           bounding variables,@ found '%s'@]"
+          (if Kernel.Unicode.get () then Utf8_logic.conj else "&&")
+          (if Kernel.Unicode.get () then Utf8_logic.implies else "==>")
+      in
+      Constraints.raise_error msg ctxt
+  | Pand(lhs, rhs) ->
+    let ctxt, _ = visit_quantif_relations ~is_forall ctxt lhs in
+    if Constraints.has_unguarded_bounded_vars ctxt then
+      visit_quantif_relations ~is_forall ctxt rhs
+    else if not is_forall then
+      ctxt, Some rhs
+    else
+      let msg =
+        Format.asprintf
+          "@[invalid quantification predicate, expecting '%s' to@ \
+           separate the hypotheses from the goal, found '%s'@]"
+          (if Kernel.Unicode.get () then Utf8_logic.implies else "==>")
+          (if Kernel.Unicode.get () then Utf8_logic.conj else "&&")
+      in
+      Constraints.raise_error msg ctxt
+  | Prel((Rlt | Rle) as r, t1, t2) ->
+    let ctxt = extract_constraint ctxt t1 r t2 in
+    ctxt, None
+  | Prel _ ->
+    Constraints.raise_error_invalid_pred ~warn_rel:true p ctxt
+  | _ ->
+    Constraints.raise_error_invalid_pred p ctxt
+
+(** [compute_quantif_guards ~is_forall quantif bounded_vars p] computes the
+    guards for the bounded variables [bounded_vars] of the quantification
+    [quantif] from the predicate [p]. If [is_forall] is [true] then [quantif] is
+    a universal quantification, otherwise [quantif] is an existential
+    quantification.
+    The function returns the list of guards for the variables and the goal
+    predicate of the quantification. *)
+let compute_quantif_guards ~is_forall quantif bounded_vars p =
+  (* Traverse the predicate of the quantification to extract the guards of the
+     bounded variables. *)
+  let ctxt = Constraints.empty quantif bounded_vars in
+  let ctxt, goal = visit_quantif_relations ~is_forall ctxt p in
+  (* Check the validity of the result of the traversal. *)
+  Constraints.check_validity ctxt;
+  if Option.is_none goal then
+    let msg =
+      Format.asprintf
+        "@[no goal found in quantification@ %a@]"
+        Printer.pp_predicate quantif
+    in
+    Error.untypable msg
+  else
+    (* Traversal is valid, the guards and the goal can be retrieved and
+       returned. *)
+    let guards = Constraints.retrieve_guards ctxt in
+    let goal = Option.get goal in
+    guards, goal
+
+(******************************************************************************)
+(** Type intersection *)
+(******************************************************************************)
+
+(* It could happen that the bounds provided for a quantifier [lv] are bigger
+   than its type. [bounds_for_small_type] handles such cases
+   and provides smaller bounds whenever possible.
+   Let B be the inferred interval and R the range of [lv.typ]
+   - Case 1: B \subseteq R
+     Example: [\forall unsigned char c; 4 <= c <= 100 ==> 0 <= c <= 255]
+     Return: B
+   - Case 2: B \not\subseteq R and the bounds of B are inferred exactly
+     Example: [\forall unsigned char c; 4 <= c <= 300 ==> 0 <= c <= 255]
+     Return: B \intersect R
+   - Case 3: B \not\subseteq R and the bounds of B are NOT inferred exactly
+     Example: [\let m = n > 0 ? 4 : 341; \forall char u; 1 < u < m ==> u > 0]
+     Return: R with a guard guaranteeing that [lv] does not overflow *)
+let bounds_for_small_type ~loc (t1, lv, t2) =
+  match lv.lv_type with
+  | Ltype _ | Lvar _ | Lreal | Larrow _ ->
+    Options.abort "quantification over non-integer type is not part of E-ACSL"
+
+  | Linteger ->
+    t1, t2, None
+
+  | Ctype ty ->
+    let iv1 = Interval.(extract_ival (infer t1)) in
+    let iv2 = Interval.(extract_ival (infer t2)) in
+    (* Ival.join is NOT correct here:
+       Eg: (Ival.join [-3..-3] [300..300]) gives {-3, 300}
+       but NOT [-3..300] *)
+    let iv = Ival.inject_range (Ival.min_int iv1) (Ival.max_int iv2) in
+    let ity = Interval.extract_ival (Interval.interv_of_typ ty) in
+    if Ival.is_included iv ity then
+      (* case 1 *)
+      t1, t2, None
+    else if Ival.is_singleton_int iv1 && Ival.is_singleton_int iv2 then begin
+      (* case 2 *)
+      let i = Ival.meet iv ity in
+      (* now we potentially have a better interval for [lv]
+         ==> update the binding *)
+      Interval.Env.replace lv (Interval.Ival i);
+      (* the smaller bounds *)
+      let min, max = Misc.finite_min_and_max i in
+      let t1 = Logic_const.tint ~loc min in
+      let t2 = Logic_const.tint ~loc max in
+      let ctx = Typing.number_ty_of_typ ~post:false ty in
+      (* we are assured that we will not have a GMP,
+         once again because we intersected with [ity] *)
+      Typing.type_term ~use_gmp_opt:false ~ctx t1;
+      Typing.type_term ~use_gmp_opt:false ~ctx t2;
+      t1, t2, None
+    end else
+      (* case 3 *)
+      let min, max = Misc.finite_min_and_max ity in
+      let guard_lower = Logic_const.tint ~loc min in
+      let guard_upper = Logic_const.tint ~loc max in
+      let lv_term = Logic_const.tvar ~loc lv in
+      let guard_lower = Logic_const.prel ~loc (Rle, guard_lower, lv_term) in
+      let guard_upper = Logic_const.prel ~loc (Rle, lv_term, guard_upper) in
+      let guard = Logic_const.pand ~loc (guard_lower, guard_upper) in
+      t1, t2, Some guard
+
+let () = Typing.compute_quantif_guards_ref := compute_quantif_guards
diff --git a/src/plugins/e-acsl/src/code_generator/loops.ml b/src/plugins/e-acsl/src/code_generator/loops.ml
index c6d6e726ba7e5f183f42551b3bba4e57472811ad..6221f6ec5c815bdec1dd102f3b812c3b73cbaf99 100644
--- a/src/plugins/e-acsl/src/code_generator/loops.ml
+++ b/src/plugins/e-acsl/src/code_generator/loops.ml
@@ -200,66 +200,6 @@ let handle_annotations env kf stmt =
 (**************************************************************************)
 (**************************** Nested loops ********************************)
 (**************************************************************************)
-
-(* It could happen that the bounds provided for a quantifier [lv] are bigger
-   than its type. [bounds_for_small_type] handles such cases
-   and provides smaller bounds whenever possible.
-   Let B be the inferred interval and R the range of [lv.typ]
-   - Case 1: B \subseteq R
-     Example: [\forall unsigned char c; 4 <= c <= 100 ==> 0 <= c <= 255]
-     Return: B
-   - Case 2: B \not\subseteq R and the bounds of B are inferred exactly
-     Example: [\forall unsigned char c; 4 <= c <= 300 ==> 0 <= c <= 255]
-     Return: B \intersect R
-   - Case 3: B \not\subseteq R and the bounds of B are NOT inferred exactly
-     Example: [\let m = n > 0 ? 4 : 341; \forall char u; 1 < u < m ==> u > 0]
-     Return: R with a guard guaranteeing that [lv] does not overflow *)
-let bounds_for_small_type ~loc (t1, lv, t2) =
-  match lv.lv_type with
-  | Ltype _ | Lvar _ | Lreal | Larrow _ ->
-    Options.abort "quantification over non-integer type is not part of E-ACSL"
-
-  | Linteger ->
-    t1, t2, None
-
-  | Ctype ty ->
-    let iv1 = Interval.(extract_ival (infer t1)) in
-    let iv2 = Interval.(extract_ival (infer t2)) in
-    (* Ival.join is NOT correct here:
-       Eg: (Ival.join [-3..-3] [300..300]) gives {-3, 300}
-       but NOT [-3..300] *)
-    let iv = Ival.inject_range (Ival.min_int iv1) (Ival.max_int iv2) in
-    let ity = Interval.extract_ival (Interval.interv_of_typ ty) in
-    if Ival.is_included iv ity then
-      (* case 1 *)
-      t1, t2, None
-    else if Ival.is_singleton_int iv1 && Ival.is_singleton_int iv2 then begin
-      (* case 2 *)
-      let i = Ival.meet iv ity in
-      (* now we potentially have a better interval for [lv]
-         ==> update the binding *)
-      Interval.Env.replace lv (Interval.Ival i);
-      (* the smaller bounds *)
-      let min, max = Misc.finite_min_and_max i in
-      let t1 = Logic_const.tint ~loc min in
-      let t2 = Logic_const.tint ~loc max in
-      let ctx = Typing.number_ty_of_typ ~post:false ty in
-      (* we are assured that we will not have a GMP,
-         once again because we intersected with [ity] *)
-      Typing.type_term ~use_gmp_opt:false ~ctx t1;
-      Typing.type_term ~use_gmp_opt:false ~ctx t2;
-      t1, t2, None
-    end else
-      (* case 3 *)
-      let min, max = Misc.finite_min_and_max ity in
-      let guard_lower = Logic_const.tint ~loc min in
-      let guard_upper = Logic_const.tint ~loc max in
-      let lv_term = Logic_const.tvar ~loc lv in
-      let guard_lower = Logic_const.prel ~loc (Rle, guard_lower, lv_term) in
-      let guard_upper = Logic_const.prel ~loc (Rle, lv_term, guard_upper) in
-      let guard = Logic_const.pand ~loc (guard_lower, guard_upper) in
-      t1, t2, Some guard
-
 let rec mk_nested_loops ~loc mk_innermost_block kf env lscope_vars =
   let term_to_exp = !term_to_exp_ref in
   match lscope_vars with
diff --git a/src/plugins/e-acsl/src/code_generator/quantif.ml b/src/plugins/e-acsl/src/code_generator/quantif.ml
index 2e95c2c5699ccc1b585919ac6bbf0703bb3684b0..59bdc3e243b7b8324321c5bcb880133e7be7ce55 100644
--- a/src/plugins/e-acsl/src/code_generator/quantif.ml
+++ b/src/plugins/e-acsl/src/code_generator/quantif.ml
@@ -29,516 +29,6 @@ let predicate_to_exp_ref
   : (kernel_function -> Env.t -> predicate -> exp * Env.t) ref
   = Extlib.mk_fun "predicate_to_exp_ref"
 
-(** [error_msg quantif msg pp x] creates an error message from the string [msg]
-    containing the value [x] pretty-printed by [pp] and the predicate [quantif]
-    pretty-printed. *)
-let error_msg quantif msg pp x =
-  let msg1 = Format.asprintf msg pp x in
-  let msg2 =
-    Format.asprintf "@[ in quantification@ %a@]"
-      Printer.pp_predicate quantif
-  in
-  msg1 ^ msg2
-
-(** Helper module to process the constraints in the quantification and extract
-    guards for the quantified variables. *)
-module Constraints: sig
-  (** Context type manipulated by the functions of the module. *)
-  type t
-
-  (** [empty quantif bounded_vars] creates an empty context from a
-      quantification predicate and the list of bounded variables for the
-      predicate. *)
-  val empty: predicate -> logic_var list -> t
-
-  (** [get_bounded_var ctxt t] returns the logic var corresponding to the given
-      term if the term is a variable ([TLval(Tvar _, TNoOffset)]) that is a
-      bounded variable for the quantification being processed, or [None]
-      otherwise. *)
-  val get_bounded_var: term -> t -> logic_var option
-
-  (** [has_unguarded_bounded_vars ctxt] returns true iff some bounded variables
-      in [ctxt] do not have a guard extracted from the quantification
-      predicate. *)
-  val has_unguarded_bounded_vars: t -> bool
-
-  (** [add_lower_bound ctxt t r lv] adds the lower bound [t r lv] to the list
-      of guards for the quantification.
-      @raises Typing_error if a lower bound already exists for [lv]. *)
-  val add_lower_bound: term -> relation -> logic_var -> t -> t
-
-  (** [add_linked_upper_bound ctxt lv1 r lv2] adds a link between two bounded
-      variables with still incomplete guards. [lv1] should already have at least
-      a lower bound.
-      @raises Typing_error if [lv1] do not have an existing lower bound. *)
-  val add_linked_upper_bound: logic_var -> relation -> logic_var -> t -> t
-
-  (** [add_upper_bound ctxt lv r t] adds the upper bound [lv r t] to the list of
-      guards for the quantification.
-      For each existing linked relation [lv' r' lv], also adds the upper bound
-      [lv' r'' t] to the list of guards, with [r''] being the strictest relation
-      between [r] and [r'].
-      @raises Typing_error if either [lv] or [lv'] does not have an existing
-      lower bound. *)
-  val add_upper_bound: logic_var -> relation -> term -> t -> t
-
-  (** [check_validity ctxt] checks the validity of the quantification after
-      processing.
-      @raises Typing_error if some bound (lower or upper) cound not be extracted
-      from the quantification for each bounded variable. *)
-  val check_validity: t -> unit
-
-  (** [retrieve_guards ctxt] returns the list of guards for the bounded
-      variables of the quantification, in the order in which they must be
-      generated, ie. if [j] depends on [i] then the guard for [i] will be before
-      the guard for [j] in the list.
-      [check_validity ctxt] must have been called before calling
-      [retrieve_guards]. *)
-  val retrieve_guards: t -> (term * relation * logic_var * relation * term) list
-
-  (** [raise_error ctxt msg] raises a [Typing_error] exception with the given
-      message after appending the quantification from the context. *)
-  val raise_error: string -> t -> 'a
-
-  (** [error_invalid_pred ?warn_rel ctxt p] raises a [Typing_error] exception
-      with a message indicating that the predicate [p] is not valid in the
-      quantification. Depending on the state of [ctxt], more information about
-      missing bounds is added to the message. If [warn_rel] is [true], then a
-      reminder that only [Rle] and [Rlt] are allowed to guard quantified
-      variables is added to the message. *)
-  val raise_error_invalid_pred: ?warn_rel:bool -> predicate -> t -> 'a
-end = struct
-  type t = {
-    (** Quantification predicate being analyzed. *)
-    quantif: predicate;
-    (** Variables of the quantification that still need guards. *)
-    bounded_vars: Logic_var.Set.t;
-    (** Bounded variables list in reverse order in which they must be
-        generated. *)
-    rev_order: Logic_var.t list;
-    (** Table associating a bounded variable with its guard. *)
-    guards: (term * relation * (relation * term) option) Logic_var.Map.t;
-    (** Table associating a bounded variable with a relation with another
-        bounded variable. *)
-    linked_upper_bounds: (logic_var * relation) Logic_var.Map.t;
-  }
-
-  let empty quantif bounded_vars =
-    (* Check that the bounded vars have integer type and store them in a set. *)
-    let bounded_vars =
-      List.fold_left
-        (fun s v ->
-           let v =
-             match v.lv_type with
-             | Ctype ty when isIntegralType ty -> v
-             | Linteger -> v
-             | Ltype _ as ty when Logic_const.is_boolean_type ty -> v
-             | Ctype _ | Ltype _ | Lvar _ | Lreal | Larrow _ ->
-               Error.not_yet
-                 (error_msg
-                    quantif
-                    "@[non integer variable %a@]"
-                    Printer.pp_logic_var v)
-           in
-           Logic_var.Set.add v s
-        )
-        Logic_var.Set.empty
-        bounded_vars
-    in
-    {
-      quantif;
-      bounded_vars;
-      rev_order = [];
-      guards = Logic_var.Map.empty;
-      linked_upper_bounds = Logic_var.Map.empty;
-    }
-
-  let get_bounded_var t ctxt =
-    let rec aux t =
-      match t.term_node with
-      | TLogic_coerce(_, t) -> aux t
-      | TLval(TVar lv, TNoOffset) when Logic_var.Set.mem lv ctxt.bounded_vars ->
-        Some lv
-      | _ -> None
-    in
-    aux t
-
-  let has_unguarded_bounded_vars ctxt =
-    not (Logic_var.Set.is_empty ctxt.bounded_vars)
-
-  (** Pretty printer for a guard, represented by a tuple
-      [(term, relation, logic_var, relation, term)]. *)
-  let pp_guard fmt (t1, r1, lv, r2, t2) =
-    Format.fprintf
-      fmt
-      "@[%a %a %a %a %a@]"
-      Printer.pp_term t1
-      Printer.pp_relation r1
-      Printer.pp_logic_var lv
-      Printer.pp_relation r2
-      Printer.pp_term t2
-
-  (** Pretty printer for a lower bound, represented by the tuple
-      [(term, relation, logic_var)]. *)
-  let pp_lbound fmt (t, r, lv) =
-    Format.fprintf
-      fmt
-      "@[%a %a %a@]"
-      Printer.pp_term t
-      Printer.pp_relation r
-      Printer.pp_logic_var lv
-
-  (** Pretty printer for a bound between two quantified variables,
-      represented by the tuple [(logic_var, relation, logic_var)]. *)
-  let pp_linked_bound fmt (lv1, r, lv2) =
-    Format.fprintf
-      fmt
-      "@[%a %a %a@]"
-      Printer.pp_logic_var lv1
-      Printer.pp_relation r
-      Printer.pp_logic_var lv2
-
-  let add_lower_bound t r lv ctxt =
-    match Logic_var.Map.find_opt lv ctxt.guards with
-    | None ->
-      { ctxt with
-        guards = Logic_var.Map.add lv (t, r, None) ctxt.guards; }
-    | Some (t', r', None) ->
-      let msg =
-        Format.asprintf
-          "@[found existing lower bound %a@ when processing %a@ \
-           in quantification@ %a@]"
-          pp_lbound (t', r', lv)
-          pp_lbound (t, r, lv)
-          Printer.pp_predicate ctxt.quantif
-      in
-      Error.untypable msg
-    | Some (t1', r1', Some (r2', t2')) ->
-      let msg =
-        Format.asprintf
-          "@[found existing guard %a@ when processing %a@ \
-           in quantification@ %a@]"
-          pp_guard (t1', r1', lv, r2', t2')
-          pp_lbound (t, r, lv)
-          Printer.pp_predicate ctxt.quantif
-      in
-      Error.untypable msg
-
-  let add_linked_upper_bound lv1 r lv2 ctxt =
-    if Logic_var.Map.mem lv1 ctxt.guards then begin
-      { ctxt with
-        linked_upper_bounds =
-          Logic_var.Map.add lv2
-            (lv1, r)
-            ctxt.linked_upper_bounds; }
-    end else
-      let msg=
-        Format.asprintf
-          "@[missing lower bound for %a@ when processing the linked upper \
-           bound %a@ in quantification@ %a@]"
-          Printer.pp_logic_var lv1
-          pp_linked_bound (lv1, r, lv2)
-          Printer.pp_predicate ctxt.quantif
-      in
-      Error.untypable msg
-
-  let add_upper_bound lv r t ctxt =
-    (* Select the strictest relation between [r1] and [r2], with both relations
-       being either [Rlt] or [Rle]. *)
-    let strictest_relation r1 r2 =
-      match r1, r2 with
-      | (Rlt | Rle), Rlt | Rlt, Rle -> Rlt
-      | Rle, Rle -> Rle
-      | _, _ ->
-        Options.fatal
-          "invalid relations %a and %a in quantification %a"
-          Printer.pp_relation r1
-          Printer.pp_relation r2
-          Printer.pp_predicate ctxt.quantif
-    in
-    (* Replace the guard for [lv] to add the upper bound [lv r t], and
-       recursively walk the bounds linked to [lv] to also add upper bounds. *)
-    let rec replace_guard lv r t ctxt =
-      try
-        let lower_bound_t, lower_bound_r, _ =
-          Logic_var.Map.find lv ctxt.guards
-        in
-        let ctxt =
-          { ctxt with
-            guards =
-              Logic_var.Map.add
-                lv
-                (lower_bound_t, lower_bound_r, Some (r, t))
-                ctxt.guards; }
-        in
-        let ctxt =
-          { ctxt with
-            bounded_vars = Logic_var.Set.remove lv ctxt.bounded_vars; }
-        in
-        let need_upper_bound =
-          Logic_var.Map.find_opt lv ctxt.linked_upper_bounds
-        in
-        let ctxt =
-          match need_upper_bound with
-          | Some (lv', r') ->
-            let ctxt =
-              { ctxt with
-                linked_upper_bounds =
-                  Logic_var.Map.remove lv ctxt.linked_upper_bounds; }
-            in
-            replace_guard lv' (strictest_relation r r') t ctxt
-          | None -> ctxt
-        in
-        { ctxt with rev_order = lv :: ctxt.rev_order }
-      with Not_found ->
-        Error.untypable
-          (error_msg ctxt.quantif
-             "@[missing lower bound for %a@]"
-             Printer.pp_logic_var lv)
-    in
-    replace_guard lv r t ctxt
-
-  let check_validity ctxt =
-    if not (Logic_var.Map.is_empty ctxt.linked_upper_bounds) then
-      let msg =
-        let iter_keys f map_seq =
-          Seq.iter
-            (fun (key, _) -> f key)
-            map_seq
-        in
-        Format.asprintf
-          "@[missing upper bound%s for %a@ in quantification@ %a@]"
-          (if Logic_var.Map.cardinal ctxt.linked_upper_bounds = 1 then ""
-           else "s")
-          (Pretty_utils.pp_iter
-             ~sep:", "
-             iter_keys
-             Printer.pp_logic_var)
-          (Logic_var.Map.to_seq ctxt.linked_upper_bounds)
-          Printer.pp_predicate ctxt.quantif
-      in
-      Error.untypable msg
-    else if not (Logic_var.Set.is_empty ctxt.bounded_vars) then
-      let msg =
-        Format.asprintf
-          "@[missing lower bound%s for %a@ in quantification@ %a@]"
-          (if Logic_var.Set.cardinal ctxt.bounded_vars = 1 then "" else "s")
-          (Pretty_utils.pp_iter
-             ~sep:", "
-             Logic_var.Set.iter
-             Printer.pp_logic_var)
-          ctxt.bounded_vars
-          Printer.pp_predicate ctxt.quantif
-      in
-      Error.untypable msg
-
-  let retrieve_guards ctxt =
-    List.fold_left
-      (fun acc lv ->
-         match Logic_var.Map.find_opt lv ctxt.guards with
-         | Some (t1, r1, Some (r2, t2)) ->
-           (t1, r1, lv, r2, t2) :: acc
-
-         (* The error cases should not occur if the traversal of the
-            quantification was completed and [check_validity] was called
-            successfully. *)
-         | Some (_, _, None) ->
-           Options.fatal
-             "Missing upper bound when trying to retrieve the guard for %a"
-             Printer.pp_logic_var lv
-         | None -> Options.fatal "Missing guard for %a" Printer.pp_logic_var lv
-      )
-      []
-      ctxt.rev_order
-
-  let raise_error msg ctxt =
-    let msg2 =
-      Format.asprintf "@[ in quantification@ %a@]"
-        Printer.pp_predicate ctxt.quantif
-    in
-    Error.untypable (msg ^ msg2)
-
-  let raise_error_invalid_pred ?(warn_rel=false) p ctxt =
-    (* Extract the set of variables that have another variable for upper bound.
-       They will be considered valid for the purpose of the error message, ie.
-       if we have the relation [0 < i < j] with [0 < i] as an incomplete guard
-       and [i < j] as a linked upper bound, then the error is about [j] not
-       having an upper bound, not about [i]. *)
-    let linked_upper_bounds =
-      Logic_var.Map.fold
-        (fun _ (lv, _) acc -> Logic_var.Set.add lv acc)
-        ctxt.linked_upper_bounds
-        Logic_var.Set.empty
-    in
-
-    let missing_guards, missing_upper_bounds =
-      Logic_var.Set.fold
-        (fun lv (missing_guards, missing_upper_bounds) ->
-           match Logic_var.Map.find_opt lv ctxt.guards with
-           | Some (_, _, None)
-             when not (Logic_var.Set.mem lv linked_upper_bounds) ->
-             (* A variable with an incomplete constraint and without a linked
-                upper bound has a missing upper bound. *)
-             missing_guards, lv :: missing_upper_bounds
-           | None ->
-             (* A variable without a constraint has a missing guard. *)
-             lv :: missing_guards, missing_upper_bounds
-           | _ ->
-             (* Otherwise the variable either has a complete constraint, or an
-                incomplete constraint but with a linked upper bound. *)
-             missing_guards, missing_upper_bounds)
-        ctxt.bounded_vars
-        ([], [])
-    in
-
-    let msg =
-      Format.asprintf
-        "@[invalid guard %a@ in quantification@ %a.@ \
-         %a@,%a@ \
-         %t@]"
-        Printer.pp_predicate p Printer.pp_predicate ctxt.quantif
-        (Pretty_utils.pp_list
-           ~pre:"@[Missing guard for "
-           ~sep:",@ "
-           ~suf:".@]"
-           Printer.pp_logic_var)
-        (List.rev missing_guards)
-        (Pretty_utils.pp_list
-           ~pre:"@[Missing upper bound for "
-           ~sep:",@ "
-           ~suf:".@]"
-           Printer.pp_logic_var)
-        (List.rev missing_upper_bounds)
-        (fun fmt ->
-           if warn_rel then
-             Format.fprintf fmt
-               "@[Only %a and %a are allowed to guard quantifier variables@]"
-               Printer.pp_relation Rlt Printer.pp_relation Rle)
-    in
-    Error.untypable msg
-end
-
-(** [extract_constraint ctxt t1 r t2] populates the quantification context
-    [ctxt] with the constraint [t1 r t2], either adding a lower bound if [t2] is
-    a bounded variable or adding an upper bound if [t1] is a bounded variable.
-    @raises Typing_error if no constraint can be extracted or if the constraint
-    is invalid (no bounded variable in [t1] or [t2] for instance). *)
-let extract_constraint ctxt t1 r t2 =
-  (* Return the logic var corresponding to the given term or [None] if the term
-     is not a variable ([TLval(TVar _, TNoOffset)]). *)
-  let rec _get_logic_var_opt t =
-    match t.term_node with
-    | TLogic_coerce(_, t) -> _get_logic_var_opt t
-    | TLval(TVar x, TNoOffset) -> Some x
-    | _ -> None
-  in
-  (* Process the given relation *)
-  let lv1 = Constraints.get_bounded_var t1 ctxt in
-  let lv2 = Constraints.get_bounded_var t2 ctxt in
-  match lv1, lv2 with
-  | None, Some lv2 -> (* t1 value, t2 variable: store lower bound *)
-    Constraints.add_lower_bound t1 r lv2 ctxt
-  | Some lv1, None -> (* t1 variable, t2 value: store upper bound *)
-    Constraints.add_upper_bound lv1 r t2 ctxt
-  | Some lv1, Some lv2 ->
-    (* t1 variable, t2 variable: store link between t1 and t2 *)
-    let ctxt = Constraints.add_linked_upper_bound lv1 r lv2 ctxt in
-    Constraints.add_lower_bound t1 r lv2 ctxt
-  | None, None -> (* t1 value, t2 value: error *)
-    let msg =
-      Format.asprintf
-        "@[invalid constraint %a %a %a, both operands are constants or \
-         already bounded@]"
-        Printer.pp_term t1
-        Printer.pp_relation r
-        Printer.pp_term t2
-    in
-    Constraints.raise_error msg ctxt
-
-(** [visit_quantif_relations ~is_forall ctxt p] traverses the predicate [p] of
-    the quantification being analyzed in the context [ctxt] from left to right
-    as long as the predicate is [Pimplies], [Pand] or [Prel(Rlt | Rle)], and
-    calls [extract_constraint] on each relation [Rlt] or [Rle] it encounters
-    until all the guards of the quantification have been found or the predicate
-    is finished. If [is_forall] is [true] then the predicate being traversed is
-    a universal quantification, otherwise it is an existential quantification.
-    The function returns a tuple [ctxt, goal_opt] where [ctxt] is the
-    quantification context and [goal_opt] is either [None] if the goal of the
-    quantification has not been found yet or [Some goal] if [goal] is the
-    predicate corresponding to the goal of the quantification.
-    @raises Typing_error if the predicate contains something other than
-    [Pimplies], [Pand] or [Prel] with a relation that is neither [Rlt] nor
-    [Rle]. *)
-let rec visit_quantif_relations ~is_forall ctxt p =
-  match p.pred_content with
-  | Pimplies(lhs, rhs) ->
-    let ctxt, _ = visit_quantif_relations ~is_forall ctxt lhs in
-    if is_forall then begin
-      if Constraints.has_unguarded_bounded_vars ctxt then
-        visit_quantif_relations ~is_forall ctxt rhs
-      else
-        ctxt, Some rhs
-    end else
-      let msg =
-        Format.asprintf
-          "@[invalid quantification guard, expecting '%s' to continue@ \
-           bounding variables,@ found '%s'@]"
-          (if Kernel.Unicode.get () then Utf8_logic.conj else "&&")
-          (if Kernel.Unicode.get () then Utf8_logic.implies else "==>")
-      in
-      Constraints.raise_error msg ctxt
-  | Pand(lhs, rhs) ->
-    let ctxt, _ = visit_quantif_relations ~is_forall ctxt lhs in
-    if Constraints.has_unguarded_bounded_vars ctxt then
-      visit_quantif_relations ~is_forall ctxt rhs
-    else if not is_forall then
-      ctxt, Some rhs
-    else
-      let msg =
-        Format.asprintf
-          "@[invalid quantification predicate, expecting '%s' to@ \
-           separate the hypotheses from the goal, found '%s'@]"
-          (if Kernel.Unicode.get () then Utf8_logic.implies else "==>")
-          (if Kernel.Unicode.get () then Utf8_logic.conj else "&&")
-      in
-      Constraints.raise_error msg ctxt
-  | Prel((Rlt | Rle) as r, t1, t2) ->
-    let ctxt = extract_constraint ctxt t1 r t2 in
-    ctxt, None
-  | Prel _ ->
-    Constraints.raise_error_invalid_pred ~warn_rel:true p ctxt
-  | _ ->
-    Constraints.raise_error_invalid_pred p ctxt
-
-(** [compute_quantif_guards ~is_forall quantif bounded_vars p] computes the
-    guards for the bounded variables [bounded_vars] of the quantification
-    [quantif] from the predicate [p]. If [is_forall] is [true] then [quantif] is
-    a universal quantification, otherwise [quantif] is an existential
-    quantification.
-    The function returns the list of guards for the variables and the goal
-    predicate of the quantification. *)
-let compute_quantif_guards ~is_forall quantif bounded_vars p =
-  (* Traverse the predicate of the quantification to extract the guards of the
-     bounded variables. *)
-  let ctxt = Constraints.empty quantif bounded_vars in
-  let ctxt, goal = visit_quantif_relations ~is_forall ctxt p in
-  (* Check the validity of the result of the traversal. *)
-  Constraints.check_validity ctxt;
-  if Option.is_none goal then
-    let msg =
-      Format.asprintf
-        "@[no goal found in quantification@ %a@]"
-        Printer.pp_predicate quantif
-    in
-    Error.untypable msg
-  else
-    (* Traversal is valid, the guards and the goal can be retrieved and
-       returned. *)
-    let guards = Constraints.retrieve_guards ctxt in
-    let goal = Option.get goal in
-    guards, goal
-
-let () = Typing.compute_quantif_guards_ref := compute_quantif_guards
 
 (* It could happen that the bounds provided for a quantified [lv] are empty
    in the sense that [min <= lv <= max] but [min > max]. In such cases, \true