let eval_expr ~with_alarms state expr = match expr.enode with
| BinOp ((MinusA | MinusPP | Eq | Ne | Ge | Le | Gt | Lt as op),e1,e2,_) ->
let state, ev1 = !Db.Value.eval_expr_with_state ~with_alarms state e1 in
let state, ev2 = !Db.Value.eval_expr_with_state ~with_alarms state e2 in
CilE.set_syntactic_context (CilE.SyBinOp (op,e1,e2));
begin
match unrollType (typeOf e1) with
| TFloat _ ->
state,Cvalue_type.V.top
| TInt _ | TPtr (_, _) | _ ->
let compute_diff acc =
let lv1 = !Db.Value.find_lv_plus ~with_alarms state e1 in
let lv2 = !Db.Value.find_lv_plus ~with_alarms state e2 in
List.fold_left
(fun acc (lv1, offs1) ->
let loc1 = !Db.Value.lval_to_loc_state state lv1 in
List.fold_left
(fun acc (lv2, offs2) ->
let loc2 = !Db.Value.lval_to_loc_state state lv2 in
try
let new_v =
V.location_shift
(Ival.sub offs1 offs2)
(Relations_type.Model.compute_diff
state loc1 loc2)
in
assert (V.is_included new_v acc);
new_v
with Relations_type.Use_Main_Memory -> acc)
acc
lv2)
acc
lv1
in
match op with
| MinusA -> state,compute_diff Cvalue_type.V.top
| MinusPP ->
let minus_val = compute_diff Cvalue_type.V.top in
let r =
try
let size = Int_Base.project
(sizeof_pointed(Cil.typeOf e1))
in
let size = Int.div size Int.eight in
if Int.is_one size then
minus_val
else
let minus_val =
Cvalue_type.V.project_ival minus_val
in
Cvalue_type.V.inject_ival
(Ival.scale_div ~pos:true size minus_val)
with
Int_Base.Error_Top
| Cvalue_type.V.Not_based_on_null
| Not_found ->
V.join
(V.topify_arith_origin ev1)
(V.topify_arith_origin ev2)
in
state, r
| Eq | Ne | Ge | Le | Gt | Lt ->
let r =
let warn, ev1, ev2 = check_comparable ev1 ev2 in
if warn
then begin
CilE.warn_pointer_comparison with_alarms;
end;
if warn && Value_parameters.UndefinedPointerComparisonPropagateAll.get ()
then V.zero_or_one
else
let f = match op with
| Eq -> V.check_equal true
| Ne -> V.check_equal false
| Ge -> V.comparisons ">=" V.do_ge
| Le -> V.comparisons "<=" V.do_le
| Gt -> V.comparisons ">" V.do_gt
| Lt -> V.comparisons "<" V.do_lt
| _ -> assert false
in
let diff = compute_diff V.top in
let result = f diff V.singleton_zero in
if V.cardinal_zero_or_one result
then result
else f ev1 ev2
in
state, r
| _ -> state,Cvalue_type.V.top
end
| _ -> state,Cvalue_type.V.top