diff --git a/facebook-clang-plugins b/facebook-clang-plugins index 10eb1ac9b..4c1ba5051 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit 10eb1ac9bb9e94ae8332e84058f39699422a0e85 +Subproject commit 4c1ba505123398d1bfb81fca198cafabffa84da9 diff --git a/infer/src/clang/CMethodProperties.ml b/infer/src/clang/CMethodProperties.ml index 19c19c8f7..2818349a4 100644 --- a/infer/src/clang/CMethodProperties.ml +++ b/infer/src/clang/CMethodProperties.ml @@ -28,6 +28,21 @@ let get_method_kind meth_decl = raise CFrontend_config.Invalid_declaration +let rec is_inside_objc_class_method meth_decl = + let open Clang_ast_t in + match meth_decl with + | ObjCMethodDecl _ -> + ProcAttributes.equal_clang_method_kind (get_method_kind meth_decl) ProcAttributes.OBJC_CLASS + | BlockDecl (di, _) -> ( + match CAst_utils.get_decl_opt di.di_parent_pointer with + | Some decl -> + is_inside_objc_class_method decl + | None -> + false ) + | _ -> + false + + let get_return_type method_decl = let open Clang_ast_t in match method_decl with @@ -147,3 +162,12 @@ let is_variadic method_decl = block_decl_info.bdi_is_variadic | _ -> raise CFrontend_config.Invalid_declaration + + +let get_block_captured_variables method_decl = + let open Clang_ast_t in + match method_decl with + | BlockDecl (_, block_decl_info) -> + block_decl_info.bdi_captured_variables + | _ -> + [] diff --git a/infer/src/clang/CMethodProperties.mli b/infer/src/clang/CMethodProperties.mli index 710aa6281..70d3c28ac 100644 --- a/infer/src/clang/CMethodProperties.mli +++ b/infer/src/clang/CMethodProperties.mli @@ -11,6 +11,8 @@ open! IStd val get_method_kind : Clang_ast_t.decl -> ProcAttributes.clang_method_kind +val is_inside_objc_class_method : Clang_ast_t.decl -> bool + val get_return_type : Clang_ast_t.decl -> Clang_ast_t.qual_type val get_param_decls : Clang_ast_t.decl -> Clang_ast_t.decl list @@ -29,3 +31,5 @@ val get_pointer_to_property : Clang_ast_t.decl -> Clang_ast_t.pointer option val is_objc_method : Clang_ast_t.decl -> bool val is_variadic : Clang_ast_t.decl -> bool + +val get_block_captured_variables : Clang_ast_t.decl -> Clang_ast_t.block_captured_variable list diff --git a/infer/src/clang/CType_decl.ml b/infer/src/clang/CType_decl.ml index 48a027e9d..70e142412 100644 --- a/infer/src/clang/CType_decl.ml +++ b/infer/src/clang/CType_decl.ml @@ -110,6 +110,37 @@ module BuildMethodSignature = struct params @ return_param + let type_of_captured_var qual_type_to_sil_type tenv ~is_block_inside_objc_class_method decl_ref = + match decl_ref with + | {Clang_ast_t.dr_name= Some {Clang_ast_t.ni_name}} -> + (* In Objective-C class methods, self is not the standard self instance, since in this + context we don't have an instance. Instead it is used to get the class of the method. + We translate this variables in a different way than normal, we don't treat them as + variables in Sil, instead we remove them and get the class directly in the frontend. + For that reason, we shouldn't add them as captured variables of blocks, since they + don't appear anywhere else in the translation. *) + if is_block_inside_objc_class_method && String.equal ni_name CFrontend_config.self then + None + else Some (Option.value_exn decl_ref.Clang_ast_t.dr_qual_type |> qual_type_to_sil_type tenv) + | _ -> + assert false + + + let types_of_captured_vars qual_type_to_sil_type tenv meth_decl = + let captured_vars = CMethodProperties.get_block_captured_variables meth_decl in + let is_block = + ProcAttributes.equal_clang_method_kind + (CMethodProperties.get_method_kind meth_decl) + ProcAttributes.BLOCK + in + let is_block_inside_objc_class_method = + is_block && CMethodProperties.is_inside_objc_class_method meth_decl + in + List.map ~f:(fun cv -> Option.value_exn cv.Clang_ast_t.bcv_variable) captured_vars + |> List.filter_map + ~f:(type_of_captured_var qual_type_to_sil_type tenv ~is_block_inside_objc_class_method) + + (** get return type of the function and optionally type of function's return parameter *) let get_return_val_and_param_types qual_type_to_sil_type tenv ~block_return_type method_decl = let return_qual_type = @@ -614,9 +645,13 @@ and procname_from_decl ?tenv ?block_return_type ?outer_proc meth_decl = BuildMethodSignature.get_parameters qual_type_to_sil_type ~block_return_type tenv meth_decl in - List.map - ~f:(fun ({typ}: CMethodSignature.param_type) -> Typ.Procname.Parameter.of_typ typ) - parameters + let parameter_types = + List.map ~f:(fun ({typ}: CMethodSignature.param_type) -> typ) parameters + in + let captured_vars_types = + BuildMethodSignature.types_of_captured_vars qual_type_to_sil_type tenv meth_decl + in + List.map ~f:Typ.Procname.Parameter.of_typ (captured_vars_types @ parameter_types) | None -> [] in @@ -707,6 +742,8 @@ let method_signature_of_decl = BuildMethodSignature.method_signature_of_decl qua let should_add_return_param = BuildMethodSignature.should_add_return_param +let type_of_captured_var = BuildMethodSignature.type_of_captured_var qual_type_to_sil_type + module CProcname = struct let from_decl = procname_from_decl diff --git a/infer/src/clang/CType_decl.mli b/infer/src/clang/CType_decl.mli index 5cac69c5c..2284b7da7 100644 --- a/infer/src/clang/CType_decl.mli +++ b/infer/src/clang/CType_decl.mli @@ -58,3 +58,6 @@ val method_signature_body_of_decl : * [> `CXXConstructorInit of Clang_ast_t.cxx_ctor_initializer] list val should_add_return_param : Typ.typ -> is_objc_method:bool -> bool + +val type_of_captured_var : + Tenv.t -> is_block_inside_objc_class_method:bool -> Clang_ast_t.decl_ref -> Typ.typ option diff --git a/infer/src/clang/cContext.ml b/infer/src/clang/cContext.ml index dda8fe032..245c3ae01 100644 --- a/infer/src/clang/cContext.ml +++ b/infer/src/clang/cContext.ml @@ -27,7 +27,6 @@ type t = ; tenv: Tenv.t ; cfg: Cfg.t ; procdesc: Procdesc.t - ; is_immediate_objc_method: bool ; immediate_curr_class: curr_class ; return_param_typ: Typ.t option ; outer_context: t option @@ -36,14 +35,13 @@ type t = ; vars_to_destroy: Clang_ast_t.decl list StmtMap.t } let create_context translation_unit_context tenv cfg procdesc immediate_curr_class return_param_typ - is_immediate_objc_method outer_context vars_to_destroy = + outer_context vars_to_destroy = { translation_unit_context ; tenv ; cfg ; procdesc ; immediate_curr_class ; return_param_typ - ; is_immediate_objc_method ; outer_context ; blocks_static_vars= Typ.Procname.Map.empty ; label_map= Hashtbl.create 17 @@ -55,17 +53,17 @@ let rec is_objc_method context = | Some outer_context -> is_objc_method outer_context | None -> - context.is_immediate_objc_method + context.procdesc |> Procdesc.get_proc_name |> Typ.Procname.is_objc_method -let rec is_objc_instance context = +let rec is_objc_class_method context = match context.outer_context with | Some outer_context -> - is_objc_instance outer_context + is_objc_class_method outer_context | None -> let attrs = Procdesc.get_attributes context.procdesc in ProcAttributes.equal_clang_method_kind attrs.ProcAttributes.clang_method_kind - ProcAttributes.OBJC_INSTANCE + ProcAttributes.OBJC_CLASS let rec get_curr_class context = diff --git a/infer/src/clang/cContext.mli b/infer/src/clang/cContext.mli index b88b8cc6a..936946a1f 100644 --- a/infer/src/clang/cContext.mli +++ b/infer/src/clang/cContext.mli @@ -22,7 +22,6 @@ type t = ; tenv: Tenv.t ; cfg: Cfg.t ; procdesc: Procdesc.t - ; is_immediate_objc_method: bool ; immediate_curr_class: curr_class ; return_param_typ: Typ.t option ; outer_context: t option @@ -42,12 +41,12 @@ val get_curr_class_decl_ptr : Clang_ast_t.stmt_info -> curr_class -> Clang_ast_t val is_objc_method : t -> bool +val is_objc_class_method : t -> bool + val create_context : CFrontend_config.translation_unit_context -> Tenv.t -> Cfg.t -> Procdesc.t -> curr_class - -> Typ.t option -> bool -> t option -> Clang_ast_t.decl list StmtMap.t -> t + -> Typ.t option -> t option -> Clang_ast_t.decl list StmtMap.t -> t val add_block_static_var : t -> Typ.Procname.t -> Pvar.t * Typ.t -> unit -val is_objc_instance : t -> bool - val get_outer_procname : t -> Typ.Procname.t diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 8be6173eb..5ebdab847 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -45,7 +45,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron (** Translates the method/function's body into nodes of the cfg. *) let add_method ?(is_destructor_wrapper= false) trans_unit_ctx tenv cfg class_decl_opt procname - body ms has_return_param is_objc_method outer_context_opt extra_instrs = + body ms has_return_param outer_context_opt extra_instrs = L.(debug Capture Verbose) "@\n@\n>>---------- ADDING METHOD: '%a' ---------<<@\n@\n" Typ.Procname.pp procname ; incr CFrontend_config.procedures_attempted ; @@ -65,7 +65,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron let vars_to_destroy = CTrans_utils.Scope.compute_vars_to_destroy body in let context = CContext.create_context trans_unit_ctx tenv cfg procdesc class_decl_opt - has_return_param is_objc_method outer_context_opt vars_to_destroy + has_return_param outer_context_opt vars_to_destroy in let start_node = Procdesc.get_start_node procdesc in let exit_node = Procdesc.get_exit_node procdesc in @@ -121,7 +121,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron if CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] captured_vars then add_method trans_unit_ctx tenv cfg CContext.ContextNoCls procname body ms - return_param_typ_opt false outer_context_opt extra_instrs + return_param_typ_opt outer_context_opt extra_instrs | None -> () with CFrontend_config.IncorrectAssumption e -> @@ -130,7 +130,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron let process_method_decl ?(set_objc_accessor_attr= false) ?(is_destructor= false) trans_unit_ctx - tenv cfg curr_class meth_decl ~is_objc = + tenv cfg curr_class meth_decl = try let ms, body_opt, extra_instrs = let procname = CType_decl.CProcname.from_decl ~tenv meth_decl in @@ -150,7 +150,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron ms [body] [] then add_method trans_unit_ctx tenv cfg curr_class procname body ms return_param_typ_opt - is_objc None extra_instrs ~is_destructor_wrapper:true ; + None extra_instrs ~is_destructor_wrapper:true ; let new_method_name = Config.clang_inner_destructor_prefix ^ Typ.Procname.get_method procname in @@ -166,7 +166,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron [body] [] then add_method trans_unit_ctx tenv cfg curr_class procname' body ms' return_param_typ_opt - is_objc None extra_instrs ~is_destructor_wrapper:false + None extra_instrs ~is_destructor_wrapper:false | None -> if set_objc_accessor_attr then ignore @@ -186,7 +186,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron match CAst_utils.get_decl_opt_with_decl_ref pointer with | Some (ObjCMethodDecl _ as dec) -> process_method_decl ~set_objc_accessor_attr:true trans_unit_ctx tenv cfg curr_class - dec ~is_objc:true + dec | _ -> () in @@ -200,12 +200,11 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron let open Clang_ast_t in match dec with | CXXMethodDecl _ | CXXConstructorDecl _ | CXXConversionDecl _ -> - process_method_decl trans_unit_ctx tenv cfg curr_class dec ~is_objc:false + process_method_decl trans_unit_ctx tenv cfg curr_class dec | CXXDestructorDecl _ -> - process_method_decl trans_unit_ctx tenv cfg curr_class dec ~is_objc:false - ~is_destructor:true + process_method_decl trans_unit_ctx tenv cfg curr_class dec ~is_destructor:true | ObjCMethodDecl _ -> - process_method_decl trans_unit_ctx tenv cfg curr_class dec ~is_objc:true + process_method_decl trans_unit_ctx tenv cfg curr_class dec | ObjCPropertyImplDecl (_, obj_c_property_impl_decl_info) -> process_property_implementation trans_unit_ctx tenv cfg curr_class obj_c_property_impl_decl_info @@ -429,8 +428,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron in let body = Clang_ast_t.DeclStmt (stmt_info, [], [dec]) in ignore (CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] []) ; - add_method trans_unit_ctx tenv cfg CContext.ContextNoCls procname body ms None false - None [] + add_method trans_unit_ctx tenv cfg CContext.ContextNoCls procname body ms None None [] (* Note that C and C++ records are treated the same way Skip translating implicit struct declarations, unless they have full definition (which happens with C++ lambdas) *) diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 1bb2e9051..d73620fec 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -2680,8 +2680,9 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let lambda_pname = CMethod_trans.get_procname_from_cpp_lambda context lei_lambda_decl in let typ = CType_decl.qual_type_to_sil_type context.tenv qual_type in let get_captured_pvar_typ decl_ref = - CVar_decl.sil_var_of_captured_var decl_ref context stmt_info.Clang_ast_t.si_source_range - procname + Option.value_exn + (CVar_decl.sil_var_of_captured_var context stmt_info.Clang_ast_t.si_source_range procname + decl_ref) in let translate_capture_init (pvar, typ) init_decl = match init_decl with diff --git a/infer/src/clang/cVar_decl.ml b/infer/src/clang/cVar_decl.ml index 6ffcff38c..809f2188c 100644 --- a/infer/src/clang/cVar_decl.ml +++ b/infer/src/clang/cVar_decl.ml @@ -75,25 +75,43 @@ let add_var_to_locals procdesc var_decl typ pvar = assert false -let sil_var_of_captured_var decl_ref context source_range procname = - match decl_ref with - | {Clang_ast_t.dr_qual_type= Some qual_type} -> - ( sil_var_of_decl_ref context source_range decl_ref procname - , CType_decl.qual_type_to_sil_type context.CContext.tenv qual_type ) +(* The context here is of the method that contains the block *) +let sil_var_of_captured_var context source_range procname decl_ref = + let is_block_inside_objc_class_method = CContext.is_objc_class_method context in + let var_opt = + match decl_ref with + | {Clang_ast_t.dr_name= Some {Clang_ast_t.ni_name}} -> + (* In Objective-C class methods, self is not the standard self instance, since in this + context we don't have an instance. Instead it is used to get the class of the method. + We translate this variables in a different way than normal, we don't treat them as + variables in Sil, instead we remove them and get the class directly in the frontend. + For that reason, we shouldn't add them as captured variables of blocks, since they + don't appear anywhere else in the translation. *) + if is_block_inside_objc_class_method && String.equal ni_name CFrontend_config.self then + None + else Some (sil_var_of_decl_ref context source_range decl_ref procname) + | _ -> + assert false + in + let typ_opt = + CType_decl.type_of_captured_var context.CContext.tenv ~is_block_inside_objc_class_method + decl_ref + in + match (var_opt, typ_opt) with + | Some var, Some typ -> + Some (var, typ) + | None, None -> + None | _ -> - assert false + Logging.die InternalError + "Not possible case, captured variable and its type should both be available or not at %s" + (Clang_ast_j.string_of_source_range source_range) (* Returns a list of captured variables as sil variables. *) -let captured_vars_from_block_info context source_range cvl = +let captured_vars_from_block_info context source_range captured_vars = let procname = Procdesc.get_proc_name context.CContext.procdesc in - let sil_var_of_captured_var {Clang_ast_t.bcv_variable} vars_acc = - match bcv_variable with - | Some ({Clang_ast_t.dr_name= Some {Clang_ast_t.ni_name}} as decl_ref) -> - if String.equal ni_name CFrontend_config.self && not (CContext.is_objc_instance context) - then vars_acc - else sil_var_of_captured_var decl_ref context source_range procname :: vars_acc - | _ -> - assert false + let cv_decl_ref_list = + List.map ~f:(fun cv -> Option.value_exn cv.Clang_ast_t.bcv_variable) captured_vars in - List.fold_right ~f:sil_var_of_captured_var cvl ~init:[] + List.filter_map ~f:(sil_var_of_captured_var context source_range procname) cv_decl_ref_list diff --git a/infer/src/clang/cVar_decl.mli b/infer/src/clang/cVar_decl.mli index a35fb8d67..99837b7fa 100644 --- a/infer/src/clang/cVar_decl.mli +++ b/infer/src/clang/cVar_decl.mli @@ -19,8 +19,8 @@ val sil_var_of_decl_ref : val add_var_to_locals : Procdesc.t -> Clang_ast_t.decl -> Typ.t -> Pvar.t -> unit val sil_var_of_captured_var : - Clang_ast_t.decl_ref -> CContext.t -> Clang_ast_t.source_range -> Typ.Procname.t - -> Pvar.t * Typ.typ + CContext.t -> Clang_ast_t.source_range -> Typ.Procname.t -> Clang_ast_t.decl_ref + -> (Pvar.t * Typ.typ) option val captured_vars_from_block_info : CContext.t -> Clang_ast_t.source_range -> Clang_ast_t.block_captured_variable list diff --git a/infer/tests/codetoanalyze/objc/errors/issues.exp b/infer/tests/codetoanalyze/objc/errors/issues.exp index 2fdce260b..b4f16f86c 100644 --- a/infer/tests/codetoanalyze/objc/errors/issues.exp +++ b/infer/tests/codetoanalyze/objc/errors/issues.exp @@ -84,6 +84,7 @@ codetoanalyze/objc/errors/npe/block.m, BlockA_foo3:, 3, NULL_DEREFERENCE, B1, ER codetoanalyze/objc/errors/npe/block.m, BlockA_foo4:, 6, NULL_DEREFERENCE, B1, ERROR, [start of procedure foo4:] codetoanalyze/objc/errors/npe/block.m, BlockA_foo7, 2, IVAR_NOT_NULL_CHECKED, B1, WARNING, [start of procedure foo7] codetoanalyze/objc/errors/npe/dynamic_dispatch.m, DynamicDispatchMain_npe_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure npe_bad,start of procedure get_ddclass_from:,start of procedure get_ddclass,return from a call to PInstance_get_ddclass,return from a call to DynamicDispatchMain_get_ddclass_from:] +codetoanalyze/objc/errors/npe/dynamic_dispatch.m, objc_blockDynamicDispatchMain_dispatch_async_block_npe_bad_1, 3, NULL_DEREFERENCE, B5, ERROR, [start of procedure block,start of procedure get_ddclass_from:,start of procedure get_ddclass,return from a call to PInstance_get_ddclass,return from a call to DynamicDispatchMain_get_ddclass_from:] codetoanalyze/objc/errors/npe/ivar_blocks.m, MyClass_ivar_npe, 1, IVAR_NOT_NULL_CHECKED, B1, WARNING, [start of procedure ivar_npe] codetoanalyze/objc/errors/npe/skip_method_with_nil_object.m, SkipMethodNilA_testBug:, 6, PARAMETER_NOT_NULL_CHECKED, B2, WARNING, [start of procedure testBug:,Message get_a with receiver nil returns nil.,Message skip_method with receiver nil returns nil.,Taking false branch] codetoanalyze/objc/errors/property/main.c, property_main, 3, MEMORY_LEAK, no_bucket, ERROR, [start of procedure property_main(),Skipping aProperty: method has no implementation] diff --git a/infer/tests/codetoanalyze/objc/errors/npe/dynamic_dispatch.m b/infer/tests/codetoanalyze/objc/errors/npe/dynamic_dispatch.m index fe7b66e1c..17c6f5f8d 100644 --- a/infer/tests/codetoanalyze/objc/errors/npe/dynamic_dispatch.m +++ b/infer/tests/codetoanalyze/objc/errors/npe/dynamic_dispatch.m @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -#import +#import @interface DynamicDispatchClass : NSObject @end @@ -49,4 +49,14 @@ return [self get_ddclass_from:object] -> x; } ++ (int)dispatch_async_block_npe_bad { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), + ^{ + PInstance* object = [PInstance new]; + DynamicDispatchMain* main = [DynamicDispatchMain new]; + int x = [main get_ddclass_from:object] -> x; + }); + return 0; +} + @end diff --git a/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot b/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot index 8a3a7ab30..d97ed418b 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot @@ -34,17 +34,17 @@ digraph cfg { "main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ; -"objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_1" [label="1: Start objc_blockA_capture_1\nFormals: self:A* d:D*\nLocals: \nCaptured: self:A* \n DECLARE_LOCALS(&return); [line 45, column 16]\n " color=yellow style=filled] +"objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_1" [label="1: Start objc_blockA_capture_1\nFormals: self:A* d:D*\nLocals: \nCaptured: self:A* \n DECLARE_LOCALS(&return); [line 45, column 16]\n " color=yellow style=filled] - "objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_1" -> "objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_3" ; -"objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_2" [label="2: Exit objc_blockA_capture_1 \n " color=yellow style=filled] + "objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_1" -> "objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_3" ; +"objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_2" [label="2: Exit objc_blockA_capture_1 \n " color=yellow style=filled] -"objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_3" [label="3: BinaryOperatorStmt: Assign \n n$1=*&self:A* [line 46, column 5]\n n$2=*&d:D* [line 46, column 13]\n *n$1._data:D*=n$2 [line 46, column 5]\n " shape="box"] +"objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_3" [label="3: BinaryOperatorStmt: Assign \n n$1=*&self:A* [line 46, column 5]\n n$2=*&d:D* [line 46, column 13]\n *n$1._data:D*=n$2 [line 46, column 5]\n " shape="box"] - "objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_3" -> "objc_blockA_capture_1(class D).ce4342d16a7487aa29e55ea807813fe8_2" ; + "objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_3" -> "objc_blockA_capture_1(class A,class D).d4c908ef76f37b34ec8aa31647489ab4_2" ; "capture#A#instance.d411336575e4bf632a1828f5f5979726_1" [label="1: Start A_capture\nFormals: self:A*\nLocals: \n DECLARE_LOCALS(&return); [line 43, column 1]\n " color=yellow style=filled] diff --git a/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot b/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot index 061174c7f..a8625f63e 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot @@ -1,16 +1,16 @@ /* @generated */ digraph cfg { -"objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_1" [label="1: Start objc_blockB_f_1\nFormals: self:B* const \nLocals: \nCaptured: self:B* const \n DECLARE_LOCALS(&return); [line 24, column 11]\n " color=yellow style=filled] +"objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_1" [label="1: Start objc_blockB_f_1\nFormals: self:B* const \nLocals: \nCaptured: self:B* const \n DECLARE_LOCALS(&return); [line 24, column 11]\n " color=yellow style=filled] - "objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_1" -> "objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_3" ; -"objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_2" [label="2: Exit objc_blockB_f_1 \n " color=yellow style=filled] + "objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_1" -> "objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_3" ; +"objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_2" [label="2: Exit objc_blockB_f_1 \n " color=yellow style=filled] -"objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_3" [label="3: BinaryOperatorStmt: Assign \n n$3=*&self:B* [line 25, column 9]\n *n$3.x:int=5 [line 25, column 9]\n " shape="box"] +"objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_3" [label="3: BinaryOperatorStmt: Assign \n n$3=*&self:B* [line 25, column 9]\n *n$3.x:int=5 [line 25, column 9]\n " shape="box"] - "objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_3" -> "objc_blockB_f_1.9ca2cd9875647cc0e2a4803d22445f9c_2" ; + "objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_3" -> "objc_blockB_f_1(class B).6b5af83d1cf19e8038483ea8b08b7439_2" ; "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_1" [label="1: Start B_f\nFormals: self:B*\nLocals: \n DECLARE_LOCALS(&return); [line 22, column 1]\n " color=yellow style=filled] diff --git a/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot b/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot index 72a8cd444..75e98bd06 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot @@ -1,33 +1,33 @@ /* @generated */ digraph cfg { -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_1" [label="1: Start objc_blockMy_manager_blockReleaseNoLeak_1\nFormals: newImage:CGImage* a:int\nLocals: \nCaptured: newImage:CGImage* \n DECLARE_LOCALS(&return); [line 23, column 7]\n " color=yellow style=filled] +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_1" [label="1: Start objc_blockMy_manager_blockReleaseNoLeak_1\nFormals: newImage:CGImage* a:int\nLocals: \nCaptured: newImage:CGImage* \n DECLARE_LOCALS(&return); [line 23, column 7]\n " color=yellow style=filled] - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_1" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_5" ; - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_1" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_6" ; -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_2" [label="2: Exit objc_blockMy_manager_blockReleaseNoLeak_1 \n " color=yellow style=filled] + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_1" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_5" ; + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_1" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_6" ; +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_2" [label="2: Exit objc_blockMy_manager_blockReleaseNoLeak_1 \n " color=yellow style=filled] -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_3" [label="3: + \n " ] +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_3" [label="3: + \n " ] - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_3" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_4" ; -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_4" [label="4: between_join_and_exit \n " shape="box"] + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_3" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_4" ; +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_4" [label="4: between_join_and_exit \n " shape="box"] - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_4" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_2" ; -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_5" [label="5: Prune (true branch, if) \n n$10=*&newImage:CGImage* [line 24, column 9]\n PRUNE(n$10, true); [line 24, column 9]\n " shape="invhouse"] + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_4" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_2" ; +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_5" [label="5: Prune (true branch, if) \n n$10=*&newImage:CGImage* [line 24, column 9]\n PRUNE(n$10, true); [line 24, column 9]\n " shape="invhouse"] - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_5" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_7" ; -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_6" [label="6: Prune (false branch, if) \n n$10=*&newImage:CGImage* [line 24, column 9]\n PRUNE(!n$10, false); [line 24, column 9]\n " shape="invhouse"] + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_5" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_7" ; +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_6" [label="6: Prune (false branch, if) \n n$10=*&newImage:CGImage* [line 24, column 9]\n PRUNE(!n$10, false); [line 24, column 9]\n " shape="invhouse"] - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_6" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_3" ; -"objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_7" [label="7: Call _fun_CGImageRelease \n n$11=*&newImage:CGImage* [line 25, column 22]\n n$12=_fun_CGImageRelease(n$11:CGImage*) [line 25, column 7]\n " shape="box"] + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_6" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_3" ; +"objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_7" [label="7: Call _fun_CGImageRelease \n n$11=*&newImage:CGImage* [line 25, column 22]\n n$12=_fun_CGImageRelease(n$11:CGImage*) [line 25, column 7]\n " shape="box"] - "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_7" -> "objc_blockMy_manager_blockReleaseNoLeak_1.a1f2f2c370e78fee994cf9a9d53a7210_3" ; + "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_7" -> "objc_blockMy_manager_blockReleaseNoLeak_1(struct CGImage).d9015a9be6e156b53b1e0a2e237f4578_3" ; "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_1" [label="1: Start My_manager_blockReleaseNoLeak\nFormals: self:My_manager*\nLocals: newImage:CGImage* context:CGContext* z:int b:_fn_(*) \n DECLARE_LOCALS(&return,&newImage,&context,&z,&b); [line 18, column 1]\n " color=yellow style=filled] diff --git a/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot b/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot index ee4a18fea..87947b80b 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot @@ -44,17 +44,17 @@ digraph cfg { "DispatchMain.f6461dbdaeaf9a114cbe40f5f72fbb3f_11" -> "DispatchMain.f6461dbdaeaf9a114cbe40f5f72fbb3f_10" ; -"objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_1" [label="1: Start objc_blockDispatchA_block_attribute_2\nFormals: a:DispatchA*\nLocals: \nCaptured: a:DispatchA* \n DECLARE_LOCALS(&return); [line 37, column 24]\n " color=yellow style=filled] +"objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_1" [label="1: Start objc_blockDispatchA_block_attribute_2\nFormals: a:DispatchA*\nLocals: \nCaptured: a:DispatchA* \n DECLARE_LOCALS(&return); [line 37, column 24]\n " color=yellow style=filled] - "objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_1" -> "objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_3" ; -"objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_2" [label="2: Exit objc_blockDispatchA_block_attribute_2 \n " color=yellow style=filled] + "objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_1" -> "objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_3" ; +"objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_2" [label="2: Exit objc_blockDispatchA_block_attribute_2 \n " color=yellow style=filled] -"objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_3" [label="3: BinaryOperatorStmt: Assign \n n$8=*&a:DispatchA* [line 38, column 5]\n *n$8._x:int=10 [line 38, column 5]\n " shape="box"] +"objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_3" [label="3: BinaryOperatorStmt: Assign \n n$8=*&a:DispatchA* [line 38, column 5]\n *n$8._x:int=10 [line 38, column 5]\n " shape="box"] - "objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_3" -> "objc_blockDispatchA_block_attribute_2.871f06a0b12b5767153a5d30f3798261_2" ; + "objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_3" -> "objc_blockDispatchA_block_attribute_2(class DispatchA).2825198b53dffef0e3209a90789e506f_2" ; "objc_blockDispatchA_dispatch_a_block_variable_4.2eedc45fca2c35e6e8c11937ba7a2df8_1" [label="1: Start objc_blockDispatchA_dispatch_a_block_variable_4\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 54, column 38]\n " color=yellow style=filled]