1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -verify %s
2
3typedef unsigned int NSUInteger;
4typedef __typeof__(sizeof(int)) size_t;
5
6void *malloc(size_t);
7void *calloc(size_t nmemb, size_t size);
8void free(void *);
9
10void clang_analyzer_eval(int);
11
12@interface A
13- (NSUInteger)foo;
14@end
15
16NSUInteger f8(A* x){
17  const NSUInteger n = [x foo];
18  int* bogus;  
19
20  if (n > 0) {    // tests const cast transfer function logic
21    NSUInteger i;
22    
23    for (i = 0; i < n; ++i)
24      bogus = 0;
25
26    if (bogus)  // no-warning
27      return n+1;
28  }
29  
30  return n;
31}
32
33
34// PR10163 -- don't warn for default-initialized float arrays.
35// (An additional test is in uninit-vals-ps-region.m)
36void test_PR10163(float);
37void PR10163 (void) {
38  float x[2] = {0};
39  test_PR10163(x[1]); // no-warning  
40}
41
42
43typedef struct {
44  float x;
45  float y;
46  float z;
47} Point;
48typedef struct {
49  Point origin;
50  int size;
51} Circle;
52
53Point makePoint(float x, float y) {
54  Point result;
55  result.x = x;
56  result.y = y;
57  result.z = 0.0;
58  return result;
59}
60
61void PR14765_test() {
62  Circle *testObj = calloc(sizeof(Circle), 1);
63
64  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
65
66  testObj->origin = makePoint(0.0, 0.0);
67  if (testObj->size > 0) { ; } // warning occurs here
68
69  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
70  // whole region, meaning that we've forgotten that testObj->size should also
71  // default to 0. Tracked by <rdar://problem/12701038>.
72  // This should be TRUE.
73  clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
74
75  free(testObj);
76}
77
78void PR14765_argument(Circle *testObj) {
79  int oldSize = testObj->size;
80  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
81
82  testObj->origin = makePoint(0.0, 0.0);
83  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
84}
85
86
87typedef struct {
88  int x;
89  int y;
90  int z;
91} IntPoint;
92typedef struct {
93  IntPoint origin;
94  int size;
95} IntCircle;
96
97IntPoint makeIntPoint(int x, int y) {
98  IntPoint result;
99  result.x = x;
100  result.y = y;
101  result.z = 0;
102  return result;
103}
104
105void PR14765_test_int() {
106  IntCircle *testObj = calloc(sizeof(IntCircle), 1);
107
108  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
109  clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
110  clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
111  clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
112
113  testObj->origin = makeIntPoint(1, 2);
114  if (testObj->size > 0) { ; } // warning occurs here
115
116  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
117  // whole region, meaning that we've forgotten that testObj->size should also
118  // default to 0. Tracked by <rdar://problem/12701038>.
119  // This should be TRUE.
120  clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
121  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
122  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
123  clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
124
125  free(testObj);
126}
127
128void PR14765_argument_int(IntCircle *testObj) {
129  int oldSize = testObj->size;
130  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
131
132  testObj->origin = makeIntPoint(1, 2);
133  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
134  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
135  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
136  clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
137}
138
139
140void rdar13292559(Circle input) {
141  extern void useCircle(Circle);
142
143  Circle obj = input;
144  useCircle(obj); // no-warning
145
146  // This generated an "uninitialized 'size' field" warning for a (short) while.
147  obj.origin = makePoint(0.0, 0.0);
148  useCircle(obj); // no-warning
149}
150
151
152typedef struct {
153  int x;
154  int y;
155} IntPoint2D;
156typedef struct {
157  IntPoint2D origin;
158  int size;
159} IntCircle2D;
160
161IntPoint2D makeIntPoint2D(int x, int y) {
162  IntPoint2D result;
163  result.x = x;
164  result.y = y;
165  return result;
166}
167
168void testSmallStructsCopiedPerField() {
169  IntPoint2D a;
170  a.x = 0;
171
172  IntPoint2D b = a;
173  extern void useInt(int);
174  useInt(b.x); // no-warning
175  useInt(b.y); // expected-warning{{uninitialized}}
176}
177
178void testLargeStructsNotCopiedPerField() {
179  IntPoint a;
180  a.x = 0;
181
182  IntPoint b = a;
183  extern void useInt(int);
184  useInt(b.x); // no-warning
185  useInt(b.y); // no-warning
186}
187
188void testSmallStructInLargerStruct() {
189  IntCircle2D *testObj = calloc(sizeof(IntCircle2D), 1);
190
191  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
192  clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
193  clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
194
195  testObj->origin = makeIntPoint2D(1, 2);
196  if (testObj->size > 0) { ; } // warning occurs here
197
198  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
199  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
200  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
201
202  free(testObj);
203}
204
205void testCopySmallStructIntoArgument(IntCircle2D *testObj) {
206  int oldSize = testObj->size;
207  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
208
209  testObj->origin = makeIntPoint2D(1, 2);
210  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
211  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
212  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
213}
214
215void testSmallStructBitfields() {
216  struct {
217    int x : 4;
218    int y : 4;
219  } a, b;
220
221  a.x = 1;
222  a.y = 2;
223
224  b = a;
225  clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
226  clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
227}
228
229void testSmallStructBitfieldsFirstUndef() {
230  struct {
231    int x : 4;
232    int y : 4;
233  } a, b;
234
235  a.y = 2;
236
237  b = a;
238  clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
239  clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}
240}
241
242void testSmallStructBitfieldsSecondUndef() {
243  struct {
244    int x : 4;
245    int y : 4;
246  } a, b;
247
248  a.x = 1;
249
250  b = a;
251  clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
252  clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}
253}
254
255void testSmallStructBitfieldsFirstUnnamed() {
256  struct {
257    int : 4;
258    int y : 4;
259  } a, b, c;
260
261  a.y = 2;
262
263  b = a;
264  clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
265
266  b = c;
267  clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}
268}
269
270void testSmallStructBitfieldsSecondUnnamed() {
271  struct {
272    int x : 4;
273    int : 4;
274  } a, b, c;
275
276  a.x = 1;
277
278  b = a;
279  clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
280
281  b = c;
282  clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}
283}
284
285