1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -fblocks -verify -Wno-objc-root-class -analyzer-config eagerly-assume=false %s |
2 | |
3 | void clang_analyzer_eval(int); |
4 | |
5 | @interface Root { |
6 | @public |
7 | int uniqueID; |
8 | } |
9 | |
10 | - (void)refreshID; |
11 | @end |
12 | |
13 | void testInvalidation(Root *obj) { |
14 | int savedID = obj->uniqueID; |
15 | clang_analyzer_eval(savedID == obj->uniqueID); // expected-warning{{TRUE}} |
16 | |
17 | [obj refreshID]; |
18 | clang_analyzer_eval(savedID == obj->uniqueID); // expected-warning{{UNKNOWN}} |
19 | } |
20 | |
21 | |
22 | @interface Child : Root |
23 | @end |
24 | |
25 | @implementation Child |
26 | - (void)testSuperInvalidation { |
27 | int savedID = self->uniqueID; |
28 | clang_analyzer_eval(savedID == self->uniqueID); // expected-warning{{TRUE}} |
29 | |
30 | [super refreshID]; |
31 | clang_analyzer_eval(savedID == self->uniqueID); // expected-warning{{UNKNOWN}} |
32 | } |
33 | @end |
34 | |
35 | |
36 | @interface ManyIvars { |
37 | struct S { int a, b; } s; |
38 | int c; |
39 | int d; |
40 | } |
41 | @end |
42 | |
43 | struct S makeS(); |
44 | |
45 | @implementation ManyIvars |
46 | |
47 | - (void)testMultipleIvarInvalidation:(int)useConstraints { |
48 | if (useConstraints) { |
49 | if (s.a != 1) return; |
50 | if (s.b != 2) return; |
51 | if (c != 3) return; |
52 | if (d != 4) return; |
53 | return; |
54 | } else { |
55 | s.a = 1; |
56 | s.b = 2; |
57 | c = 3; |
58 | d = 4; |
59 | } |
60 | |
61 | clang_analyzer_eval(s.a == 1); // expected-warning{{TRUE}} |
62 | clang_analyzer_eval(s.b == 2); // expected-warning{{TRUE}} |
63 | clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} |
64 | clang_analyzer_eval(d == 4); // expected-warning{{TRUE}} |
65 | |
66 | d = 0; |
67 | |
68 | clang_analyzer_eval(s.a == 1); // expected-warning{{TRUE}} |
69 | clang_analyzer_eval(s.b == 2); // expected-warning{{TRUE}} |
70 | clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} |
71 | clang_analyzer_eval(d == 0); // expected-warning{{TRUE}} |
72 | |
73 | d = 4; |
74 | s = makeS(); |
75 | |
76 | clang_analyzer_eval(s.a == 1); // expected-warning{{UNKNOWN}} |
77 | clang_analyzer_eval(s.b == 2); // expected-warning{{UNKNOWN}} |
78 | clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} |
79 | clang_analyzer_eval(d == 4); // expected-warning{{TRUE}} |
80 | |
81 | s.a = 1; |
82 | |
83 | clang_analyzer_eval(s.a == 1); // expected-warning{{TRUE}} |
84 | clang_analyzer_eval(s.b == 2); // expected-warning{{UNKNOWN}} |
85 | clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} |
86 | clang_analyzer_eval(d == 4); // expected-warning{{TRUE}} |
87 | } |
88 | |
89 | + (void)testMultipleIvarInvalidation:(int)useConstraints |
90 | forObject:(ManyIvars *)obj { |
91 | if (useConstraints) { |
92 | if (obj->s.a != 1) return; |
93 | if (obj->s.b != 2) return; |
94 | if (obj->c != 3) return; |
95 | if (obj->d != 4) return; |
96 | return; |
97 | } else { |
98 | obj->s.a = 1; |
99 | obj->s.b = 2; |
100 | obj->c = 3; |
101 | obj->d = 4; |
102 | } |
103 | |
104 | clang_analyzer_eval(obj->s.a == 1); // expected-warning{{TRUE}} |
105 | clang_analyzer_eval(obj->s.b == 2); // expected-warning{{TRUE}} |
106 | clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}} |
107 | clang_analyzer_eval(obj->d == 4); // expected-warning{{TRUE}} |
108 | |
109 | obj->d = 0; |
110 | |
111 | clang_analyzer_eval(obj->s.a == 1); // expected-warning{{TRUE}} |
112 | clang_analyzer_eval(obj->s.b == 2); // expected-warning{{TRUE}} |
113 | clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}} |
114 | clang_analyzer_eval(obj->d == 0); // expected-warning{{TRUE}} |
115 | |
116 | obj->d = 4; |
117 | obj->s = makeS(); |
118 | |
119 | clang_analyzer_eval(obj->s.a == 1); // expected-warning{{UNKNOWN}} |
120 | clang_analyzer_eval(obj->s.b == 2); // expected-warning{{UNKNOWN}} |
121 | clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}} |
122 | clang_analyzer_eval(obj->d == 4); // expected-warning{{TRUE}} |
123 | |
124 | obj->s.a = 1; |
125 | |
126 | clang_analyzer_eval(obj->s.a == 1); // expected-warning{{TRUE}} |
127 | clang_analyzer_eval(obj->s.b == 2); // expected-warning{{UNKNOWN}} |
128 | clang_analyzer_eval(obj->c == 3); // expected-warning{{TRUE}} |
129 | clang_analyzer_eval(obj->d == 4); // expected-warning{{TRUE}} |
130 | } |
131 | |
132 | @end |
133 | |
134 | |
135 | int testNull(Root *obj) { |
136 | if (obj) return 0; |
137 | |
138 | int *x = &obj->uniqueID; |
139 | return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} |
140 | } |
141 | |