diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog
index 8b4811dcab9a7ff97db822f5f320e5272f156ffc..d7d32d53a4dd0612e6d93c27e4c2d82b40ffdea3 100644
--- a/src/plugins/e-acsl/doc/Changelog
+++ b/src/plugins/e-acsl/doc/Changelog
@@ -15,6 +15,10 @@
 #   E-ACSL: the Whole E-ACSL plug-in
 ###############################################################################
 
+-* E-ACSL       [2017/01/23] Fix bug with typing of unary and binary
+	        operations in a few cases: the generated code might have
+	        overflowed.
+
 #########################
 Plugin E-ACSL 0.8 Silicon
 #########################
diff --git a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c
index dc4cf863aa5d8da608a865a67699f723b633e52c..43b8d770a10ef6628fbb64bdb8c2d5ec8574127d 100644
--- a/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c
+++ b/src/plugins/e-acsl/tests/bts/oracle/gen_bts1326.c
@@ -121,7 +121,7 @@ void __gen_e_acsl_atp_NORMAL_computeAverageAccel(ArrayInt *Accel,
     __e_acsl_assert(__gen_e_acsl_valid_read_6,(char *)"RTE",
                     (char *)"atp_NORMAL_computeAverageAccel",
                     (char *)"mem_access: \\valid_read(__gen_e_acsl_at)",8);
-    __e_acsl_assert(*__gen_e_acsl_at == (int)((((((*__gen_e_acsl_at_2)[4L] + (*__gen_e_acsl_at_3)[3L]) + (*__gen_e_acsl_at_4)[2L]) + (*__gen_e_acsl_at_5)[1L]) + (*__gen_e_acsl_at_6)[0L]) / 5L),
+    __e_acsl_assert(*__gen_e_acsl_at == (int)((((((*__gen_e_acsl_at_2)[4L] + (long)(*__gen_e_acsl_at_3)[3L]) + (*__gen_e_acsl_at_4)[2L]) + (*__gen_e_acsl_at_5)[1L]) + (*__gen_e_acsl_at_6)[0L]) / 5L),
                     (char *)"Postcondition",
                     (char *)"atp_NORMAL_computeAverageAccel",
                     (char *)"*\\old(AverageAccel) ==\n(((((*\\old(Accel))[4] + (*\\old(Accel))[3]) + (*\\old(Accel))[2]) +\n  (*\\old(Accel))[1])\n + (*\\old(Accel))[0])\n/ 5",
diff --git a/src/plugins/e-acsl/tests/gmp/arith.i b/src/plugins/e-acsl/tests/gmp/arith.i
index eed3887af85ba1a70ad066546745204144166854..df97877fb148968c52cd69013790c311dcf6160b 100644
--- a/src/plugins/e-acsl/tests/gmp/arith.i
+++ b/src/plugins/e-acsl/tests/gmp/arith.i
@@ -33,5 +33,7 @@ int main(void) {
   // example from the JFLA'15 paper (but for a 64-bit architecture)
   /*@ assert 1 + ((z+1) / (y-123456789123456789)) == 1; */
 
+  /*@ assert 1 - x == -x + 1; */ // test GIT issue #37
+
   return 0;
 }
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_arith.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_arith.c
index 56530af0d60dc28ef6da987a0b645806ae960094..c73057d06af41dc853049df7332779b0d64e0227 100644
--- a/src/plugins/e-acsl/tests/gmp/oracle/gen_arith.c
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_arith.c
@@ -69,7 +69,7 @@ int main(void)
   __e_acsl_assert(3 % -2 == 1,(char *)"Assertion",(char *)"main",
                   (char *)"3 % -2 == 1",21);
   /*@ assert ((x * 2 + (3 + y)) - 4) + (x - y) ≡ -10; */
-  __e_acsl_assert(((x * 2L + (3L + y)) - 4L) + (x - y) == -10,
+  __e_acsl_assert(((x * 2L + (3L + y)) - 4L) + (x - (long)y) == -10,
                   (char *)"Assertion",(char *)"main",
                   (char *)"((x * 2 + (3 + y)) - 4) + (x - y) == -10",23);
   /*@ assert (0 ≡ 1) ≡ !(0 ≡ 0); */
@@ -140,6 +140,9 @@ int main(void)
       __gmpz_clear(__gen_e_acsl_div_2);
     }
   }
+  /*@ assert 1 - x ≡ -x + 1; */
+  __e_acsl_assert(1L - x == - ((long)x) + 1L,(char *)"Assertion",
+                  (char *)"main",(char *)"1 - x == -x + 1",36);
   __retres = 0;
   return __retres;
 }
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_arith2.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_arith2.c
index fc3b73b7c6fc4a1aa940119988e5f88abd312882..b092d8e8ad93c34d05743915c1c8681d875334af 100644
--- a/src/plugins/e-acsl/tests/gmp/oracle/gen_arith2.c
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_arith2.c
@@ -688,6 +688,39 @@ int main(void)
       __gmpz_clear(__gen_e_acsl_add_6);
     }
   }
+  /*@ assert 1 - x ≡ -x + 1; */
+  {
+    {
+      __e_acsl_mpz_t __gen_e_acsl__60;
+      __e_acsl_mpz_t __gen_e_acsl_x_9;
+      __e_acsl_mpz_t __gen_e_acsl_sub_5;
+      __e_acsl_mpz_t __gen_e_acsl_neg_15;
+      __e_acsl_mpz_t __gen_e_acsl_add_7;
+      int __gen_e_acsl_eq_21;
+      __gmpz_init_set_si(__gen_e_acsl__60,1L);
+      __gmpz_init_set_si(__gen_e_acsl_x_9,(long)x);
+      __gmpz_init(__gen_e_acsl_sub_5);
+      __gmpz_sub(__gen_e_acsl_sub_5,
+                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__60),
+                 (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_9));
+      __gmpz_init(__gen_e_acsl_neg_15);
+      __gmpz_neg(__gen_e_acsl_neg_15,
+                 (__e_acsl_mpz_struct const *)(__gen_e_acsl_x_9));
+      __gmpz_init(__gen_e_acsl_add_7);
+      __gmpz_add(__gen_e_acsl_add_7,
+                 (__e_acsl_mpz_struct const *)(__gen_e_acsl_neg_15),
+                 (__e_acsl_mpz_struct const *)(__gen_e_acsl__60));
+      __gen_e_acsl_eq_21 = __gmpz_cmp((__e_acsl_mpz_struct const *)(__gen_e_acsl_sub_5),
+                                      (__e_acsl_mpz_struct const *)(__gen_e_acsl_add_7));
+      __e_acsl_assert(__gen_e_acsl_eq_21 == 0,(char *)"Assertion",
+                      (char *)"main",(char *)"1 - x == -x + 1",36);
+      __gmpz_clear(__gen_e_acsl__60);
+      __gmpz_clear(__gen_e_acsl_x_9);
+      __gmpz_clear(__gen_e_acsl_sub_5);
+      __gmpz_clear(__gen_e_acsl_neg_15);
+      __gmpz_clear(__gen_e_acsl_add_7);
+    }
+  }
   __retres = 0;
   return __retres;
 }
diff --git a/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c b/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c
index 4a5071bb3d864f0ba84a6858981168053b4faeee..ff2254d54665a3f37e39f4cce403ebec896364fa 100644
--- a/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c
+++ b/src/plugins/e-acsl/tests/gmp/oracle/gen_at.c
@@ -113,7 +113,7 @@ int h(int x)
 
 int main(void)
 {
-  int __gen_e_acsl_at_3;
+  long __gen_e_acsl_at_3;
   long __gen_e_acsl_at_2;
   int __gen_e_acsl_at;
   int __retres;
@@ -125,7 +125,7 @@ int main(void)
   __e_acsl_full_init((void *)(& x));
   x = __gen_e_acsl_h(0);
   L:
-    __gen_e_acsl_at_3 = x;
+    __gen_e_acsl_at_3 = (long)x;
     __gen_e_acsl_at_2 = x + 1L;
     __gen_e_acsl_at = x;
     /*@ assert x ≡ 0; */
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_function_contract.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_function_contract.c
index 5cde7c00ea1752ff48fb5a6cab651253e8dbbeb3..a27a3104873ffe16294aee8f1e98b1190c03a967 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/gen_function_contract.c
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_function_contract.c
@@ -233,11 +233,11 @@ void __gen_e_acsl_n(void)
  */
 void __gen_e_acsl_m(void)
 {
-  int __gen_e_acsl_at_4;
+  long __gen_e_acsl_at_4;
   int __gen_e_acsl_at_3;
   int __gen_e_acsl_at_2;
   int __gen_e_acsl_at;
-  __gen_e_acsl_at_4 = X;
+  __gen_e_acsl_at_4 = (long)X;
   {
     int __gen_e_acsl_and_2;
     if (X == 5) __gen_e_acsl_and_2 = Y == 2; else __gen_e_acsl_and_2 = 0;
@@ -312,7 +312,7 @@ void __gen_e_acsl_k(void)
                     (char *)"k",(char *)"X == 3 && Y == 2 ==> X == 3",42);
     if (X == 3) __gen_e_acsl_and_2 = Y == 2; else __gen_e_acsl_and_2 = 0;
     if (! __gen_e_acsl_and_2) __gen_e_acsl_implies_3 = 1;
-    else __gen_e_acsl_implies_3 = X + Y == 5L;
+    else __gen_e_acsl_implies_3 = X + (long)Y == 5L;
     __e_acsl_assert(__gen_e_acsl_implies_3,(char *)"Precondition",
                     (char *)"k",(char *)"X == 3 && Y == 2 ==> X + Y == 5",43);
     k();
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_result.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_result.c
index 196e1a37605049d23495bcc07b7a8b45d30c3ae2..4b706094131500fea65fe8e1d68882cb5b16b853 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/gen_result.c
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_result.c
@@ -64,10 +64,10 @@ int __gen_e_acsl_g(int x)
 int __gen_e_acsl_f(int x)
 {
   int __gen_e_acsl_at_2;
-  int __gen_e_acsl_at;
+  long __gen_e_acsl_at;
   int __retres;
   __gen_e_acsl_at_2 = x;
-  __gen_e_acsl_at = x;
+  __gen_e_acsl_at = (long)x;
   __retres = f(x);
   __e_acsl_assert(__retres == (int)(__gen_e_acsl_at - __gen_e_acsl_at_2),
                   (char *)"Postcondition",(char *)"f",
diff --git a/src/plugins/e-acsl/tests/runtime/oracle/gen_stmt_contract.c b/src/plugins/e-acsl/tests/runtime/oracle/gen_stmt_contract.c
index 79680b69a4a6b7788e6b44ce003cfe60c0b5bda6..820ed8e257187d129ec5adfb9d838270c0911b5c 100644
--- a/src/plugins/e-acsl/tests/runtime/oracle/gen_stmt_contract.c
+++ b/src/plugins/e-acsl/tests/runtime/oracle/gen_stmt_contract.c
@@ -87,7 +87,7 @@ int main(void)
                       37);
       if (x == 3) __gen_e_acsl_and_2 = y == 2; else __gen_e_acsl_and_2 = 0;
       if (! __gen_e_acsl_and_2) __gen_e_acsl_implies_3 = 1;
-      else __gen_e_acsl_implies_3 = x + y == 5L;
+      else __gen_e_acsl_implies_3 = x + (long)y == 5L;
       __e_acsl_assert(__gen_e_acsl_implies_3,(char *)"Precondition",
                       (char *)"main",
                       (char *)"x == 3 && y == 2 ==> x + y == 5",38);
diff --git a/src/plugins/e-acsl/typing.ml b/src/plugins/e-acsl/typing.ml
index f15a5d1612a49dc6b9e080bf877196f1aeb292cb..69d75cfcbc566c6f8bb35423bbc30ef5fe0423fb 100644
--- a/src/plugins/e-acsl/typing.ml
+++ b/src/plugins/e-acsl/typing.ml
@@ -197,14 +197,18 @@ let ty_of_interv ?ctx i =
 
 (* compute a new {!computed_info} by coercing the given type [ty] to the given
    context [ctx]. [op] is the type for the operator. *)
-let coerce ~ctx ~op ty =
+let coerce ~arith_operand ~ctx ~op ty =
   if compare ty ctx = 1 then begin
     (* type larger than the expected context,
        so we must introduce an explicit cast *)
     { ty; op; cast = Some ctx }
   end else
-    (* only add an explicit cast if the context is [Gmp] and [ty] is not *)
-    if ctx = Gmp && ty <> Gmp then { ty; op; cast = Some Gmp }
+    (* only add an explicit cast if the context is [Gmp] and [ty] is not;
+       or if the term corresponding to [ty] is an operand of an arithmetic
+       operation which must be explicitely coerced in order to force the
+       operation to be of the expected type. *)
+    if (ctx = Gmp && ty <> Gmp) || arith_operand
+    then { ty; op; cast = Some ctx }
     else { ty; op; cast = None }
 
 (******************************************************************************)
@@ -221,7 +225,7 @@ let mk_ctx ~force c =
 
 (* type the term [t] in a context [ctx]. Take --e-acsl-gmp-only into account iff
    not [force]. *)
-let rec type_term ~force ?ctx t =
+let rec type_term ~force ?(arith_operand=false) ?ctx t =
   let ctx = Extlib.opt_map (mk_ctx ~force) ctx in
   let dup ty = ty, ty in
   let compute_ctx ?ctx i =
@@ -302,7 +306,7 @@ let rec type_term ~force ?ctx t =
         with Interval.Not_an_integer ->
           dup Other (* real *)
       in
-      ignore (type_term ~force:false ~ctx t');
+      ignore (type_term ~force ~arith_operand:true ~ctx t');
       (match unop with
       | LNot -> c_int, ctx_res (* converted into [t == 0] in case of GMP *)
       | Neg | BNot -> dup ctx_res)
@@ -317,8 +321,18 @@ let rec type_term ~force ?ctx t =
         with Interval.Not_an_integer ->
           dup Other (* real *)
       in
-      ignore (type_term ~force ~ctx t1);
-      ignore (type_term ~force ~ctx t2);
+      (* it is enough to explicitely coerce when required one operand to [ctx]
+         (through [arith_operand]) in order to force the type of the operation.
+         Heuristic: coerce the operand which is not a lval in order to lower
+         the number of explicit casts *)
+      let rec cast_first t1 t2 = match t1.term_node with
+        | TLval _ -> false
+        | TLogic_coerce(_, t) -> cast_first t t2
+        | _ -> true
+      in
+      let cast_first = cast_first t1 t2 in
+      ignore (type_term ~force ~arith_operand:cast_first ~ctx t1);
+      ignore (type_term ~force ~arith_operand:(not cast_first) ~ctx t2);
       dup ctx_res
 
     | TBinOp ((Lt | Gt | Le | Ge | Eq | Ne), t1, t2) ->
@@ -390,7 +404,7 @@ let rec type_term ~force ?ctx t =
       dup ctx
 
     | Tat (t, _)
-    | TLogic_coerce (_, t) -> dup (type_term ~force ?ctx t).ty
+    | TLogic_coerce (_, t) -> dup (type_term ~force ~arith_operand ?ctx t).ty
 
     | TCoerceE (t1, t2) ->
       let ctx =
@@ -454,7 +468,7 @@ let rec type_term ~force ?ctx t =
       let ty, op = infer t in
       match ctx with
       | None -> { ty; op; cast = None }
-      | Some ctx -> coerce ~ctx ~op ty)
+      | Some ctx -> coerce ~arith_operand ~ctx ~op ty)
     t
 
 and type_term_lval (host, offset) =
@@ -574,7 +588,7 @@ let rec type_predicate p =
     | Pfresh _ -> Error.not_yet "\\fresh"
     | Psubtype _ -> Error.not_yet "subtyping relation" (* Jessie specific *)
   in
-  coerce ~ctx:c_int ~op c_int
+  coerce ~arith_operand:false ~ctx:c_int ~op c_int
 
 let type_term ~force ?ctx t =
   Options.feedback ~dkey ~level:4 "typing term '%a' in ctx '%a'."