Skip to content

Commit c5941fc

Browse files
authored
Merge pull request #199 from goblint/cast-kind
Add cast kinds
2 parents 1b48fc0 + 7525631 commit c5941fc

File tree

11 files changed

+170
-121
lines changed

11 files changed

+170
-121
lines changed

src/check.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,8 @@ and checkExp (isconst: bool) (e: exp) : typ =
601601
| _ -> E.s (bug "StartOf on a non-array")
602602
end
603603

604-
| CastE (tres, e) -> begin
604+
| CastE (_, tres, e) -> begin
605+
(* TODO: check castkind w.r.t. tres? *)
605606
let et = checkExp isconst e in
606607
checkType tres CTExp;
607608
(* Not all types can be cast *)

src/cil.ml

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ and exp =
535535
| Question of exp * exp * exp * typ
536536
(** (a ? b : c) operation. Includes
537537
the type of the result *)
538-
| CastE of typ * exp (** Use {!mkCast} to make casts *)
538+
| CastE of castkind * typ * exp (** Use {!mkCast} to make casts *)
539539

540540
| AddrOf of lval (** Always use {!mkAddrOf} to
541541
construct one of these. Apply to an
@@ -615,8 +615,15 @@ and binop =
615615
| LAnd (** logical and *)
616616
| LOr (** logical or *)
617617

618-
619-
618+
and castkind =
619+
| Explicit (** Explicit conversion. @see C11 6.3.1. *)
620+
| IntegerPromotion (** Integer promotion. @see C11 6.3.1.1.2. *)
621+
| DefaultArgumentPromotion (** Default argument promotion. @see C11 6.5.2.2.6. *)
622+
| ArithmeticConversion (** Usual arithmetic conversion. @see C11 6.3.1.8. *)
623+
| ConditionalConversion (** Conditional conversion (non-standard terminology). @see C11 6.5.15.5 and 6.5.15.6. *)
624+
| PointerConversion (** Pointer conversion (non-standard). @see C11 6.5.6.8, 6.5.8.5 and 6.5.9.5. *)
625+
| Implicit (** Implicit conversion. @see C11 6.3.1, 6.5.2.2.7, 6.5.2.4.2, 6.5.16.1.2, 6.5.16.2.3, 6.7.9.11, 6.8.4.2.5 and 6.8.6.4.3. *)
626+
| Internal (** CIL-internal conversion (non-standard). *)
620627

621628
(** An lvalue denotes the contents of a range of memory addresses. This range
622629
is denoted as a host object along with an offset within the object. The
@@ -1729,7 +1736,7 @@ let mkForIncr ~(iter : varinfo) ~(first: exp) ~stopat:(past: exp) ~(incr: exp)
17291736

17301737

17311738
let rec stripCasts (e: exp) =
1732-
match e with CastE(_, e') -> stripCasts e' | _ -> e
1739+
match e with CastE(_, _, e') -> stripCasts e' | _ -> e
17331740

17341741

17351742

@@ -1909,7 +1916,7 @@ let getParenthLevel (e: exp) =
19091916
(* Unary *)
19101917
| Real _ -> 30
19111918
| Imag _ -> 30
1912-
| CastE(_,_) -> 30
1919+
| CastE(_,_,_) -> 30
19131920
| AddrOf(_) -> 30
19141921
| AddrOfLabel(_) -> 30
19151922
| StartOf(_) -> 30
@@ -1991,7 +1998,7 @@ let rec typeOf (e: exp) : typ =
19911998
| UnOp (_, _, t)
19921999
| BinOp (_, _, _, t)
19932000
| Question (_, _, _, t)
1994-
| CastE (t, _) -> t
2001+
| CastE (_, t, _) -> t
19952002
| AddrOf (lv) -> TPtr(typeOfLval lv, [])
19962003
| AddrOfLabel (lv) -> voidPtrType
19972004
| StartOf (lv) -> begin
@@ -2215,7 +2222,7 @@ let rec getInteger (e:exp) : cilint option =
22152222
| Const(CInt (n, ik, _)) -> Some (mkCilintIk ik n)
22162223
| Const(CChr c) -> getInteger (Const (charConstToInt c))
22172224
| Const(CEnum(v, _, _)) -> getInteger v
2218-
| CastE(t, e) -> begin
2225+
| CastE(_, t, e) -> begin
22192226
(* Handle any truncation due to cast. We optimistically ignore
22202227
loss-of-precision due to floating-point casts. *)
22212228
let mkInt ik n = Some (fst (truncateCilint ik n)) in
@@ -2622,19 +2629,19 @@ and constFold (machdep: bool) (e: exp) : exp =
26222629
| _ -> constFold machdep (AlignOf (typeOf e))
26232630
end
26242631

2625-
| CastE(it,
2626-
AddrOf (Mem (CastE(TPtr(bt, _), z)), off))
2632+
| CastE (k, it,
2633+
AddrOf (Mem (CastE(_, TPtr(bt, _), z)), off))
26272634
when machdep && isZero z -> begin
26282635
try
26292636
let start, width = bitsOffset bt off in
26302637
if start mod 8 <> 0 then
26312638
E.s (error "Using offset of bitfield");
2632-
constFold machdep (CastE(it, (kinteger !kindOfSizeOf (start / 8))))
2639+
constFold machdep (CastE(k, it, (kinteger !kindOfSizeOf (start / 8))))
26332640
with SizeOfError _ -> e
26342641
end
26352642

26362643

2637-
| CastE (t, e) -> begin
2644+
| CastE (k, t, e) -> begin
26382645
match constFold machdep e, unrollType t with
26392646
(* Might truncate silently *)
26402647
| Const(CInt(i,k,_)), TInt(nk,a)
@@ -2643,7 +2650,7 @@ and constFold (machdep: bool) (e: exp) : exp =
26432650
when (dropAttributes ["const"; "pconst"] a) = [] ->
26442651
let i', _ = truncateCilint nk (mkCilintIk k i) in
26452652
Const(CInt(i', nk, None))
2646-
| e', _ -> CastE (t, e')
2653+
| e', _ -> CastE (k, t, e')
26472654
end
26482655
| Lval lv -> Lval (constFoldLval machdep lv)
26492656
| AddrOf lv -> AddrOf (constFoldLval machdep lv)
@@ -2765,7 +2772,7 @@ let isArrayType t =
27652772
An integer constant expr with value 0, or such an expr cast to void *, is called a null pointer constant. *)
27662773
let isNullPtrConstant e =
27672774
let rec isNullPtrConstant = function
2768-
| CastE (TPtr (TVoid [], []), e) -> isNullPtrConstant e (* no qualifiers allowed on void or ptr *)
2775+
| CastE (_, TPtr (TVoid [], []), e) -> isNullPtrConstant e (* no qualifiers allowed on void or ptr *)
27692776
| e -> isZero e
27702777
in
27712778
isNullPtrConstant (constFold true e)
@@ -2781,7 +2788,7 @@ let rec isConstant = function
27812788
| Real e -> isConstant e
27822789
| Imag e -> isConstant e
27832790
| SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ -> true
2784-
| CastE (_, e) -> isConstant e
2791+
| CastE (_, _, e) -> isConstant e
27852792
| AddrOf (Var vi, off) | StartOf (Var vi, off)
27862793
-> vi.vglob && isConstantOffset off
27872794
| AddrOf (Mem e, off) | StartOf(Mem e, off)
@@ -2875,6 +2882,17 @@ let d_binop () b =
28752882
| LAnd -> text "&&"
28762883
| LOr -> text "||"
28772884

2885+
let d_castkind () k =
2886+
match k with
2887+
| Explicit -> text "Explicit"
2888+
| IntegerPromotion -> text "IntegerPromotion"
2889+
| DefaultArgumentPromotion -> text "DefaultArgumentPromotion"
2890+
| ArithmeticConversion -> text "ArithmeticConversion"
2891+
| ConditionalConversion -> text "ConditionalConversion"
2892+
| PointerConversion -> text "PointerConversion"
2893+
| Implicit -> text "Implicit"
2894+
| Internal -> text "Internal"
2895+
28782896
let invalidStmt = mkStmt (Instr [])
28792897

28802898
(** Construct a hash with the builtins *)
@@ -3405,9 +3423,12 @@ class defaultCilPrinterClass : cilPrinter = object (self)
34053423
++ text " : "
34063424
++ (self#pExpPrec level () e3)
34073425

3408-
| CastE(t,e) ->
3426+
| CastE(k,t,e) ->
34093427
text "("
3410-
++ self#pType None () t
3428+
++ self#pType None () t (* TODO: option to not print implicit casts? *)
3429+
(* ++ text "/*"
3430+
++ d_castkind () k (* convenient for debugging castkinds *)
3431+
++ text "*/" *)
34113432
++ text ")"
34123433
++ self#pExpPrec level () e
34133434

@@ -3698,7 +3719,7 @@ class defaultCilPrinterClass : cilPrinter = object (self)
36983719
in
36993720
let patchArgNotUseVLACast exp =
37003721
match exp with
3701-
| CastE(t, e) -> CastE(patchTypeNotVLA t, e)
3722+
| CastE(k, t, e) -> CastE(k, patchTypeNotVLA t, e)
37023723
| e -> e
37033724
in
37043725
self#pLineDirective l
@@ -4698,7 +4719,7 @@ class plainCilPrinterClass =
46984719
++ unalign)
46994720
++ text ")"
47004721

4701-
| CastE(t,e) -> dprintf "CastE(@[%a,@?%a@])" self#pOnlyType t self#pExp e
4722+
| CastE(k,t,e) -> dprintf "CastE(@[%a,@?%a,@?%a@])" d_castkind k self#pOnlyType t self#pExp e
47024723

47034724
| UnOp(u,e1,_) ->
47044725
dprintf "UnOp(@[%a,@?%a@])"
@@ -5242,9 +5263,9 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp =
52425263
| Question (e1, e2, e3, t) ->
52435264
let e1' = vExp e1 in let e2' = vExp e2 in let e3' = vExp e3 in let t' = vTyp t in
52445265
if e1' != e1 || e2' != e2 || e3' != e3 || t' != t then Question(e1',e2',e3',t') else e
5245-
| CastE (t, e1) ->
5266+
| CastE (k, t, e1) ->
52465267
let t' = vTyp t in let e1' = vExp e1 in
5247-
if t' != t || e1' != e1 then CastE(t', e1') else e
5268+
if t' != t || e1' != e1 then CastE(k, t', e1') else e
52485269
| AddrOf lv ->
52495270
let lv' = vLval lv in
52505271
if lv' != lv then AddrOf lv' else e
@@ -6097,7 +6118,7 @@ let getCompField (cinfo:compinfo) (fieldName:string) : fieldinfo =
60976118
(List.find (fun fi -> fi.fname = fieldName) cinfo.cfields)
60986119

60996120

6100-
let mkCastT ~(e: exp) ~(oldt: typ) ~(newt: typ) =
6121+
let mkCastT ~(kind: castkind) ~(e: exp) ~(oldt: typ) ~(newt: typ) =
61016122
(* Do not remove old casts because they are conversions !!! *)
61026123
if Util.equals (typeSig oldt) (typeSig newt) then begin
61036124
e
@@ -6109,11 +6130,11 @@ let mkCastT ~(e: exp) ~(oldt: typ) ~(newt: typ) =
61096130
let v = if compare i zero_cilint = 0 then zero_cilint else one_cilint in
61106131
Const (CInt(v, IBool, None))
61116132
| TInt(newik, []), Const(CInt(i, _, _)) -> kintegerCilint newik i
6112-
| _ -> CastE(newt,e)
6133+
| _ -> CastE(kind,newt,e)
61136134
end
61146135

6115-
let mkCast ~(e: exp) ~(newt: typ) =
6116-
mkCastT ~e:e ~oldt:(typeOf e) ~newt:newt
6136+
let mkCast ~kind ~(e: exp) ~(newt: typ) =
6137+
mkCastT ~kind ~e:e ~oldt:(typeOf e) ~newt:newt
61176138

61186139
type existsAction =
61196140
ExistsTrue (* We have found it *)
@@ -6230,7 +6251,7 @@ let rec makeZeroInit (t: typ) : init =
62306251
CompoundInit (t', [])
62316252

62326253
| TPtr _ as t ->
6233-
SingleInit(if !insertImplicitCasts then mkCast ~e:zero ~newt:t else zero)
6254+
SingleInit(if !insertImplicitCasts then mkCast ~kind:Internal ~e:zero ~newt:t else zero)
62346255
| x -> E.s (unimp "Cannot initialize type: %a" d_type x)
62356256

62366257

src/cil.mli

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ and exp =
617617
| Question of exp * exp * exp * typ
618618
(** (a ? b : c) operation. Includes the type of the result *)
619619

620-
| CastE of typ * exp
620+
| CastE of castkind * typ * exp
621621
(** Use {!mkCast} to make casts. *)
622622

623623
| AddrOf of lval
@@ -724,6 +724,16 @@ and binop =
724724
you want to use these, you must
725725
set {!useLogicalOperators}. *)
726726

727+
and castkind =
728+
| Explicit (** Explicit conversion. @see C11 6.3.1. *)
729+
| IntegerPromotion (** Integer promotion. @see C11 6.3.1.1.2. *)
730+
| DefaultArgumentPromotion (** Default argument promotion. @see C11 6.5.2.2.6. *)
731+
| ArithmeticConversion (** Usual arithmetic conversion. @see C11 6.3.1.8. *)
732+
| ConditionalConversion (** Conditional conversion (non-standard terminology). @see C11 6.5.15.5 and 6.5.15.6. *)
733+
| PointerConversion (** Pointer conversion (non-standard). @see C11 6.5.6.8, 6.5.8.5 and 6.5.9.5. *)
734+
| Implicit (** Implicit conversion. @see C11 6.3.1, 6.5.2.2.7, 6.5.2.4.2, 6.5.16.1.2, 6.5.16.2.3, 6.7.9.11, 6.8.4.2.5 and 6.8.6.4.3. *)
735+
| Internal (** CIL-internal conversion (non-standard). *)
736+
727737
(** {b Lvalues.} Lvalues are the sublanguage of expressions that can appear at the left of an assignment or as operand to the address-of operator.
728738
In C the syntax for lvalues is not always a good indication of the meaning
729739
of the lvalue. For example the C value
@@ -1717,10 +1727,10 @@ val mkString: string -> exp
17171727

17181728
(** Construct a cast when having the old type of the expression. If the new
17191729
type is the same as the old type, then no cast is added. *)
1720-
val mkCastT: e:exp -> oldt:typ -> newt:typ -> exp
1730+
val mkCastT: kind:castkind -> e:exp -> oldt:typ -> newt:typ -> exp
17211731

17221732
(** Like {!mkCastT} but uses typeOf to get [oldt] *)
1723-
val mkCast: e:exp -> newt:typ -> exp
1733+
val mkCast: kind:castkind -> e:exp -> newt:typ -> exp
17241734

17251735
(** Removes casts from this expression, but ignores casts within
17261736
other expression constructs. So we delete the (A) and (B) casts from
@@ -2386,6 +2396,9 @@ val d_binop: unit -> binop -> Pretty.doc
23862396
(** Pretty-print a unary operator *)
23872397
val d_unop: unit -> unop -> Pretty.doc
23882398

2399+
(** Pretty-print a cast kind *)
2400+
val d_castkind: unit -> castkind -> Pretty.doc
2401+
23892402
(** Pretty-print an attribute using {!defaultCilPrinter} *)
23902403
val d_attr: unit -> attribute -> Pretty.doc
23912404

src/expcompare.ml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ let rec compareExp (e1: exp) (e2: exp) : bool =
5757
| AddrOf lv1, AddrOf lv2 -> compareLval lv1 lv2
5858
| BinOp(bop1, l1, r1, _), BinOp(bop2, l2, r2, _) ->
5959
bop1 = bop2 && compareExp l1 l2 && compareExp r1 r2
60-
| CastE(t1, e1), CastE(t2, e2) ->
61-
t1 == t2 && compareExp e1 e2
60+
| CastE(k1, t1, e1), CastE(k2, t2, e2) ->
61+
k1 = k2 && t1 == t2 && compareExp e1 e2
6262
| _ -> begin
6363
match getInteger (constFold true e1), getInteger (constFold true e2) with
6464
Some i1, Some i2 -> compare_cilint i1 i2 = 0
@@ -95,7 +95,7 @@ and compareLval (lv1: lval) (lv2: lval) : bool =
9595
since they actually change the value of the expression. *)
9696
let rec stripNopCasts (e:exp): exp =
9797
match e with
98-
CastE(t, e') -> begin
98+
CastE(_, t, e') -> begin
9999
match unrollType (typeOf e'), unrollType t with
100100
TPtr (bt1, a1), TPtr (bt2, a2)
101101
when isConstType bt1 = isConstType bt2 ->
@@ -127,7 +127,7 @@ let compareExpStripCasts (e1: exp) (e2: exp) : bool =
127127
of pointer arithmetic shouldn't change the resulting value. *)
128128
let rec stripCastsForPtrArith (e:exp): exp =
129129
match e with
130-
| CastE(t, e') -> begin
130+
| CastE(_, t, e') -> begin
131131
match unrollType (typeOf e'), unrollType t with
132132
(* Keep casts from void to something else. Among other things,
133133
we keep casts from void* to char* that would otherwise be
@@ -209,7 +209,7 @@ let isTypeVolatile t =
209209
(* strip every cast between equal pointer types *)
210210
let rec stripCastsDeepForPtrArith (e:exp): exp =
211211
match e with
212-
| CastE(t, e') when not(isTypeVolatile t) -> begin
212+
| CastE(k, t, e') when not(isTypeVolatile t) -> begin
213213
let e' = stripCastsDeepForPtrArith e' in
214214
match unrollType (typeOf e'), unrollType t with
215215
(* Keep casts from void to something else. Among other things,
@@ -224,11 +224,11 @@ let rec stripCastsDeepForPtrArith (e:exp): exp =
224224
isConstType bt1 = isConstType bt2 then
225225
e'
226226
else
227-
CastE(t,e')
227+
CastE(k,t,e')
228228
with SizeOfError _ -> (* bt1 or bt2 is abstract; don't strip. *)
229-
CastE(t,e')
229+
CastE(k,t,e')
230230
end
231-
| _, _ -> CastE(t,e')
231+
| _, _ -> CastE(k,t,e')
232232
end
233233
| UnOp(op,e,t) ->
234234
let e = stripCastsDeepForPtrArith e in
@@ -238,7 +238,7 @@ let rec stripCastsDeepForPtrArith (e:exp): exp =
238238
let e2 = stripCastsDeepForPtrArith e2 in
239239
if not(compareTypesNoAttributes ~ignoreSign:false
240240
(typeOf e1) (typeOf e2))
241-
then BinOp(MinusPP, mkCast ~e:e1 ~newt:(typeOf e2), e2, t)
241+
then BinOp(MinusPP, mkCast ~kind:PointerConversion ~e:e1 ~newt:(typeOf e2), e2, t)
242242
else BinOp(MinusPP, e1, e2, t)
243243
| BinOp(op,e1,e2,t) ->
244244
let e1 = stripCastsDeepForPtrArith e1 in

src/ext/dataslicing/dataslicing.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,13 @@ and sliceExp (i : int) (e : exp) : exp =
234234
| UnOp (op, e1, t) -> UnOp (op, sliceExp i e1, sliceType i t)
235235
| BinOp (op, e1, e2, t) -> BinOp (op, sliceExp i e1, sliceExp i e2,
236236
sliceType i t)
237-
| CastE (t, e) -> sliceCast i t e
237+
| CastE (k, t, e) -> sliceCast i k t e
238238
| AddrOf lv -> AddrOf (sliceLval i lv)
239239
| StartOf lv -> StartOf (sliceLval i lv)
240240
| SizeOf t -> SizeOf (sliceTypeAll t)
241241
| _ -> E.s (unimp "exp %a" d_exp e)
242242

243-
and sliceCast (i : int) (t : typ) (e : exp) : exp =
243+
and sliceCast (i : int) (k : castkind) (t : typ) (e : exp) : exp =
244244
let te = typeOf e in
245245
match t, te with
246246
| TInt (k1, _), TInt (k2, attrs2) when k1 = k2 ->
@@ -250,9 +250,9 @@ and sliceCast (i : int) (t : typ) (e : exp) : exp =
250250
(* Note: We strip off integer cast operations. *)
251251
sliceExp i e
252252
| TPtr _, _ when isZero e ->
253-
CastE (sliceType i t, sliceExp i e)
253+
CastE (k, sliceType i t, sliceExp i e)
254254
| TPtr (bt1, _), TPtr (bt2, _) when (typeSig bt1) = (typeSig bt2) ->
255-
CastE (sliceType i t, sliceExp i e)
255+
CastE (k, sliceType i t, sliceExp i e)
256256
| _ ->
257257
E.s (unimp "sketchy cast (%a) -> (%a)\n" d_type te d_type t)
258258

src/ext/pta/ptranal.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ and analyze_expr (e : exp ) : A.tau =
244244
| UnOp (op, e, t) -> analyze_expr e
245245
| BinOp (op, e, e', t) -> A.join (analyze_expr e) (analyze_expr e')
246246
| Question (_, e, e', _) -> A.join (analyze_expr e) (analyze_expr e')
247-
| CastE (t, e) -> analyze_expr e
247+
| CastE (_, t, e) -> analyze_expr e
248248
| AddrOf l ->
249249
if !fun_ptrs_as_funs && isFunctionType (typeOfLval l) then
250250
A.rvalue (analyze_lval l)

0 commit comments

Comments
 (0)