let get_multsubadd_assertion
~simplify_constants:simplify_constants
~warning:warning
full_expr op expr1 expr2 =
let t = Cil.typeOf full_expr in
let size = bitsSizeOf t
in if (size > 64) then (
rte_warn "bitsSize of %a > 64: not treated" d_exp full_expr ;
[]
)
else
let (minType,maxType) = (get_signed_min size, get_signed_max size) in
let full_add_term () =
let term1 = translate_C_expr_to_term ~cast:false expr1
and term2 = translate_C_expr_to_term ~cast:false expr2
in Logic_const.term (TBinOp (op, term1,term2)) (Ctype t)
in
let assertion_le () = assertion_le (full_add_term ()) maxType
and assertion_ge () = assertion_ge (full_add_term ()) minType in
let full_assertion () = Logic_const.pand (assertion_le (), assertion_ge ())
in
if simplify_constants then (
match get_expr_val expr1, get_expr_val expr2 with
| Some a64, Some b64 ->
let big_a64 = Int.of_int64 a64
and big_b64 = Int.of_int64 b64
in
if op = MinusA then
let big_diff = Int.sub big_a64 big_b64
in if Int.compare big_diff (Int.of_int64 minType) < 0 then
let assertion = assertion_ge ()
in
if warning then
rte_warn
"signed overflow assert broken: %a"
d_predicate_named assertion
;
[ (assertion, Some (make_check_false ())) ]
else [ ]
else if op = PlusA then
let big_add = Int.add big_a64 big_b64
in if Int.compare big_add (Int.of_int64 maxType) > 0 then
let assertion = assertion_le ()
in
if warning then
rte_warn
"signed overflow assert broken: %a"
d_predicate_named assertion
;
[ (assertion, Some (make_check_false ())) ]
else [ ]
else (
assert(op = Mult) ;
let big_mult = Int.mul big_a64 big_b64
in let b_ov = (Int.compare big_mult (Int.of_int64 maxType) > 0)
in if b_ov then
let assertion = assertion_le ()
in
if warning then
rte_warn
"signed overflow assert broken: %a"
d_predicate_named assertion
;
[ (assertion, Some (make_check_false ())) ]
else let b_uv = (Int.compare big_mult (Int.of_int64 minType) < 0)
in if b_uv then
let assertion = assertion_ge ()
in
if warning then
rte_warn
"signed overflow assert broken: %a"
d_predicate_named assertion
;
[ (assertion, Some (make_check_false ())) ]
else [ ]
)
| Some a64, None
| None, Some a64 ->
if op = MinusA then [ (assertion_ge (), None) ]
else if op = PlusA then [ (assertion_le (), None) ]
else (
assert(op = Mult);
if (Int64.compare a64 Int64.zero = 0) ||
(Int64.compare a64 Int64.one = 0) then []
else
if (Int64.compare a64 (Int64.of_int (-1)) = 0) then
[ (assertion_le (), None) ]
else [ (full_assertion (), None) ]
)
| None,None -> [ (full_assertion (), None) ]
) else [ (full_assertion (), None) ]