let rec stripCastsDeepForPtrArith (e:exp): exp =
match e.enode with
| CastE(t, e') when not(isTypeVolatile t) -> begin
let e' = stripCastsDeepForPtrArith e' in
match unrollType (typeOf e'), unrollType t with
| TPtr (bt1, _), TPtr (bt2, _) -> begin
try
if bitsSizeOf bt1 = bitsSizeOf bt2 then
e'
else
new_exp (CastE(t,e'))
with SizeOfError _ ->
new_exp (CastE(t,e'))
end
| _, _ -> new_exp (CastE(t,e'))
end
| UnOp(op,e,t) ->
let e = stripCastsDeepForPtrArith e in
new_exp (UnOp(op, e, t))
| BinOp(MinusPP,e1,e2,t) ->
let e1 = stripCastsDeepForPtrArith e1 in
let e2 = stripCastsDeepForPtrArith e2 in
if not(compareTypesNoAttributes ~ignoreSign:false
(typeOf e1) (typeOf e2))
then new_exp (BinOp(MinusPP, mkCast ~e:e1 ~newt:(typeOf e2), e2, t))
else new_exp (BinOp(MinusPP, e1, e2, t))
| BinOp(op,e1,e2,t) ->
let e1 = stripCastsDeepForPtrArith e1 in
let e2 = stripCastsDeepForPtrArith e2 in
new_exp (BinOp(op,e1,e2,t))
| Lval lv -> new_exp (Lval(stripCastsForPtrArithLval lv))
| AddrOf lv -> new_exp (AddrOf(stripCastsForPtrArithLval lv))
| StartOf lv -> new_exp (StartOf(stripCastsForPtrArithLval lv))
| _ -> e
and stripCastsForPtrArithLval (lv : lval) : lval =
match lv with
| (Var vi, off) -> (Var vi, stripCastsForPtrArithOff off)
| (Mem e, off) ->
let e = stripCastsDeepForPtrArith e in
let off = stripCastsForPtrArithOff off in
(Mem e, off)
and stripCastsForPtrArithOff (off : offset ) : offset =
match off with
| NoOffset -> NoOffset
| Field(fi, off) -> Field(fi, stripCastsForPtrArithOff off)
| Index(e, off) ->
let e = stripCastsDeepForPtrArith e in
let off = stripCastsForPtrArithOff off in
Index(e, off)