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 division)
  *)

  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 fmt_warn_bitsize_over_64 d_exp divisor_expr ;
    []
  )
  else
    let badValDividend =
      (* compute smallest representable "size bits" (signed) integer *)
      min_signed_number 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 = My_bigint.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 My_bigint.equal c64 badValDivisor then (true,true)
                else (true,false)
            and problem_with_dividend () =
              match get_expr_val dividend_expr with
              | None -> (false,false)
              | Some c64 ->
                if My_bigint.equal c64 badValDividend 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
                  fmt_signed_overflow_assert
                  d_predicate_named assertion ;
              [ assertion, Some Property_status.False_if_reachable ]
            | (true,false), _
            | _ , (true,false->
              (* one of divisor or dividend is constant and has a good value *)
              []
            | (true,true), (false,_) ->
              (* divisor is constant and has bad value, dividend is not
                 constant *)

              [ Logic_const.pnot (assert_for_dividend ()), 
                None ]
            | (false,_), (true,true->
              (* divisor is not constant, dividend is constant and has bad
                 value *)

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