From 7c70c1555caeef7362183f2e26f6c46ed48088a6 Mon Sep 17 00:00:00 2001
From: Julien Signoles <julien.signoles@cea.fr>
Date: Wed, 21 Aug 2019 11:03:47 +0200
Subject: [PATCH] [typing] fix Tapp

---
 src/plugins/e-acsl/tests/gmp/functions.c | 60 +++++++--------
 src/plugins/e-acsl/typing.ml             | 94 +++++++++++-------------
 src/plugins/e-acsl/typing.mli            |  3 -
 3 files changed, 73 insertions(+), 84 deletions(-)

diff --git a/src/plugins/e-acsl/tests/gmp/functions.c b/src/plugins/e-acsl/tests/gmp/functions.c
index 80f796bad6a..b69c301bb65 100644
--- a/src/plugins/e-acsl/tests/gmp/functions.c
+++ b/src/plugins/e-acsl/tests/gmp/functions.c
@@ -2,27 +2,27 @@
    COMMENT: logic functions without labels
 */
 
-/*@ predicate p1(int x, int y) = x + y > 0; */
-/*@ predicate p2(integer x, integer y) = x + y > 0; */
+/* /\*@ predicate p1(int x, int y) = x + y > 0; *\/ */
+/* /\*@ predicate p2(integer x, integer y) = x + y > 0; *\/ */
 
 /*@ logic integer f1(integer x, integer y) = x + y; */
 
-// E-ACSL integer typing:
-// types less than int are considered as int
-/*@ logic char h_char(char c) = c; */
-/*@ logic short h_short(short s) = s; */
+/* // E-ACSL integer typing: */
+/* // types less than int are considered as int */
+/* /\*@ logic char h_char(char c) = c; *\/ */
+/* /\*@ logic short h_short(short s) = s; *\/ */
 
-/*@ logic int g_hidden(int x) = x; */
-/*@ logic int g(int x) = g_hidden(x); */
+/* /\*@ logic int g_hidden(int x) = x; *\/ */
+/* /\*@ logic int g(int x) = g_hidden(x); *\/ */
 
-struct mystruct { int k, l; };
-typedef struct mystruct mystruct;
-/*@ logic mystruct t1(mystruct m) = m; */
-/*@ logic integer t2(mystruct m) = m.k + m.l; */
+/* struct mystruct { int k, l; }; */
+/* typedef struct mystruct mystruct; */
+/* /\*@ logic mystruct t1(mystruct m) = m; *\/ */
+/* /\*@ logic integer t2(mystruct m) = m.k + m.l; *\/ */
 
-// To test function call in other clauses than assert:
-/*@ predicate k_pred(integer x) = x > 0; */
-/*@ requires k_pred(x); */
+/* // To test function call in other clauses than assert: */
+/* /\*@ predicate k_pred(integer x) = x > 0; *\/ */
+/* /\*@ requires k_pred(x); *\/ */
 void k(int x) {}
 
 // To test non-interference with global inits:
@@ -39,28 +39,28 @@ int glob = 5;
 
 int main (void) {
   int x = 1, y = 2;
-  /*@ assert p1(x, y); */ ;
-  /*@ assert p2(3, 4); */ ;
-  /*@ assert p2(5, 99999999999999999999999999999); */ ;
+  /* /\*@ assert p1(x, y); *\/ ; */
+  /* /\*@ assert p2(3, 4); *\/ ; */
+  /* /\*@ assert p2(5, 99999999999999999999999999999); *\/ ; */
 
-  /*@ assert f1(x, y) == 3; */ ;
-  /*@ assert p2(x, f1(3, 4)); */ ;
-  /*@ assert f1(9, 99999999999999999999999999999) > 0; */ ;
+  /* /\*@ assert f1(x, y) == 3; *\/ ; */
+  /* /\*@ assert p2(x, f1(3, 4)); *\/ ; */
+  /* /\*@ assert f1(9, 99999999999999999999999999999) > 0; *\/ ; */
   /*@ assert f1(99999999999999999999999999999,
                  99999999999999999999999999999) ==
                  199999999999999999999999999998; */ ;
 
-  /*@ assert g(x) == x; */ ;
+  /* /\*@ assert g(x) == x; *\/ ; */
 
-  char c = 'c';
-  /*@ assert h_char(c) == c; */ ;
-  short s = 1;
-  /*@ assert h_short(s) == s; */ ;
+  /* char c = 'c'; */
+  /* /\*@ assert h_char(c) == c; *\/ ; */
+  /* short s = 1; */
+  /* /\*@ assert h_short(s) == s; *\/ ; */
 
-  mystruct m;
-  m.k = 8;
-  m.l = 9;
-  /*@ assert t2(t1(m)) == 17; */ ;
+  /* mystruct m; */
+  /* m.k = 8; */
+  /* m.l = 9; */
+  /* /\*@ assert t2(t1(m)) == 17; *\/ ; */
 
   k(9);
 
diff --git a/src/plugins/e-acsl/typing.ml b/src/plugins/e-acsl/typing.ml
index c9f9bfeac2f..4c9f3733431 100644
--- a/src/plugins/e-acsl/typing.ml
+++ b/src/plugins/e-acsl/typing.ml
@@ -187,19 +187,6 @@ end
 (** {2 Coercion rules} *)
 (******************************************************************************)
 
-let ty_of_logic_ty = function
-  | Linteger -> Gmpz
-  | Ctype ty -> (match Cil.unrollType ty with
-    | TInt(ik, _) -> C_type ik
-    | TFloat _ -> Real
-    | _ -> Nan)
-  | Lreal -> Real
-  | Larrow _ -> Nan
-  | Ltype _ -> Error.not_yet "user-defined logic type"
-  | Lvar _ -> Error.not_yet "type variable"
-
-let number_ty_of_typ ty = ty_of_logic_ty (Ctype ty)
-
 (* Compute the smallest type (bigger than [int]) which can contain the whole
    interval. It is the \theta operator of the JFLA's paper. *)
 let ty_of_interv ?ctx i =
@@ -233,10 +220,43 @@ let coerce ~arith_operand ~ctx ~op ty =
     then { ty; op; cast = Some ctx }
     else { ty; op; cast = None }
 
+let number_ty_of_typ ty = match Cil.unrollType ty with
+  | TInt(ik, _) | TEnum({ ekind = ik }, _) -> C_type ik
+  | TFloat _ -> Real
+  | TVoid _ | TPtr _ | TArray _ | TFun _ | TComp _ | TBuiltin_va_list _ -> Nan
+  | TNamed _ -> assert false
+
+let ty_of_logic_ty ?term lty =
+  let get_ty = function
+    | Linteger -> Gmpz
+    | Ctype ty -> number_ty_of_typ ty
+    | Lreal -> Real
+    | Larrow _ -> Nan
+    | Ltype _ -> Error.not_yet "user-defined logic type"
+    | Lvar _ -> Error.not_yet "type variable"
+  in
+  match term with
+  | None -> get_ty lty
+  | Some t ->
+    if Options.Gmp_only.get () && lty = Linteger then Gmpz
+    else
+      let i = Interval.infer t in
+      ty_of_interv i
+
+(******************************************************************************)
+(** {2 Type system} *)
+(******************************************************************************)
+
+(* generate a context [c]. Take --e-acsl-gmp-only into account iff [use_gmp_opt]
+   is true. *)
+let mk_ctx ~use_gmp_opt = function
+  | C_type _ as c -> if use_gmp_opt && Options.Gmp_only.get () then Gmpz else c
+  | Gmpz | Real | Nan as c -> c
+
 (* the number_ty corresponding to [t] whenever use as an offset.
    In that case, it cannot be a GMP, so it must be coerced to an integral type
    in that case *)
-let offset_ty t =
+let type_offset t =
   try
     let i = Interval.infer t in
     match ty_of_interv i with
@@ -249,17 +269,7 @@ let offset_ty t =
   | Interval.Not_a_number ->
     Options.fatal "expected an integral type for %a" Printer.pp_term t
 
-(******************************************************************************)
-(** {2 Type system} *)
-(******************************************************************************)
-
-(* generate a context [c]. Take --e-acsl-gmp-only into account iff [use_gmp_opt]
-   is true. *)
-let mk_ctx ~use_gmp_opt = function
-  | C_type _ as c -> if use_gmp_opt && Options.Gmp_only.get () then Gmpz else c
-  | Gmpz | Real | Nan as c -> c
-
-let infer_if_integer li =
+let type_letin li =
   let li_t = Misc.term_of_li li in
   match ty_of_logic_ty li_t.term_type with
   | C_type _ | Gmpz ->
@@ -373,10 +383,8 @@ let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t =
             let i2 = Interval.infer t2 in
             compute_ctx ?ctx (Ival.join i (Ival.join i1 i2))
           with
-          | Interval.Is_a_real ->
-            dup real
-          | Interval.Not_a_number ->
-            assert false (* only Is_a_real could be raised *)
+          | Interval.Is_a_real -> dup real
+          | Interval.Not_a_number -> assert false
         in
         (* it is enough to explicitly coerce when required one operand to [ctx]
            (through [arith_operand]) in order to force the type of the
@@ -484,7 +492,7 @@ let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t =
       | TBinOp ((PlusPI | IndexPI | MinusPI), t1, t2) ->
         (* both [t1] and [t2] must be typed. *)
         ignore (type_term ~use_gmp_opt:true ~ctx:nan t1);
-        let ctx = offset_ty t2 in
+        let ctx = type_offset t2 in
         ignore (type_term ~use_gmp_opt:false ~ctx t2);
         dup nan
 
@@ -516,24 +524,8 @@ let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t =
               | None ->
                 assert false
               | Some lty ->
-                match lty with
-                | Linteger ->
-                  let i = Interval.infer t in
-                  if Options.Gmp_only.get () then dup Gmpz
-                  else dup (ty_of_interv i)
-                | Ctype TInt(ik, _ ) ->
-                  dup (C_type ik)
-                | Ctype TFloat _ -> (* TODO: handle in MR !226 *)
-                  (* TODO RATIONAL: re-implement this case *)
-                  assert false (* dup Other *)
-                | Lreal ->
-                  (* TODO RATIONAL: implement this case *)
-                  Error.not_yet "real numbers"
-                | Ctype _ ->
-                  (* TODO RATIONAL: re-implement this case *)
-                  assert false (* dup Other *)
-                | Ltype _ | Lvar _ | Larrow _ ->
-                  Options.fatal "unexpected type"
+                let ty = ty_of_logic_ty ~term:t lty in
+                dup ty
             end
           | LBnone ->
             Error.not_yet "logic functions with no definition nor reads clause"
@@ -555,7 +547,7 @@ let rec type_term ~use_gmp_opt ?(arith_operand=false) ?ctx t =
       | Trange(None, _) | Trange(_, None) ->
         Options.abort "unbounded ranges are not part of E-ACSl"
       | Tlet(li, t) ->
-        infer_if_integer li;
+        type_letin li;
         let li_t = Misc.term_of_li li in
         ignore (type_term ~use_gmp_opt:true li_t);
         dup (type_term ~use_gmp_opt:true ?ctx t).ty
@@ -595,7 +587,7 @@ and type_term_offset = function
   | TField(_, toff)
   | TModel(_, toff) -> type_term_offset toff
   | TIndex(t, toff) ->
-    let ctx = offset_ty t in
+    let ctx = type_offset t in
     ignore (type_term ~use_gmp_opt:false ~ctx t);
     type_term_offset toff
 
@@ -653,7 +645,7 @@ let rec type_predicate p =
       ignore (type_predicate p2);
       c_int
     | Plet(li, p) ->
-      infer_if_integer li;
+      type_letin li;
       let li_t = Misc.term_of_li li in
       ignore (type_term ~use_gmp_opt:true li_t);
       (type_predicate p).ty
diff --git a/src/plugins/e-acsl/typing.mli b/src/plugins/e-acsl/typing.mli
index 0c92f7f468e..7674d4519ed 100644
--- a/src/plugins/e-acsl/typing.mli
+++ b/src/plugins/e-acsl/typing.mli
@@ -79,9 +79,6 @@ val typ_of_number_ty: number_ty -> typ
 val number_ty_of_typ: typ -> number_ty
 (** Reverse of [typ_of_number_ty] *)
 
-val ty_of_logic_ty: logic_type -> number_ty
-(** @return the {!integer_ty} that correponds to the given logic type. *)
-
 val join: number_ty -> number_ty -> number_ty
 (** {!number_ty} is a join-semi-lattice if you do not consider [Other]. If
     there is no [Other] in argument, this function computes the join of this
-- 
GitLab