1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -fblocks -verify -Wno-objc-root-class %s
2
3void clang_analyzer_eval(int);
4
5@interface Root {
6@public
7  int uniqueID;
8}
9
10- (void)refreshID;
11@end
12
13void 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
43struct 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
135int 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