diff --git a/infer/src/backend/abs.ml b/infer/src/backend/abs.ml index 5c431f5bb..7b43d0791 100644 --- a/infer/src/backend/abs.ml +++ b/infer/src/backend/abs.ml @@ -423,7 +423,8 @@ let typ_get_recursive_flds tenv te = (match typ with | Sil.Tvar _ -> assert false (* there should be no indirection *) | Sil.Tint _ | Sil.Tvoid | Sil.Tfun _ | Sil.Tptr _ | Sil.Tfloat _ | Sil.Tenum _ -> [] - | Sil.Tstruct (fld_typ_ann_list, _, _, _, _, _, _) -> IList.map (fun (x, y, z) -> x) (IList.filter filter fld_typ_ann_list) + | Sil.Tstruct { Sil.instance_fields } -> + IList.map (fun (x, y, z) -> x) (IList.filter filter instance_fields) | Sil.Tarray _ -> []) | Sil.Var _ -> [] (* type of |-> not known yet *) | Sil.Const _ -> [] @@ -769,9 +770,9 @@ let is_simply_recursive tenv tname = assert false (* there should be no indirection *) | Sil.Tint _ | Sil.Tfloat _ | Sil.Tvoid | Sil.Tfun _ | Sil.Tptr _ | Sil.Tenum _ -> None - | Sil.Tstruct (fld_typ_ann_list, _, _, _, _, _, _) -> + | Sil.Tstruct { Sil.instance_fields } -> begin - match (IList.filter filter fld_typ_ann_list) with + match (IList.filter filter instance_fields) with | [(fld, _, _)] -> Some fld | _ -> None end @@ -1192,10 +1193,11 @@ let cycle_has_weak_or_unretained_or_assign_field cycle = (* returns items annotation for field fn in struct t *) let get_item_annotation t fn = match t with - | Sil.Tstruct(nsf, sf, _, _, _, _, _) -> + | Sil.Tstruct { Sil.instance_fields; static_fields } -> let ia = ref [] in IList.iter (fun (fn', t', ia') -> - if Ident.fieldname_equal fn fn' then ia := ia') (nsf@sf); + if Ident.fieldname_equal fn fn' then ia := ia') + (instance_fields @ static_fields); !ia | _ -> [] in let rec has_weak_or_unretained_or_assign params = diff --git a/infer/src/backend/absarray.ml b/infer/src/backend/absarray.ml index d9d4741b7..090c808df 100644 --- a/infer/src/backend/absarray.ml +++ b/infer/src/backend/absarray.ml @@ -66,9 +66,11 @@ end = struct let rec get_strexp_at_syn_offsets se t syn_offs = match se, t, syn_offs with | _, _, [] -> (se, t) - | Sil.Estruct (fsel, _), Sil.Tstruct (ftal, sftal, _, _, _, _, _), Field (fld, _) :: syn_offs' -> + | Sil.Estruct (fsel, _), Sil.Tstruct { Sil.instance_fields }, Field (fld, _) :: syn_offs' -> let se' = snd (IList.find (fun (f', se') -> Sil.fld_equal f' fld) fsel) in - let t' = (fun (x,y,z) -> y) (IList.find (fun (f', t', a') -> Sil.fld_equal f' fld) ftal) in + let t' = (fun (x,y,z) -> y) + (IList.find (fun (f', t', a') -> + Sil.fld_equal f' fld) instance_fields) in get_strexp_at_syn_offsets se' t' syn_offs' | Sil.Earray (size, esel, _), Sil.Tarray(t', _), Index ind :: syn_offs' -> let se' = snd (IList.find (fun (i', se') -> Sil.exp_equal i' ind) esel) in @@ -84,9 +86,11 @@ end = struct match se, t, syn_offs with | _, _, [] -> update se t - | Sil.Estruct (fsel, inst), Sil.Tstruct (ftal, sftal, _, _, _, _, _), Field (fld, _) :: syn_offs' -> + | Sil.Estruct (fsel, inst), Sil.Tstruct { Sil.instance_fields }, Field (fld, _) :: syn_offs' -> let se' = snd (IList.find (fun (f', _) -> Sil.fld_equal f' fld) fsel) in - let t' = (fun (x,y,z) -> y) (IList.find (fun (f', _, _) -> Sil.fld_equal f' fld) ftal) in + let t' = (fun (x,y,z) -> y) + (IList.find (fun (f', _, _) -> + Sil.fld_equal f' fld) instance_fields) in let se_mod = replace_strexp_at_syn_offsets se' t' syn_offs' update in let fsel' = IList.map (fun (f'', se'') -> if Sil.fld_equal f'' fld then (fld, se_mod) else (f'', se'')) fsel in Sil.Estruct (fsel', inst) @@ -142,8 +146,8 @@ end = struct if pred sigma_other (path, se, typ) then found := (sigma, hpred, offs') :: !found else begin match se, typ with - | Sil.Estruct (fsel, _), Sil.Tstruct (ftal, sftal, _, _, _, _, _) -> - find_offset_fsel sigma_other hpred root offs fsel ftal typ + | Sil.Estruct (fsel, _), Sil.Tstruct { Sil.instance_fields } -> + find_offset_fsel sigma_other hpred root offs fsel instance_fields typ | Sil.Earray (size, esel, _), Sil.Tarray (t, _) -> find_offset_esel sigma_other hpred root offs esel t | _ -> () diff --git a/infer/src/backend/autounit.ml b/infer/src/backend/autounit.ml index 909143795..f3ea69b6f 100644 --- a/infer/src/backend/autounit.ml +++ b/infer/src/backend/autounit.ml @@ -304,8 +304,8 @@ let create_idmap sigma : idmap = let rec do_se se typ = match se, typ with | Sil.Eexp (e, inst), _ -> do_exp e typ - | Sil.Estruct (fsel, _), Sil.Tstruct (ftal, sftal, _, _, _, _, _) -> - do_struct fsel ftal + | Sil.Estruct (fsel, _), Sil.Tstruct { Sil.instance_fields } -> + do_struct fsel instance_fields | Sil.Earray (size, esel, _), Sil.Tarray (typ, size') -> do_se (Sil.Eexp (size, Sil.inst_none)) (Sil.Tint Sil.IULong); do_array esel typ @@ -419,9 +419,10 @@ let pp_texp_for_malloc fmt = typ | Sil.Tptr (t, pk) -> Sil.Tptr (handle_arr_size t, pk) - | Sil.Tstruct (ftal, sftal, csu, nameo, supers, def_mthds, iann) -> - Sil.Tstruct (IList.map (fun (f, t, a) -> - (f, handle_arr_size t, a)) ftal, sftal, csu, nameo, supers, def_mthds, iann) + | Sil.Tstruct struct_typ -> + let instance_fields = + IList.map (fun (f, t, a) -> (f, handle_arr_size t, a)) struct_typ.Sil.instance_fields in + Sil.Tstruct { struct_typ with Sil.instance_fields } | Sil.Tarray (t, e) -> Sil.Tarray (handle_arr_size t, e) in function diff --git a/infer/src/backend/errdesc.ml b/infer/src/backend/errdesc.ml index 1e1ae26ee..1592aebab 100644 --- a/infer/src/backend/errdesc.ml +++ b/infer/src/backend/errdesc.ml @@ -542,9 +542,12 @@ let vpath_find prop _exp : Sil.dexp option * Sil.typ option = (match lexp with | Sil.Lvar pv -> let typo = match texp with - | Sil.Sizeof (Sil.Tstruct (ftl, ftal, _, _, _, _, _), _) -> + | Sil.Sizeof (Sil.Tstruct struct_typ, _) -> (try - let _, t, _ = IList.find (fun (_f, _t, _) -> Ident.fieldname_equal _f f) ftl in + let _, t, _ = + IList.find (fun (f', _, _) -> + Ident.fieldname_equal f' f) + struct_typ.Sil.instance_fields in Some t with Not_found -> None) | _ -> None in diff --git a/infer/src/backend/localise.ml b/infer/src/backend/localise.ml index 8ace3bf44..98df41036 100644 --- a/infer/src/backend/localise.ml +++ b/infer/src/backend/localise.ml @@ -604,7 +604,10 @@ let desc_leak hpred_type_opt value_str_opt resource_opt resource_action_opt loc s, " to ", " on " in let typ_str = match hpred_type_opt with - | Some (Sil.Sizeof (Sil.Tstruct (_, _, Csu.Class, Some classname, _, _, _), _)) + | Some (Sil.Sizeof (Sil.Tstruct + { Sil.csu = Csu.Class; + Sil.struct_name = Some classname; + }, _)) when !Config.curr_language = Config.Java -> " of type " ^ Mangled.to_string classname ^ " " | _ -> " " in diff --git a/infer/src/backend/objc_models.ml b/infer/src/backend/objc_models.ml index e7c8354d8..500dc8221 100644 --- a/infer/src/backend/objc_models.ml +++ b/infer/src/backend/objc_models.ml @@ -209,7 +209,7 @@ struct | Sil.Tptr (styp, _ ) -> is_core_lib lib styp | Sil.Tvar (Typename.TN_csu (_, name) ) - | Sil.Tstruct (_, _, _, (Some name), _, _, _) -> + | Sil.Tstruct { Sil.struct_name = Some name } -> let core_lib_types = core_lib_to_type_list lib in IList.mem (=) (Mangled.to_string name) core_lib_types | _ -> false diff --git a/infer/src/backend/prop.ml b/infer/src/backend/prop.ml index 2475b59f6..b25667117 100644 --- a/infer/src/backend/prop.ml +++ b/infer/src/backend/prop.ml @@ -598,21 +598,23 @@ let sym_eval abs e = eval (Sil.BinOp (Sil.PlusPI, e11, e2')) | Sil.BinOp (Sil.PlusA, - (Sil.Sizeof - (Sil.Tstruct (ftal, sftal, csu, name_opt, supers, def_mthds, iann), st) as e1), + (Sil.Sizeof (Sil.Tstruct struct_typ, st) as e1), e2) -> (* pattern for extensible structs given a struct declatead as struct s { ... t arr[n] ... }, allocation pattern malloc(sizeof(struct s) + k * siezof(t)) turn it into struct s { ... t arr[n + k] ... } *) let e1' = eval e1 in let e2' = eval e2 in - (match IList.rev ftal, e2' with - (fname, Sil.Tarray(typ, size), _):: ltfa, Sil.BinOp(Sil.Mult, num_elem, Sil.Sizeof (texp, st)) when ftal != [] && Sil.typ_equal typ texp -> + let instance_fields = struct_typ.Sil.instance_fields in + (match IList.rev instance_fields, e2' with + (fname, Sil.Tarray (typ, size), _) :: ltfa, + Sil.BinOp(Sil.Mult, num_elem, Sil.Sizeof (texp, st)) + when instance_fields != [] && Sil.typ_equal typ texp -> let size' = Sil.BinOp(Sil.PlusA, size, num_elem) in let ltfa' = (fname, Sil.Tarray(typ, size'), Sil.item_annotation_empty) :: ltfa in - Sil.Sizeof - (Sil.Tstruct - (IList.rev ltfa', sftal, csu, name_opt, supers, def_mthds, iann), st) + let struct_typ' = + { struct_typ with Sil.instance_fields = ltfa' } in + Sil.Sizeof (Sil.Tstruct struct_typ', st) | _ -> Sil.BinOp(Sil.PlusA, e1', e2')) | Sil.BinOp (Sil.PlusA as oplus, e1, e2) | Sil.BinOp (Sil.PlusPI as oplus, e1, e2) -> @@ -853,9 +855,15 @@ and typ_normalize sub typ = match typ with typ | Sil.Tptr (t', pk) -> Sil.Tptr (typ_normalize sub t', pk) - | Sil.Tstruct (ftal, sftal, csu, nameo, supers, def_mthds, iann) -> + | Sil.Tstruct struct_typ -> let fld_norm = IList.map (fun (f, t, a) -> (f, typ_normalize sub t, a)) in - Sil.Tstruct (fld_norm ftal, fld_norm sftal, csu, nameo, supers, def_mthds, iann) + let instance_fields = fld_norm struct_typ.Sil.instance_fields in + let static_fields = fld_norm struct_typ.Sil.static_fields in + Sil.Tstruct + { struct_typ with + Sil.instance_fields; + static_fields; + } | Sil.Tarray (t, e) -> Sil.Tarray (typ_normalize sub t, exp_normalize sub e) | Sil.Tenum econsts -> @@ -1119,7 +1127,7 @@ let rec create_strexp_of_type tenvo struct_init_mode typ inst = match typ with | Sil.Tint _ | Sil.Tfloat _ | Sil.Tvoid | Sil.Tfun _ | Sil.Tptr _ | Sil.Tenum _ -> Sil.Eexp (init_value (), inst) - | Sil.Tstruct (ftal, sftal, _, _, _, _, _) -> + | Sil.Tstruct { Sil.instance_fields } -> begin match struct_init_mode with | No_init -> Sil.Estruct ([], inst) @@ -1129,7 +1137,7 @@ let rec create_strexp_of_type tenvo struct_init_mode typ inst = (fld, Sil.Eexp (Sil.exp_one, inst)) else (fld, create_strexp_of_type tenvo struct_init_mode t inst) in - Sil.Estruct (IList.map f ftal, inst) + Sil.Estruct (IList.map f instance_fields, inst) end | Sil.Tarray (_, size) -> Sil.Earray (size, [], inst) @@ -1661,15 +1669,15 @@ let sigma_intro_nonemptylseg e1 e2 sigma = f (hpred :: sigma_passed) sigma' | Sil.Hlseg (Sil.Lseg_PE, para, f1, f2, shared) :: sigma' when (Sil.exp_equal e1 f1 && Sil.exp_equal e2 f2) - || (Sil.exp_equal e2 f1 && Sil.exp_equal e1 f2) -> + || (Sil.exp_equal e2 f1 && Sil.exp_equal e1 f2) -> f (Sil.Hlseg (Sil.Lseg_NE, para, f1, f2, shared) :: sigma_passed) sigma' | Sil.Hlseg _ as hpred :: sigma' -> f (hpred :: sigma_passed) sigma' | Sil.Hdllseg (Sil.Lseg_PE, para, iF, oB, oF, iB, shared) :: sigma' when (Sil.exp_equal e1 iF && Sil.exp_equal e2 oF) - || (Sil.exp_equal e2 iF && Sil.exp_equal e1 oF) - || (Sil.exp_equal e1 iB && Sil.exp_equal e2 oB) - || (Sil.exp_equal e2 iB && Sil.exp_equal e1 oB) -> + || (Sil.exp_equal e2 iF && Sil.exp_equal e1 oF) + || (Sil.exp_equal e1 iB && Sil.exp_equal e2 oB) + || (Sil.exp_equal e2 iB && Sil.exp_equal e1 oB) -> f (Sil.Hdllseg (Sil.Lseg_NE, para, iF, oB, oF, iB, shared) :: sigma_passed) sigma' | Sil.Hdllseg _ as hpred :: sigma' -> f (hpred :: sigma_passed) sigma' diff --git a/infer/src/backend/prover.ml b/infer/src/backend/prover.ml index f5b767792..2ba65de94 100644 --- a/infer/src/backend/prover.ml +++ b/infer/src/backend/prover.ml @@ -1120,7 +1120,7 @@ let exp_imply calc_missing subs e1_in e2_in : subst2 = | e1, Sil.Var v2 -> let occurs_check v e = (* check whether [v] occurs in normalized [e] *) if Sil.fav_mem (Sil.exp_fav e) v - && Sil.fav_mem (Sil.exp_fav (Prop.exp_normalize_prop Prop.prop_emp e)) v + && Sil.fav_mem (Sil.exp_fav (Prop.exp_normalize_prop Prop.prop_emp e)) v then raise (IMPL_EXC ("occurs check", subs, (EXC_FALSE_EXPS (e1, e2)))) in if Ident.is_primed v2 then let () = occurs_check v2 e1 in @@ -1414,11 +1414,17 @@ let expand_hpred_pointer calc_index_frame hpred : bool * bool * Sil.hpred = let t' = match t, typ_fld with | _, Sil.Tstruct _ -> (* the struct type of fld is known *) Sil.Sizeof (typ_fld, Sil.Subtype.exact) - | Sil.Sizeof (_t, st), _ -> (* the struct type of fld is not known -- typically Tvoid *) + | Sil.Sizeof (t1, st), _ -> (* the struct type of fld is not known -- typically Tvoid *) Sil.Sizeof (Sil.Tstruct - ([(fld, _t, Sil.item_annotation_empty)], - [], Csu.Struct, None, [], [], Sil.item_annotation_empty), st) + { Sil.instance_fields = [(fld, t1, Sil.item_annotation_empty)]; + static_fields = []; + csu = Csu.Struct; + struct_name = None; + Sil.superclasses = []; + Sil.def_methods = []; + Sil.struct_annotations = Sil.item_annotation_empty; + }, st) (* None as we don't know the stuct name *) | _ -> raise (Failure "expand_hpred_pointer: Unexpected non-sizeof type in Lfield") in let hpred' = Sil.Hpointsto (e, Sil.Estruct ([(fld, se)], Sil.inst_none), t') in @@ -1448,8 +1454,9 @@ let cloneable_type = Typename.Java.from_string "java.lang.Cloneable" let is_interface tenv class_name = match Sil.tenv_lookup tenv class_name with - | Some (Sil.Tstruct (fields, sfields, Csu.Class, Some c1', supers1, methods, iann)) -> - (IList.length fields = 0) && (IList.length methods = 0) + | Some (Sil.Tstruct ( { Sil.csu = Csu.Class; struct_name = Some _ } as struct_typ )) -> + (IList.length struct_typ.Sil.instance_fields = 0) && + (IList.length struct_typ.Sil.def_methods = 0) | _ -> false (** check if c1 is a subclass of c2 *) @@ -1457,8 +1464,8 @@ let check_subclass_tenv tenv c1 c2 = let rec check cn = Typename.equal cn c2 || Typename.equal c2 object_type || match Sil.tenv_lookup tenv cn with - | Some (Sil.Tstruct (_, _, Csu.Class, Some c1', supers1, _, _)) -> - IList.exists check supers1 + | Some (Sil.Tstruct { Sil.struct_name = Some _; csu = Csu.Class; superclasses }) -> + IList.exists check superclasses | _ -> false in check c1 @@ -1478,8 +1485,8 @@ let check_subtype_basic_type t1 t2 = (** check if t1 is a subtype of t2 *) let rec check_subtype tenv t1 t2 = match t1, t2 with - | Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), - Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c1 }, + Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c2 } -> let cn1 = Typename.TN_csu (Csu.Class, c1) and cn2 = Typename.TN_csu (Csu.Class, c2) in (check_subclass tenv cn1 cn2) @@ -1490,7 +1497,7 @@ let rec check_subtype tenv t1 t2 = | Sil.Tptr (dom_type1, _), Sil.Tptr (dom_type2, _) -> check_subtype tenv dom_type1 dom_type2 - | Sil.Tarray _, Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) -> + | Sil.Tarray _, Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c2 } -> let cn2 = Typename.TN_csu (Csu.Class, c2) in Typename.equal cn2 serializable_type || Typename.equal cn2 cloneable_type @@ -1500,8 +1507,8 @@ let rec check_subtype tenv t1 t2 = let rec case_analysis_type tenv (t1, st1) (t2, st2) = match t1, t2 with - | Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), - Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c1 }, + Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c2 } -> let cn1 = Typename.TN_csu (Csu.Class, c1) and cn2 = Typename.TN_csu (Csu.Class, c2) in (Sil.Subtype.case_analysis (cn1, st1) (cn2, st2) (check_subclass tenv) (is_interface tenv)) @@ -1512,7 +1519,7 @@ let rec case_analysis_type tenv (t1, st1) (t2, st2) = | Sil.Tptr (dom_type1, _), Sil.Tptr (dom_type2, _) -> (case_analysis_type tenv (dom_type1, st1) (dom_type2, st2)) - | Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), Sil.Tarray _ -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c1 }, Sil.Tarray _ -> let cn1 = Typename.TN_csu (Csu.Class, c1) in if (Typename.equal cn1 serializable_type || Typename.equal cn1 cloneable_type diff --git a/infer/src/backend/rearrange.ml b/infer/src/backend/rearrange.ml index a379b602a..760673403 100644 --- a/infer/src/backend/rearrange.ml +++ b/infer/src/backend/rearrange.ml @@ -102,13 +102,14 @@ let rec create_struct_values pname tenv orig_prop footprint_part kind max_stamp Ident.create kind !max_stamp in let res = match t, off with - | Sil.Tstruct (ftal, sftal, _, _, _, _, _),[] -> + | Sil.Tstruct _, [] -> ([], Sil.Estruct ([], inst), t) - | Sil.Tstruct (ftal, sftal, csu, nameo, supers, def_mthds, iann), + | Sil.Tstruct ({ Sil.instance_fields; static_fields } as struct_typ ), (Sil.Off_fld (f, _)):: off' -> let _, t', _ = try - IList.find (fun (f', _, _) -> Ident.fieldname_equal f f') (ftal @ sftal) + IList.find (fun (f', _, _) -> Ident.fieldname_equal f f') + (instance_fields @ static_fields) with Not_found -> raise (Exceptions.Bad_footprint (try assert false with Assert_failure x -> x)) in let atoms', se', res_t' = @@ -116,8 +117,9 @@ let rec create_struct_values pname tenv orig_prop footprint_part kind max_stamp pname tenv orig_prop footprint_part kind max_stamp t' off' inst in let se = Sil.Estruct ([(f, se')], inst) in let replace_typ_of_f (f', t', a') = if Ident.fieldname_equal f f' then (f, res_t', a') else (f', t', a') in - let ftal' = IList.sort Sil.fld_typ_ann_compare (IList.map replace_typ_of_f ftal) in - (atoms', se, Sil.Tstruct (ftal', sftal, csu, nameo, supers, def_mthds, iann)) + let instance_fields' = + IList.sort Sil.fld_typ_ann_compare (IList.map replace_typ_of_f instance_fields) in + (atoms', se, Sil.Tstruct { struct_typ with Sil.instance_fields = instance_fields'}) | Sil.Tstruct _, (Sil.Off_index e):: off' -> let atoms', se', res_t' = create_struct_values @@ -200,11 +202,12 @@ let rec _strexp_extend_values _strexp_extend_values pname tenv orig_prop footprint_part kind max_stamp se typ off_new inst | (Sil.Off_fld (f, _)):: off', Sil.Estruct (fsel, inst'), - Sil.Tstruct (ftal, sftal, csu, nameo, supers, def_mthds, iann) -> + Sil.Tstruct ({ Sil.instance_fields; static_fields } as struct_typ) -> let replace_fv new_v fv = if Ident.fieldname_equal (fst fv) f then (f, new_v) else fv in let _, typ', _ = try - IList.find (fun (f', t', a') -> Ident.fieldname_equal f f') (ftal @ sftal) + IList.find (fun (f', t', a') -> Ident.fieldname_equal f f') + (instance_fields @ static_fields) with Not_found -> raise (Exceptions.Missing_fld (f, try assert false with Assert_failure x -> x)) in begin @@ -217,9 +220,10 @@ let rec _strexp_extend_values let replace_fse = replace_fv res_se' in let res_fsel' = IList.sort Sil.fld_strexp_compare (IList.map replace_fse fsel) in let replace_fta (f, t, a) = let f', t' = replace_fv res_typ' (f, t) in (f', t', a) in - let res_ftl' = IList.sort Sil.fld_typ_ann_compare (IList.map replace_fta ftal) in + let instance_fields' = + IList.sort Sil.fld_typ_ann_compare (IList.map replace_fta instance_fields) in let struct_typ = - Sil.Tstruct (res_ftl', sftal, csu, nameo, supers, def_mthds, iann) in + Sil.Tstruct { struct_typ with Sil.instance_fields = instance_fields' } in (res_atoms', Sil.Estruct (res_fsel', inst'), struct_typ) :: acc in IList.fold_left replace [] atoms_se_typ_list' with Not_found -> @@ -228,8 +232,9 @@ let rec _strexp_extend_values pname tenv orig_prop footprint_part kind max_stamp typ' off' inst in let res_fsel' = IList.sort Sil.fld_strexp_compare ((f, se'):: fsel) in let replace_fta (f', t', a') = if Ident.fieldname_equal f' f then (f, res_typ', a') else (f', t', a') in - let res_ftl' = IList.sort Sil.fld_typ_ann_compare (IList.map replace_fta ftal) in - let struct_typ = Sil.Tstruct (res_ftl', sftal, csu, nameo, supers, def_mthds, iann) in + let instance_fields' = + IList.sort Sil.fld_typ_ann_compare (IList.map replace_fta instance_fields) in + let struct_typ = Sil.Tstruct { struct_typ with Sil.instance_fields = instance_fields' } in [(atoms', Sil.Estruct (res_fsel', inst'), struct_typ)] end | (Sil.Off_fld (f, _)):: off', _, _ -> @@ -801,11 +806,11 @@ let iter_rearrange_pe_dllseg_last recurse_on_iters default_case_iter iter para_d let type_at_offset texp off = let rec strip_offset off typ = match off, typ with | [], _ -> Some typ - | (Sil.Off_fld (f, _)):: off', Sil.Tstruct (ftal, sftal, _, _, _, _, _) -> + | (Sil.Off_fld (f, _)):: off', Sil.Tstruct { Sil.instance_fields } -> (try let typ' = (fun (x, y, z) -> y) - (IList.find (fun (f', t', a') -> Ident.fieldname_equal f f') ftal) in + (IList.find (fun (f', t', a') -> Ident.fieldname_equal f f') instance_fields) in strip_offset off' typ' with Not_found -> None) | (Sil.Off_index _):: off', Sil.Tarray (typ', _) -> diff --git a/infer/src/backend/sil.ml b/infer/src/backend/sil.ml index 9ee39ce5b..1468623d2 100644 --- a/infer/src/backend/sil.ml +++ b/infer/src/backend/sil.ml @@ -648,6 +648,17 @@ and const = and struct_fields = (Ident.fieldname * typ * item_annotation) list +(** Type for a structured value. *) +and struct_typ = { + instance_fields : struct_fields; (** non-static fields *) + static_fields : struct_fields; (** static fields *) + csu : Csu.t; (** class/struct/union *) + struct_name : Mangled.t option; (** name *) + superclasses : Typename.t list; (** list of superclasses *) + def_methods : Procname.t list; (** methods defined *) + struct_annotations : item_annotation; (** annotations *) +} + (** types for sil (structured) expressions *) and typ = | Tvar of Typename.t (** named type *) @@ -656,12 +667,7 @@ and typ = | Tvoid (** void type *) | Tfun of bool (** function type with noreturn attribute *) | Tptr of typ * ptr_kind (** pointer type *) - | Tstruct of struct_fields * struct_fields * Csu.t * Mangled.t option * - Typename.t list * Procname.t list * item_annotation - (** Structure type with nonstatic and static fields, class/struct/union flag, name, - list of superclasses, methods defined, and annotations. - The fld - typ pairs are always sorted. This means that we don't support programs that exploit specific layouts - of C structs. *) + | Tstruct of struct_typ (** Type for a structured value *) | Tarray of typ * exp (** array type with fixed size *) | Tenum of (Mangled.t * const) list @@ -828,8 +834,8 @@ let is_objc_ref_counter_field (fld, t, a) = let has_objc_ref_counter hpred = match hpred with - | Hpointsto(_, _, Sizeof(Tstruct(fl, _, _, _, _, _, _), _)) -> - IList.exists is_objc_ref_counter_field fl + | Hpointsto(_, _, Sizeof(Tstruct struct_typ, _)) -> + IList.exists is_objc_ref_counter_field struct_typ.instance_fields | _ -> false let objc_class_str = "ObjC-Class" @@ -847,8 +853,8 @@ let cpp_class_annotation = let is_class_of_language typ class_string = match typ with - | Tstruct(_, _, Csu.Class, _, _, _, a) -> - (match a with + | Tstruct { csu = Csu.Class; struct_annotations } -> + (match struct_annotations with | [({ class_name = n; parameters = []}, true)] when n = class_string -> true | _ -> false) @@ -1288,6 +1294,13 @@ let rec const_compare (c1 : const) (c2 : const) : int = | _, Cptr_to_fld _ -> 1 | Ctuple el1, Ctuple el2 -> IList.compare exp_compare el1 el2 +and struct_typ_compare struct_typ1 struct_typ2 = + let n = fld_typ_ann_list_compare struct_typ1.instance_fields struct_typ2.instance_fields in + if n <> 0 then n else + let n = fld_typ_ann_list_compare struct_typ1.static_fields struct_typ2.static_fields in + if n <> 0 then n else let n = Csu.compare struct_typ1.csu struct_typ2.csu in + if n <> 0 then n else cname_opt_compare struct_typ1.struct_name struct_typ2.struct_name + (** Comparision for types. *) and typ_compare t1 t2 = if t1 == t2 then 0 else match t1, t2 with @@ -1311,12 +1324,8 @@ and typ_compare t1 t2 = if n <> 0 then n else ptr_kind_compare pk1 pk2 | Tptr _, _ -> - 1 | _, Tptr _ -> 1 - | Tstruct (ntal1, sntal1, csu1, nameo1, _, _, _), - Tstruct (ntal2, sntal2, csu2, nameo2, _, _, _) -> - let n = fld_typ_ann_list_compare ntal1 ntal2 in - if n <> 0 then n else let n = fld_typ_ann_list_compare sntal1 sntal2 in - if n <> 0 then n else let n = Csu.compare csu1 csu2 in - if n <> 0 then n else cname_opt_compare nameo1 nameo2 + | Tstruct struct_typ1, Tstruct struct_typ2 -> + struct_typ_compare struct_typ1 struct_typ2 | Tstruct _, _ -> - 1 | _, Tstruct _ -> 1 | Tarray (t1, _), Tarray (t2, _) -> typ_compare t1 t2 @@ -1969,17 +1978,29 @@ and pp_type_decl pe pp_base pp_size f = function | Tptr (typ, pk) -> let pp_base' fmt () = F.fprintf fmt "%s%a" (ptr_kind_string pk) pp_base () in pp_type_decl pe pp_base' pp_size f typ - | Tstruct (ftal, sftal, csu, Some name, _, _, _) when false -> + | Tstruct ({struct_name = Some name} as struct_typ) when false -> (* remove "when false" to print the details of struct *) - F.fprintf f "%s %a {%a} %a" (Csu.name csu) Mangled.pp name + F.fprintf f "%s %a {%a} %a" + (Csu.name struct_typ.csu) + Mangled.pp name + (pp_seq (fun f (fld, t, ann) -> + F.fprintf f "%a %a" + (pp_typ_full pe) t + Ident.pp_fieldname fld)) struct_typ.instance_fields + pp_base () + | Tstruct ({struct_name = Some name} as struct_typ) -> + F.fprintf f "%s %a %a" + (Csu.name struct_typ.csu) + Mangled.pp name + pp_base () + | Tstruct ({struct_name = None} as struct_typ) -> + F.fprintf f "%s {%a} %a" + (Csu.name struct_typ.csu) (pp_seq (fun f (fld, t, ann) -> - F.fprintf f "%a %a" (pp_typ_full pe) t Ident.pp_fieldname fld)) - ftal pp_base () - | Tstruct (ftal, sftal, csu, Some name, _, _, _) -> - F.fprintf f "%s %a %a" (Csu.name csu) Mangled.pp name pp_base () - | Tstruct (ftal, sftal, csu, None, _, _, _) -> - F.fprintf f "%s {%a} %a" (Csu.name csu) - (pp_seq (fun f (fld, t, ann) -> F.fprintf f "%a %a" (pp_typ_full pe) t Ident.pp_fieldname fld)) ftal pp_base () + F.fprintf f "%a %a" + (pp_typ_full pe) t + Ident.pp_fieldname fld)) struct_typ.instance_fields + pp_base () | Tarray (typ, size) -> let pp_base' fmt () = F.fprintf fmt "%a[%a]" pp_base () (pp_size pe) size in pp_type_decl pe pp_base' pp_size f typ @@ -2203,8 +2224,8 @@ let rec typ_iter_types (f : typ -> unit) typ = () | Tptr (t', pk) -> typ_iter_types f t' - | Tstruct (ftal, sftal, csu, nameo, supers, def_mthds, iann) -> - IList.iter (fun (_, t, _) -> typ_iter_types f t) ftal + | Tstruct struct_typ -> + IList.iter (fun (_, t, _) -> typ_iter_types f t) struct_typ.instance_fields | Tarray (t, e) -> typ_iter_types f t; exp_iter_types f e @@ -2814,8 +2835,10 @@ let texp_to_typ default_opt = function let struct_typ_fld default_opt f = let def () = unsome_typ "struct_typ_fld" default_opt in function - | Tstruct (ftal, sftal, _, _, _, _, _) -> - (try (fun (x, y, z) -> y) (IList.find (fun (_f, t, ann) -> Ident.fieldname_equal _f f) ftal) + | Tstruct struct_typ -> + (try (fun (x, y, z) -> y) + (IList.find (fun (_f, t, ann) -> + Ident.fieldname_equal _f f) struct_typ.instance_fields) with Not_found -> def ()) | _ -> def () diff --git a/infer/src/backend/sil.mli b/infer/src/backend/sil.mli index c2161de48..8afd36409 100644 --- a/infer/src/backend/sil.mli +++ b/infer/src/backend/sil.mli @@ -279,6 +279,17 @@ and const = and struct_fields = (Ident.fieldname * typ * item_annotation) list +(** Type for a structured value. *) +and struct_typ = { + instance_fields : struct_fields; (** non-static fields *) + static_fields : struct_fields; (** static fields *) + csu : Csu.t; (** class/struct/union *) + struct_name : Mangled.t option; (** name *) + superclasses : Typename.t list; (** list of superclasses *) + def_methods : Procname.t list; (** methods defined *) + struct_annotations : item_annotation; (** annotations *) +} + (** Types for sil (structured) expressions. *) and typ = | Tvar of Typename.t (** named type *) @@ -287,12 +298,7 @@ and typ = | Tvoid (** void type *) | Tfun of bool (** function type with noreturn attribute *) | Tptr of typ * ptr_kind (** pointer type *) - | Tstruct of struct_fields * struct_fields * Csu.t * Mangled.t option * - Typename.t list * Procname.t list * item_annotation - (** Structure type with nonstatic and static fields, class/struct/union flag, name, list of superclasses, - methods defined, and annotations. - The fld - typ pairs are always sorted. This means that we don't support programs that exploit specific layouts - of C structs. *) + | Tstruct of struct_typ (** Type for a structured value *) | Tarray of typ * exp (** array type with fixed size *) | Tenum of (Mangled.t * const) list diff --git a/infer/src/backend/symExec.ml b/infer/src/backend/symExec.ml index 516784233..0ef226817 100644 --- a/infer/src/backend/symExec.ml +++ b/infer/src/backend/symExec.ml @@ -42,9 +42,9 @@ let rec unroll_type tenv typ off = | Sil.Tvar _, _ -> let typ' = Sil.expand_type tenv typ in unroll_type tenv typ' off - | Sil.Tstruct (ftal, sftal, _, _, _, _, _), Sil.Off_fld (fld, _) -> + | Sil.Tstruct { Sil.instance_fields; static_fields }, Sil.Off_fld (fld, _) -> begin - try fldlist_assoc fld (ftal @ sftal) + try fldlist_assoc fld (instance_fields @ static_fields) with Not_found -> L.d_strln ".... Invalid Field Access ...."; L.d_strln ("Fld : " ^ Ident.fieldname_to_string fld); @@ -156,10 +156,10 @@ let rec apply_offlist | (Sil.Off_fld (fld, fld_typ)):: offlist', Sil.Estruct (fsel, inst') -> begin let typ' = Sil.expand_type tenv typ in - let ftal, sftal, csu, nameo, supers, def_mthds, iann = + let struct_typ = match typ' with - | Sil.Tstruct (ftal, sftal, csu, nameo, supers, def_mthds, iann) -> - ftal, sftal, csu, nameo, supers, def_mthds, iann + | Sil.Tstruct struct_typ -> + struct_typ | _ -> assert false in let t' = unroll_type tenv typ (Sil.Off_fld (fld, fld_typ)) in try @@ -171,9 +171,9 @@ let rec apply_offlist let replace_fse fse = if Sil.fld_equal fld (fst fse) then (fld, res_se') else fse in let res_se = Sil.Estruct (IList.map replace_fse fsel, inst') in let replace_fta (f, t, a) = if Sil.fld_equal fld f then (fld, res_t', a) else (f, t, a) in + let instance_fields' = IList.map replace_fta struct_typ.Sil.instance_fields in let res_t = - Sil.Tstruct - (IList.map replace_fta ftal, sftal, csu, nameo, supers, def_mthds, iann) in + Sil.Tstruct { struct_typ with Sil.instance_fields = instance_fields' } in (res_e', res_se, res_t, res_pred_insts_op') with Not_found -> pp_error(); @@ -606,11 +606,11 @@ let resolve_method tenv class_name proc_name = Procname.java_replace_class proc_name (Typename.name class_name) else Procname.c_method_replace_class proc_name (Typename.name class_name) in match Sil.tenv_lookup tenv class_name with - | Some (Sil.Tstruct (_, _, Csu.Class, cls, super_classes, methods, iann)) -> - if method_exists right_proc_name methods then + | Some (Sil.Tstruct { Sil.csu = Csu.Class; def_methods; superclasses }) -> + if method_exists right_proc_name def_methods then Some right_proc_name else - (match super_classes with + (match superclasses with | super_classname:: interfaces -> if not (Typename.Set.mem super_classname !visited) then resolve super_classname @@ -634,8 +634,8 @@ let resolve_typename prop arg = | _ :: hpreds -> loop hpreds in loop (Prop.get_sigma prop) in match typexp_opt with - | Some (Sil.Sizeof (Sil.Tstruct (_, _, _, None, _, _, _), _)) -> None - | Some (Sil.Sizeof (Sil.Tstruct (_, _, Csu.Class, Some name, _, _, _), _)) -> + | Some (Sil.Sizeof (Sil.Tstruct { Sil.struct_name = None }, _)) -> None + | Some (Sil.Sizeof (Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some name }, _)) -> Some (Typename.TN_csu (Csu.Class, name)) | _ -> None @@ -659,7 +659,7 @@ let resolve_virtual_pname cfg tenv prop args pname call_flags : Procname.t = let redirect_shared_ptr tenv cfg pname actual_params = let class_shared_ptr typ = try match Sil.expand_type tenv typ with - | Sil.Tstruct (_, _, Csu.Class, Some cl_name, _, _, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some cl_name } -> let name = Mangled.to_string cl_name in name = "shared_ptr" || name = "__shared_ptr" | t -> false @@ -1468,7 +1468,7 @@ and sym_exec_call cfg pdesc tenv pre path ret_ids actual_pars summary loc = | _, [id] -> Errdesc.id_is_assigned_then_dead (State.get_node ()) id | _ -> false in if is_ignored - && Specs.get_flag callee_pname proc_flag_ignore_return = None then + && Specs.get_flag callee_pname proc_flag_ignore_return = None then let err_desc = Localise.desc_return_value_ignored callee_pname loc in let exn = (Exceptions.Return_value_ignored (err_desc, try assert false with Assert_failure x -> x)) in let pre_opt = State.get_normalized_pre (Abs.abstract_no_symop caller_pname) in diff --git a/infer/src/backend/tabulation.ml b/infer/src/backend/tabulation.ml index ef6067868..8554c0a53 100644 --- a/infer/src/backend/tabulation.ml +++ b/infer/src/backend/tabulation.ml @@ -443,9 +443,9 @@ let texp_star texp1 texp2 = | 0 -> ftal_sub ftal1' ftal2' | _ -> ftal_sub ftal1 ftal2' end in let typ_star t1 t2 = match t1, t2 with - | Sil.Tstruct (ftal1, sftal1, csu1, _, _, _, _), - Sil.Tstruct (ftal2, sftal2, csu2, _, _, _, _) when csu1 = csu2 -> - if ftal_sub ftal1 ftal2 then t2 else t1 + | Sil.Tstruct { Sil.instance_fields = instance_fields1; csu = csu1 }, + Sil.Tstruct { Sil.instance_fields = instance_fields2; csu = csu2 } when csu1 = csu2 -> + if ftal_sub instance_fields1 instance_fields2 then t2 else t1 | _ -> t1 in match texp1, texp2 with | Sil.Sizeof (t1, st1), Sil.Sizeof (t2, st2) -> Sil.Sizeof (typ_star t1 t2, Sil.Subtype.join st1 st2) @@ -597,7 +597,8 @@ let prop_get_exn_name pname prop = let exn_name = ref (Typename.Java.from_string "") in let find_exn_name e = let do_hpred = function - | Sil.Hpointsto (e1, _, Sil.Sizeof(Sil.Tstruct (_, _, _, Some name, _, _, _), _)) when Sil.exp_equal e1 e -> + | Sil.Hpointsto (e1, _, Sil.Sizeof (Sil.Tstruct { Sil.struct_name = Some name }, _)) + when Sil.exp_equal e1 e -> let found_exn_name = Typename.TN_csu (Csu.Class, name) in exn_name := found_exn_name | _ -> () in diff --git a/infer/src/backend/type_prop.ml b/infer/src/backend/type_prop.ml index 3542c51fc..2a95dc5c1 100644 --- a/infer/src/backend/type_prop.ml +++ b/infer/src/backend/type_prop.ml @@ -99,8 +99,8 @@ struct let rec type_to_string typ = match typ with | Sil.Tptr (typ , _) -> type_to_string typ - | Sil.Tstruct (_, _, Csu.Class, Some mangled, _, _, _) - | Sil.Tvar (Typename.TN_csu (Csu.Class, (mangled))) -> Mangled.to_string mangled + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some mangled } + | Sil.Tvar (Typename.TN_csu (Csu.Class, mangled)) -> Mangled.to_string mangled | _ -> Sil.typ_to_string typ let string_typ_to_string (s, typ) = @@ -311,7 +311,7 @@ let initial_node = ref (Cfg.Node.dummy ()) let rec super tenv t = match t with - | Sil.Tstruct (_, _, Csu.Class, Some c2, class_name :: rest, _, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some _; superclasses = class_name :: _ } -> Sil.tenv_lookup tenv class_name | Sil.Tarray (dom_type, _) -> None | Sil.Tptr (dom_type, p) -> @@ -430,9 +430,9 @@ struct | _ -> let ityp = Sil.expand_type tenv typ in match ityp with - | Sil.Tstruct (fields, sftal, csu, nameo, supers, def_mthds, iann) -> + | Sil.Tstruct { Sil.instance_fields } -> let (_, typ, _) = - try ((IList.find (fun (f, t, _) -> Ident.fieldname_equal f field)) fields) + try ((IList.find (fun (f, t, _) -> Ident.fieldname_equal f field)) instance_fields) with Not_found -> assert false in typ | _ -> assert false @@ -488,8 +488,8 @@ struct let pred = try IList.find (fun p -> not (Set.mem p set)) preds with Not_found -> - try IList.hd preds - with Failure "hd" -> Set.min_elt set in + try IList.hd preds + with Failure "hd" -> Set.min_elt set in (aux pred) in if (Set.mem old_node set) then backtrack () else diff --git a/infer/src/checkers/annotations.ml b/infer/src/checkers/annotations.ml index 06dd2a008..af1718a99 100644 --- a/infer/src/checkers/annotations.ml +++ b/infer/src/checkers/annotations.ml @@ -37,10 +37,12 @@ let suppressLint = "android.annotation.SuppressLint" let get_field_type_and_annotation fn = function - | Sil.Tptr (Sil.Tstruct (ftal, sftal, _, _, _, _, _), _) - | Sil.Tstruct (ftal, sftal, _, _, _, _, _) -> + | Sil.Tptr (Sil.Tstruct struct_typ, _) + | Sil.Tstruct struct_typ -> (try - let (_, t, a) = IList.find (fun (f, t, a) -> Sil.fld_equal f fn) (ftal @ sftal) in + let (_, t, a) = IList.find (fun (f, t, a) -> + Sil.fld_equal f fn) + (struct_typ.Sil.instance_fields @ struct_typ.Sil.static_fields) in Some (t, a) with Not_found -> None) | _ -> None diff --git a/infer/src/checkers/callbackChecker.ml b/infer/src/checkers/callbackChecker.ml index 27ac19ea6..7e801233f 100644 --- a/infer/src/checkers/callbackChecker.ml +++ b/infer/src/checkers/callbackChecker.ml @@ -83,7 +83,7 @@ let callback_checker_main all_procs get_procdesc idenv tenv proc_name proc_desc let typename = Typename.TN_csu (Csu.Class, Mangled.from_string (Procname.java_get_class proc_name)) in match Sil.tenv_lookup tenv typename with - | Some (Sil.Tstruct(_, _, csu, Some class_name, _, methods, _) as typ) -> + | Some (Sil.Tstruct { Sil.csu; struct_name = Some class_name; def_methods } as typ) -> let lifecycle_typs = get_or_create_lifecycle_typs tenv in let proc_belongs_to_lifecycle_typ = IList.exists (fun lifecycle_typ -> AndroidFramework.typ_is_lifecycle_typ typ lifecycle_typ tenv) @@ -96,13 +96,14 @@ let callback_checker_main all_procs get_procdesc idenv tenv proc_name proc_desc let registered_callback_procs' = IList.fold_left (fun callback_procs callback_typ -> match callback_typ with - | Sil.Tptr (Sil.Tstruct(_, _, Csu.Class, Some class_name, _, methods, _), _) -> + | Sil.Tptr (Sil.Tstruct + { Sil.struct_name = Some _; def_methods = def_methods'}, _) -> IList.fold_left (fun callback_procs callback_proc -> if Procname.is_constructor callback_proc then callback_procs else Procname.Set.add callback_proc callback_procs) callback_procs - methods + def_methods' | typ -> callback_procs) !registered_callback_procs registered_callback_typs in @@ -111,6 +112,6 @@ let callback_checker_main all_procs get_procdesc idenv tenv proc_name proc_desc (* compute the set of fields nullified by this procedure *) (* TODO (t4959422): get fields that are nullified in callees of the destroy method *) fields_nullified := FldSet.union (get_fields_nullified proc_desc) !fields_nullified in - if done_checking (IList.length methods) then + if done_checking (IList.length def_methods) then do_eradicate_check all_procs get_procdesc idenv tenv | _ -> () diff --git a/infer/src/checkers/checkers.ml b/infer/src/checkers/checkers.ml index b7d62dc28..919bc968d 100644 --- a/infer/src/checkers/checkers.ml +++ b/infer/src/checkers/checkers.ml @@ -207,8 +207,8 @@ let callback_check_write_to_parcel all_procs get_proc_desc idenv tenv proc_name PatternMatch.has_formal_method_argument_type_names proc_desc proc_name ["android.os.Parcel"] in let parcel_constructors = function - | Sil.Tptr (Sil.Tstruct (_, _, _, _, _, methods, _), _) -> - IList.filter is_parcel_constructor methods + | Sil.Tptr (Sil.Tstruct { Sil.def_methods }, _) -> + IList.filter is_parcel_constructor def_methods | _ -> [] in let check r_name r_desc w_name w_desc = diff --git a/infer/src/checkers/patternMatch.ml b/infer/src/checkers/patternMatch.ml index 5c1af844e..af9df5ece 100644 --- a/infer/src/checkers/patternMatch.ml +++ b/infer/src/checkers/patternMatch.ml @@ -16,7 +16,8 @@ open Utils let object_name = Mangled.from_string "java.lang.Object" let type_is_object = function - | Sil.Tptr (Sil.Tstruct (_, _, _, Some name, _, _, _), _) -> Mangled.equal name object_name + | Sil.Tptr (Sil.Tstruct { Sil.struct_name = Some name }, _) -> + Mangled.equal name object_name | _ -> false let java_proc_name_with_class_method pn class_with_path method_name = @@ -27,8 +28,8 @@ let java_proc_name_with_class_method pn class_with_path method_name = let is_direct_subtype_of this_type super_type_name = match this_type with - | Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) -> - IList.exists (fun cn -> Typename.equal cn super_type_name) supertypes + | Sil.Tptr (Sil.Tstruct { Sil.superclasses }, _) -> + IList.exists (fun cn -> Typename.equal cn super_type_name) superclasses | _ -> false (** The type the method is invoked on *) @@ -37,12 +38,13 @@ let get_this_type proc_attributes = match proc_attributes.ProcAttributes.formals | _ -> None let type_get_direct_supertypes = function - | Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) - | Sil.Tstruct (_, _, _, _, supertypes, _, _) -> supertypes + | Sil.Tptr (Sil.Tstruct { Sil.superclasses }, _) + | Sil.Tstruct { Sil.superclasses } -> + superclasses | _ -> [] let type_get_class_name t = match t with - | Sil.Tptr (Sil.Tstruct (_, _, _, Some cn, _, _, _), _) -> + | Sil.Tptr (Sil.Tstruct { Sil.struct_name = Some cn }, _) -> Some cn | Sil.Tptr (Sil.Tvar (Typename.TN_csu (Csu.Class, cn)), _) -> Some cn @@ -51,8 +53,9 @@ let type_get_class_name t = match t with let type_get_annotation (t: Sil.typ): Sil.item_annotation option = match t with - | Sil.Tptr (Sil.Tstruct (_, _, _, _, _, _, ia), _) - | Sil.Tstruct (_, _, _, _, _, _, ia) -> Some ia + | Sil.Tptr (Sil.Tstruct { Sil.struct_annotations }, _) + | Sil.Tstruct { Sil.struct_annotations } -> + Some struct_annotations | _ -> None let type_has_class_name t name = @@ -71,8 +74,8 @@ let type_has_supertype else begin match Sil.expand_type tenv typ with - | Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) - | Sil.Tstruct (_, _, _, _, supertypes, _, _) -> + | Sil.Tptr (Sil.Tstruct { Sil.superclasses }, _) + | Sil.Tstruct { Sil.superclasses } -> let match_supertype cn = let match_name () = Typename.equal cn class_name in let has_indirect_supertype () = @@ -80,15 +83,15 @@ let type_has_supertype | Some supertype -> has_supertype supertype (Sil.TypSet.add typ visited) | None -> false in (match_name () || has_indirect_supertype ()) in - IList.exists match_supertype supertypes + IList.exists match_supertype superclasses | _ -> false end in has_supertype typ Sil.TypSet.empty let type_is_nested_in_type t n = match t with - | Sil.Tptr (Sil.Tstruct (_, _, _, Some m, _, _, _), _) -> - string_is_prefix (Mangled.to_string n ^ "$") (Mangled.to_string m) + | Sil.Tptr (Sil.Tstruct { Sil.struct_name = Some name }, _) -> + string_is_prefix (Mangled.to_string n ^ "$") (Mangled.to_string name) | _ -> false let type_is_nested_in_direct_supertype t n = @@ -96,7 +99,8 @@ let type_is_nested_in_direct_supertype t n = IList.exists (is_nested_in n) (type_get_direct_supertypes t) let rec get_type_name = function - | Sil.Tstruct (_, _, _, Some mangled, _, _, _) -> Mangled.to_string mangled + | Sil.Tstruct { Sil.struct_name = Some name } -> + Mangled.to_string name | Sil.Tptr (t, _) -> get_type_name t | Sil.Tvar tn -> Typename.name tn | _ -> "_" @@ -105,12 +109,12 @@ let get_field_type_name (typ: Sil.typ) (fieldname: Ident.fieldname): string option = match typ with - | Sil.Tstruct (fields, _, _, _, _, _, _) - | Sil.Tptr (Sil.Tstruct (fields, _, _, _, _, _, _), _) -> ( + | Sil.Tstruct { Sil.instance_fields } + | Sil.Tptr (Sil.Tstruct { Sil.instance_fields }, _) -> ( try let _, ft, _ = IList.find (function | (fn, _, _) -> Ident.fieldname_equal fn fieldname) - fields in + instance_fields in Some (get_type_name ft) with Not_found -> None) | _ -> None @@ -304,7 +308,7 @@ let proc_iter_overridden_methods f tenv proc_name = let super_proc_name = Procname.java_replace_class proc_name (Typename.name super_class_name) in match Sil.tenv_lookup tenv super_class_name with - | Some (Sil.Tstruct (_, _, _, _, _, methods, _)) -> + | Some (Sil.Tstruct { Sil.def_methods }) -> let is_override pname = Procname.equal pname super_proc_name && not (Procname.is_constructor pname) in @@ -312,7 +316,7 @@ let proc_iter_overridden_methods f tenv proc_name = (fun pname -> if is_override pname then f pname) - methods + def_methods | _ -> () in if Procname.is_java proc_name then diff --git a/infer/src/clang/cContext.ml b/infer/src/clang/cContext.ml index 5db0759bf..eb8cdb2b1 100644 --- a/infer/src/clang/cContext.ml +++ b/infer/src/clang/cContext.ml @@ -118,7 +118,7 @@ let curr_class_hash curr_class = let create_curr_class tenv class_name = let class_tn_name = Typename.TN_csu (Csu.Class, (Mangled.from_string class_name)) in match Sil.tenv_lookup tenv class_tn_name with - | Some Sil.Tstruct(intf_fields, _, _, _, superclasses, methods, annotation) -> + | Some Sil.Tstruct { Sil.superclasses } -> (let superclasses_names = IList.map Typename.name superclasses in match superclasses_names with | superclass:: protocols -> diff --git a/infer/src/clang/cField_decl.ml b/infer/src/clang/cField_decl.ml index bb7c9d40b..5cd666f4e 100644 --- a/infer/src/clang/cField_decl.ml +++ b/infer/src/clang/cField_decl.ml @@ -20,10 +20,10 @@ let rec get_fields_super_classes tenv super_class = Printing.log_out " ... Getting fields of superclass '%s'\n" (Typename.to_string super_class); match Sil.tenv_lookup tenv super_class with | None -> [] - | Some Sil.Tstruct (fields, _, _, _, super_class :: _, _, _) -> + | Some Sil.Tstruct { Sil.instance_fields; superclasses = super_class :: _ } -> let sc_fields = get_fields_super_classes tenv super_class in - General_utils.append_no_duplicates_fields fields sc_fields - | Some Sil.Tstruct (fields, _, _, _, _, _, _) -> fields + General_utils.append_no_duplicates_fields instance_fields sc_fields + | Some Sil.Tstruct { Sil.instance_fields } -> instance_fields | Some _ -> [] let fields_superclass tenv interface_decl_info = @@ -79,13 +79,17 @@ let add_missing_fields tenv class_name fields = let mang_name = Mangled.from_string class_name in let class_tn_name = Typename.TN_csu (Csu.Class, mang_name) in match Sil.tenv_lookup tenv class_tn_name with - | Some Sil.Tstruct(intf_fields, _, _, _, superclass, methods, annotation) -> - let new_fields = General_utils.append_no_duplicates_fields fields intf_fields in + | Some Sil.Tstruct ({ Sil.instance_fields } as struct_typ) -> + let new_fields = General_utils.append_no_duplicates_fields fields instance_fields in let new_fields = CFrontend_utils.General_utils.sort_fields new_fields in let class_type_info = - Sil.Tstruct ( - new_fields, [], Csu.Class, Some mang_name, superclass, methods, annotation - ) in + Sil.Tstruct + { struct_typ with + Sil.instance_fields = new_fields; + static_fields = []; + csu = Csu.Class; + struct_name = Some mang_name; + } in Printing.log_out " Updating info for class '%s' in tenv\n" class_name; Sil.tenv_add tenv class_tn_name class_type_info | _ -> () diff --git a/infer/src/clang/cFrontend_checkers.ml b/infer/src/clang/cFrontend_checkers.ml index 512c21556..ac4d367a9 100644 --- a/infer/src/clang/cFrontend_checkers.ml +++ b/infer/src/clang/cFrontend_checkers.ml @@ -43,13 +43,13 @@ let direct_atomic_property_access context stmt_info ivar_name = let tname = Typename.TN_csu (Csu.Class, Mangled.from_string cname) in let loc = CLocation.get_sil_location_from_range stmt_info.Clang_ast_t.si_source_range true in match Sil.tenv_lookup tenv tname with - | Some Sil.Tstruct (flds1, flds2, _, _, _, _, _) -> + | Some Sil.Tstruct { Sil.instance_fields; static_fields } -> (* We give the warning when: (1) the property has the atomic attribute and (2) the access of the ivar is not in a getter or setter method. (3) the access of the ivar is not in the init method Last two conditions avoids false positives *) - let condition = (CField_decl.is_ivar_atomic ivar (flds1 @ flds2)) + let condition = (CField_decl.is_ivar_atomic ivar (instance_fields @ static_fields)) && not (CContext.is_curr_proc_objc_getter context ivar) && not (CContext.is_curr_proc_objc_setter context ivar) && not (Procname.is_constructor mname) diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 756c63797..6df2d1814 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -45,15 +45,16 @@ struct match typname with | Typename.TN_csu (Csu.Class, _) | Typename.TN_csu (Csu.Protocol, _) -> (match typ with - | Sil.Tstruct (fields, _, _, cls, super_classes, methods, iann) -> + | Sil.Tstruct { Sil.instance_fields; superclasses; def_methods; struct_annotations } -> print_endline ( - (Typename.to_string typname) ^ " " ^ (Sil.item_annotation_to_string iann) ^ "\n" ^ + (Typename.to_string typname) ^ " " ^ + (Sil.item_annotation_to_string struct_annotations) ^ "\n" ^ "---> superclass and protocols " ^ (IList.to_string (fun tn -> - "\t" ^ (Typename.to_string tn) ^ "\n") super_classes) ^ + "\t" ^ (Typename.to_string tn) ^ "\n") superclasses) ^ "---> methods " ^ - (IList.to_string (fun x ->"\t" ^ (Procname.to_string x) ^ "\n") methods) + (IList.to_string (fun x ->"\t" ^ (Procname.to_string x) ^ "\n") def_methods) ^ " " ^ - "\t---> fields " ^ (IList.to_string field_to_string fields) ^ "\n") + "\t---> fields " ^ (IList.to_string field_to_string instance_fields) ^ "\n") | _ -> ()) | _ -> () ) tenv @@ -63,19 +64,19 @@ struct match typname with | Typename.TN_csu (Csu.Struct, _) | Typename.TN_csu (Csu.Union, _) -> (match typ with - | (Sil.Tstruct (fields, static_fields, _, cls, super_classes, methods, iann)) -> - (print_endline ( - (Typename.to_string typname)^"\n"^ - "\t---> fields "^(IList.to_string (fun (fieldname, typ, _) -> - match typ with - | Sil.Tvar tname -> "tvar"^(Typename.to_string tname) - | Sil.Tstruct (_, _, _, _, _, _, _) | _ -> - "\t struct "^(Ident.fieldname_to_string fieldname)^" "^ - (Sil.typ_to_string typ)^"\n") fields - ) - ) + | Sil.Tstruct { Sil.instance_fields } -> + print_endline ( + (Typename.to_string typname)^"\n"^ + "\t---> fields "^(IList.to_string (fun (fieldname, typ, _) -> + match typ with + | Sil.Tvar tname -> "tvar"^(Typename.to_string tname) + | Sil.Tstruct _ | _ -> + "\t struct "^(Ident.fieldname_to_string fieldname)^" "^ + (Sil.typ_to_string typ)^"\n") instance_fields + ) ) - | _ -> ()) + | _ -> () + ) | Typename.TN_typedef typname -> print_endline ((Mangled.to_string typname)^"-->"^(Sil.typ_to_string typ)) | _ -> () diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 5e65bf062..7de6b0de9 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -191,7 +191,7 @@ let get_superclass_curr_class context = let iname = Typename.TN_csu (Csu.Class, Mangled.from_string cname) in Printing.log_out "Checking for superclass = '%s'\n\n%!" (Typename.to_string iname); match Sil.tenv_lookup (CContext.get_tenv context) iname with - | Some Sil.Tstruct(_, _, _, _, super_name :: _, _, _) -> + | Some Sil.Tstruct { Sil.superclasses = super_name :: _ } -> Typename.name super_name | _ -> Printing.log_err "NOT FOUND superclass = '%s'\n\n%!" (Typename.to_string iname); diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 3e9408093..9cf511678 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -118,7 +118,15 @@ struct IList.iter (fun (fn, ft, _) -> Printing.log_out "-----> field: '%s'\n" (Ident.fieldname_to_string fn)) fields; let mblock = Mangled.from_string block_name in - let block_type = Sil.Tstruct (fields, [], Csu.Class, Some mblock, [], [], []) in + let block_type = Sil.Tstruct + { Sil.instance_fields = fields; + static_fields = []; + csu = Csu.Class; + struct_name = Some mblock; + superclasses = []; + def_methods = []; + struct_annotations = []; + } in let block_name = Typename.TN_csu (Csu.Class, mblock) in Sil.tenv_add tenv block_name block_type; let trans_res = CTrans_utils.alloc_trans trans_state loc (Ast_expressions.dummy_stmt_info ()) block_type true in @@ -1395,12 +1403,12 @@ struct else collect_left_hand_exprs e tvar (StringSet.add (Typename.to_string typename) tns) | _ -> [[(e, typ)]] (*This case is an error, shouldn't happen.*)) - | Sil.Tstruct (struct_fields, _, _, _, _, _, _) as type_struct -> + | Sil.Tstruct { Sil.instance_fields } as type_struct -> let lh_exprs = IList.map ( fun (fieldname, fieldtype, _) -> Sil.Lfield (e, fieldname, type_struct) ) - struct_fields in + instance_fields in let lh_types = IList.map ( fun (fieldname, fieldtype, _) -> fieldtype) - struct_fields in + instance_fields in IList.map (fun (e, t) -> IList.flatten (collect_left_hand_exprs e t tns)) (zip lh_exprs lh_types) | Sil.Tarray (arrtyp, Sil.Const (Sil.Cint n)) -> let size = Sil.Int.to_int n in diff --git a/infer/src/clang/cTypes.ml b/infer/src/clang/cTypes.ml index e16a7680a..2d0b373cf 100644 --- a/infer/src/clang/cTypes.ml +++ b/infer/src/clang/cTypes.ml @@ -18,7 +18,7 @@ let get_type_from_expr_info ei = let get_name_from_struct s = match s with - | Sil.Tstruct(_, _, _, Some n, _, _, _) -> n + | Sil.Tstruct { Sil.struct_name = Some n } -> n | _ -> assert false let rec get_type_list nn ll = @@ -41,7 +41,7 @@ let remove_pointer_to_typ typ = let classname_of_type typ = match typ with | Sil.Tvar (Typename.TN_csu (_, name) ) - | Sil.Tstruct(_, _, _, (Some name), _, _, _) + | Sil.Tstruct { Sil.struct_name = Some name } | Sil.Tvar (Typename.TN_typedef name) -> Mangled.to_string name | Sil.Tfun _ -> CFrontend_config.objc_object | _ -> @@ -73,8 +73,8 @@ let mk_enumname n = Typename.TN_enum (Mangled.from_string n) let is_class typ = match typ with - | Sil.Tptr( Sil.Tstruct(_, _, _, (Some name), _, _, _), _) - | Sil.Tptr( Sil.Tvar (Typename.TN_csu (_, name) ), _) -> + | Sil.Tptr (Sil.Tstruct { Sil.struct_name = Some name }, _) + | Sil.Tptr (Sil.Tvar (Typename.TN_csu (_, name) ), _) -> (Mangled.to_string name) = CFrontend_config.objc_class | _ -> false diff --git a/infer/src/clang/cTypes_decl.ml b/infer/src/clang/cTypes_decl.ml index 5843334be..74f31cec4 100644 --- a/infer/src/clang/cTypes_decl.ml +++ b/infer/src/clang/cTypes_decl.ml @@ -19,8 +19,15 @@ let add_predefined_objc_types tenv = let objc_class_mangled = Mangled.from_string CFrontend_config.objc_class in let objc_class_name = Typename.TN_csu (Csu.Class, objc_class_mangled) in let objc_class_type_info = - Sil.Tstruct ([], [], Csu.Struct, - Some (Mangled.from_string CFrontend_config.objc_class), [], [], []) in + Sil.Tstruct { + Sil.instance_fields = []; + static_fields = []; + csu = Csu.Struct; + struct_name = Some (Mangled.from_string CFrontend_config.objc_class); + superclasses = []; + def_methods = []; + struct_annotations = []; + } in Sil.tenv_add tenv objc_class_name objc_class_type_info; let class_typename = CType_to_sil_type.get_builtin_objc_typename `ObjCClass in let class_typ = Sil.Tvar (Typename.TN_csu (Csu.Struct, objc_class_mangled)) in @@ -31,8 +38,15 @@ let add_predefined_objc_types tenv = let id_typename = CType_to_sil_type.get_builtin_objc_typename `ObjCId in Sil.tenv_add tenv id_typename id_typedef; let objc_object_type_info = - Sil.Tstruct ([], [], Csu.Struct, - Some (Mangled.from_string CFrontend_config.objc_object), [], [], []) in + Sil.Tstruct { + Sil.instance_fields = []; + static_fields = []; + csu = Csu.Struct; + struct_name = Some (Mangled.from_string CFrontend_config.objc_object); + superclasses = []; + def_methods = []; + struct_annotations = []; + } in Sil.tenv_add tenv typename_objc_object objc_object_type_info (* Whenever new type are added manually to the translation in ast_expressions, *) @@ -134,7 +148,7 @@ let get_superclass_list decl = let add_struct_to_tenv tenv typ = let csu = match typ with - | Sil.Tstruct(_, _, csu, _, _, _, _) -> csu + | Sil.Tstruct { Sil.csu } -> csu | _ -> assert false in let mangled = CTypes.get_name_from_struct typ in let typename = Typename.TN_csu(csu, mangled) in @@ -179,13 +193,20 @@ and get_struct_cpp_class_declaration_type tenv decl = else non_static_fields in let sorted_non_static_fields = CFrontend_utils.General_utils.sort_fields non_static_fields' in let static_fields = [] in (* Warning for the moment we do not treat static field. *) - let methods = get_class_methods tenv name decl_list in (* C++ methods only *) + let def_methods = get_class_methods tenv name decl_list in (* C++ methods only *) let superclasses = get_superclass_list decl in - let item_annotation = + let struct_annotations = if csu = Csu.Class then Sil.cpp_class_annotation else Sil.item_annotation_empty in (* No annotations for structs *) - let sil_type = Sil.Tstruct (sorted_non_static_fields, static_fields, csu, - Some mangled_name, superclasses, methods, item_annotation) in + let sil_type = Sil.Tstruct + { Sil.instance_fields = sorted_non_static_fields; + static_fields; + csu; + struct_name = Some mangled_name; + superclasses; + def_methods; + struct_annotations; + } in Ast_utils.update_sil_types_map type_ptr sil_type; add_struct_to_tenv tenv sil_type; sil_type diff --git a/infer/src/clang/objcCategory_decl.ml b/infer/src/clang/objcCategory_decl.ml index b1434bc6c..e2f134f65 100644 --- a/infer/src/clang/objcCategory_decl.ml +++ b/infer/src/clang/objcCategory_decl.ml @@ -77,14 +77,20 @@ let process_category type_ptr_to_sil_type tenv curr_class decl_info decl_list = let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in Ast_utils.update_sil_types_map decl_key (Sil.Tvar class_tn_name); (match Sil.tenv_lookup tenv class_tn_name with - | Some Sil.Tstruct (intf_fields, _, _, _, superclass, intf_methods, annotation) -> - let new_fields = General_utils.append_no_duplicates_fields fields intf_fields in + | Some Sil.Tstruct + ({ Sil.instance_fields; def_methods } + as struct_typ) -> + let new_fields = General_utils.append_no_duplicates_fields fields instance_fields in let new_fields = CFrontend_utils.General_utils.sort_fields new_fields in - let new_methods = General_utils.append_no_duplicates_methods methods intf_methods in + let new_methods = General_utils.append_no_duplicates_methods methods def_methods in let class_type_info = - Sil.Tstruct ( - new_fields, [], Csu.Class, Some mang_name, superclass, new_methods, annotation - ) in + Sil.Tstruct { struct_typ with + Sil.instance_fields = new_fields; + static_fields = []; + csu = Csu.Class; + struct_name = Some mang_name; + def_methods = new_methods; + } in Printing.log_out " Updating info for class '%s' in tenv\n" class_name; Sil.tenv_add tenv class_tn_name class_type_info | _ -> ()); diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index 44d717ae2..605d5c7e5 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -114,10 +114,10 @@ let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info class_name (*In case we found categories, or partial definition of this class earlier and they are already in the tenv *) let fields, (superclasses : Typename.t list), methods = match Sil.tenv_lookup tenv interface_name with - | Some (Sil.Tstruct (saved_fields, _, _, _, saved_superclasses, saved_methods, _)) -> - General_utils.append_no_duplicates_fields fields saved_fields, - General_utils.append_no_duplicates_csu superclasses saved_superclasses, - General_utils.append_no_duplicates_methods methods saved_methods + | Some (Sil.Tstruct { Sil.instance_fields; superclasses; def_methods }) -> + General_utils.append_no_duplicates_fields fields instance_fields, + General_utils.append_no_duplicates_csu superclasses superclasses, + General_utils.append_no_duplicates_methods methods def_methods | _ -> fields, superclasses, methods in let fields = General_utils.append_no_duplicates_fields fields fields_sc in (* We add the special hidden counter_field for implementing reference counting *) @@ -127,8 +127,15 @@ let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info class_name IList.iter (fun (fn, ft, _) -> Printing.log_out "-----> field: '%s'\n" (Ident.fieldname_to_string fn)) fields; let interface_type_info = - Sil.Tstruct(fields, [], Csu.Class, Some (Mangled.from_string class_name), - superclasses, methods, Sil.objc_class_annotation) in + Sil.Tstruct { + Sil.instance_fields = fields; + static_fields = []; + csu = Csu.Class; + struct_name = Some (Mangled.from_string class_name); + superclasses; + def_methods = methods; + struct_annotations = Sil.objc_class_annotation; + } in Sil.tenv_add tenv interface_name interface_type_info; Printing.log_out " >>>Verifying that Typename '%s' is in tenv\n" (Typename.to_string interface_name); @@ -143,11 +150,17 @@ let add_missing_methods tenv class_name decl_info decl_list curr_class = let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in Ast_utils.update_sil_types_map decl_key (Sil.Tvar class_tn_name); (match Sil.tenv_lookup tenv class_tn_name with - | Some Sil.Tstruct (fields, [], Csu.Class, Some name, - superclass, existing_methods, annotation) -> - let methods = General_utils.append_no_duplicates_methods existing_methods methods in + | Some Sil.Tstruct + ({ Sil.static_fields = []; + csu = Csu.Class; + struct_name = Some name; + def_methods; + } as struct_typ) -> + let methods = General_utils.append_no_duplicates_methods def_methods methods in let typ = - Sil.Tstruct (fields, [], Csu.Class, Some name, superclass, methods, annotation) in + Sil.Tstruct + { struct_typ with + Sil.def_methods = methods; } in Sil.tenv_add tenv class_tn_name typ | _ -> ()); Sil.Tvar class_tn_name diff --git a/infer/src/clang/objcProtocol_decl.ml b/infer/src/clang/objcProtocol_decl.ml index 66b015221..40b1cba3b 100644 --- a/infer/src/clang/objcProtocol_decl.ml +++ b/infer/src/clang/objcProtocol_decl.ml @@ -31,9 +31,17 @@ let protocol_decl type_ptr_to_sil_type tenv decl = let protocol_name = Typename.TN_csu (Csu.Protocol, mang_name) in let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in Ast_utils.update_sil_types_map decl_key (Sil.Tvar protocol_name); - let methods = ObjcProperty_decl.get_methods curr_class decl_list in + let def_methods = ObjcProperty_decl.get_methods curr_class decl_list in let protocol_type_info = - Sil.Tstruct ([], [], Csu.Protocol, Some mang_name, [], methods, []) in + Sil.Tstruct { + Sil.instance_fields = []; + static_fields = []; + csu = Csu.Protocol; + struct_name = Some mang_name; + superclasses = []; + def_methods; + struct_annotations = []; + } in Sil.tenv_add tenv protocol_name protocol_type_info; add_protocol_super type_ptr_to_sil_type tenv obj_c_protocol_decl_info; Sil.Tvar protocol_name diff --git a/infer/src/eradicate/eradicateChecks.ml b/infer/src/eradicate/eradicateChecks.ml index 0b8456de4..ddd503549 100644 --- a/infer/src/eradicate/eradicateChecks.ml +++ b/infer/src/eradicate/eradicateChecks.ml @@ -134,7 +134,7 @@ let check_condition case_zero find_canonical_duplicate get_proc_desc curr_pname let throwable_found = ref false in let throwable_class = Mangled.from_string "java.lang.Throwable" in let typ_is_throwable = function - | Sil.Tstruct (_, _, Csu.Class, Some c, _, _, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some c } -> Mangled.equal c throwable_class | _ -> false in let do_instr = function @@ -253,8 +253,8 @@ let check_constructor_initialization if Procname.is_constructor curr_pname then begin match PatternMatch.get_this_type (Cfg.Procdesc.get_attributes curr_pdesc) with - | Some (Sil.Tptr (Sil.Tstruct (ftal, _, _, nameo, _, _, _) as ts, _)) -> - let do_fta (fn, ft, ia) = + | Some (Sil.Tptr (Sil.Tstruct { Sil.instance_fields; struct_name } as ts, _)) -> + let do_field (fn, ft, ia) = let annotated_with f = match get_field_annotation fn ts with | None -> false | Some (_, ia) -> f ia in @@ -289,7 +289,7 @@ let check_constructor_initialization let should_check_field = let in_current_class = let fld_cname = Ident.java_fieldname_get_class fn in - match nameo with + match struct_name with | None -> false | Some name -> Mangled.equal name (Mangled.from_string fld_cname) in not inject_annotated && @@ -325,7 +325,7 @@ let check_constructor_initialization curr_pname; end in - IList.iter do_fta ftal + IList.iter do_field instance_fields | _ -> () end diff --git a/infer/src/harness/androidFramework.ml b/infer/src/harness/androidFramework.ml index 90b15832b..06cf52c17 100644 --- a/infer/src/harness/androidFramework.ml +++ b/infer/src/harness/androidFramework.ml @@ -253,7 +253,8 @@ let android_callbacks = (* TODO (t4644852): factor out subtyping functions into some sort of JavaUtil module *) let get_all_supertypes typ tenv = let get_direct_supers = function - | Sil.Tstruct (_, _, Csu.Class, _, supers, _, _) -> supers + | Sil.Tstruct { Sil.csu = Csu.Class; superclasses } -> + superclasses | _ -> [] in let rec add_typ class_name typs = match Sil.tenv_lookup tenv class_name with @@ -295,7 +296,7 @@ let is_callback_class_name class_name = Mangled.MangledSet.mem class_name androi let is_callback_class typ tenv = let supertyps = get_all_supertypes typ tenv in TypSet.exists (fun typ -> match typ with - | Sil.Tstruct (_, _, Csu.Class, Some classname, _, _, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some classname } -> is_callback_class_name classname | _ -> false) supertyps @@ -356,12 +357,13 @@ let is_callback_register_method procname args tenv = a list of method names [lifecycle_procs_strs], get the appropriate typ and procnames *) let get_lifecycle_for_framework_typ_opt lifecycle_typ lifecycle_proc_strs tenv = match Sil.tenv_lookup tenv (Typename.TN_csu (Csu.Class, lifecycle_typ)) with - | Some (Sil.Tstruct(_, _, Csu.Class, Some class_name, _, decl_procs, _) as lifecycle_typ) -> + | Some (Sil.Tstruct + { Sil.csu = Csu.Class; struct_name = Some _; def_methods } as lifecycle_typ) -> (* TODO (t4645631): collect the procedures for which is_java is returning false *) let lookup_proc lifecycle_proc = IList.find (fun decl_proc -> Procname.is_java decl_proc && lifecycle_proc = Procname.java_get_method decl_proc - ) decl_procs in + ) def_methods in (* convert each of the framework lifecycle proc strings to a lifecycle method procname *) let lifecycle_procs = IList.fold_left (fun lifecycle_procs lifecycle_proc_str -> diff --git a/infer/src/harness/harness.ml b/infer/src/harness/harness.ml index d9f06997f..d4de1249c 100644 --- a/infer/src/harness/harness.ml +++ b/infer/src/harness/harness.ml @@ -118,7 +118,7 @@ let find_registered_callbacks lifecycle_trace harness_name proc_file_map tenv = (** if [typ] is a lifecycle type, generate a list of (method call, receiver) pairs constituting a lifecycle trace *) let try_create_lifecycle_trace typ lifecycle_typ lifecycle_procs proc_file_map tenv = match typ with - | Sil.Tstruct(_, _, Csu.Class, Some name, _, methods, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some name } -> let class_name = Typename.TN_csu (Csu.Class, name) in if AndroidFramework.typ_is_lifecycle_typ typ lifecycle_typ tenv && not (AndroidFramework.is_android_lib_class class_name) then @@ -143,7 +143,15 @@ let extract_callbacks lifecycle_trace harness_procname proc_file_map tenv = let fields = IList.map (fun (fld, typ, _) -> (fld, typ, [])) registered_cbs in (* create a new typ for the harness containing all of the cb extraction vars as static fields *) let harness_typ = - Sil.Tstruct (fields, [], Csu.Class, Some harness_name, [], [harness_procname], []) in + Sil.Tstruct { + Sil.instance_fields = fields; + static_fields = []; + csu = Csu.Class; + struct_name = Some harness_name; + superclasses = []; + def_methods = [harness_procname]; + struct_annotations = []; + } in (* update the tenv with our created harness typ. we don't have to save the tenv to disk here * because this is done immediately after harness generation runs in jMain.ml *) let harness_class = Typename.TN_csu (Csu.Class, harness_name) in diff --git a/infer/src/harness/inhabit.ml b/infer/src/harness/inhabit.ml index 154aa5ee8..db8868cbf 100644 --- a/infer/src/harness/inhabit.ml +++ b/infer/src/harness/inhabit.ml @@ -108,14 +108,14 @@ let rec inhabit_typ typ proc_file_map env = (* select methods that are constructors and won't force us into infinite recursion because * we are already inhabiting one of their argument types *) let get_all_suitable_constructors typ = match typ with - | Sil.Tstruct (_, _, Csu.Class, _, superclasses, methods, _) -> + | Sil.Tstruct { Sil.csu = Csu.Class; def_methods } -> let is_suitable_constructor p = let try_get_non_receiver_formals p = try get_non_receiver_formals (formals_from_name p proc_file_map) with Not_found -> [] in Procname.is_constructor p && IList.for_all (fun (_, typ) -> not (TypSet.mem typ env.cur_inhabiting)) (try_get_non_receiver_formals p) in - IList.filter (fun p -> is_suitable_constructor p) methods + IList.filter (fun p -> is_suitable_constructor p) def_methods | _ -> [] in let (env, typ_class_name) = match get_all_suitable_constructors typ with | constructor :: _ -> @@ -205,7 +205,7 @@ let inhabit_fld_trace flds proc_file_map env = Sil.Letderef (lhs, fld_exp, fld_typ, env.pc) in let env = env_add_instr fld_read_instr [lhs] env in match fld_typ with - | Sil.Tptr (Sil.Tstruct (_, _, Csu.Class, _, _, procs, _), _) -> + | Sil.Tptr (Sil.Tstruct { Sil.csu = Csu.Class; def_methods }, _) -> let inhabit_cb_call procname env = try let procdesc = procdesc_from_name procname proc_file_map in @@ -220,7 +220,7 @@ let inhabit_fld_trace flds proc_file_map env = IList.fold_left (fun env procname -> if not (Procname.is_constructor procname) && not (Procname.java_is_access_method procname) then inhabit_cb_call procname env - else env) env procs + else env) env def_methods | _ -> assert false in IList.fold_left (fun env fld -> invoke_cb fld env) env flds diff --git a/infer/src/harness/stacktrace.ml b/infer/src/harness/stacktrace.ml index 39b645cd0..c34f4925e 100644 --- a/infer/src/harness/stacktrace.ml +++ b/infer/src/harness/stacktrace.ml @@ -43,11 +43,11 @@ let try_resolve_frame str_frame exe_env tenv = * in the stack trace. Note that the stack trace does not have any type or argument information; * the name is all that we have to go on *) match Sil.tenv_lookup tenv (Typename.TN_csu (Csu.Class, class_name)) with - | Some Sil.Tstruct (_, _, Csu.Class, _, _, decl_procs, _) -> + | Some Sil.Tstruct { Sil.csu = Csu.Class; def_methods } -> let possible_calls = IList.filter (fun proc -> Procname.java_get_method proc = str_frame.method_str) - decl_procs in + def_methods in if IList.length possible_calls > 0 then (* using IList.hd here assumes that all of the possible calls are declared in the * same file, which will be true in Java but not necessarily in other languages *) diff --git a/infer/src/java/jTrans.ml b/infer/src/java/jTrans.ml index ef0252673..f7a23bdbc 100644 --- a/infer/src/java/jTrans.ml +++ b/infer/src/java/jTrans.ml @@ -107,12 +107,12 @@ let retrieve_fieldname fieldname = let get_field_name program static tenv cn fs context = match JTransType.get_class_type_no_pointer program tenv cn with - | Sil.Tstruct (fields, sfields, Csu.Class, _, _, _, _) -> + | Sil.Tstruct { Sil.instance_fields; static_fields; csu = Csu.Class } -> let fieldname, _, _ = try IList.find (fun (fieldname, _, _) -> retrieve_fieldname fieldname = JBasics.fs_name fs) - (if static then sfields else fields) + (if static then static_fields else instance_fields) with Not_found -> (* TODO: understand why fields cannot be found here *) JUtils.log "cannot find %s.%s@." (JBasics.cn_name cn) (JBasics.fs_name fs); diff --git a/infer/src/java/jTransType.ml b/infer/src/java/jTransType.ml index 70348e6be..cd1691eb2 100644 --- a/infer/src/java/jTransType.ml +++ b/infer/src/java/jTransType.ml @@ -91,7 +91,8 @@ let rec create_array_type typ dim = let extract_cn_no_obj typ = match typ with - | Sil.Tptr (Sil.Tstruct (_, _, Csu.Class, Some classname, _, _, _), Sil.Pk_pointer) -> + | Sil.Tptr (Sil.Tstruct { Sil.csu = Csu.Class; struct_name = Some classname }, + Sil.Pk_pointer) -> let class_name = (Mangled.to_string classname) in if class_name = JConfig.object_cl then None else @@ -239,7 +240,15 @@ let collect_interface_field cn inf l = let dummy_type cn = let classname = Mangled.from_string (JBasics.cn_name cn) in - Sil.Tstruct ([], [], Csu.Class, Some classname, [], [], Sil.item_annotation_empty) + Sil.Tstruct { + Sil.instance_fields = []; + static_fields = []; + csu = Csu.Class; + struct_name = Some classname; + superclasses = []; + def_methods = []; + struct_annotations = Sil.item_annotation_empty; + } let collect_models_class_fields classpath_field_map cn cf fields = @@ -283,7 +292,7 @@ let add_model_fields program classpath_fields cn = let rec get_all_fields program tenv cn = let extract_class_fields classname = match get_class_type_no_pointer program tenv classname with - | Sil.Tstruct (nonstatic, static, _, _, _, _, _) -> (static, nonstatic) + | Sil.Tstruct { Sil.instance_fields; static_fields } -> (static_fields, instance_fields) | _ -> assert false in let trans_fields classname = match JClasspath.lookup_node classname program with @@ -307,7 +316,7 @@ and create_sil_type program tenv cn = | Some node -> let create_super_list interface_names = IList.map typename_of_classname interface_names in - let (super_list, nonstatic_fields, static_fields, item_annotation) = + let superclasses, instance_fields, static_fields, struct_annotations = match node with | Javalib.JInterface jinterface -> let static_fields, _ = get_all_fields program tenv cn in @@ -326,15 +335,22 @@ and create_sil_type program tenv cn = | Some super_cn -> let super_classname = match get_class_type_no_pointer program tenv super_cn with - | Sil.Tstruct (_, _, _, Some classname, _, _, _) -> + | Sil.Tstruct { Sil.struct_name = Some classname } -> Typename.TN_csu (Csu.Class, classname) | _ -> assert false in super_classname :: interface_list in (super_classname_list, nonstatic_fields, static_fields, item_annotation) in let classname = Mangled.from_string (JBasics.cn_name cn) in - let method_procnames = get_class_procnames cn node in - Sil.Tstruct (nonstatic_fields, static_fields, Csu.Class, - Some classname, super_list, method_procnames, item_annotation) + let def_methods = get_class_procnames cn node in + Sil.Tstruct { + Sil.instance_fields; + static_fields; + csu = Csu.Class; + struct_name = Some classname; + superclasses; + def_methods; + struct_annotations; + } and get_class_type_no_pointer program tenv cn =