|
|
|
digraph iCFG {
|
Using clang's method resolution if possible
Summary: public
Using clang's method resolution. This means that, in method calls, clang gives you a pointer to the declaration of the method.
In some cases though, clang doesn't find the right method. For example, when it finds a method in a category, we
need to make it into a method in the corresponding class, because that's how we treat categories in Infer. Moreover,
when it finds a method in a protocol, that is not useful for us, since the implementation will be in some class. Finally,
sometimes the call is on an object of type id, in which case clang doesn't know what is the correct declaration. In
those cases, we fall back to what we were doing before of approximating the method resolution. We also refactor
some of the code.
Reviewed By: akotulski
Differential Revision: D2679766
fb-gh-sync-id: b79bb85
9 years ago
|
|
|
39 [label="39: DeclStmt \n n$7=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 39]\n n$5=_fun_NSObject_init(n$7:class A *) virtual [line 39]\n *&a:class A *=n$5 [line 39]\n REMOVE_TEMPS(n$5,n$7); [line 39]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
39 -> 38 ;
|
|
|
|
38 [label="38: Message Call: setLast_name: \n n$1=*&a:class A * [line 40]\n n$2=*&a2:class A * [line 40]\n _fun_A_setLast_name:(n$1:class A *,n$2:class A *) virtual [line 40]\n REMOVE_TEMPS(n$1,n$2); [line 40]\n NULLIFY(&a2,false); [line 40]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
38 -> 34 ;
|
|
|
|
37 [label="37: BinaryOperatorStmt: Assign \n n$3=*&self:class A * [line 18]\n n$4=*&last_name:class A * [line 18]\n *n$3._last_name:class A *=n$4 [line 18]\n REMOVE_TEMPS(n$3,n$4); [line 18]\n NULLIFY(&last_name,false); [line 18]\n NULLIFY(&self,false); [line 18]\n APPLY_ABSTRACTION; [line 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
37 -> 36 ;
|
|
|
|
36 [label="36: Exit A_setLast_name: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
35 [label="35: Start A_setLast_name: (generated)\nFormals: self:class A * last_name:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 18]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
35 -> 37 ;
|
|
|
|
34 [label="34: Message Call: release \n n$0=*&a:class A * [line 41]\n _fun___objc_release(n$0:class A *) [line 41]\n REMOVE_TEMPS(n$0); [line 41]\n NULLIFY(&a,false); [line 41]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
34 -> 33 ;
|
|
|
|
33 [label="33: Return Stmt \n *&return:int =0 [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
33 -> 32 ;
|
|
|
|
32 [label="32: Exit test \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
31 [label="31: Start test\nFormals: a2:class A *\nLocals: a:class A * \n DECLARE_LOCALS(&return,&a); [line 38]\n NULLIFY(&a,false); [line 38]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
31 -> 39 ;
|
|
|
|
27 [label="27: Return Stmt \n n$28=*&self:class A * [line 18]\n n$29=*n$28._last_name:class A * [line 18]\n *&return:class A *=n$29 [line 18]\n REMOVE_TEMPS(n$28,n$29); [line 18]\n NULLIFY(&self,false); [line 18]\n APPLY_ABSTRACTION; [line 18]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
27 -> 26 ;
|
|
|
|
26 [label="26: Exit A_last_name \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
25 [label="25: Start A_last_name (generated)\nFormals: self:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 18]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
25 -> 27 ;
|
|
|
|
24 [label="24: Message Call: retain \n n$27=*&name:class A * [line 16]\n n$26=_fun___objc_retain(n$27:class A *) [line 16]\n REMOVE_TEMPS(n$26,n$27); [line 16]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
24 -> 23 ;
|
|
|
|
23 [label="23: Message Call: release \n n$24=*&self:class A * [line 16]\n n$25=*n$24._name:class A * [line 16]\n n$23=_fun___objc_release(n$25:class A *) [line 16]\n REMOVE_TEMPS(n$23,n$24,n$25); [line 16]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
23 -> 22 ;
|
|
|
|
22 [label="22: BinaryOperatorStmt: Assign \n n$21=*&self:class A * [line 16]\n n$22=*&name:class A * [line 16]\n *n$21._name:class A *=n$22 [line 16]\n REMOVE_TEMPS(n$21,n$22); [line 16]\n NULLIFY(&name,false); [line 16]\n NULLIFY(&self,false); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
22 -> 21 ;
|
|
|
|
21 [label="21: Exit A_setName: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
20 [label="20: Start A_setName: (generated)\nFormals: self:class A * name:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 16]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
20 -> 24 ;
|
|
|
|
19 [label="19: Return Stmt \n n$19=*&self:class A * [line 16]\n n$20=*n$19._name:class A * [line 16]\n *&return:class A *=n$20 [line 16]\n REMOVE_TEMPS(n$19,n$20); [line 16]\n NULLIFY(&self,false); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
19 -> 18 ;
|
|
|
|
18 [label="18: Exit A_name \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
17 [label="17: Start A_name (generated)\nFormals: self:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 16]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
17 -> 19 ;
|
|
|
|
16 [label="16: BinaryOperatorStmt: Assign \n n$16=*&self:class A * [line 14]\n n$18=*&child:class A * [line 14]\n n$17=_fun_A_copy(n$18:class A *) virtual [line 14]\n *n$16._child:class A *=n$17 [line 14]\n REMOVE_TEMPS(n$16,n$17,n$18); [line 14]\n NULLIFY(&child,false); [line 14]\n NULLIFY(&self,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
16 -> 15 ;
|
|
|
|
15 [label="15: Exit A_setChild: \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
14 [label="14: Start A_setChild: (generated)\nFormals: self:class A * child:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
14 -> 16 ;
|
|
|
|
13 [label="13: Return Stmt \n n$14=*&self:class A * [line 14]\n n$15=*n$14._child:class A * [line 14]\n *&return:class A *=n$15 [line 14]\n REMOVE_TEMPS(n$14,n$15); [line 14]\n NULLIFY(&self,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
13 -> 12 ;
|
|
|
|
12 [label="12: Exit A_child \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
11 [label="11: Start A_child (generated)\nFormals: self:class A *\nLocals: \n DECLARE_LOCALS(&return); [line 14]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
11 -> 13 ;
|
Using clang's method resolution if possible
Summary: public
Using clang's method resolution. This means that, in method calls, clang gives you a pointer to the declaration of the method.
In some cases though, clang doesn't find the right method. For example, when it finds a method in a category, we
need to make it into a method in the corresponding class, because that's how we treat categories in Infer. Moreover,
when it finds a method in a protocol, that is not useful for us, since the implementation will be in some class. Finally,
sometimes the call is on an object of type id, in which case clang doesn't know what is the correct declaration. In
those cases, we fall back to what we were doing before of approximating the method resolution. We also refactor
some of the code.
Reviewed By: akotulski
Differential Revision: D2679766
fb-gh-sync-id: b79bb85
9 years ago
|
|
|
10 [label="10: DeclStmt \n n$13=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 27]\n n$11=_fun_NSObject_init(n$13:class A *) virtual [line 27]\n *&other:class A *=n$11 [line 27]\n REMOVE_TEMPS(n$11,n$13); [line 27]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
10 -> 5 ;
|
|
|
|
10 -> 6 ;
|
|
|
|
9 [label="9: BinaryOperatorStmt: Assign \n n$8=*&other:class A * [line 29]\n n$9=*&self:class A * [line 29]\n n$10=*n$9._name:class A * [line 29]\n *n$8._name:class A *=n$10 [line 29]\n REMOVE_TEMPS(n$8,n$9,n$10); [line 29]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
9 -> 8 ;
|
|
|
|
8 [label="8: BinaryOperatorStmt: Assign \n n$5=*&other:class A * [line 30]\n n$6=*&self:class A * [line 30]\n n$7=*n$6._last_name:class A * [line 30]\n *n$5._last_name:class A *=n$7 [line 30]\n REMOVE_TEMPS(n$5,n$6,n$7); [line 30]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
8 -> 7 ;
|
|
|
|
7 [label="7: BinaryOperatorStmt: Assign \n n$2=*&other:class A * [line 31]\n n$3=*&self:class A * [line 31]\n n$4=*n$3._child:class A * [line 31]\n *n$2._child:class A *=n$4 [line 31]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
7 -> 4 ;
|
|
|
|
6 [label="6: Prune (false branch) \n n$1=*&other:class A * [line 28]\n PRUNE((n$1 == 0), false); [line 28]\n REMOVE_TEMPS(n$1); [line 28]\n APPLY_ABSTRACTION; [line 28]\n " shape="invhouse"]
|
|
|
|
|
|
|
|
|
|
|
|
6 -> 4 ;
|
|
|
|
5 [label="5: Prune (true branch) \n n$1=*&other:class A * [line 28]\n PRUNE((n$1 != 0), true); [line 28]\n REMOVE_TEMPS(n$1); [line 28]\n " shape="invhouse"]
|
|
|
|
|
|
|
|
|
|
|
|
5 -> 9 ;
|
|
|
|
4 [label="4: + \n " ]
|
|
|
|
|
|
|
|
|
|
|
|
4 -> 3 ;
|
|
|
|
3 [label="3: Return Stmt \n NULLIFY(&self,false); [line 33]\n n$0=*&other:class A * [line 33]\n *&return:class A *=n$0 [line 33]\n REMOVE_TEMPS(n$0); [line 33]\n NULLIFY(&other,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"]
|
|
|
|
|
|
|
|
|
|
|
|
3 -> 2 ;
|
|
|
|
2 [label="2: Exit A_copy \n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
1 [label="1: Start A_copy\nFormals: self:class A *\nLocals: other:class A * \n DECLARE_LOCALS(&return,&other); [line 26]\n NULLIFY(&other,false); [line 26]\n " color=yellow style=filled]
|
|
|
|
|
|
|
|
|
|
|
|
1 -> 10 ;
|
|
|
|
}
|