[clang] Add the types of captured variables to the procname of blocks

Reviewed By: mbouaziz

Differential Revision: D8735374

fbshipit-source-id: 5c7c0b2
master
Dulma Churchill 6 years ago committed by Facebook Github Bot
parent 5cff9c91f9
commit 5653839540

@ -1 +1 @@
Subproject commit 10eb1ac9bb9e94ae8332e84058f39699422a0e85
Subproject commit 4c1ba505123398d1bfb81fca198cafabffa84da9

@ -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
| _ ->
[]

@ -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

@ -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

@ -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

@ -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 =

@ -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

@ -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) *)

@ -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

@ -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

@ -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

@ -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]

@ -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 <Foundation/NSObject.h>
#import <Foundation/Foundation.h>
@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

@ -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]

@ -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]

@ -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]

@ -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]

Loading…
Cancel
Save