Clang Project

clang_source_code/test/Analysis/uninit-vals.m
1// RUN: %clang_analyze_cc1 -analyzer-store=region -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-output=text -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
12struct s {
13  int data;
14};
15
16struct s global;
17
18void g(int);
19
20void f4() {
21  int a;
22  if (global.data == 0)
23    a = 3;
24  if (global.data == 0) // When the true branch is feasible 'a = 3'.
25    g(a); // no-warning
26}
27
28
29// Test uninitialized value due to part of the structure being uninitialized.
30struct TestUninit { int x; int y; };
31struct TestUninit test_uninit_aux();
32void test_unit_aux2(int);
33void test_uninit_pos() {
34  struct TestUninit v1 = { 0, 0 };
35  struct TestUninit v2 = test_uninit_aux();
36  int z; // expected-note{{'z' declared without an initial value}}
37  v1.y = z; // expected-warning{{Assigned value is garbage or undefined}}
38            // expected-note@-1{{Assigned value is garbage or undefined}}
39  test_unit_aux2(v2.x + v1.y);
40}
41void test_uninit_pos_2() {
42  struct TestUninit v1 = { 0, 0 };
43  struct TestUninit v2;
44  test_unit_aux2(v2.x + v1.y);  // expected-warning{{The left operand of '+' is a garbage value}}
45                                // expected-note@-1{{The left operand of '+' is a garbage value}}
46}
47void test_uninit_pos_3() {
48  struct TestUninit v1 = { 0, 0 };
49  struct TestUninit v2;
50  test_unit_aux2(v1.y + v2.x);  // expected-warning{{The right operand of '+' is a garbage value}}
51                                // expected-note@-1{{The right operand of '+' is a garbage value}}
52}
53
54void test_uninit_neg() {
55  struct TestUninit v1 = { 0, 0 };
56  struct TestUninit v2 = test_uninit_aux();
57  test_unit_aux2(v2.x + v1.y);
58}
59
60extern void test_uninit_struct_arg_aux(struct TestUninit arg);
61void test_uninit_struct_arg() {
62  struct TestUninit x; // expected-note{{'x' initialized here}}
63  test_uninit_struct_arg_aux(x); // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
64                                 // expected-note@-1{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
65}
66
67@interface Foo
68- (void) passVal:(struct TestUninit)arg;
69@end
70void testFoo(Foo *o) {
71  struct TestUninit x; // expected-note{{'x' initialized here}}
72  [o passVal:x]; // expected-warning{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
73                 // expected-note@-1{{Passed-by-value struct argument contains uninitialized data (e.g., field: 'x')}}
74}
75
76// Test case from <rdar://problem/7780304>.  That shows an uninitialized value
77// being used in the LHS of a compound assignment.
78void rdar_7780304() {
79  typedef struct s_r7780304 { int x; } s_r7780304;
80  s_r7780304 b;
81  b.x |= 1; // expected-warning{{The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage}}
82            // expected-note@-1{{The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage}}
83}
84
85
86// The flip side of PR10163 -- float arrays that are actually uninitialized
87void test_PR10163(float);
88void PR10163 (void) {
89  float x[2];
90  test_PR10163(x[1]); // expected-warning{{uninitialized value}}
91                      // expected-note@-1{{1st function call argument is an uninitialized value}}
92}
93
94// PR10163 -- don't warn for default-initialized float arrays.
95void PR10163_default_initialized_arrays(void) {
96  float x[2] = {0};
97  test_PR10163(x[1]); // no-warning  
98}
99
100struct MyStr {
101  int x;
102  int y;
103};
104void swap(struct MyStr *To, struct MyStr *From) {
105  // This is not really a swap but close enough for our test.
106  To->x = From->x;
107  To->y = From->y; // expected-note{{Uninitialized value stored to field 'y'}}
108}
109int test_undefined_member_assignment_in_swap(struct MyStr *s2) {
110  struct MyStr s1;
111  s1.x = 5;
112  swap(s2, &s1); // expected-note{{Calling 'swap'}}
113                 // expected-note@-1{{Returning from 'swap'}}
114  return s2->y; // expected-warning{{Undefined or garbage value returned to caller}}
115                // expected-note@-1{{Undefined or garbage value returned to caller}}
116}
117
118@interface A
119- (NSUInteger)foo;
120@end
121
122NSUInteger f8(A* x){
123  const NSUInteger n = [x foo];
124  int* bogus;  
125
126  if (n > 0) {    // tests const cast transfer function logic
127    NSUInteger i;
128    
129    for (i = 0; i < n; ++i)
130      bogus = 0;
131
132    if (bogus)  // no-warning
133      return n+1;
134  }
135  
136  return n;
137}
138
139
140
141
142typedef struct {
143  float x;
144  float y;
145  float z;
146} Point;
147typedef struct {
148  Point origin;
149  int size;
150} Circle;
151
152Point makePoint(float x, float y) {
153  Point result;
154  result.x = x;
155  result.y = y;
156  result.z = 0.0;
157  return result;
158}
159
160void PR14765_test() {
161  Circle *testObj = calloc(sizeof(Circle), 1);
162
163  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
164                                           // expected-note@-1{{TRUE}}
165
166  testObj->origin = makePoint(0.0, 0.0);
167  if (testObj->size > 0) { ; } // expected-note{{Assuming the condition is false}}
168                               // expected-note@-1{{Taking false branch}}
169
170  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
171  // whole region, meaning that we've forgotten that testObj->size should also
172  // default to 0. Tracked by <rdar://problem/12701038>.
173  // This should be TRUE.
174  clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
175                                           // expected-note@-1{{UNKNOWN}}
176
177  free(testObj);
178}
179
180void PR14765_argument(Circle *testObj) {
181  int oldSize = testObj->size;
182  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
183                                                 // expected-note@-1{{TRUE}}
184
185  testObj->origin = makePoint(0.0, 0.0);
186  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
187                                                 // expected-note@-1{{TRUE}}
188}
189
190
191typedef struct {
192  int x;
193  int y;
194  int z;
195} IntPoint;
196typedef struct {
197  IntPoint origin;
198  int size;
199} IntCircle;
200
201IntPoint makeIntPoint(int x, int y) {
202  IntPoint result;
203  result.x = x;
204  result.y = y;
205  result.z = 0;
206  return result;
207}
208
209void PR14765_test_int() {
210  IntCircle *testObj = calloc(sizeof(IntCircle), 1);
211
212  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
213                                           // expected-note@-1{{TRUE}}
214  clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
215                                               // expected-note@-1{{TRUE}}
216  clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
217                                               // expected-note@-1{{TRUE}}
218  clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
219                                               // expected-note@-1{{TRUE}}
220
221  testObj->origin = makeIntPoint(1, 2);
222  if (testObj->size > 0) { ; } // expected-note{{Assuming the condition is false}}
223                               // expected-note@-1{{Taking false branch}}
224                               // expected-note@-2{{Assuming the condition is false}}
225                               // expected-note@-3{{Taking false branch}}
226                               // expected-note@-4{{Assuming the condition is false}}
227                               // expected-note@-5{{Taking false branch}}
228                               // expected-note@-6{{Assuming the condition is false}}
229                               // expected-note@-7{{Taking false branch}}
230
231  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
232  // whole region, meaning that we've forgotten that testObj->size should also
233  // default to 0. Tracked by <rdar://problem/12701038>.
234  // This should be TRUE.
235  clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
236                                           // expected-note@-1{{UNKNOWN}}
237  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
238                                               // expected-note@-1{{TRUE}}
239  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
240                                               // expected-note@-1{{TRUE}}
241  clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
242                                               // expected-note@-1{{TRUE}}
243
244  free(testObj);
245}
246
247void PR14765_argument_int(IntCircle *testObj) {
248  int oldSize = testObj->size;
249  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
250                                                 // expected-note@-1{{TRUE}}
251
252  testObj->origin = makeIntPoint(1, 2);
253  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
254                                                 // expected-note@-1{{TRUE}}
255  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
256                                               // expected-note@-1{{TRUE}}
257  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
258                                               // expected-note@-1{{TRUE}}
259  clang_analyzer_eval(testObj->origin.z == 0); // expected-warning{{TRUE}}
260                                               // expected-note@-1{{TRUE}}
261}
262
263
264void rdar13292559(Circle input) {
265  extern void useCircle(Circle);
266
267  Circle obj = input;
268  useCircle(obj); // no-warning
269
270  // This generated an "uninitialized 'size' field" warning for a (short) while.
271  obj.origin = makePoint(0.0, 0.0);
272  useCircle(obj); // no-warning
273}
274
275
276typedef struct {
277  int x;
278  int y;
279} IntPoint2D;
280typedef struct {
281  IntPoint2D origin;
282  int size;
283} IntCircle2D;
284
285IntPoint2D makeIntPoint2D(int x, int y) {
286  IntPoint2D result;
287  result.x = x;
288  result.y = y;
289  return result;
290}
291
292void testSmallStructsCopiedPerField() {
293  IntPoint2D a;
294  a.x = 0;
295
296  IntPoint2D b = a;
297  extern void useInt(int);
298  useInt(b.x); // no-warning
299  useInt(b.y); // expected-warning{{uninitialized}}
300               // expected-note@-1{{uninitialized}}
301}
302
303void testLargeStructsNotCopiedPerField() {
304  IntPoint a;
305  a.x = 0;
306
307  IntPoint b = a;
308  extern void useInt(int);
309  useInt(b.x); // no-warning
310  useInt(b.y); // no-warning
311}
312
313void testSmallStructInLargerStruct() {
314  IntCircle2D *testObj = calloc(sizeof(IntCircle2D), 1);
315
316  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
317                                           // expected-note@-1{{TRUE}}
318  clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
319                                               // expected-note@-1{{TRUE}}
320  clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
321                                               // expected-note@-1{{TRUE}}
322
323  testObj->origin = makeIntPoint2D(1, 2);
324  if (testObj->size > 0) { ; } // expected-note{{Taking false branch}}
325                               // expected-note@-1{{Taking false branch}}
326                               // expected-note@-2{{Taking false branch}}
327
328  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
329                                           // expected-note@-1{{TRUE}}
330  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
331                                               // expected-note@-1{{TRUE}}
332  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
333                                               // expected-note@-1{{TRUE}}
334
335  free(testObj);
336}
337
338void testCopySmallStructIntoArgument(IntCircle2D *testObj) {
339  int oldSize = testObj->size;
340  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
341                                                 // expected-note@-1{{TRUE}}
342
343  testObj->origin = makeIntPoint2D(1, 2);
344  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
345                                                 // expected-note@-1{{TRUE}}
346  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
347                                               // expected-note@-1{{TRUE}}
348  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
349                                               // expected-note@-1{{TRUE}}
350}
351
352void testSmallStructBitfields() {
353  struct {
354    int x : 4;
355    int y : 4;
356  } a, b;
357
358  a.x = 1;
359  a.y = 2;
360
361  b = a;
362  clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
363                                 // expected-note@-1{{TRUE}}
364  clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
365                                 // expected-note@-1{{TRUE}}
366}
367
368void testSmallStructBitfieldsFirstUndef() {
369  struct {
370    int x : 4;
371    int y : 4;
372  } a, b;
373
374  a.y = 2;
375
376  b = a;
377  clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
378                                 // expected-note@-1{{TRUE}}
379  clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}
380                                 // expected-note@-1{{garbage}}
381}
382
383void testSmallStructBitfieldsSecondUndef() {
384  struct {
385    int x : 4;
386    int y : 4;
387  } a, b;
388
389  a.x = 1;
390
391  b = a;
392  clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
393                                 // expected-note@-1{{TRUE}}
394  clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}
395                                 // expected-note@-1{{garbage}}
396}
397
398void testSmallStructBitfieldsFirstUnnamed() {
399  struct {
400    int : 4;
401    int y : 4;
402  } a, b, c; // expected-note{{'c' initialized here}}
403
404  a.y = 2;
405
406  b = a;
407  clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}}
408                                 // expected-note@-1{{TRUE}}
409
410  b = c; // expected-note{{Uninitialized value stored to 'b.y'}}
411  clang_analyzer_eval(b.y == 2); // expected-warning{{garbage}}
412                                 // expected-note@-1{{garbage}}
413}
414
415void testSmallStructBitfieldsSecondUnnamed() {
416  struct {
417    int x : 4;
418    int : 4;
419  } a, b, c; // expected-note{{'c' initialized here}}
420
421  a.x = 1;
422
423  b = a;
424  clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}}
425                                 // expected-note@-1{{TRUE}}
426
427  b = c; // expected-note{{Uninitialized value stored to 'b.x'}}
428  clang_analyzer_eval(b.x == 1); // expected-warning{{garbage}}
429                                 // expected-note@-1{{garbage}}
430}
431