diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 57aa8c961..e37b52e76 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -21,6 +21,8 @@ open CGen_trans (* Translate one global declaration *) let rec translate_one_declaration tenv cg cfg parent_dec dec = let open Clang_ast_t in + (* Run the frontend checkers on this declaration *) + CFrontend_errors.run_frontend_checkers_on_decl tenv cg cfg dec; (* each procedure has different scope: start names from id 0 *) Ident.NameGenerator.reset (); let info = Clang_ast_proj.get_decl_tuple dec in @@ -56,24 +58,12 @@ let rec translate_one_declaration tenv cg cfg parent_dec dec = let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in ignore (ObjcCategory_decl.category_impl_decl CTypes_decl.type_ptr_to_sil_type tenv dec); CMethod_declImpl.process_methods tenv cg cfg curr_class decl_list; - (match Ast_utils.get_decl_opt_with_decl_ref ocidi.Clang_ast_t.ocidi_category_decl with - | Some ObjCCategoryDecl(_, _, cat_decl_list, _, _) -> - let name = CContext.get_curr_class_name curr_class in - let decls = cat_decl_list @ decl_list in - CFrontend_errors.check_for_property_errors cfg cg tenv name decls - | _ -> ()) | ObjCImplementationDecl(_, _, decl_list, _, idi) -> let curr_class = ObjcInterface_decl.get_curr_class_impl idi in let type_ptr_to_sil_type = CTypes_decl.type_ptr_to_sil_type in ignore (ObjcInterface_decl.interface_impl_declaration type_ptr_to_sil_type tenv dec); CMethod_declImpl.process_methods tenv cg cfg curr_class decl_list; - (match Ast_utils.get_decl_opt_with_decl_ref idi.Clang_ast_t.oidi_class_interface with - | Some ObjCInterfaceDecl(_, _, cl_decl_list, _, _) -> - let name = CContext.get_curr_class_name curr_class in - let decls = cl_decl_list @ decl_list in - CFrontend_errors.check_for_property_errors cfg cg tenv name decls - | _ -> ()) | CXXMethodDecl (decl_info, _, _, _, _) | CXXConstructorDecl (decl_info, _, _, _, _) diff --git a/infer/src/clang/cFrontend_checkers.ml b/infer/src/clang/cFrontend_checkers.ml index 1e7861d61..d36607725 100644 --- a/infer/src/clang/cFrontend_checkers.ml +++ b/infer/src/clang/cFrontend_checkers.ml @@ -8,82 +8,107 @@ *) open CFrontend_utils -open General_utils +(* To create a new checker you should: *) +(* 1. Define a checker function, say my_checker, in this module. *) +(* my_checker should define: *) +(* -a) a condition that determine if the checker fires *) +(* -b) a warning_desc that describes the warning (see warning_desc definition) *) +(* 2. Add your checker to the CFrontend_checkers interface *) +(* 3. Decide in which element of the AST my_checker should be evaluated. *) +(* - If it is a statement then you need to invoke my_checker from *) +(* run_frontend_checkers_on_stmt in CFrontend_error module.*) +(* - If it is a declaration invoke it from run_frontend_checkers_on_decl *) + +type warning_desc = { + name : string; (* name for the checker, this will be a kind of bug *) + description : string; (* Description in the error message *) + suggestion : string; (* an optional suggestion or correction *) + loc : Location.t; (* location in the code *) +} + +(* Helper functions *) + +let property_name_contains_word pname word = + let rexp = Str.regexp_string_case_fold word in + try + Str.search_forward rexp pname.Clang_ast_t.ni_name 0 >= 0 + with Not_found -> false + +let location_from_sinfo info = + CLocation.get_sil_location_from_range info.Clang_ast_t.si_source_range true + +let location_from_dinfo info = + CLocation.get_sil_location_from_range info.Clang_ast_t.di_source_range true + +let proc_name_from_context context = + Cfg.Procdesc.get_proc_name (CContext.get_procdesc context) (* === Warnings on properties === *) (* Strong Delegate Warning: a property with name delegate should not be declared strong *) -let checker_strong_delegate_warning decl_info pname obj_c_property_decl_info = - Printing.log_out "Checking for STRONG_DELEGATE property warning\n"; - let delegate_regexp = Str.regexp_string_case_fold "delegate" in - let pname_contains_delegate = try - Str.search_forward delegate_regexp pname.Clang_ast_t.ni_name 0 >= 0 - with Not_found -> false in - let condition = pname_contains_delegate +let strong_delegate_warning decl_info pname obj_c_property_decl_info = + let condition = property_name_contains_word pname "delegate" && ObjcProperty_decl.is_strong_property obj_c_property_decl_info in - let warning_desc = - { name = "STRONG_DELEGATE_WARNING"; - description = "Property or ivar "^pname.Clang_ast_t.ni_name^" declared strong"; - suggestion = "In general delegates should be declared weak or assign"; - loc = CLocation.get_sil_location_from_range decl_info.Clang_ast_t.di_source_range true; - } in - (condition, warning_desc) + if condition then + Some { name = "STRONG_DELEGATE_WARNING"; + description = "Property or ivar "^pname.Clang_ast_t.ni_name^" declared strong"; + suggestion = "In general delegates should be declared weak or assign"; + loc = location_from_dinfo decl_info; } + else None (* Direct Atomic Property access: a property declared atomic should not be accessed directly via its ivar *) -let direct_atomic_property_access context stmt_info ivar_name = +let direct_atomic_property_access_warning context stmt_info ivar_name = let tenv = CContext.get_tenv context in - let mname = Cfg.Procdesc.get_proc_name (CContext.get_procdesc context) in + let mname = proc_name_from_context context in let ivar, cname = match ivar_name with | Some n -> General_utils.mk_class_field_name n, Ast_utils.get_class_name_from_member n | _ -> Ident.create_fieldname (Mangled.from_string "") 0, "" in let tname = Typename.TN_csu (Csu.Class Csu.Objc, 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 { 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 (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) - && not (Procname.is_objc_dealloc mname) in - let warning_desc = { - name = "DIRECT_ATOMIC_PROPERTY_ACCESS"; - description = "Direct access to ivar " ^ (Ident.fieldname_to_string ivar) ^ - " of an atomic property"; - suggestion = "Accessing an ivar of an atomic property makes the property nonatomic"; - loc = loc; - } in - (condition, Some warning_desc) - | _ -> (false, None) (* No warning *) + let condition = match Sil.tenv_lookup tenv tname with + | 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 *) + (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) + && not (Procname.is_objc_dealloc mname) + | _ -> false in + if condition then + Some { + name = "DIRECT_ATOMIC_PROPERTY_ACCESS"; + description = "Direct access to ivar " ^ (Ident.fieldname_to_string ivar) ^ + " of an atomic property"; + suggestion = "Accessing an ivar of an atomic property makes the property nonatomic"; + loc = location_from_sinfo stmt_info; } + else None + (* CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK: C++ references should not be captured in blocks. *) -let captured_cxx_ref_in_objc_block stmt_info captured_vars = +let captured_cxx_ref_in_objc_block_warning stmt_info captured_vars = let is_cxx_ref (_, typ) = match typ with | Sil.Tptr(_, Sil.Pk_reference) -> true | _ -> false in let capt_refs = IList.filter is_cxx_ref captured_vars in - match capt_refs with - | [] -> (false, None) (* No warning *) - | _ -> - let pvar_descs = - IList.fold_left (fun s (v, _) -> s ^ " '" ^ (Sil.pvar_to_string v) ^ "' ") "" capt_refs in - let loc = CLocation.get_sil_location_from_range stmt_info.Clang_ast_t.si_source_range true in - let warning_desc = { - name = "CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK"; - description = "C++ Reference variable(s) " ^ pvar_descs ^ - " captured by Objective-C block"; - suggestion = "C++ References are unmanaged and may be invalid " ^ - "by the time the block executes."; - loc = loc; - } in - (true, Some warning_desc) + let pvar_descs = + IList.fold_left (fun s (v, _) -> s ^ " '" ^ (Sil.pvar_to_string v) ^ "' ") "" capt_refs in + (* Fire if the list of captured references is not empty *) + let condition = IList.length capt_refs > 0 in + if condition then + Some { + name = "CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK"; + description = "C++ Reference variable(s) " ^ pvar_descs ^ + " captured by Objective-C block"; + suggestion = "C++ References are unmanaged and may be invalid " ^ + "by the time the block executes."; + loc = location_from_sinfo stmt_info; } + else None diff --git a/infer/src/clang/cFrontend_checkers.mli b/infer/src/clang/cFrontend_checkers.mli index 26fbce09b..077e733d8 100644 --- a/infer/src/clang/cFrontend_checkers.mli +++ b/infer/src/clang/cFrontend_checkers.mli @@ -7,20 +7,26 @@ * of patent rights can be found in the PATENTS file in the same directory. *) +type warning_desc = { + name : string; (* name for the checker, this will be a kind of bug *) + description : string; (* Description in the error message *) + suggestion : string; (* an optional suggestion or correction *) + loc : Location.t; (* location in the code *) +} (* === Warnings on properties === *) (* Strong Delegate Warning: a property with name delegate should not be declared strong *) -val checker_strong_delegate_warning : Clang_ast_t.decl_info -> Clang_ast_t.named_decl_info -> - Clang_ast_t.obj_c_property_decl_info -> (bool * CFrontend_utils.General_utils.warning_desc) +val strong_delegate_warning : Clang_ast_t.decl_info -> Clang_ast_t.named_decl_info -> + Clang_ast_t.obj_c_property_decl_info -> warning_desc option (* Direct Atomic Property access: a property declared atomic should not be accesses directly via its iva *) -val direct_atomic_property_access : +val direct_atomic_property_access_warning : CContext.t -> Clang_ast_t.stmt_info -> Clang_ast_t.named_decl_info option -> - (bool * CFrontend_utils.General_utils.warning_desc option) + warning_desc option (* CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK: C++ references should not be captured in blocks. *) -val captured_cxx_ref_in_objc_block : Clang_ast_t.stmt_info -> (Sil.pvar * Sil.typ) list -> - (bool * CFrontend_utils.General_utils.warning_desc option) +val captured_cxx_ref_in_objc_block_warning : Clang_ast_t.stmt_info -> (Sil.pvar * Sil.typ) list -> + warning_desc option diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index f9107b8d9..d31dda836 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -7,27 +7,32 @@ * of patent rights can be found in the PATENTS file in the same directory. *) -(* Module for warnings detected at translation time by the frontend - * To specify a checker define the following: - * - condition: a boolean condition when the warning should be flagged - * - description: a string describing the warning - * - loc: the location where is occurs -*) - open CFrontend_utils -open General_utils (* List of checkers on properties *) -let property_checkers_list = [CFrontend_checkers.checker_strong_delegate_warning] +let property_checkers_list = [CFrontend_checkers.strong_delegate_warning] + +(* Invocation of checker belonging to property_checker_list *) +let checkers_for_property decl_info pname_info pdi checker = + checker decl_info pname_info pdi (* List of checkers on ivar access *) -let ivar_access_checker_list = [CFrontend_checkers.direct_atomic_property_access] +let ivar_access_checker_list = [CFrontend_checkers.direct_atomic_property_access_warning] + +(* Invocation of checker belonging to ivar_access_checker_list *) +let checkers_for_ivar context stmt_info dr_name checker = + checker context stmt_info dr_name (* List of checkers for captured vars in objc blocks *) -let captured_vars_checker_list = [CFrontend_checkers.captured_cxx_ref_in_objc_block] +let captured_vars_checker_list = [CFrontend_checkers.captured_cxx_ref_in_objc_block_warning] + +(* Invocation of checker belonging to captured_vars_checker_list *) +let checkers_for_capture_vars stmt_info captured_vars checker = + checker stmt_info captured_vars (* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *) let log_frontend_warning pdesc warn_desc = + let open CFrontend_checkers in let loc = warn_desc.loc in let errlog = Cfg.Procdesc.get_err_log pdesc in let err_desc = @@ -36,16 +41,25 @@ let log_frontend_warning pdesc warn_desc = (warn_desc.name, err_desc, __POS__) in Reporting.log_error_from_errlog errlog exn ~loc:(Some loc) +(* General invocation function for checkers + Takes + 1. f a particular way to apply a checker, it's a partial function + 2. context + 3. the list of checkers to be applied *) +let invoke_set_of_checkers f pdesc checkers = + IList.iter (fun checker -> + match f checker with + | Some warning_desc -> log_frontend_warning pdesc warning_desc + | None -> ()) checkers + (* Call all checkers on properties of class c *) let rec check_for_property_errors cfg cg tenv class_name decl_list = let open Clang_ast_t in let do_one_property decl_info pname_info pdi = - IList.iter (fun checker -> - let (condition, warning_desc) = checker decl_info pname_info pdi in - if condition then - let proc_desc = - CMethod_trans.get_method_for_frontend_checks cfg cg tenv class_name decl_info in - log_frontend_warning proc_desc warning_desc) property_checkers_list in + let pdesc = + CMethod_trans.get_method_for_frontend_checks cfg cg tenv class_name decl_info in + let call_property_checker = checkers_for_property decl_info pname_info pdi in + invoke_set_of_checkers call_property_checker pdesc property_checkers_list in match decl_list with | [] -> () | ObjCPropertyDecl (decl_info, pname_info, pdi) :: rest -> @@ -54,18 +68,40 @@ let rec check_for_property_errors cfg cg tenv class_name decl_list = | _ :: rest -> check_for_property_errors cfg cg tenv class_name rest -(* Call checkers on a specific access of an ivar *) -let check_for_ivar_errors context stmt_info obj_c_ivar_ref_expr_info = - let dr_name = obj_c_ivar_ref_expr_info.Clang_ast_t.ovrei_decl_ref.Clang_ast_t.dr_name in - let pdesc = CContext.get_procdesc context in - IList.iter (fun checker -> - match checker context stmt_info dr_name with - | true, Some warning_desc -> log_frontend_warning pdesc warning_desc - | _, _ -> ()) ivar_access_checker_list +let get_categories_decls decl_ref = + match Ast_utils.get_decl_opt_with_decl_ref decl_ref with + | Some ObjCCategoryDecl (_, _, decls, _, _) + | Some ObjCInterfaceDecl (_, _, decls, _, _) -> decls + | _ -> [] -let check_for_captured_vars context stmt_info captured_vars = +let run_frontend_checkers_on_stmt trans_state instr = + let open Clang_ast_t in + let context = trans_state.CTrans_utils.context in let pdesc = CContext.get_procdesc context in - IList.iter (fun checker -> - match checker stmt_info captured_vars with - | true, Some warning_desc -> log_frontend_warning pdesc warning_desc - | _, _ -> ()) captured_vars_checker_list + match instr with + | ObjCIvarRefExpr(stmt_info, _, _, obj_c_ivar_ref_expr_info) -> + let dr_name = obj_c_ivar_ref_expr_info.Clang_ast_t.ovrei_decl_ref.Clang_ast_t.dr_name in + let call_checker_for_ivar = checkers_for_ivar context stmt_info dr_name in + invoke_set_of_checkers call_checker_for_ivar pdesc ivar_access_checker_list + | BlockExpr(stmt_info, _ , _, Clang_ast_t.BlockDecl (_, block_decl_info)) -> + let captured_block_vars = block_decl_info.Clang_ast_t.bdi_captured_variables in + let captured_vars = CVar_decl.captured_vars_from_block_info context captured_block_vars in + let call_captured_vars_checker = checkers_for_capture_vars stmt_info captured_vars in + invoke_set_of_checkers call_captured_vars_checker pdesc captured_vars_checker_list + | _ -> () + +let run_frontend_checkers_on_decl tenv cg cfg dec = + let open Clang_ast_t in + match dec with + | ObjCCategoryImplDecl(_, name_info, decl_list, _, ocidi) -> + let name = Ast_utils.get_qualified_name name_info in + let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in + let decls = (get_categories_decls ocidi.Clang_ast_t.ocidi_category_decl) @ decl_list in + let name = CContext.get_curr_class_name curr_class in + check_for_property_errors cfg cg tenv name decls + | ObjCImplementationDecl(_, _, decl_list, _, idi) -> + let curr_class = ObjcInterface_decl.get_curr_class_impl idi in + let name = CContext.get_curr_class_name curr_class in + let decls = (get_categories_decls idi.Clang_ast_t.oidi_class_interface) @ decl_list in + check_for_property_errors cfg cg tenv name decls + | _ -> () diff --git a/infer/src/clang/cFrontend_errors.mli b/infer/src/clang/cFrontend_errors.mli index a35b4c0a1..622036bea 100644 --- a/infer/src/clang/cFrontend_errors.mli +++ b/infer/src/clang/cFrontend_errors.mli @@ -10,14 +10,9 @@ (* Module for warnings detected at translation time by the frontend *) +(* Run frontend checkers on a statement *) +val run_frontend_checkers_on_stmt : CTrans_utils.trans_state -> Clang_ast_t.stmt -> unit -(* Checks for warnings on properties of class c *) -val check_for_property_errors : Cfg.cfg -> Cg.t -> Sil.tenv -> string -> Clang_ast_t.decl list -> - unit +(* Run frontend checkers on a declaration *) +val run_frontend_checkers_on_decl : Sil.tenv -> Cg.t -> Cfg.cfg -> Clang_ast_t.decl -> unit -(* Call checkers on a specific access of an ivar *) -val check_for_ivar_errors : - CContext.t -> Clang_ast_t.stmt_info -> Clang_ast_t.obj_c_ivar_ref_expr_info -> unit - -val check_for_captured_vars : CContext.t -> Clang_ast_t.stmt_info -> - (Sil.pvar * Sil.typ) list -> unit diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 502136bdf..bbb9523a2 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -396,13 +396,6 @@ let get_fresh_block_index () = module General_utils = struct - type warning_desc = { - name : string; - description : string; - suggestion : string; (* an optional suggestion or correction *) - loc : Location.t; - } - type var_info = Clang_ast_t.decl_info * Clang_ast_t.type_ptr * Clang_ast_t.var_decl_info * bool let rec swap_elements_list l = diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index 135dd2bae..88d4b32b2 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -124,13 +124,6 @@ end module General_utils : sig - type warning_desc = { - name : string; - description : string; - suggestion : string; (* an optional suggestion or correction *) - loc : Location.t; - } - type var_info = Clang_ast_t.decl_info * Clang_ast_t.type_ptr * Clang_ast_t.var_decl_info * bool val string_from_list : string list -> string diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index f4b180bc6..f6b83a13b 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -1773,7 +1773,6 @@ struct and objCIvarRefExpr_trans trans_state stmt_info stmt_list obj_c_ivar_ref_expr_info = let decl_ref = obj_c_ivar_ref_expr_info.Clang_ast_t.ovrei_decl_ref in - CFrontend_errors.check_for_ivar_errors trans_state.context stmt_info obj_c_ivar_ref_expr_info; do_memb_ivar_ref_exp trans_state stmt_info stmt_list decl_ref and memberExpr_trans trans_state stmt_info stmt_list member_expr_info = @@ -1941,7 +1940,6 @@ struct Cg.add_edge context.cg procname block_pname; let captured_block_vars = block_decl_info.Clang_ast_t.bdi_captured_variables in let captured_vars = CVar_decl.captured_vars_from_block_info context captured_block_vars in - CFrontend_errors.check_for_captured_vars context stmt_info captured_vars; let ids_instrs = IList.map assign_captured_var captured_vars in let ids, instrs = IList.split ids_instrs in let block_data = (context, type_ptr, block_pname, captured_vars) in @@ -2054,6 +2052,8 @@ struct (* a trans_state containing current info on the translation and it returns *) (* a result_state.*) and instruction trans_state instr = + (* Run the frontend checkers on this instruction *) + CFrontend_errors.run_frontend_checkers_on_stmt trans_state instr; let stmt_kind = Clang_ast_proj.get_stmt_kind_string instr in let stmt_info, _ = Clang_ast_proj.get_stmt_tuple instr in let stmt_pointer = stmt_info.Clang_ast_t.si_pointer in diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/ArcExample.dot b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/ArcExample.dot index ff0c3827b..cecc181d7 100644 --- a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/ArcExample.dot +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/ArcExample.dot @@ -1,32 +1,39 @@ digraph iCFG { -8 [label="8: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 29]\n *&s:class NSString *=n$4 [line 29]\n REMOVE_TEMPS(n$4); [line 29]\n " shape="box"] +10 [label="10: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 29]\n *&s:class NSString *=n$4 [line 29]\n REMOVE_TEMPS(n$4); [line 29]\n " shape="box"] - 8 -> 7 ; -7 [label="7: Return Stmt \n n$3=*&s:class NSString * [line 30]\n *&return:class NSString *=n$3 [line 30]\n REMOVE_TEMPS(n$3); [line 30]\n NULLIFY(&s,false); [line 30]\n APPLY_ABSTRACTION; [line 30]\n " shape="box"] + 10 -> 9 ; +9 [label="9: Return Stmt \n n$3=*&s:class NSString * [line 30]\n *&return:class NSString *=n$3 [line 30]\n REMOVE_TEMPS(n$3); [line 30]\n NULLIFY(&s,false); [line 30]\n APPLY_ABSTRACTION; [line 30]\n " shape="box"] - 7 -> 6 ; -6 [label="6: Exit A_newS \n " color=yellow style=filled] + 9 -> 8 ; +8 [label="8: Exit A_newS \n " color=yellow style=filled] -5 [label="5: Start A_newS\nFormals: self:class A *\nLocals: s:class NSString * \n DECLARE_LOCALS(&return,&s); [line 28]\n NULLIFY(&s,false); [line 28]\n NULLIFY(&self,false); [line 28]\n " color=yellow style=filled] +7 [label="7: Start A_newS\nFormals: self:class A *\nLocals: s:class NSString * \n DECLARE_LOCALS(&return,&s); [line 28]\n NULLIFY(&s,false); [line 28]\n NULLIFY(&self,false); [line 28]\n " color=yellow style=filled] - 5 -> 8 ; -4 [label="4: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 23]\n *&s:class NSString *=n$2 [line 23]\n REMOVE_TEMPS(n$2); [line 23]\n " shape="box"] + 7 -> 10 ; +6 [label="6: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 23]\n *&s:class NSString *=n$2 [line 23]\n REMOVE_TEMPS(n$2); [line 23]\n " shape="box"] - 4 -> 3 ; -3 [label="3: Return Stmt \n n$0=*&s:class NSString * [line 24]\n *&return:class NSString *=n$0 [line 24]\n n$1=_fun___set_autorelease_attribute(n$0:class NSString *) [line 24]\n REMOVE_TEMPS(n$0,n$1); [line 24]\n NULLIFY(&s,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] + 6 -> 5 ; +5 [label="5: Return Stmt \n n$0=*&s:class NSString * [line 24]\n *&return:class NSString *=n$0 [line 24]\n n$1=_fun___set_autorelease_attribute(n$0:class NSString *) [line 24]\n REMOVE_TEMPS(n$0,n$1); [line 24]\n NULLIFY(&s,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] - 3 -> 2 ; -2 [label="2: Exit A_getS \n " color=yellow style=filled] + 5 -> 4 ; +4 [label="4: Exit A_getS \n " color=yellow style=filled] -1 [label="1: Start A_getS\nFormals: self:class A *\nLocals: s:class NSString * \n DECLARE_LOCALS(&return,&s); [line 22]\n NULLIFY(&s,false); [line 22]\n NULLIFY(&self,false); [line 22]\n " color=yellow style=filled] +3 [label="3: Start A_getS\nFormals: self:class A *\nLocals: s:class NSString * \n DECLARE_LOCALS(&return,&s); [line 22]\n NULLIFY(&s,false); [line 22]\n NULLIFY(&self,false); [line 22]\n " color=yellow style=filled] - 1 -> 4 ; + 3 -> 6 ; +2 [label="2: Exit A_frontendChecks \n " color=yellow style=filled] + + +1 [label="1: Start A_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] + + + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/AutoreleaseExample.dot b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/AutoreleaseExample.dot index b24faf707..108ef7441 100644 --- a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/AutoreleaseExample.dot +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/AutoreleaseExample.dot @@ -1,137 +1,144 @@ digraph iCFG { -35 [label="35: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class NSAutoreleasePool ):unsigned long ) [line 60]\n n$5=_fun_NSObject_init(n$4:class NSAutoreleasePool *) virtual [line 60]\n *&pool:class NSAutoreleasePool *=n$5 [line 60]\n REMOVE_TEMPS(n$4,n$5); [line 60]\n " shape="box"] +37 [label="37: DeclStmt \n n$4=_fun___objc_alloc_no_fail(sizeof(class NSAutoreleasePool ):unsigned long ) [line 60]\n n$5=_fun_NSObject_init(n$4:class NSAutoreleasePool *) virtual [line 60]\n *&pool:class NSAutoreleasePool *=n$5 [line 60]\n REMOVE_TEMPS(n$4,n$5); [line 60]\n " shape="box"] + + + 37 -> 36 ; +36 [label="36: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 61]\n n$3=_fun___set_autorelease_attribute(n$2:class NSString *) [line 61]\n *&string:class NSString *=n$3 [line 61]\n REMOVE_TEMPS(n$2,n$3); [line 61]\n " shape="box"] + + + 36 -> 35 ; +35 [label="35: Message Call: release \n n$1=*&pool:class NSAutoreleasePool * [line 63]\n _fun___objc_release_autorelease_pool(n$1:class NSAutoreleasePool *) [line 63]\n REMOVE_TEMPS(n$1); [line 63]\n NULLIFY(&pool,false); [line 63]\n " shape="box"] 35 -> 34 ; -34 [label="34: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 61]\n n$3=_fun___set_autorelease_attribute(n$2:class NSString *) [line 61]\n *&string:class NSString *=n$3 [line 61]\n REMOVE_TEMPS(n$2,n$3); [line 61]\n " shape="box"] +34 [label="34: DeclStmt \n n$0=*&string:class NSString * [line 64]\n *&c:class NSString *=n$0 [line 64]\n REMOVE_TEMPS(n$0); [line 64]\n NULLIFY(&c,false); [line 64]\n NULLIFY(&string,false); [line 64]\n APPLY_ABSTRACTION; [line 64]\n " shape="box"] 34 -> 33 ; -33 [label="33: Message Call: release \n n$1=*&pool:class NSAutoreleasePool * [line 63]\n _fun___objc_release_autorelease_pool(n$1:class NSAutoreleasePool *) [line 63]\n REMOVE_TEMPS(n$1); [line 63]\n NULLIFY(&pool,false); [line 63]\n " shape="box"] +33 [label="33: Exit test3 \n " color=yellow style=filled] - 33 -> 32 ; -32 [label="32: DeclStmt \n n$0=*&string:class NSString * [line 64]\n *&c:class NSString *=n$0 [line 64]\n REMOVE_TEMPS(n$0); [line 64]\n NULLIFY(&c,false); [line 64]\n NULLIFY(&string,false); [line 64]\n APPLY_ABSTRACTION; [line 64]\n " shape="box"] +32 [label="32: Start test3\nFormals: \nLocals: c:class NSString * string:class NSString * pool:class NSAutoreleasePool * \n DECLARE_LOCALS(&return,&c,&string,&pool); [line 59]\n NULLIFY(&c,false); [line 59]\n NULLIFY(&pool,false); [line 59]\n NULLIFY(&string,false); [line 59]\n " color=yellow style=filled] - 32 -> 31 ; -31 [label="31: Exit test3 \n " color=yellow style=filled] + 32 -> 37 ; +31 [label="31: DeclStmt \n *&s1:class A *=0 [line 48]\n " shape="box"] -30 [label="30: Start test3\nFormals: \nLocals: c:class NSString * string:class NSString * pool:class NSAutoreleasePool * \n DECLARE_LOCALS(&return,&c,&string,&pool); [line 59]\n NULLIFY(&c,false); [line 59]\n NULLIFY(&pool,false); [line 59]\n NULLIFY(&string,false); [line 59]\n " color=yellow style=filled] + 31 -> 30 ; +30 [label="30: DeclStmt \n *&s2:class A *=0 [line 49]\n " shape="box"] - 30 -> 35 ; -29 [label="29: DeclStmt \n *&s1:class A *=0 [line 48]\n " shape="box"] + 30 -> 29 ; +29 [label="29: DeclStmt \n *&s3:class A *=0 [line 50]\n " shape="box"] 29 -> 28 ; -28 [label="28: DeclStmt \n *&s2:class A *=0 [line 49]\n " shape="box"] +28 [label="28: BinaryOperatorStmt: Assign \n n$3=_fun_createA() [line 52]\n *&s1:class A *=n$3 [line 52]\n REMOVE_TEMPS(n$3); [line 52]\n " shape="box"] 28 -> 27 ; -27 [label="27: DeclStmt \n *&s3:class A *=0 [line 50]\n " shape="box"] +27 [label="27: BinaryOperatorStmt: Assign \n n$2=_fun_createA() [line 53]\n *&s2:class A *=n$2 [line 53]\n REMOVE_TEMPS(n$2); [line 53]\n " shape="box"] 27 -> 26 ; -26 [label="26: BinaryOperatorStmt: Assign \n n$3=_fun_createA() [line 52]\n *&s1:class A *=n$3 [line 52]\n REMOVE_TEMPS(n$3); [line 52]\n " shape="box"] +26 [label="26: BinaryOperatorStmt: Assign \n n$1=_fun_createA() [line 54]\n *&s3:class A *=n$1 [line 54]\n REMOVE_TEMPS(n$1); [line 54]\n " shape="box"] 26 -> 25 ; -25 [label="25: BinaryOperatorStmt: Assign \n n$2=_fun_createA() [line 53]\n *&s2:class A *=n$2 [line 53]\n REMOVE_TEMPS(n$2); [line 53]\n " shape="box"] +25 [label="25: Release the autorelease pool \n n$0=_fun___objc_release_autorelease_pool(&s1:class A *,&s3:class A *,&s2:class A *) [line 51]\n REMOVE_TEMPS(n$0); [line 51]\n " shape="box"] 25 -> 24 ; -24 [label="24: BinaryOperatorStmt: Assign \n n$1=_fun_createA() [line 54]\n *&s3:class A *=n$1 [line 54]\n REMOVE_TEMPS(n$1); [line 54]\n " shape="box"] +24 [label="24: Return Stmt \n *&return:int =0 [line 56]\n NULLIFY(&s1,false); [line 56]\n NULLIFY(&s2,false); [line 56]\n NULLIFY(&s3,false); [line 56]\n APPLY_ABSTRACTION; [line 56]\n " shape="box"] 24 -> 23 ; -23 [label="23: Release the autorelease pool \n n$0=_fun___objc_release_autorelease_pool(&s1:class A *,&s3:class A *,&s2:class A *) [line 51]\n REMOVE_TEMPS(n$0); [line 51]\n " shape="box"] +23 [label="23: Exit test2 \n " color=yellow style=filled] - 23 -> 22 ; -22 [label="22: Return Stmt \n *&return:int =0 [line 56]\n NULLIFY(&s1,false); [line 56]\n NULLIFY(&s2,false); [line 56]\n NULLIFY(&s3,false); [line 56]\n APPLY_ABSTRACTION; [line 56]\n " shape="box"] +22 [label="22: Start test2\nFormals: \nLocals: s3:class A * s2:class A * s1:class A * \n DECLARE_LOCALS(&return,&s3,&s2,&s1); [line 47]\n " color=yellow style=filled] - 22 -> 21 ; -21 [label="21: Exit test2 \n " color=yellow style=filled] + 22 -> 31 ; +21 [label="21: DeclStmt \n *&s1:class A *=0 [line 35]\n " shape="box"] -20 [label="20: Start test2\nFormals: \nLocals: s3:class A * s2:class A * s1:class A * \n DECLARE_LOCALS(&return,&s3,&s2,&s1); [line 47]\n " color=yellow style=filled] + 21 -> 20 ; +20 [label="20: DeclStmt \n *&s2:class A *=0 [line 36]\n " shape="box"] - 20 -> 29 ; -19 [label="19: DeclStmt \n *&s1:class A *=0 [line 35]\n " shape="box"] + 20 -> 19 ; +19 [label="19: DeclStmt \n *&s3:class A *=0 [line 37]\n " shape="box"] 19 -> 18 ; -18 [label="18: DeclStmt \n *&s2:class A *=0 [line 36]\n " shape="box"] +18 [label="18: BinaryOperatorStmt: Assign \n n$5=_fun_createA() [line 39]\n *&s1:class A *=n$5 [line 39]\n REMOVE_TEMPS(n$5); [line 39]\n " shape="box"] 18 -> 17 ; -17 [label="17: DeclStmt \n *&s3:class A *=0 [line 37]\n " shape="box"] +17 [label="17: Message Call: retain \n n$3=*&s1:class A * [line 40]\n n$4=_fun___objc_retain(n$3:class A *) [line 40]\n REMOVE_TEMPS(n$3,n$4); [line 40]\n " shape="box"] 17 -> 16 ; -16 [label="16: BinaryOperatorStmt: Assign \n n$5=_fun_createA() [line 39]\n *&s1:class A *=n$5 [line 39]\n REMOVE_TEMPS(n$5); [line 39]\n " shape="box"] +16 [label="16: BinaryOperatorStmt: Assign \n n$2=_fun_createA() [line 41]\n *&s2:class A *=n$2 [line 41]\n REMOVE_TEMPS(n$2); [line 41]\n " shape="box"] 16 -> 15 ; -15 [label="15: Message Call: retain \n n$3=*&s1:class A * [line 40]\n n$4=_fun___objc_retain(n$3:class A *) [line 40]\n REMOVE_TEMPS(n$3,n$4); [line 40]\n " shape="box"] +15 [label="15: BinaryOperatorStmt: Assign \n n$1=_fun_createA() [line 42]\n *&s3:class A *=n$1 [line 42]\n REMOVE_TEMPS(n$1); [line 42]\n " shape="box"] 15 -> 14 ; -14 [label="14: BinaryOperatorStmt: Assign \n n$2=_fun_createA() [line 41]\n *&s2:class A *=n$2 [line 41]\n REMOVE_TEMPS(n$2); [line 41]\n " shape="box"] +14 [label="14: Release the autorelease pool \n n$0=_fun___objc_release_autorelease_pool(&s1:class A *,&s2:class A *,&s3:class A *) [line 38]\n REMOVE_TEMPS(n$0); [line 38]\n " shape="box"] 14 -> 13 ; -13 [label="13: BinaryOperatorStmt: Assign \n n$1=_fun_createA() [line 42]\n *&s3:class A *=n$1 [line 42]\n REMOVE_TEMPS(n$1); [line 42]\n " shape="box"] +13 [label="13: Return Stmt \n *&return:int =0 [line 44]\n NULLIFY(&s1,false); [line 44]\n NULLIFY(&s2,false); [line 44]\n NULLIFY(&s3,false); [line 44]\n APPLY_ABSTRACTION; [line 44]\n " shape="box"] 13 -> 12 ; -12 [label="12: Release the autorelease pool \n n$0=_fun___objc_release_autorelease_pool(&s1:class A *,&s2:class A *,&s3:class A *) [line 38]\n REMOVE_TEMPS(n$0); [line 38]\n " shape="box"] +12 [label="12: Exit test1 \n " color=yellow style=filled] - 12 -> 11 ; -11 [label="11: Return Stmt \n *&return:int =0 [line 44]\n NULLIFY(&s1,false); [line 44]\n NULLIFY(&s2,false); [line 44]\n NULLIFY(&s3,false); [line 44]\n APPLY_ABSTRACTION; [line 44]\n " shape="box"] +11 [label="11: Start test1\nFormals: \nLocals: s3:class A * s2:class A * s1:class A * \n DECLARE_LOCALS(&return,&s3,&s2,&s1); [line 34]\n " color=yellow style=filled] - 11 -> 10 ; -10 [label="10: Exit test1 \n " color=yellow style=filled] + 11 -> 21 ; +10 [label="10: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 30]\n n$3=_fun_NSObject_init(n$2:class A *) virtual [line 30]\n *&s1:class A *=n$3 [line 30]\n REMOVE_TEMPS(n$2,n$3); [line 30]\n " shape="box"] -9 [label="9: Start test1\nFormals: \nLocals: s3:class A * s2:class A * s1:class A * \n DECLARE_LOCALS(&return,&s3,&s2,&s1); [line 34]\n " color=yellow style=filled] + 10 -> 9 ; +9 [label="9: Return Stmt \n n$0=*&s1:class A * [line 31]\n n$1=_fun___set_autorelease_attribute(n$0:class A *) [line 31]\n *&return:class A *=n$1 [line 31]\n REMOVE_TEMPS(n$0,n$1); [line 31]\n NULLIFY(&s1,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] - 9 -> 19 ; -8 [label="8: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 30]\n n$3=_fun_NSObject_init(n$2:class A *) virtual [line 30]\n *&s1:class A *=n$3 [line 30]\n REMOVE_TEMPS(n$2,n$3); [line 30]\n " shape="box"] + 9 -> 8 ; +8 [label="8: Exit createA \n " color=yellow style=filled] - 8 -> 7 ; -7 [label="7: Return Stmt \n n$0=*&s1:class A * [line 31]\n n$1=_fun___set_autorelease_attribute(n$0:class A *) [line 31]\n *&return:class A *=n$1 [line 31]\n REMOVE_TEMPS(n$0,n$1); [line 31]\n NULLIFY(&s1,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] +7 [label="7: Start createA\nFormals: \nLocals: s1:class A * \n DECLARE_LOCALS(&return,&s1); [line 29]\n NULLIFY(&s1,false); [line 29]\n " color=yellow style=filled] - 7 -> 6 ; -6 [label="6: Exit createA \n " color=yellow style=filled] + 7 -> 10 ; +6 [label="6: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 23]\n *&s:class NSString *=n$2 [line 23]\n REMOVE_TEMPS(n$2); [line 23]\n " shape="box"] -5 [label="5: Start createA\nFormals: \nLocals: s1:class A * \n DECLARE_LOCALS(&return,&s1); [line 29]\n NULLIFY(&s1,false); [line 29]\n " color=yellow style=filled] + 6 -> 5 ; +5 [label="5: Return Stmt \n n$0=*&s:class NSString * [line 24]\n n$1=_fun___set_autorelease_attribute(n$0:class NSString *) [line 24]\n *&return:class NSString *=n$1 [line 24]\n REMOVE_TEMPS(n$0,n$1); [line 24]\n NULLIFY(&s,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] - 5 -> 8 ; -4 [label="4: DeclStmt \n n$2=_fun___objc_alloc_no_fail(sizeof(class NSString ):unsigned long ) [line 23]\n *&s:class NSString *=n$2 [line 23]\n REMOVE_TEMPS(n$2); [line 23]\n " shape="box"] + 5 -> 4 ; +4 [label="4: Exit A_main \n " color=yellow style=filled] - 4 -> 3 ; -3 [label="3: Return Stmt \n n$0=*&s:class NSString * [line 24]\n n$1=_fun___set_autorelease_attribute(n$0:class NSString *) [line 24]\n *&return:class NSString *=n$1 [line 24]\n REMOVE_TEMPS(n$0,n$1); [line 24]\n NULLIFY(&s,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] +3 [label="3: Start A_main\nFormals: self:class A *\nLocals: s:class NSString * \n DECLARE_LOCALS(&return,&s); [line 22]\n NULLIFY(&s,false); [line 22]\n NULLIFY(&self,false); [line 22]\n " color=yellow style=filled] - 3 -> 2 ; -2 [label="2: Exit A_main \n " color=yellow style=filled] + 3 -> 6 ; +2 [label="2: Exit A_frontendChecks \n " color=yellow style=filled] -1 [label="1: Start A_main\nFormals: self:class A *\nLocals: s:class NSString * \n DECLARE_LOCALS(&return,&s); [line 22]\n NULLIFY(&s,false); [line 22]\n NULLIFY(&self,false); [line 22]\n " color=yellow style=filled] +1 [label="1: Start A_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] - 1 -> 4 ; + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot index 25e57cde1..2abd2be5c 100644 --- a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot @@ -1,182 +1,189 @@ digraph iCFG { -48 [label="48: DeclStmt \n n$35=_fun_FBColorCreateWithGray(0.000000:double ,0.300000:double ) [line 86]\n *&borderColor:struct CGColor *=n$35 [line 86]\n REMOVE_TEMPS(n$35); [line 86]\n " shape="box"] +50 [label="50: DeclStmt \n n$35=_fun_FBColorCreateWithGray(0.000000:double ,0.300000:double ) [line 86]\n *&borderColor:struct CGColor *=n$35 [line 86]\n REMOVE_TEMPS(n$35); [line 86]\n " shape="box"] - 48 -> 47 ; -47 [label="47: Call _fun_CGColorRelease \n n$34=*&borderColor:struct CGColor * [line 87]\n _fun_CGColorRelease(n$34:struct CGColor *) [line 87]\n REMOVE_TEMPS(n$34); [line 87]\n NULLIFY(&borderColor,false); [line 87]\n APPLY_ABSTRACTION; [line 87]\n " shape="box"] + 50 -> 49 ; +49 [label="49: Call _fun_CGColorRelease \n n$34=*&borderColor:struct CGColor * [line 87]\n _fun_CGColorRelease(n$34:struct CGColor *) [line 87]\n REMOVE_TEMPS(n$34); [line 87]\n NULLIFY(&borderColor,false); [line 87]\n APPLY_ABSTRACTION; [line 87]\n " shape="box"] - 47 -> 46 ; -46 [label="46: Exit MemoryLeakExample_testFBColorCreateWithGray \n " color=yellow style=filled] + 49 -> 48 ; +48 [label="48: Exit MemoryLeakExample_testFBColorCreateWithGray \n " color=yellow style=filled] -45 [label="45: Start MemoryLeakExample_testFBColorCreateWithGray\nFormals: self:class MemoryLeakExample *\nLocals: borderColor:struct CGColor * \n DECLARE_LOCALS(&return,&borderColor); [line 85]\n NULLIFY(&borderColor,false); [line 85]\n NULLIFY(&self,false); [line 85]\n " color=yellow style=filled] +47 [label="47: Start MemoryLeakExample_testFBColorCreateWithGray\nFormals: self:class MemoryLeakExample *\nLocals: borderColor:struct CGColor * \n DECLARE_LOCALS(&return,&borderColor); [line 85]\n NULLIFY(&borderColor,false); [line 85]\n NULLIFY(&self,false); [line 85]\n " color=yellow style=filled] - 45 -> 48 ; -44 [label="44: DeclStmt \n n$33=_fun_CGBitmapContextCreateImage(0:struct CGContext *) [line 79]\n *&newImage:struct CGImage *=n$33 [line 79]\n REMOVE_TEMPS(n$33); [line 79]\n " shape="box"] + 47 -> 50 ; +46 [label="46: DeclStmt \n n$33=_fun_CGBitmapContextCreateImage(0:struct CGContext *) [line 79]\n *&newImage:struct CGImage *=n$33 [line 79]\n REMOVE_TEMPS(n$33); [line 79]\n " shape="box"] - 44 -> 43 ; -43 [label="43: Call _fun_CGImageRelease \n n$32=*&newImage:struct CGImage * [line 80]\n _fun_CGImageRelease(n$32:struct CGImage *) [line 80]\n REMOVE_TEMPS(n$32); [line 80]\n NULLIFY(&newImage,false); [line 80]\n APPLY_ABSTRACTION; [line 80]\n " shape="box"] + 46 -> 45 ; +45 [label="45: Call _fun_CGImageRelease \n n$32=*&newImage:struct CGImage * [line 80]\n _fun_CGImageRelease(n$32:struct CGImage *) [line 80]\n REMOVE_TEMPS(n$32); [line 80]\n NULLIFY(&newImage,false); [line 80]\n APPLY_ABSTRACTION; [line 80]\n " shape="box"] - 43 -> 42 ; -42 [label="42: Exit MemoryLeakExample_testImageRefRelease \n " color=yellow style=filled] + 45 -> 44 ; +44 [label="44: Exit MemoryLeakExample_testImageRefRelease \n " color=yellow style=filled] -41 [label="41: Start MemoryLeakExample_testImageRefRelease\nFormals: \nLocals: newImage:struct CGImage * \n DECLARE_LOCALS(&return,&newImage); [line 78]\n NULLIFY(&newImage,false); [line 78]\n " color=yellow style=filled] +43 [label="43: Start MemoryLeakExample_testImageRefRelease\nFormals: \nLocals: newImage:struct CGImage * \n DECLARE_LOCALS(&return,&newImage); [line 78]\n NULLIFY(&newImage,false); [line 78]\n " color=yellow style=filled] - 41 -> 44 ; -40 [label="40: DeclStmt \n n$31=_fun_SecTrustCopyPublicKey(0:struct __SecTrust *) [line 74]\n *&allowedPublicKey:struct __SecKey *=n$31 [line 74]\n REMOVE_TEMPS(n$31); [line 74]\n " shape="box"] + 43 -> 46 ; +42 [label="42: DeclStmt \n n$31=_fun_SecTrustCopyPublicKey(0:struct __SecTrust *) [line 74]\n *&allowedPublicKey:struct __SecKey *=n$31 [line 74]\n REMOVE_TEMPS(n$31); [line 74]\n " shape="box"] - 40 -> 39 ; -39 [label="39: Call _fun___objc_release_cf \n n$30=*&allowedPublicKey:struct __SecKey * [line 75]\n _fun___objc_release_cf(1:_Bool ,n$30:void *) [line 75]\n REMOVE_TEMPS(n$30); [line 75]\n NULLIFY(&allowedPublicKey,false); [line 75]\n APPLY_ABSTRACTION; [line 75]\n " shape="box"] + 42 -> 41 ; +41 [label="41: Call _fun___objc_release_cf \n n$30=*&allowedPublicKey:struct __SecKey * [line 75]\n _fun___objc_release_cf(1:_Bool ,n$30:void *) [line 75]\n REMOVE_TEMPS(n$30); [line 75]\n NULLIFY(&allowedPublicKey,false); [line 75]\n APPLY_ABSTRACTION; [line 75]\n " shape="box"] - 39 -> 38 ; -38 [label="38: Exit MemoryLeakExample_test2NoLeak \n " color=yellow style=filled] + 41 -> 40 ; +40 [label="40: Exit MemoryLeakExample_test2NoLeak \n " color=yellow style=filled] -37 [label="37: Start MemoryLeakExample_test2NoLeak\nFormals: \nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 73]\n NULLIFY(&allowedPublicKey,false); [line 73]\n " color=yellow style=filled] +39 [label="39: Start MemoryLeakExample_test2NoLeak\nFormals: \nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 73]\n NULLIFY(&allowedPublicKey,false); [line 73]\n " color=yellow style=filled] - 37 -> 40 ; -36 [label="36: DeclStmt \n n$28=*&trust:struct __SecTrust * [line 70]\n n$29=_fun_SecTrustCopyPublicKey(n$28:struct __SecTrust *) [line 70]\n *&allowedPublicKey:struct __SecKey *=n$29 [line 70]\n REMOVE_TEMPS(n$28,n$29); [line 70]\n NULLIFY(&allowedPublicKey,false); [line 70]\n NULLIFY(&trust,false); [line 70]\n APPLY_ABSTRACTION; [line 70]\n " shape="box"] + 39 -> 42 ; +38 [label="38: DeclStmt \n n$28=*&trust:struct __SecTrust * [line 70]\n n$29=_fun_SecTrustCopyPublicKey(n$28:struct __SecTrust *) [line 70]\n *&allowedPublicKey:struct __SecKey *=n$29 [line 70]\n REMOVE_TEMPS(n$28,n$29); [line 70]\n NULLIFY(&allowedPublicKey,false); [line 70]\n NULLIFY(&trust,false); [line 70]\n APPLY_ABSTRACTION; [line 70]\n " shape="box"] - 36 -> 35 ; -35 [label="35: Exit MemoryLeakExample_test2: \n " color=yellow style=filled] + 38 -> 37 ; +37 [label="37: Exit MemoryLeakExample_test2: \n " color=yellow style=filled] -34 [label="34: Start MemoryLeakExample_test2:\nFormals: trust:struct __SecTrust *\nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 69]\n NULLIFY(&allowedPublicKey,false); [line 69]\n " color=yellow style=filled] +36 [label="36: Start MemoryLeakExample_test2:\nFormals: trust:struct __SecTrust *\nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 69]\n NULLIFY(&allowedPublicKey,false); [line 69]\n " color=yellow style=filled] - 34 -> 36 ; -33 [label="33: DeclStmt \n n$26=*&rect:struct CGRect [line 62]\n n$27=_fun_CGRectGetHeight(n$26:struct CGRect ) [line 62]\n *&lineThickness:double =(0.200000 * n$27) [line 62]\n REMOVE_TEMPS(n$26,n$27); [line 62]\n NULLIFY(&rect,false); [line 62]\n NULLIFY(&lineThickness,false); [line 62]\n " shape="box"] + 36 -> 38 ; +35 [label="35: DeclStmt \n n$26=*&rect:struct CGRect [line 62]\n n$27=_fun_CGRectGetHeight(n$26:struct CGRect ) [line 62]\n *&lineThickness:double =(0.200000 * n$27) [line 62]\n REMOVE_TEMPS(n$26,n$27); [line 62]\n NULLIFY(&rect,false); [line 62]\n NULLIFY(&lineThickness,false); [line 62]\n " shape="box"] + + + 35 -> 34 ; +34 [label="34: DeclStmt \n n$25=_fun_CGPathCreateMutable() [line 65]\n *&path1:struct CGPath *=n$25 [line 65]\n REMOVE_TEMPS(n$25); [line 65]\n " shape="box"] + + + 34 -> 33 ; +33 [label="33: Call _fun___objc_release_cf \n n$24=*&path1:struct CGPath * [line 66]\n _fun___objc_release_cf(1:_Bool ,n$24:void *) [line 66]\n REMOVE_TEMPS(n$24); [line 66]\n NULLIFY(&path1,false); [line 66]\n APPLY_ABSTRACTION; [line 66]\n " shape="box"] 33 -> 32 ; -32 [label="32: DeclStmt \n n$25=_fun_CGPathCreateMutable() [line 65]\n *&path1:struct CGPath *=n$25 [line 65]\n REMOVE_TEMPS(n$25); [line 65]\n " shape="box"] +32 [label="32: Exit MemoryLeakExample_createCloseCrossGlyphNoLeak: \n " color=yellow style=filled] - 32 -> 31 ; -31 [label="31: Call _fun___objc_release_cf \n n$24=*&path1:struct CGPath * [line 66]\n _fun___objc_release_cf(1:_Bool ,n$24:void *) [line 66]\n REMOVE_TEMPS(n$24); [line 66]\n NULLIFY(&path1,false); [line 66]\n APPLY_ABSTRACTION; [line 66]\n " shape="box"] +31 [label="31: Start MemoryLeakExample_createCloseCrossGlyphNoLeak:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 61]\n NULLIFY(&lineThickness,false); [line 61]\n NULLIFY(&path1,false); [line 61]\n " color=yellow style=filled] - 31 -> 30 ; -30 [label="30: Exit MemoryLeakExample_createCloseCrossGlyphNoLeak: \n " color=yellow style=filled] + 31 -> 35 ; +30 [label="30: DeclStmt \n n$22=*&rect:struct CGRect [line 55]\n n$23=_fun_CGRectGetHeight(n$22:struct CGRect ) [line 55]\n *&lineThickness:double =(0.200000 * n$23) [line 55]\n REMOVE_TEMPS(n$22,n$23); [line 55]\n NULLIFY(&rect,false); [line 55]\n NULLIFY(&lineThickness,false); [line 55]\n " shape="box"] -29 [label="29: Start MemoryLeakExample_createCloseCrossGlyphNoLeak:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 61]\n NULLIFY(&lineThickness,false); [line 61]\n NULLIFY(&path1,false); [line 61]\n " color=yellow style=filled] + 30 -> 29 ; +29 [label="29: DeclStmt \n n$21=_fun_CGPathCreateMutable() [line 58]\n *&path1:struct CGPath *=n$21 [line 58]\n REMOVE_TEMPS(n$21); [line 58]\n NULLIFY(&path1,false); [line 58]\n APPLY_ABSTRACTION; [line 58]\n " shape="box"] - 29 -> 33 ; -28 [label="28: DeclStmt \n n$22=*&rect:struct CGRect [line 55]\n n$23=_fun_CGRectGetHeight(n$22:struct CGRect ) [line 55]\n *&lineThickness:double =(0.200000 * n$23) [line 55]\n REMOVE_TEMPS(n$22,n$23); [line 55]\n NULLIFY(&rect,false); [line 55]\n NULLIFY(&lineThickness,false); [line 55]\n " shape="box"] + 29 -> 28 ; +28 [label="28: Exit MemoryLeakExample_createCloseCrossGlyph: \n " color=yellow style=filled] - 28 -> 27 ; -27 [label="27: DeclStmt \n n$21=_fun_CGPathCreateMutable() [line 58]\n *&path1:struct CGPath *=n$21 [line 58]\n REMOVE_TEMPS(n$21); [line 58]\n NULLIFY(&path1,false); [line 58]\n APPLY_ABSTRACTION; [line 58]\n " shape="box"] +27 [label="27: Start MemoryLeakExample_createCloseCrossGlyph:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 54]\n NULLIFY(&lineThickness,false); [line 54]\n NULLIFY(&path1,false); [line 54]\n " color=yellow style=filled] - 27 -> 26 ; -26 [label="26: Exit MemoryLeakExample_createCloseCrossGlyph: \n " color=yellow style=filled] + 27 -> 30 ; +26 [label="26: DeclStmt \n n$20=_fun_CTFramesetterCreateWithAttributedString(0:struct __CFAttributedString *) [line 50]\n *&framesetter:struct __CTFramesetter *=n$20 [line 50]\n REMOVE_TEMPS(n$20); [line 50]\n " shape="box"] -25 [label="25: Start MemoryLeakExample_createCloseCrossGlyph:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 54]\n NULLIFY(&lineThickness,false); [line 54]\n NULLIFY(&path1,false); [line 54]\n " color=yellow style=filled] + 26 -> 25 ; +25 [label="25: Call _fun___objc_release_cf \n n$19=*&framesetter:struct __CTFramesetter * [line 51]\n _fun___objc_release_cf(1:_Bool ,n$19:void *) [line 51]\n REMOVE_TEMPS(n$19); [line 51]\n NULLIFY(&framesetter,false); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="box"] - 25 -> 28 ; -24 [label="24: DeclStmt \n n$20=_fun_CTFramesetterCreateWithAttributedString(0:struct __CFAttributedString *) [line 50]\n *&framesetter:struct __CTFramesetter *=n$20 [line 50]\n REMOVE_TEMPS(n$20); [line 50]\n " shape="box"] + 25 -> 24 ; +24 [label="24: Exit MemoryLeakExample_test1NoLeak \n " color=yellow style=filled] - 24 -> 23 ; -23 [label="23: Call _fun___objc_release_cf \n n$19=*&framesetter:struct __CTFramesetter * [line 51]\n _fun___objc_release_cf(1:_Bool ,n$19:void *) [line 51]\n REMOVE_TEMPS(n$19); [line 51]\n NULLIFY(&framesetter,false); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="box"] +23 [label="23: Start MemoryLeakExample_test1NoLeak\nFormals: \nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 49]\n NULLIFY(&framesetter,false); [line 49]\n " color=yellow style=filled] - 23 -> 22 ; -22 [label="22: Exit MemoryLeakExample_test1NoLeak \n " color=yellow style=filled] + 23 -> 26 ; +22 [label="22: DeclStmt \n n$17=*&str:struct __CFAttributedString * [line 46]\n n$18=_fun_CTFramesetterCreateWithAttributedString(n$17:struct __CFAttributedString *) [line 46]\n *&framesetter:struct __CTFramesetter *=n$18 [line 46]\n REMOVE_TEMPS(n$17,n$18); [line 46]\n NULLIFY(&framesetter,false); [line 46]\n NULLIFY(&str,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] -21 [label="21: Start MemoryLeakExample_test1NoLeak\nFormals: \nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 49]\n NULLIFY(&framesetter,false); [line 49]\n " color=yellow style=filled] + 22 -> 21 ; +21 [label="21: Exit MemoryLeakExample_test1: \n " color=yellow style=filled] - 21 -> 24 ; -20 [label="20: DeclStmt \n n$17=*&str:struct __CFAttributedString * [line 46]\n n$18=_fun_CTFramesetterCreateWithAttributedString(n$17:struct __CFAttributedString *) [line 46]\n *&framesetter:struct __CTFramesetter *=n$18 [line 46]\n REMOVE_TEMPS(n$17,n$18); [line 46]\n NULLIFY(&framesetter,false); [line 46]\n NULLIFY(&str,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] +20 [label="20: Start MemoryLeakExample_test1:\nFormals: str:struct __CFAttributedString *\nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 45]\n NULLIFY(&framesetter,false); [line 45]\n " color=yellow style=filled] - 20 -> 19 ; -19 [label="19: Exit MemoryLeakExample_test1: \n " color=yellow style=filled] + 20 -> 22 ; +19 [label="19: DeclStmt \n n$16=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 41]\n *&maString:struct __CFAttributedString *=n$16 [line 41]\n REMOVE_TEMPS(n$16); [line 41]\n " shape="box"] -18 [label="18: Start MemoryLeakExample_test1:\nFormals: str:struct __CFAttributedString *\nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 45]\n NULLIFY(&framesetter,false); [line 45]\n " color=yellow style=filled] + 19 -> 18 ; +18 [label="18: Call _fun___objc_release_cf \n n$15=*&maString:struct __CFAttributedString * [line 42]\n _fun___objc_release_cf(1:_Bool ,n$15:void *) [line 42]\n REMOVE_TEMPS(n$15); [line 42]\n NULLIFY(&maString,false); [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"] - 18 -> 20 ; -17 [label="17: DeclStmt \n n$16=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 41]\n *&maString:struct __CFAttributedString *=n$16 [line 41]\n REMOVE_TEMPS(n$16); [line 41]\n " shape="box"] + 18 -> 17 ; +17 [label="17: Exit MemoryLeakExample_measureFrameSizeForTextNoLeak \n " color=yellow style=filled] - 17 -> 16 ; -16 [label="16: Call _fun___objc_release_cf \n n$15=*&maString:struct __CFAttributedString * [line 42]\n _fun___objc_release_cf(1:_Bool ,n$15:void *) [line 42]\n REMOVE_TEMPS(n$15); [line 42]\n NULLIFY(&maString,false); [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"] +16 [label="16: Start MemoryLeakExample_measureFrameSizeForTextNoLeak\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 39]\n NULLIFY(&maString,false); [line 39]\n " color=yellow style=filled] - 16 -> 15 ; -15 [label="15: Exit MemoryLeakExample_measureFrameSizeForTextNoLeak \n " color=yellow style=filled] + 16 -> 19 ; +15 [label="15: DeclStmt \n n$14=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 36]\n *&maString:struct __CFAttributedString *=n$14 [line 36]\n REMOVE_TEMPS(n$14); [line 36]\n NULLIFY(&maString,false); [line 36]\n APPLY_ABSTRACTION; [line 36]\n " shape="box"] -14 [label="14: Start MemoryLeakExample_measureFrameSizeForTextNoLeak\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 39]\n NULLIFY(&maString,false); [line 39]\n " color=yellow style=filled] + 15 -> 14 ; +14 [label="14: Exit MemoryLeakExample_measureFrameSizeForText \n " color=yellow style=filled] - 14 -> 17 ; -13 [label="13: DeclStmt \n n$14=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 36]\n *&maString:struct __CFAttributedString *=n$14 [line 36]\n REMOVE_TEMPS(n$14); [line 36]\n NULLIFY(&maString,false); [line 36]\n APPLY_ABSTRACTION; [line 36]\n " shape="box"] +13 [label="13: Start MemoryLeakExample_measureFrameSizeForText\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 34]\n NULLIFY(&maString,false); [line 34]\n " color=yellow style=filled] - 13 -> 12 ; -12 [label="12: Exit MemoryLeakExample_measureFrameSizeForText \n " color=yellow style=filled] + 13 -> 15 ; +12 [label="12: DeclStmt \n n$10=*&self:class MemoryLeakExample * [line 30]\n n$11=_fun_MemoryLeakExample_backgroundCoveringView(n$10:class MemoryLeakExample *) [line 30]\n n$12=_fun_UIView_bounds(n$11:class UIView *) [line 30]\n n$13=_fun_CGPathCreateWithRect(n$12:struct CGRect ,0:struct CGAffineTransform *) [line 30]\n *&shadowPath:struct CGPath *=n$13 [line 30]\n REMOVE_TEMPS(n$10,n$11,n$12,n$13); [line 30]\n " shape="box"] -11 [label="11: Start MemoryLeakExample_measureFrameSizeForText\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 34]\n NULLIFY(&maString,false); [line 34]\n " color=yellow style=filled] + 12 -> 11 ; +11 [label="11: Message Call: setShadowPath: \n n$6=*&self:class MemoryLeakExample * [line 31]\n n$7=_fun_MemoryLeakExample_backgroundCoveringView(n$6:class MemoryLeakExample *) [line 31]\n n$8=_fun_UIView_layer(n$7:class UIView *) [line 31]\n n$9=*&shadowPath:struct CGPath * [line 31]\n _fun_CALayer_setShadowPath:(n$8:class CALayer *,n$9:struct CGPath *) [line 31]\n REMOVE_TEMPS(n$6,n$7,n$8,n$9); [line 31]\n NULLIFY(&self,false); [line 31]\n NULLIFY(&shadowPath,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] - 11 -> 13 ; -10 [label="10: DeclStmt \n n$10=*&self:class MemoryLeakExample * [line 30]\n n$11=_fun_MemoryLeakExample_backgroundCoveringView(n$10:class MemoryLeakExample *) [line 30]\n n$12=_fun_UIView_bounds(n$11:class UIView *) [line 30]\n n$13=_fun_CGPathCreateWithRect(n$12:struct CGRect ,0:struct CGAffineTransform *) [line 30]\n *&shadowPath:struct CGPath *=n$13 [line 30]\n REMOVE_TEMPS(n$10,n$11,n$12,n$13); [line 30]\n " shape="box"] + 11 -> 10 ; +10 [label="10: Exit MemoryLeakExample_test \n " color=yellow style=filled] - 10 -> 9 ; -9 [label="9: Message Call: setShadowPath: \n n$6=*&self:class MemoryLeakExample * [line 31]\n n$7=_fun_MemoryLeakExample_backgroundCoveringView(n$6:class MemoryLeakExample *) [line 31]\n n$8=_fun_UIView_layer(n$7:class UIView *) [line 31]\n n$9=*&shadowPath:struct CGPath * [line 31]\n _fun_CALayer_setShadowPath:(n$8:class CALayer *,n$9:struct CGPath *) [line 31]\n REMOVE_TEMPS(n$6,n$7,n$8,n$9); [line 31]\n NULLIFY(&self,false); [line 31]\n NULLIFY(&shadowPath,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] +9 [label="9: Start MemoryLeakExample_test\nFormals: self:class MemoryLeakExample *\nLocals: shadowPath:struct CGPath * \n DECLARE_LOCALS(&return,&shadowPath); [line 28]\n NULLIFY(&shadowPath,false); [line 28]\n " color=yellow style=filled] - 9 -> 8 ; -8 [label="8: Exit MemoryLeakExample_test \n " color=yellow style=filled] + 9 -> 12 ; +8 [label="8: DeclStmt \n n$5=_fun___objc_alloc_no_fail(sizeof(class UIView ):unsigned long ) [line 20]\n *&attachmentContainerView:class UIView *=n$5 [line 20]\n REMOVE_TEMPS(n$5); [line 20]\n " shape="box"] -7 [label="7: Start MemoryLeakExample_test\nFormals: self:class MemoryLeakExample *\nLocals: shadowPath:struct CGPath * \n DECLARE_LOCALS(&return,&shadowPath); [line 28]\n NULLIFY(&shadowPath,false); [line 28]\n " color=yellow style=filled] + 8 -> 7 ; +7 [label="7: DeclStmt \n n$2=*&attachmentContainerView:class UIView * [line 22]\n n$3=_fun_UIView_bounds(n$2:class UIView *) [line 22]\n n$4=_fun_CGPathCreateWithRect(n$3:struct CGRect ,0:struct CGAffineTransform *) [line 22]\n *&shadowPath:struct CGPath *=n$4 [line 22]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 22]\n " shape="box"] - 7 -> 10 ; -6 [label="6: DeclStmt \n n$5=_fun___objc_alloc_no_fail(sizeof(class UIView ):unsigned long ) [line 20]\n *&attachmentContainerView:class UIView *=n$5 [line 20]\n REMOVE_TEMPS(n$5); [line 20]\n " shape="box"] + 7 -> 6 ; +6 [label="6: Call _fun_CGPathRelease \n n$1=*&shadowPath:struct CGPath * [line 24]\n _fun_CGPathRelease(n$1:struct CGPath *) [line 24]\n REMOVE_TEMPS(n$1); [line 24]\n NULLIFY(&shadowPath,false); [line 24]\n " shape="box"] 6 -> 5 ; -5 [label="5: DeclStmt \n n$2=*&attachmentContainerView:class UIView * [line 22]\n n$3=_fun_UIView_bounds(n$2:class UIView *) [line 22]\n n$4=_fun_CGPathCreateWithRect(n$3:struct CGRect ,0:struct CGAffineTransform *) [line 22]\n *&shadowPath:struct CGPath *=n$4 [line 22]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 22]\n " shape="box"] +5 [label="5: Message Call: release \n n$0=*&attachmentContainerView:class UIView * [line 25]\n _fun___objc_release(n$0:class UIView *) [line 25]\n REMOVE_TEMPS(n$0); [line 25]\n NULLIFY(&attachmentContainerView,false); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"] 5 -> 4 ; -4 [label="4: Call _fun_CGPathRelease \n n$1=*&shadowPath:struct CGPath * [line 24]\n _fun_CGPathRelease(n$1:struct CGPath *) [line 24]\n REMOVE_TEMPS(n$1); [line 24]\n NULLIFY(&shadowPath,false); [line 24]\n " shape="box"] +4 [label="4: Exit MemoryLeakExample_layoutSubviews \n " color=yellow style=filled] - 4 -> 3 ; -3 [label="3: Message Call: release \n n$0=*&attachmentContainerView:class UIView * [line 25]\n _fun___objc_release(n$0:class UIView *) [line 25]\n REMOVE_TEMPS(n$0); [line 25]\n NULLIFY(&attachmentContainerView,false); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"] +3 [label="3: Start MemoryLeakExample_layoutSubviews\nFormals: self:class MemoryLeakExample *\nLocals: shadowPath:struct CGPath * attachmentContainerView:class UIView * \n DECLARE_LOCALS(&return,&shadowPath,&attachmentContainerView); [line 19]\n NULLIFY(&attachmentContainerView,false); [line 19]\n NULLIFY(&self,false); [line 19]\n NULLIFY(&shadowPath,false); [line 19]\n " color=yellow style=filled] - 3 -> 2 ; -2 [label="2: Exit MemoryLeakExample_layoutSubviews \n " color=yellow style=filled] + 3 -> 8 ; +2 [label="2: Exit MemoryLeakExample_frontendChecks \n " color=yellow style=filled] -1 [label="1: Start MemoryLeakExample_layoutSubviews\nFormals: self:class MemoryLeakExample *\nLocals: shadowPath:struct CGPath * attachmentContainerView:class UIView * \n DECLARE_LOCALS(&return,&shadowPath,&attachmentContainerView); [line 19]\n NULLIFY(&attachmentContainerView,false); [line 19]\n NULLIFY(&self,false); [line 19]\n NULLIFY(&shadowPath,false); [line 19]\n " color=yellow style=filled] +1 [label="1: Start MemoryLeakExample_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] - 1 -> 6 ; + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot b/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot index 43914ef0e..5c93dc972 100644 --- a/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot +++ b/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot @@ -1,42 +1,49 @@ digraph iCFG { -13 [label="13: Call _fun___infer_assume \n n$1=*&callback:_fn_ (*) [line 46]\n n$2=_fun___infer_assume((n$1 != 0):_fn_ (*)) [line 46]\n REMOVE_TEMPS(n$1,n$2); [line 46]\n " shape="box"] +15 [label="15: Call _fun___infer_assume \n n$1=*&callback:_fn_ (*) [line 46]\n n$2=_fun___infer_assume((n$1 != 0):_fn_ (*)) [line 46]\n REMOVE_TEMPS(n$1,n$2); [line 46]\n " shape="box"] - 13 -> 12 ; -12 [label="12: Call n$0 \n n$0=*&callback:_fn_ (*) [line 46]\n n$0(0:class NSError *,0:struct objc_object *) [line 46]\n REMOVE_TEMPS(n$0); [line 46]\n NULLIFY(&callback,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] + 15 -> 14 ; +14 [label="14: Call n$0 \n n$0=*&callback:_fn_ (*) [line 46]\n n$0(0:class NSError *,0:struct objc_object *) [line 46]\n REMOVE_TEMPS(n$0); [line 46]\n NULLIFY(&callback,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] - 12 -> 11 ; -11 [label="11: Exit test \n " color=yellow style=filled] + 14 -> 13 ; +13 [label="13: Exit test \n " color=yellow style=filled] -10 [label="10: Start test\nFormals: callback:_fn_ (*)\nLocals: \n DECLARE_LOCALS(&return); [line 46]\n " color=yellow style=filled] +12 [label="12: Start test\nFormals: callback:_fn_ (*)\nLocals: \n DECLARE_LOCALS(&return); [line 46]\n " color=yellow style=filled] - 10 -> 13 ; -9 [label="9: Call _fun___infer_assume \n n$5=*&a:class A * [line 38]\n n$6=_fun___infer_assume((n$5 != 0):class A *) [line 38]\n REMOVE_TEMPS(n$5,n$6); [line 38]\n " shape="box"] + 12 -> 15 ; +11 [label="11: Call _fun___infer_assume \n n$5=*&a:class A * [line 38]\n n$6=_fun___infer_assume((n$5 != 0):class A *) [line 38]\n REMOVE_TEMPS(n$5,n$6); [line 38]\n " shape="box"] + + + 11 -> 10 ; +10 [label="10: DeclStmt \n n$3=*&a:class A * [line 39]\n n$4=_fun_A_getA(n$3:class A *) virtual [line 39]\n _fun___objc_retain(n$4:class A *) [line 39]\n *&a1:class A *=n$4 [line 39]\n REMOVE_TEMPS(n$3,n$4); [line 39]\n NULLIFY(&a,false); [line 39]\n " shape="box"] + + + 10 -> 9 ; +9 [label="9: DeclStmt \n n$1=*&a1:class A * [line 40]\n n$2=*n$1.x:int [line 40]\n *&y:int =n$2 [line 40]\n REMOVE_TEMPS(n$1,n$2); [line 40]\n NULLIFY(&a1,false); [line 40]\n NULLIFY(&y,false); [line 40]\n " shape="box"] 9 -> 8 ; -8 [label="8: DeclStmt \n n$3=*&a:class A * [line 39]\n n$4=_fun_A_getA(n$3:class A *) virtual [line 39]\n _fun___objc_retain(n$4:class A *) [line 39]\n *&a1:class A *=n$4 [line 39]\n REMOVE_TEMPS(n$3,n$4); [line 39]\n NULLIFY(&a,false); [line 39]\n " shape="box"] +8 [label="8: Return Stmt \n n$0=*&self:class C * [line 41]\n *&return:struct objc_object *=n$0 [line 41]\n REMOVE_TEMPS(n$0); [line 41]\n NULLIFY(&self,false); [line 41]\n APPLY_ABSTRACTION; [line 41]\n " shape="box"] 8 -> 7 ; -7 [label="7: DeclStmt \n n$1=*&a1:class A * [line 40]\n n$2=*n$1.x:int [line 40]\n *&y:int =n$2 [line 40]\n REMOVE_TEMPS(n$1,n$2); [line 40]\n NULLIFY(&a1,false); [line 40]\n NULLIFY(&y,false); [line 40]\n " shape="box"] +7 [label="7: Exit C_initWithCoder:and: \n " color=yellow style=filled] - 7 -> 6 ; -6 [label="6: Return Stmt \n n$0=*&self:class C * [line 41]\n *&return:struct objc_object *=n$0 [line 41]\n REMOVE_TEMPS(n$0); [line 41]\n NULLIFY(&self,false); [line 41]\n APPLY_ABSTRACTION; [line 41]\n " shape="box"] +6 [label="6: Start C_initWithCoder:and:\nFormals: self:class C * aDecoder:class NSString * a:class A *\nLocals: y:int a1:class A * \n DECLARE_LOCALS(&return,&y,&a1); [line 38]\n NULLIFY(&a1,false); [line 38]\n NULLIFY(&aDecoder,false); [line 38]\n NULLIFY(&y,false); [line 38]\n " color=yellow style=filled] - 6 -> 5 ; -5 [label="5: Exit C_initWithCoder:and: \n " color=yellow style=filled] + 6 -> 11 ; +5 [label="5: Exit C_frontendChecks \n " color=yellow style=filled] -4 [label="4: Start C_initWithCoder:and:\nFormals: self:class C * aDecoder:class NSString * a:class A *\nLocals: y:int a1:class A * \n DECLARE_LOCALS(&return,&y,&a1); [line 38]\n NULLIFY(&a1,false); [line 38]\n NULLIFY(&aDecoder,false); [line 38]\n NULLIFY(&y,false); [line 38]\n " color=yellow style=filled] +4 [label="4: Start C_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] - 4 -> 9 ; + 4 -> 5 ; 3 [label="3: Return Stmt \n n$0=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 26]\n n$1=_fun_NSObject_init(n$0:class A *) virtual [line 26]\n *&return:class A *=n$1 [line 26]\n n$2=_fun___set_autorelease_attribute(n$1:class A *) [line 26]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"] diff --git a/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot b/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot index 5535ea56a..c50a98120 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot @@ -1,102 +1,109 @@ digraph iCFG { -26 [label="26: DeclStmt \n n$3=_fun_A_sharedInstance() [line 43]\n *&b:class A *=n$3 [line 43]\n REMOVE_TEMPS(n$3); [line 43]\n " shape="box"] +28 [label="28: DeclStmt \n n$3=_fun_A_sharedInstance() [line 43]\n *&b:class A *=n$3 [line 43]\n REMOVE_TEMPS(n$3); [line 43]\n " shape="box"] - 26 -> 25 ; -25 [label="25: DeclStmt \n *&p:int *=0 [line 44]\n " shape="box"] + 28 -> 27 ; +27 [label="27: DeclStmt \n *&p:int *=0 [line 44]\n " shape="box"] + + + 27 -> 22 ; +26 [label="26: Return Stmt \n NULLIFY(&p,false); [line 48]\n *&return:int =0 [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"] + + + 26 -> 20 ; +25 [label="25: Return Stmt \n n$1=*&p:int * [line 46]\n n$2=*n$1:int [line 46]\n *&return:int =n$2 [line 46]\n REMOVE_TEMPS(n$1,n$2); [line 46]\n NULLIFY(&p,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] 25 -> 20 ; -24 [label="24: Return Stmt \n NULLIFY(&p,false); [line 48]\n *&return:int =0 [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"] +24 [label="24: Prune (false branch) \n PRUNE(((n$0 == 0) == 0), false); [line 45]\n REMOVE_TEMPS(n$0); [line 45]\n " shape="invhouse"] - 24 -> 18 ; -23 [label="23: Return Stmt \n n$1=*&p:int * [line 46]\n n$2=*n$1:int [line 46]\n *&return:int =n$2 [line 46]\n REMOVE_TEMPS(n$1,n$2); [line 46]\n NULLIFY(&p,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] + 24 -> 26 ; +23 [label="23: Prune (true branch) \n PRUNE(((n$0 == 0) != 0), true); [line 45]\n REMOVE_TEMPS(n$0); [line 45]\n " shape="invhouse"] - 23 -> 18 ; -22 [label="22: Prune (false branch) \n PRUNE(((n$0 == 0) == 0), false); [line 45]\n REMOVE_TEMPS(n$0); [line 45]\n " shape="invhouse"] + 23 -> 25 ; +22 [label="22: BinaryOperatorStmt: EQ \n n$0=*&b:class A * [line 45]\n NULLIFY(&b,false); [line 45]\n " shape="box"] + 22 -> 23 ; 22 -> 24 ; -21 [label="21: Prune (true branch) \n PRUNE(((n$0 == 0) != 0), true); [line 45]\n REMOVE_TEMPS(n$0); [line 45]\n " shape="invhouse"] +21 [label="21: + \n NULLIFY(&b,false); [line 45]\n NULLIFY(&p,false); [line 45]\n " ] - 21 -> 23 ; -20 [label="20: BinaryOperatorStmt: EQ \n n$0=*&b:class A * [line 45]\n NULLIFY(&b,false); [line 45]\n " shape="box"] + 21 -> 20 ; +20 [label="20: Exit main \n " color=yellow style=filled] - 20 -> 21 ; - 20 -> 22 ; -19 [label="19: + \n NULLIFY(&b,false); [line 45]\n NULLIFY(&p,false); [line 45]\n " ] +19 [label="19: Start main\nFormals: \nLocals: p:int * b:class A * \n DECLARE_LOCALS(&return,&p,&b); [line 42]\n NULLIFY(&b,false); [line 42]\n NULLIFY(&p,false); [line 42]\n " color=yellow style=filled] - 19 -> 18 ; -18 [label="18: Exit main \n " color=yellow style=filled] + 19 -> 28 ; +18 [label="18: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_A_trans______2); [line 34]\n n$11=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_trans______2 ):unsigned long ) [line 34]\n *&__objc_anonymous_block_A_trans______2:class __objc_anonymous_block_A_trans______2 =n$11 [line 34]\n n$12=*&#GB$A_trans_sharedInstance:struct objc_object * [line 34]\n *n$11.A_trans_sharedInstance:struct objc_object *=n$12 [line 34]\n *&dummy_block:_fn_ (*)=(_fun___objc_anonymous_block_A_trans______2) [line 34]\n REMOVE_TEMPS(n$11,n$12); [line 34]\n " shape="box"] -17 [label="17: Start main\nFormals: \nLocals: p:int * b:class A * \n DECLARE_LOCALS(&return,&p,&b); [line 42]\n NULLIFY(&b,false); [line 42]\n NULLIFY(&p,false); [line 42]\n " color=yellow style=filled] + 18 -> 14 ; +17 [label="17: BinaryOperatorStmt: Assign \n n$9=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 35]\n n$10=_fun_A_init(n$9:class A *) virtual [line 35]\n *&#GB$A_trans_sharedInstance:struct objc_object *=n$10 [line 35]\n REMOVE_TEMPS(n$9,n$10); [line 35]\n APPLY_ABSTRACTION; [line 35]\n " shape="box"] - 17 -> 26 ; -16 [label="16: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_A_trans______2); [line 34]\n n$11=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_trans______2 ):unsigned long ) [line 34]\n *&__objc_anonymous_block_A_trans______2:class __objc_anonymous_block_A_trans______2 =n$11 [line 34]\n n$12=*&#GB$A_trans_sharedInstance:struct objc_object * [line 34]\n *n$11.A_trans_sharedInstance:struct objc_object *=n$12 [line 34]\n *&dummy_block:_fn_ (*)=(_fun___objc_anonymous_block_A_trans______2) [line 34]\n REMOVE_TEMPS(n$11,n$12); [line 34]\n " shape="box"] + 17 -> 16 ; +16 [label="16: Exit __objc_anonymous_block_A_trans______2 \n " color=yellow style=filled] - 16 -> 12 ; -15 [label="15: BinaryOperatorStmt: Assign \n n$9=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 35]\n n$10=_fun_A_init(n$9:class A *) virtual [line 35]\n *&#GB$A_trans_sharedInstance:struct objc_object *=n$10 [line 35]\n REMOVE_TEMPS(n$9,n$10); [line 35]\n APPLY_ABSTRACTION; [line 35]\n " shape="box"] +15 [label="15: Start __objc_anonymous_block_A_trans______2\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 34]\n " color=yellow style=filled] - 15 -> 14 ; -14 [label="14: Exit __objc_anonymous_block_A_trans______2 \n " color=yellow style=filled] + 15 -> 17 ; +14 [label="14: Call n$8 \n n$8=*&dummy_block:_fn_ (*) [line 37]\n n$8() [line 37]\n REMOVE_TEMPS(n$8); [line 37]\n NULLIFY(&dummy_block,false); [line 37]\n " shape="box"] -13 [label="13: Start __objc_anonymous_block_A_trans______2\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 34]\n " color=yellow style=filled] + 14 -> 13 ; +13 [label="13: Return Stmt \n n$7=*&#GB$A_trans_sharedInstance:struct objc_object * [line 38]\n *&return:struct objc_object *=n$7 [line 38]\n REMOVE_TEMPS(n$7); [line 38]\n NULLIFY(&__objc_anonymous_block_A_trans______2,true); [line 38]\n APPLY_ABSTRACTION; [line 38]\n " shape="box"] - 13 -> 15 ; -12 [label="12: Call n$8 \n n$8=*&dummy_block:_fn_ (*) [line 37]\n n$8() [line 37]\n REMOVE_TEMPS(n$8); [line 37]\n NULLIFY(&dummy_block,false); [line 37]\n " shape="box"] + 13 -> 12 ; +12 [label="12: Exit A_trans \n " color=yellow style=filled] - 12 -> 11 ; -11 [label="11: Return Stmt \n n$7=*&#GB$A_trans_sharedInstance:struct objc_object * [line 38]\n *&return:struct objc_object *=n$7 [line 38]\n REMOVE_TEMPS(n$7); [line 38]\n NULLIFY(&__objc_anonymous_block_A_trans______2,true); [line 38]\n APPLY_ABSTRACTION; [line 38]\n " shape="box"] +11 [label="11: Start A_trans\nFormals: \nLocals: dummy_block:_fn_ (*) \n DECLARE_LOCALS(&return,&dummy_block); [line 32]\n NULLIFY(&dummy_block,false); [line 32]\n " color=yellow style=filled] - 11 -> 10 ; -10 [label="10: Exit A_trans \n " color=yellow style=filled] + 11 -> 18 ; +10 [label="10: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_A_sharedInstance______1); [line 26]\n n$5=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_sharedInstance______1 ):unsigned long ) [line 26]\n *&__objc_anonymous_block_A_sharedInstance______1:class __objc_anonymous_block_A_sharedInstance______1 =n$5 [line 26]\n n$6=*&#GB$A_sharedInstance_sharedInstance:struct objc_object * [line 26]\n *n$5.A_sharedInstance_sharedInstance:struct objc_object *=n$6 [line 26]\n *&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*)=(_fun___objc_anonymous_block_A_sharedInstance______1) [line 26]\n REMOVE_TEMPS(n$5,n$6); [line 26]\n " shape="box"] -9 [label="9: Start A_trans\nFormals: \nLocals: dummy_block:_fn_ (*) \n DECLARE_LOCALS(&return,&dummy_block); [line 32]\n NULLIFY(&dummy_block,false); [line 32]\n " color=yellow style=filled] + 10 -> 6 ; +9 [label="9: BinaryOperatorStmt: Assign \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$4=_fun_A_init(n$3:class A *) virtual [line 27]\n *&#GB$A_sharedInstance_sharedInstance:struct objc_object *=n$4 [line 27]\n REMOVE_TEMPS(n$3,n$4); [line 27]\n APPLY_ABSTRACTION; [line 27]\n " shape="box"] - 9 -> 16 ; -8 [label="8: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_A_sharedInstance______1); [line 26]\n n$5=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_sharedInstance______1 ):unsigned long ) [line 26]\n *&__objc_anonymous_block_A_sharedInstance______1:class __objc_anonymous_block_A_sharedInstance______1 =n$5 [line 26]\n n$6=*&#GB$A_sharedInstance_sharedInstance:struct objc_object * [line 26]\n *n$5.A_sharedInstance_sharedInstance:struct objc_object *=n$6 [line 26]\n *&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*)=(_fun___objc_anonymous_block_A_sharedInstance______1) [line 26]\n REMOVE_TEMPS(n$5,n$6); [line 26]\n " shape="box"] + 9 -> 8 ; +8 [label="8: Exit __objc_anonymous_block_A_sharedInstance______1 \n " color=yellow style=filled] - 8 -> 4 ; -7 [label="7: BinaryOperatorStmt: Assign \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$4=_fun_A_init(n$3:class A *) virtual [line 27]\n *&#GB$A_sharedInstance_sharedInstance:struct objc_object *=n$4 [line 27]\n REMOVE_TEMPS(n$3,n$4); [line 27]\n APPLY_ABSTRACTION; [line 27]\n " shape="box"] +7 [label="7: Start __objc_anonymous_block_A_sharedInstance______1\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 26]\n " color=yellow style=filled] - 7 -> 6 ; -6 [label="6: Exit __objc_anonymous_block_A_sharedInstance______1 \n " color=yellow style=filled] + 7 -> 9 ; +6 [label="6: Call n$1 \n n$1=*&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*) [line 26]\n n$2=n$1() [line 26]\n REMOVE_TEMPS(n$1,n$2); [line 26]\n NULLIFY(&infer___objc_anonymous_block_A_sharedInstance______1,false); [line 26]\n " shape="box"] -5 [label="5: Start __objc_anonymous_block_A_sharedInstance______1\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 26]\n " color=yellow style=filled] + 6 -> 5 ; +5 [label="5: Return Stmt \n n$0=*&#GB$A_sharedInstance_sharedInstance:struct objc_object * [line 29]\n *&return:struct objc_object *=n$0 [line 29]\n REMOVE_TEMPS(n$0); [line 29]\n NULLIFY(&__objc_anonymous_block_A_sharedInstance______1,true); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] - 5 -> 7 ; -4 [label="4: Call n$1 \n n$1=*&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*) [line 26]\n n$2=n$1() [line 26]\n REMOVE_TEMPS(n$1,n$2); [line 26]\n NULLIFY(&infer___objc_anonymous_block_A_sharedInstance______1,false); [line 26]\n " shape="box"] + 5 -> 4 ; +4 [label="4: Exit A_sharedInstance \n " color=yellow style=filled] - 4 -> 3 ; -3 [label="3: Return Stmt \n n$0=*&#GB$A_sharedInstance_sharedInstance:struct objc_object * [line 29]\n *&return:struct objc_object *=n$0 [line 29]\n REMOVE_TEMPS(n$0); [line 29]\n NULLIFY(&__objc_anonymous_block_A_sharedInstance______1,true); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] +3 [label="3: Start A_sharedInstance\nFormals: \nLocals: infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*) \n DECLARE_LOCALS(&return,&infer___objc_anonymous_block_A_sharedInstance______1); [line 23]\n NULLIFY(&infer___objc_anonymous_block_A_sharedInstance______1,false); [line 23]\n " color=yellow style=filled] - 3 -> 2 ; -2 [label="2: Exit A_sharedInstance \n " color=yellow style=filled] + 3 -> 10 ; +2 [label="2: Exit A_frontendChecks \n " color=yellow style=filled] -1 [label="1: Start A_sharedInstance\nFormals: \nLocals: infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*) \n DECLARE_LOCALS(&return,&infer___objc_anonymous_block_A_sharedInstance______1); [line 23]\n NULLIFY(&infer___objc_anonymous_block_A_sharedInstance______1,false); [line 23]\n " color=yellow style=filled] +1 [label="1: Start A_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] - 1 -> 8 ; + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/frontend/property/PropertyAttributes.dot b/infer/tests/codetoanalyze/objc/frontend/property/PropertyAttributes.dot index c5069032d..1fb17c902 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/PropertyAttributes.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/PropertyAttributes.dot @@ -1,65 +1,72 @@ digraph iCFG { -16 [label="16: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 39]\n n$4=_fun_NSObject_init(n$3:class A *) virtual [line 39]\n *&a:class A *=n$4 [line 39]\n REMOVE_TEMPS(n$3,n$4); [line 39]\n " shape="box"] +18 [label="18: DeclStmt \n n$3=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 39]\n n$4=_fun_NSObject_init(n$3:class A *) virtual [line 39]\n *&a:class A *=n$4 [line 39]\n REMOVE_TEMPS(n$3,n$4); [line 39]\n " shape="box"] + + + 18 -> 17 ; +17 [label="17: Message Call: setLast_name: \n n$1=*&a:class A * [line 40]\n n$2=*&a2:class A * [line 40]\n _fun_A_setLast_name:(n$1:class A *,n$2:class A *) [line 40]\n REMOVE_TEMPS(n$1,n$2); [line 40]\n NULLIFY(&a2,false); [line 40]\n " shape="box"] + + + 17 -> 16 ; +16 [label="16: Message Call: release \n n$0=*&a:class A * [line 41]\n _fun___objc_release(n$0:class A *) [line 41]\n REMOVE_TEMPS(n$0); [line 41]\n NULLIFY(&a,false); [line 41]\n " shape="box"] 16 -> 15 ; -15 [label="15: Message Call: setLast_name: \n n$1=*&a:class A * [line 40]\n n$2=*&a2:class A * [line 40]\n _fun_A_setLast_name:(n$1:class A *,n$2:class A *) [line 40]\n REMOVE_TEMPS(n$1,n$2); [line 40]\n NULLIFY(&a2,false); [line 40]\n " shape="box"] +15 [label="15: Return Stmt \n *&return:int =0 [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"] 15 -> 14 ; -14 [label="14: Message Call: release \n n$0=*&a:class A * [line 41]\n _fun___objc_release(n$0:class A *) [line 41]\n REMOVE_TEMPS(n$0); [line 41]\n NULLIFY(&a,false); [line 41]\n " shape="box"] +14 [label="14: Exit test \n " color=yellow style=filled] - 14 -> 13 ; -13 [label="13: Return Stmt \n *&return:int =0 [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"] +13 [label="13: Start test\nFormals: a2:class A *\nLocals: a:class A * \n DECLARE_LOCALS(&return,&a); [line 38]\n NULLIFY(&a,false); [line 38]\n " color=yellow style=filled] - 13 -> 12 ; -12 [label="12: Exit test \n " color=yellow style=filled] + 13 -> 18 ; +12 [label="12: DeclStmt \n n$11=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$12=_fun_NSObject_init(n$11:class A *) virtual [line 27]\n *&other:class A *=n$12 [line 27]\n REMOVE_TEMPS(n$11,n$12); [line 27]\n " shape="box"] -11 [label="11: Start test\nFormals: a2:class A *\nLocals: a:class A * \n DECLARE_LOCALS(&return,&a); [line 38]\n NULLIFY(&a,false); [line 38]\n " color=yellow style=filled] + 12 -> 7 ; + 12 -> 8 ; +11 [label="11: BinaryOperatorStmt: Assign \n n$8=*&other:class A * [line 29]\n n$9=*&self:class A * [line 29]\n n$10=*n$9._name:class A * [line 29]\n *n$8._name:class A *=n$10 [line 29]\n REMOVE_TEMPS(n$8,n$9,n$10); [line 29]\n " shape="box"] - 11 -> 16 ; -10 [label="10: DeclStmt \n n$11=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$12=_fun_NSObject_init(n$11:class A *) virtual [line 27]\n *&other:class A *=n$12 [line 27]\n REMOVE_TEMPS(n$11,n$12); [line 27]\n " shape="box"] + 11 -> 10 ; +10 [label="10: BinaryOperatorStmt: Assign \n n$5=*&other:class A * [line 30]\n n$6=*&self:class A * [line 30]\n n$7=*n$6._last_name:class A * [line 30]\n *n$5._last_name:class A *=n$7 [line 30]\n REMOVE_TEMPS(n$5,n$6,n$7); [line 30]\n " shape="box"] - 10 -> 5 ; - 10 -> 6 ; -9 [label="9: BinaryOperatorStmt: Assign \n n$8=*&other:class A * [line 29]\n n$9=*&self:class A * [line 29]\n n$10=*n$9._name:class A * [line 29]\n *n$8._name:class A *=n$10 [line 29]\n REMOVE_TEMPS(n$8,n$9,n$10); [line 29]\n " shape="box"] + 10 -> 9 ; +9 [label="9: BinaryOperatorStmt: Assign \n n$2=*&other:class A * [line 31]\n n$3=*&self:class A * [line 31]\n n$4=*n$3._child:class A * [line 31]\n *n$2._child:class A *=n$4 [line 31]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] - 9 -> 8 ; -8 [label="8: BinaryOperatorStmt: Assign \n n$5=*&other:class A * [line 30]\n n$6=*&self:class A * [line 30]\n n$7=*n$6._last_name:class A * [line 30]\n *n$5._last_name:class A *=n$7 [line 30]\n REMOVE_TEMPS(n$5,n$6,n$7); [line 30]\n " shape="box"] + 9 -> 6 ; +8 [label="8: Prune (false branch) \n n$1=*&other:class A * [line 28]\n PRUNE((n$1 == 0), false); [line 28]\n REMOVE_TEMPS(n$1); [line 28]\n APPLY_ABSTRACTION; [line 28]\n " shape="invhouse"] - 8 -> 7 ; -7 [label="7: BinaryOperatorStmt: Assign \n n$2=*&other:class A * [line 31]\n n$3=*&self:class A * [line 31]\n n$4=*n$3._child:class A * [line 31]\n *n$2._child:class A *=n$4 [line 31]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] + 8 -> 6 ; +7 [label="7: Prune (true branch) \n n$1=*&other:class A * [line 28]\n PRUNE((n$1 != 0), true); [line 28]\n REMOVE_TEMPS(n$1); [line 28]\n " shape="invhouse"] - 7 -> 4 ; -6 [label="6: Prune (false branch) \n n$1=*&other:class A * [line 28]\n PRUNE((n$1 == 0), false); [line 28]\n REMOVE_TEMPS(n$1); [line 28]\n APPLY_ABSTRACTION; [line 28]\n " shape="invhouse"] + 7 -> 11 ; +6 [label="6: + \n " ] - 6 -> 4 ; -5 [label="5: Prune (true branch) \n n$1=*&other:class A * [line 28]\n PRUNE((n$1 != 0), true); [line 28]\n REMOVE_TEMPS(n$1); [line 28]\n " shape="invhouse"] + 6 -> 5 ; +5 [label="5: Return Stmt \n NULLIFY(&self,false); [line 33]\n n$0=*&other:class A * [line 33]\n *&return:class A *=n$0 [line 33]\n REMOVE_TEMPS(n$0); [line 33]\n NULLIFY(&other,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"] - 5 -> 9 ; -4 [label="4: + \n " ] + 5 -> 4 ; +4 [label="4: Exit A_copy \n " color=yellow style=filled] - 4 -> 3 ; -3 [label="3: Return Stmt \n NULLIFY(&self,false); [line 33]\n n$0=*&other:class A * [line 33]\n *&return:class A *=n$0 [line 33]\n REMOVE_TEMPS(n$0); [line 33]\n NULLIFY(&other,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"] +3 [label="3: Start A_copy\nFormals: self:class A *\nLocals: other:class A * \n DECLARE_LOCALS(&return,&other); [line 26]\n NULLIFY(&other,false); [line 26]\n " color=yellow style=filled] - 3 -> 2 ; -2 [label="2: Exit A_copy \n " color=yellow style=filled] + 3 -> 12 ; +2 [label="2: Exit A_frontendChecks \n " color=yellow style=filled] -1 [label="1: Start A_copy\nFormals: self:class A *\nLocals: other:class A * \n DECLARE_LOCALS(&return,&other); [line 26]\n NULLIFY(&other,false); [line 26]\n " color=yellow style=filled] +1 [label="1: Start A_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] - 1 -> 10 ; + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.dot b/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.dot index e69de29bb..f42f4e57a 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.dot @@ -0,0 +1,9 @@ +digraph iCFG { +2 [label="2: Exit ASDisplayNode_frontendChecks \n " color=yellow style=filled] + + +1 [label="1: Start ASDisplayNode_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] + + + 1 -> 2 ; +} diff --git a/infer/tests/codetoanalyze/objc/frontend/property/PropertyImplSetter.dot b/infer/tests/codetoanalyze/objc/frontend/property/PropertyImplSetter.dot index 180f1661b..0762b6852 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/PropertyImplSetter.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/PropertyImplSetter.dot @@ -1,13 +1,20 @@ digraph iCFG { -3 [label="3: BinaryOperatorStmt: Assign \n n$0=*&self:class PropertyImplSetter * [line 15]\n *n$0._maximumFileSize:int =0 [line 15]\n REMOVE_TEMPS(n$0); [line 15]\n NULLIFY(&self,false); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] +5 [label="5: BinaryOperatorStmt: Assign \n n$0=*&self:class PropertyImplSetter * [line 15]\n *n$0._maximumFileSize:int =0 [line 15]\n REMOVE_TEMPS(n$0); [line 15]\n NULLIFY(&self,false); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] - 3 -> 2 ; -2 [label="2: Exit PropertyImplSetter_setMaximumFileSize: \n " color=yellow style=filled] + 5 -> 4 ; +4 [label="4: Exit PropertyImplSetter_setMaximumFileSize: \n " color=yellow style=filled] -1 [label="1: Start PropertyImplSetter_setMaximumFileSize:\nFormals: self:class PropertyImplSetter * newMaximumFileSize:int \nLocals: \n DECLARE_LOCALS(&return); [line 14]\n NULLIFY(&newMaximumFileSize,false); [line 14]\n " color=yellow style=filled] +3 [label="3: Start PropertyImplSetter_setMaximumFileSize:\nFormals: self:class PropertyImplSetter * newMaximumFileSize:int \nLocals: \n DECLARE_LOCALS(&return); [line 14]\n NULLIFY(&newMaximumFileSize,false); [line 14]\n " color=yellow style=filled] - 1 -> 3 ; + 3 -> 5 ; +2 [label="2: Exit PropertyImplSetter_frontendChecks \n " color=yellow style=filled] + + +1 [label="1: Start PropertyImplSetter_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] + + + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.dot b/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.dot index 5de4ae770..f3e24a536 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.dot @@ -1,13 +1,20 @@ digraph iCFG { -3 [label="3: Return Stmt \n n$0=*&target:class A * [line 19]\n n$1=_fun_A_x(n$0:class A *) [line 19]\n *&return:int =n$1 [line 19]\n REMOVE_TEMPS(n$0,n$1); [line 19]\n NULLIFY(&target,false); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"] +5 [label="5: Return Stmt \n n$0=*&target:class A * [line 19]\n n$1=_fun_A_x(n$0:class A *) [line 19]\n *&return:int =n$1 [line 19]\n REMOVE_TEMPS(n$0,n$1); [line 19]\n NULLIFY(&target,false); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"] - 3 -> 2 ; -2 [label="2: Exit A_addTarget: \n " color=yellow style=filled] + 5 -> 4 ; +4 [label="4: Exit A_addTarget: \n " color=yellow style=filled] -1 [label="1: Start A_addTarget:\nFormals: self:class A * target:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 18]\n NULLIFY(&self,false); [line 18]\n " color=yellow style=filled] +3 [label="3: Start A_addTarget:\nFormals: self:class A * target:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 18]\n NULLIFY(&self,false); [line 18]\n " color=yellow style=filled] - 1 -> 3 ; + 3 -> 5 ; +2 [label="2: Exit A_frontendChecks \n " color=yellow style=filled] + + +1 [label="1: Start A_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] + + + 1 -> 2 ; } diff --git a/infer/tests/codetoanalyze/objc/frontend/property/aclass.dot b/infer/tests/codetoanalyze/objc/frontend/property/aclass.dot index e69de29bb..06e044639 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/aclass.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/aclass.dot @@ -0,0 +1,9 @@ +digraph iCFG { +2 [label="2: Exit AClass_frontendChecks \n " color=yellow style=filled] + + +1 [label="1: Start AClass_frontendChecks\nFormals: \nLocals: \n " color=yellow style=filled] + + + 1 -> 2 ; +}