let get_signed_div_assertion
    ~simplify_constants:simplify_constants
    ~warning:warning
    dividend_expr divisor_expr =
  (* Signed division: overflow occurs when dividend is equal to the
     the minimum (negative) value for the signed integer type,
     and divisor is equal to -1. Under the hypothesis (cf value analysis) that integers are
     represented in two's completement.
     Nothing done for modulo (the result of TYPE_MIN % -1 is 0, which does not overflow)
     Still it may be dangerous on a number of compilers / architectures
     (modulo may be performed in parallel with divison)
  *)

  let t = Cil.typeOf divisor_expr in
  let size = bitsSizeOf t
  in
    (* check dividend_expr / divisor_expr : if constants ... *)
    if (size > 64) then (
      (* should never happen *)
      rte_warn "bitsSize of %a > 64: not treated" d_exp divisor_expr ;
      []
    )
    else
      let badValDividend =
        (* compute smallest representable "size bits" (signed) integer *)
        get_signed_min size
(*
        let min64 = Int64.min_int
        and shiftright_value = 64 - size
        in if shiftright_value > 0 then Int64.shift_right min64 shiftright_value else min64
*)

      and badValDivisor = Int64.minus_one
      in let assert_for_divisor () =
          Logic_const.prel
            (Req, translate_C_expr_to_term divisor_expr, Cil.lconstant badValDivisor)
         and assert_for_dividend () =
          Logic_const.prel
            (Req,
             translate_C_expr_to_term dividend_expr, Cil.lconstant badValDividend)
      in let assert_not_both () =
          Logic_const.pnot
            (Logic_const.pand (assert_for_divisor (), assert_for_dividend ()))
      in
        if simplify_constants then (
          let problem_with_divisor () =
            match get_expr_val divisor_expr with
              | None -> (false,false)
              | Some c64 ->
                  if Int64.compare c64 badValDivisor = 0
                  then (true,true)
                  else (true,false)
          and problem_with_dividend () =
            match get_expr_val dividend_expr with
              | None -> (false,false)
              | Some c64 ->
                  if Int64.compare c64 badValDividend = 0
                  then (true,true)
                  else (true,false)
          in
            match problem_with_divisor (), problem_with_dividend () with
              | (false,_), (false,_) -> (* neither divisor nor dividend is constant *)
                  (* Printf.eprintf "neither divisor nor dividend is constant\n";
                     flush stderr;  *)

                  [ (assert_not_both (), None) ]
              | (true,true), (true,true->
                  (* divisor and dividend are constant and have both bad values *)
                  (* Printf.eprintf
                     "divisor and dividend are constant and have both bad values\n";
                     flush stderr ; *)

                  let assertion = assert_not_both ()
                  in
                    if warning then
                      rte_warn
                        "signed overflow assert broken: %a" d_predicate_named assertion
                    ;
                    [ (assertion, Some (make_check_false ())) ]
              | (true,false), _
              | _ , (true,false->
                  (* one of divisor or dividend is constant and has a good value *)
                  (* Printf.eprintf
                     "one of divisor or dividend is constant and has a good value\n";
                     flush stderr; *)

                  []
              | (true,true), (false,_) ->
                  (* divisor is constant and has bad value, dividend is not constant *)
                  (* Printf.eprintf
                     "divisor is constant and has bad value, dividend is not constant\n";
                     flush stderr; *)

                  [ (Logic_const.pnot (assert_for_dividend ()), None) ]
              | (false,_), (true,true->
                  (* divisor is not constant, dividend is constant and has bad value *)
                  (* Printf.eprintf
                     "divisor is not constant, dividend is constant and has bad value\n";
                     flush stderr; *)

                  [ (Logic_const.pnot (assert_for_divisor ()), None) ]
        ) else [ (assert_not_both (), None) ]