Summary: This models ARC implementation of dealloc, see https://clang.llvm.org/docs/AutomaticReferenceCounting.html#dealloc. Dealloc methods can be added to ObjC classes to free C memory for example, but the deallocation of the ObjC instance variables of the object is done automatically. So here we add this explicitly to Infer: 1. First, we add an empty dealloc method when it is not written explicitly. 2. For each dealloc method (including the implicitly added ones) we add calls to dealloc of the ObjC instance variables. Reviewed By: jvillard Differential Revision: D21883546 fbshipit-source-id: f5d4930f2master
parent
2707ee8f4e
commit
61d5fde7c4
@ -0,0 +1,81 @@
|
||||
(*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
|
||||
let get_dealloc_call_field (self_var, self_typ) location instrs (fieldname, field_typ, _) =
|
||||
match field_typ.Typ.desc with
|
||||
| Typ.Tptr (({desc= Tstruct name} as cls), Pk_pointer) when Typ.is_objc_class cls ->
|
||||
let field_class_dealloc_name = Procname.make_objc_dealloc name in
|
||||
let id_pvar = Ident.create_fresh Ident.knormal in
|
||||
let load_pvar_instr =
|
||||
Sil.Load {id= id_pvar; e= Lvar self_var; root_typ= self_typ; typ= self_typ; loc= location}
|
||||
in
|
||||
let id_field = Ident.create_fresh Ident.knormal in
|
||||
let class_typ = match self_typ.Typ.desc with Typ.Tptr (t, _) -> t | _ -> self_typ in
|
||||
let e = Exp.Lfield (Var id_pvar, fieldname, class_typ) in
|
||||
let load_field_instr =
|
||||
Sil.Load {id= id_field; e; root_typ= field_typ; typ= field_typ; loc= location}
|
||||
in
|
||||
let ret_id = Ident.create_fresh Ident.knormal in
|
||||
let call_instr =
|
||||
Sil.Call
|
||||
( (ret_id, Typ.void)
|
||||
, Const (Cfun field_class_dealloc_name)
|
||||
, [(Var id_field, field_typ)]
|
||||
, location
|
||||
, CallFlags.default )
|
||||
in
|
||||
instrs @ [load_pvar_instr; load_field_instr; call_instr]
|
||||
| _ ->
|
||||
instrs
|
||||
|
||||
|
||||
let process_dealloc proc_desc fields self =
|
||||
let exit_node = Procdesc.get_exit_node proc_desc in
|
||||
let location = Procdesc.Node.get_last_loc exit_node in
|
||||
let fields_dealloc_call_instrs =
|
||||
List.fold ~f:(get_dealloc_call_field self location) ~init:[] fields
|
||||
in
|
||||
let exit_pred_nodes = Procdesc.Node.get_preds exit_node in
|
||||
let node_name = Procdesc.Node.Call CFrontend_config.dealloc in
|
||||
let node_kind = Procdesc.Node.Stmt_node node_name in
|
||||
let dealloc_calls_node =
|
||||
Procdesc.create_node proc_desc location node_kind fields_dealloc_call_instrs
|
||||
in
|
||||
Procdesc.node_set_succs proc_desc dealloc_calls_node ~normal:[exit_node] ~exn:[] ;
|
||||
List.iter
|
||||
~f:(fun node -> Procdesc.node_set_succs proc_desc node ~normal:[dealloc_calls_node] ~exn:[])
|
||||
exit_pred_nodes
|
||||
|
||||
|
||||
let process_procdesc tenv proc_name proc_desc =
|
||||
let get_struct_procname tenv proc_name =
|
||||
match Procname.get_class_type_name proc_name with
|
||||
| Some name ->
|
||||
Tenv.lookup tenv name
|
||||
| None ->
|
||||
None
|
||||
in
|
||||
if Procdesc.is_defined proc_desc && Procname.is_objc_dealloc proc_name then
|
||||
let struct_opt = get_struct_procname tenv proc_name in
|
||||
match struct_opt with
|
||||
| Some {fields} -> (
|
||||
let formals = Procdesc.get_formals proc_desc in
|
||||
let self = List.find ~f:(fun (var, _) -> Mangled.equal var Mangled.self) formals in
|
||||
match self with
|
||||
| Some (self, typ) ->
|
||||
let self_var = Pvar.mk self proc_name in
|
||||
process_dealloc proc_desc fields (self_var, typ)
|
||||
| None ->
|
||||
() )
|
||||
| _ ->
|
||||
()
|
||||
else ()
|
||||
|
||||
|
||||
let process cfg tenv = Procname.Hash.iter (process_procdesc tenv) cfg
|
@ -0,0 +1,18 @@
|
||||
(*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
|
||||
val process : Cfg.t -> Tenv.t -> unit
|
||||
(** This models ARC implementation of dealloc, see
|
||||
https://clang.llvm.org/docs/AutomaticReferenceCounting.html#dealloc. Dealloc methods can be
|
||||
added to ObjC classes to free C memory for example, but the deallocation of the ObjC instance
|
||||
variables of the object is done automatically. So here we add this explicitely to Infer: we add
|
||||
calls to dealloc of the ObjC instance variables. Here we assume that every ObjC class has
|
||||
already a dealloc method, because if it doesn't exist we add an empty method in
|
||||
CFrontend_decl.create_and_process_dealloc_objc_impl TODO(T68411500): add calls to dealloc of the
|
||||
superclass. *)
|
@ -1,3 +1,14 @@
|
||||
/* @generated */
|
||||
digraph cfg {
|
||||
"dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_1" [label="1: Start ASDisplayNode.dealloc\nFormals: self:ASDisplayNode*\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_1" -> "dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_3" ;
|
||||
"dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_2" [label="2: Exit ASDisplayNode.dealloc \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_3" [label="3: Call dealloc \n " shape="box"]
|
||||
|
||||
|
||||
"dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_3" -> "dealloc#ASDisplayNode#instance.2cf9321d9a068615e100a3ac2a62e774_2" ;
|
||||
}
|
||||
|
@ -1,3 +1,14 @@
|
||||
/* @generated */
|
||||
digraph cfg {
|
||||
"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_1" [label="1: Start AClass.dealloc\nFormals: self:AClass*\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_1" -> "dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_3" ;
|
||||
"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_2" [label="2: Exit AClass.dealloc \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_3" [label="3: Call dealloc \n " shape="box"]
|
||||
|
||||
|
||||
"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_3" -> "dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_2" ;
|
||||
}
|
||||
|
@ -1,3 +1,14 @@
|
||||
/* @generated */
|
||||
digraph cfg {
|
||||
"dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_1" [label="1: Start Test.dealloc\nFormals: self:Test*\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_1" -> "dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_3" ;
|
||||
"dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_2" [label="2: Exit Test.dealloc \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_3" [label="3: Call dealloc \n " shape="box"]
|
||||
|
||||
|
||||
"dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_3" -> "dealloc#Test#instance.5b6eb1b3af87ac0463c4245d2b33c913_2" ;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
codetoanalyze/objc/liveness/NestedClassCalls.m, A.nestedBad, 1, DEAD_STORE, no_bucket, ERROR, [Write of unused value]
|
||||
codetoanalyze/objc/liveness/NestedClassCalls.m, NestedClass.nestedBad, 1, DEAD_STORE, no_bucket, ERROR, [Write of unused value]
|
||||
|
@ -1,74 +1,85 @@
|
||||
/* @generated */
|
||||
digraph cfg {
|
||||
"init#A#instance.eee79aaaddd644404e17691a7e7d809a_1" [label="1: Start A.init\nFormals: self:A*\nLocals: \n " color=yellow style=filled]
|
||||
"dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_1" [label="1: Start NonnullAnnot.dealloc\nFormals: self:NonnullAnnot*\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"init#A#instance.eee79aaaddd644404e17691a7e7d809a_1" -> "init#A#instance.eee79aaaddd644404e17691a7e7d809a_3" ;
|
||||
"init#A#instance.eee79aaaddd644404e17691a7e7d809a_2" [label="2: Exit A.init \n " color=yellow style=filled]
|
||||
"dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_1" -> "dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_3" ;
|
||||
"dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_2" [label="2: Exit NonnullAnnot.dealloc \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"init#A#instance.eee79aaaddd644404e17691a7e7d809a_3" [label="3: Return Stmt \n n$0=*&self:A* [line 20, column 10]\n *&return:objc_object*=n$0 [line 20, column 3]\n " shape="box"]
|
||||
"dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_3" [label="3: Call dealloc \n n$0=*&self:NonnullAnnot* [line 43, column 1]\n n$1=*n$0._child:NonnullAnnot* [line 43, column 1]\n n$2=_fun_NonnullAnnot.dealloc(n$1:NonnullAnnot*) [line 43, column 1]\n " shape="box"]
|
||||
|
||||
|
||||
"init#A#instance.eee79aaaddd644404e17691a7e7d809a_3" -> "init#A#instance.eee79aaaddd644404e17691a7e7d809a_2" ;
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_1" [label="1: Start A.test1:\nFormals: self:A* a:A*\nLocals: aa:A* \n " color=yellow style=filled]
|
||||
"dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_3" -> "dealloc#NonnullAnnot#instance.0759b4c4bc783d3b87f6d785a8b2c369_2" ;
|
||||
"init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_1" [label="1: Start NonnullAnnot.init\nFormals: self:NonnullAnnot*\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_1" -> "test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_4" ;
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_2" [label="2: Exit A.test1: \n " color=yellow style=filled]
|
||||
"init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_1" -> "init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_3" ;
|
||||
"init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_2" [label="2: Exit NonnullAnnot.init \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_3" [label="3: Return Stmt \n n$1=*&aa:A* [line 25, column 10]\n n$2=*n$1.x:int [line 25, column 10]\n *&return:int=n$2 [line 25, column 3]\n " shape="box"]
|
||||
"init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_3" [label="3: Return Stmt \n n$0=*&self:NonnullAnnot* [line 20, column 10]\n *&return:objc_object*=n$0 [line 20, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_3" -> "test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_2" ;
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_4" [label="4: DeclStmt \n VARIABLE_DECLARED(aa:A*); [line 24, column 3]\n n$3=*&a:A* [line 24, column 12]\n n$4=_fun_A.child(n$3:A*) [line 24, column 11]\n *&aa:A*=n$4 [line 24, column 3]\n " shape="box"]
|
||||
"init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_3" -> "init#NonnullAnnot#instance.b2b74f8dde6ae5957922f59d81ccda45_2" ;
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_1" [label="1: Start NonnullAnnot.test1:\nFormals: self:NonnullAnnot* a:NonnullAnnot*\nLocals: aa:NonnullAnnot* \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_4" -> "test1:#A(class A)#instance.61440711d4e2388d4be3731c34a61289_3" ;
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_1" [label="1: Start A.test2:\nFormals: self:A* a:A*\nLocals: aa:A*\nAnnotation: <> A.test2:(<> <_Nonnull>) \n " color=yellow style=filled]
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_1" -> "test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_4" ;
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_2" [label="2: Exit NonnullAnnot.test1: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_1" -> "test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_4" ;
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_2" [label="2: Exit A.test2: \n " color=yellow style=filled]
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_3" [label="3: Return Stmt \n n$1=*&aa:NonnullAnnot* [line 25, column 10]\n n$2=*n$1.x:int [line 25, column 10]\n *&return:int=n$2 [line 25, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_3" [label="3: Return Stmt \n n$5=*&aa:A* [line 30, column 10]\n n$6=*n$5.x:int [line 30, column 10]\n *&return:int=n$6 [line 30, column 3]\n " shape="box"]
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_3" -> "test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_2" ;
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_4" [label="4: DeclStmt \n VARIABLE_DECLARED(aa:NonnullAnnot*); [line 24, column 3]\n n$3=*&a:NonnullAnnot* [line 24, column 23]\n n$4=_fun_NonnullAnnot.child(n$3:NonnullAnnot*) [line 24, column 22]\n *&aa:NonnullAnnot*=n$4 [line 24, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_3" -> "test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_2" ;
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_4" [label="4: DeclStmt \n VARIABLE_DECLARED(aa:A*); [line 29, column 3]\n n$7=*&a:A* [line 29, column 12]\n n$8=_fun_A.child(n$7:A*) [line 29, column 11]\n *&aa:A*=n$8 [line 29, column 3]\n " shape="box"]
|
||||
"test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_4" -> "test1:#NonnullAnnot(class NonnullAnnot)#instance.e1bfc3674bdae0a62d7e4bb2a1768f99_3" ;
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_1" [label="1: Start NonnullAnnot.test2:\nFormals: self:NonnullAnnot* a:NonnullAnnot*\nLocals: aa:NonnullAnnot*\nAnnotation: <> NonnullAnnot.test2:(<> <_Nonnull>) \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_4" -> "test2:#A(class A)#instance.3b9594b6f023617f19d57dee6d35cf80_3" ;
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_1" [label="1: Start A.test3:\nFormals: self:A* successBlock:_fn_(*)\nLocals: \n " color=yellow style=filled]
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_1" -> "test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_4" ;
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_2" [label="2: Exit NonnullAnnot.test2: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_1" -> "test3:#A#instance.28bc2df8df797b21818dc2037239f326_4" ;
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_2" [label="2: Exit A.test3: \n " color=yellow style=filled]
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_3" [label="3: Return Stmt \n n$5=*&aa:NonnullAnnot* [line 30, column 10]\n n$6=*n$5.x:int [line 30, column 10]\n *&return:int=n$6 [line 30, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_3" [label="3: Return Stmt \n *&return:int=0 [line 35, column 3]\n " shape="box"]
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_3" -> "test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_2" ;
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_4" [label="4: DeclStmt \n VARIABLE_DECLARED(aa:NonnullAnnot*); [line 29, column 3]\n n$7=*&a:NonnullAnnot* [line 29, column 23]\n n$8=_fun_NonnullAnnot.child(n$7:NonnullAnnot*) [line 29, column 22]\n *&aa:NonnullAnnot*=n$8 [line 29, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_3" -> "test3:#A#instance.28bc2df8df797b21818dc2037239f326_2" ;
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_4" [label="4: Call n$9 \n n$9=*&successBlock:_fn_(*) [line 34, column 3]\n n$10=_fun_NSString.stringWithUTF8String:(\"Yay\":char* const ) [line 34, column 16]\n n$11=n$9(n$10:NSString*) objc_block [line 34, column 3]\n " shape="box"]
|
||||
"test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_4" -> "test2:#NonnullAnnot(class NonnullAnnot)#instance.7992ca7f61dca07dd40b2e7d7603a016_3" ;
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_1" [label="1: Start NonnullAnnot.test3:\nFormals: self:NonnullAnnot* successBlock:_fn_(*)\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test3:#A#instance.28bc2df8df797b21818dc2037239f326_4" -> "test3:#A#instance.28bc2df8df797b21818dc2037239f326_3" ;
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_1" [label="1: Start A.test4:\nFormals: self:A* successBlock:_fn_(*)\nLocals: \nAnnotation: <> A.test4:(<> <_Nonnull>) \n " color=yellow style=filled]
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_1" -> "test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_4" ;
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_2" [label="2: Exit NonnullAnnot.test3: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_1" -> "test4:#A#instance.718a300d6fa63609a70f22221a548ee5_4" ;
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_2" [label="2: Exit A.test4: \n " color=yellow style=filled]
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_3" [label="3: Return Stmt \n *&return:int=0 [line 35, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_3" [label="3: Return Stmt \n *&return:int=0 [line 40, column 3]\n " shape="box"]
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_3" -> "test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_2" ;
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_4" [label="4: Call n$9 \n n$9=*&successBlock:_fn_(*) [line 34, column 3]\n n$10=_fun_NSString.stringWithUTF8String:(\"Yay\":char* const ) [line 34, column 16]\n n$11=n$9(n$10:NSString*) objc_block [line 34, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_3" -> "test4:#A#instance.718a300d6fa63609a70f22221a548ee5_2" ;
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_4" [label="4: Call n$12 \n n$12=*&successBlock:_fn_(*) [line 39, column 3]\n n$13=_fun_NSString.stringWithUTF8String:(\"Yay\":char* const ) [line 39, column 16]\n n$14=n$12(n$13:NSString*) objc_block [line 39, column 3]\n " shape="box"]
|
||||
"test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_4" -> "test3:#NonnullAnnot#instance.4ab04a3232d4ec4327b6040285f16196_3" ;
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_1" [label="1: Start NonnullAnnot.test4:\nFormals: self:NonnullAnnot* successBlock:_fn_(*)\nLocals: \nAnnotation: <> NonnullAnnot.test4:(<> <_Nonnull>) \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test4:#A#instance.718a300d6fa63609a70f22221a548ee5_4" -> "test4:#A#instance.718a300d6fa63609a70f22221a548ee5_3" ;
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_1" -> "test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_4" ;
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_2" [label="2: Exit NonnullAnnot.test4: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_3" [label="3: Return Stmt \n *&return:int=0 [line 40, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_3" -> "test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_2" ;
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_4" [label="4: Call n$12 \n n$12=*&successBlock:_fn_(*) [line 39, column 3]\n n$13=_fun_NSString.stringWithUTF8String:(\"Yay\":char* const ) [line 39, column 16]\n n$14=n$12(n$13:NSString*) objc_block [line 39, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_4" -> "test4:#NonnullAnnot#instance.679c6b135de319b66e5e0bd6ab2f0b43_3" ;
|
||||
}
|
||||
|
@ -1,70 +1,81 @@
|
||||
/* @generated */
|
||||
digraph cfg {
|
||||
"objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_1" [label="1: Start objc_blockMy_manager.m_1\nFormals: z:int\nLocals: \nCaptured: z:int \n " color=yellow style=filled]
|
||||
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_1" [label="1: Start objc_blockBlock_no_args.m_1\nFormals: z:int\nLocals: \nCaptured: z:int \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_1" -> "objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_3" ;
|
||||
"objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_2" [label="2: Exit objc_blockMy_manager.m_1 \n " color=yellow style=filled]
|
||||
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_1" -> "objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_3" ;
|
||||
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_2" [label="2: Exit objc_blockBlock_no_args.m_1 \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_3" [label="3: BinaryOperatorStmt: Assign \n n$8=*&z:int [line 24, column 9]\n *&#GB<codetoanalyze/objc/shared/block/block_no_args.m>$g:int=(n$8 + 3) [line 24, column 5]\n " shape="box"]
|
||||
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_3" [label="3: BinaryOperatorStmt: Assign \n n$8=*&z:int [line 24, column 9]\n *&#GB<codetoanalyze/objc/shared/block/block_no_args.m>$g:int=(n$8 + 3) [line 24, column 5]\n " shape="box"]
|
||||
|
||||
|
||||
"objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_3" -> "objc_blockMy_manager.m_1.d933a5f9ad39365b735134c5f5009061_2" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_1" [label="1: Start My_manager.m\nFormals: self:My_manager*\nLocals: p:int* z:int b:_fn_(*) \n " color=yellow style=filled]
|
||||
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_3" -> "objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_2" ;
|
||||
"dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_1" [label="1: Start Block_no_args.dealloc\nFormals: self:Block_no_args*\nLocals: \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_1" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_14" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_2" [label="2: Exit My_manager.m \n " color=yellow style=filled]
|
||||
"dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_1" -> "dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_3" ;
|
||||
"dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_2" [label="2: Exit Block_no_args.dealloc \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_3" [label="3: + \n " ]
|
||||
"dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_3" [label="3: Call dealloc \n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_3" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_4" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_4" [label="4: between_join_and_exit \n " shape="box"]
|
||||
"dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_3" -> "dealloc#Block_no_args#instance.eac76c4150c7c9dce7f36154adee0b59_2" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_1" [label="1: Start Block_no_args.m\nFormals: self:Block_no_args*\nLocals: p:int* z:int b:_fn_(*) \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_4" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_2" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_5" [label="5: BinaryOperatorStmt: EQ \n n$0=*&#GB<codetoanalyze/objc/shared/block/block_no_args.m>$g:int [line 28, column 7]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_1" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_14" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_2" [label="2: Exit Block_no_args.m \n " color=yellow style=filled]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_5" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_6" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_5" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_7" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_6" [label="6: Prune (true branch, if) \n PRUNE((n$0 == 6), true); [line 28, column 7]\n " shape="invhouse"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_3" [label="3: + \n " ]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_6" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_8" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_7" [label="7: Prune (false branch, if) \n PRUNE(!(n$0 == 6), false); [line 28, column 7]\n " shape="invhouse"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_3" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_4" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_4" [label="4: between_join_and_exit \n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_7" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_9" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_8" [label="8: Return Stmt \n n$1=*&p:int* [line 29, column 13]\n n$2=*n$1:int [line 29, column 12]\n *&return:int=n$2 [line 29, column 5]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_4" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_2" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_5" [label="5: BinaryOperatorStmt: EQ \n n$0=*&#GB<codetoanalyze/objc/shared/block/block_no_args.m>$g:int [line 28, column 7]\n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_8" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_2" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_9" [label="9: Return Stmt \n n$3=*&z:int [line 31, column 12]\n *&return:int=n$3 [line 31, column 5]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_5" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_6" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_5" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_7" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_6" [label="6: Prune (true branch, if) \n PRUNE((n$0 == 6), true); [line 28, column 7]\n " shape="invhouse"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_9" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_2" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_10" [label="10: DeclStmt \n VARIABLE_DECLARED(p:int*); [line 27, column 3]\n *&p:int*=null [line 27, column 3]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_6" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_8" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_7" [label="7: Prune (false branch, if) \n PRUNE(!(n$0 == 6), false); [line 28, column 7]\n " shape="invhouse"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_10" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_5" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_11" [label="11: Call n$5 \n n$5=*&b:_fn_(*) [line 26, column 3]\n n$6=n$5() objc_block [line 26, column 3]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_7" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_9" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_8" [label="8: Return Stmt \n n$1=*&p:int* [line 29, column 13]\n n$2=*n$1:int [line 29, column 12]\n *&return:int=n$2 [line 29, column 5]\n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_11" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_10" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_12" [label="12: BinaryOperatorStmt: Assign \n n$7=*&z:int [line 23, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager.m_1,(n$7 &z:int)) [line 23, column 3]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_8" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_2" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_9" [label="9: Return Stmt \n n$3=*&z:int [line 31, column 12]\n *&return:int=n$3 [line 31, column 5]\n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_12" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_11" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_13" [label="13: DeclStmt \n VARIABLE_DECLARED(z:int); [line 22, column 3]\n *&z:int=3 [line 22, column 3]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_9" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_2" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_10" [label="10: DeclStmt \n VARIABLE_DECLARED(p:int*); [line 27, column 3]\n *&p:int*=null [line 27, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_13" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_12" ;
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_14" [label="14: BinaryOperatorStmt: Assign \n *&#GB<codetoanalyze/objc/shared/block/block_no_args.m>$g:int=7 [line 20, column 3]\n " shape="box"]
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_10" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_5" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" [label="11: Call n$5 \n n$5=*&b:_fn_(*) [line 26, column 3]\n n$6=n$5() objc_block [line 26, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_14" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_13" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_10" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" [label="12: BinaryOperatorStmt: Assign \n n$7=*&z:int [line 23, column 7]\n *&b:_fn_(*)=(_fun_objc_blockBlock_no_args.m_1,(n$7 &z:int)) [line 23, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_13" [label="13: DeclStmt \n VARIABLE_DECLARED(z:int); [line 22, column 3]\n *&z:int=3 [line 22, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_13" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" ;
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_14" [label="14: BinaryOperatorStmt: Assign \n *&#GB<codetoanalyze/objc/shared/block/block_no_args.m>$g:int=7 [line 20, column 3]\n " shape="box"]
|
||||
|
||||
|
||||
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_14" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_13" ;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
codetoanalyze/objcpp/biabduction/BlockLfield.mm, A.mOk, 1, PRECONDITION_NOT_FOUND, no_bucket, ERROR, [start of procedure mOk]
|
||||
codetoanalyze/objcpp/biabduction/BlockLfield.mm, CFunWithBlockOk, 2, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure CFunWithBlockOk()]
|
||||
codetoanalyze/objcpp/biabduction/BlockLfield.mm, CFunWithBlockOk_objc_blockA.mOk_1, 2, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure CFunWithBlockOk()]
|
||||
codetoanalyze/objcpp/biabduction/c_functions.mm, main, 4, NULL_DEREFERENCE, B5, ERROR, [start of procedure main(),start of procedure autoUpdating,return from a call to A.autoUpdating,start of procedure autoUpdating2,Skipping dispatch_once2(): method has no implementation,return from a call to A.autoUpdating2,Executing synthesized getter block,start of procedure block,return from a call to objc_blockobjc_blockA.autoUpdating_1_2,Message block with receiver nil returns nil.]
|
||||
codetoanalyze/objcpp/biabduction/c_functions.mm, main, 4, NULL_DEREFERENCE, B5, ERROR, [start of procedure main(),start of procedure autoUpdating,return from a call to Functions.autoUpdating,start of procedure autoUpdating2,Skipping dispatch_once2(): method has no implementation,return from a call to Functions.autoUpdating2,Executing synthesized getter block,start of procedure block,return from a call to objc_blockobjc_blockFunctions.autoUpdating_1_2,Message block with receiver nil returns nil.]
|
||||
codetoanalyze/objcpp/biabduction/retain_cycles/RetainCycleWithStruct.mm, Animation.tracer, 2, BIABDUCTION_ANALYSIS_STOPS, no_bucket, WARNING, [start of procedure tracer,start of procedure _State,return from a call to _State::_State,start of procedure initWithAnimation:,Taking true branch,return from a call to Tracer.initWithAnimation:]
|
||||
codetoanalyze/objcpp/biabduction/retain_cycles/RetainCycleWithStruct.mm, Animation.tracer, 2, RETAIN_CYCLE, no_bucket, ERROR, [start of procedure tracer,start of procedure _State,return from a call to _State::_State,start of procedure initWithAnimation:,Taking true branch,return from a call to Tracer.initWithAnimation:]
|
||||
|
Loading…
Reference in new issue