uninit-vals.m revision 4d25b51d582bc7a6a4d83be1642be2f4e812beef
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} Point;
47typedef struct {
48  Point origin;
49  int size;
50} Circle;
51
52Point makePoint(float x, float y) {
53  Point result;
54  result.x = x;
55  result.y = y;
56  return result;
57}
58
59void PR14765_test() {
60  Circle *testObj = calloc(sizeof(Circle), 1);
61
62  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
63
64  testObj->origin = makePoint(0.0, 0.0);
65  if (testObj->size > 0) { ; } // warning occurs here
66
67  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
68  // whole region, meaning that we've forgotten that testObj->size should also
69  // default to 0. Tracked by <rdar://problem/12701038>.
70  // This should be TRUE.
71  clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
72
73  free(testObj);
74}
75
76void PR14765_argument(Circle *testObj) {
77  int oldSize = testObj->size;
78  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
79
80  testObj->origin = makePoint(0.0, 0.0);
81  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
82}
83
84
85typedef struct {
86  int x;
87  int y;
88} IntPoint;
89typedef struct {
90  IntPoint origin;
91  int size;
92} IntCircle;
93
94IntPoint makeIntPoint(int x, int y) {
95  IntPoint result;
96  result.x = x;
97  result.y = y;
98  return result;
99}
100
101void PR14765_test_int() {
102  IntCircle *testObj = calloc(sizeof(IntCircle), 1);
103
104  clang_analyzer_eval(testObj->size == 0); // expected-warning{{TRUE}}
105  clang_analyzer_eval(testObj->origin.x == 0); // expected-warning{{TRUE}}
106  clang_analyzer_eval(testObj->origin.y == 0); // expected-warning{{TRUE}}
107
108  testObj->origin = makeIntPoint(1, 2);
109  if (testObj->size > 0) { ; } // warning occurs here
110
111  // FIXME: Assigning to 'testObj->origin' kills the default binding for the
112  // whole region, meaning that we've forgotten that testObj->size should also
113  // default to 0. Tracked by <rdar://problem/12701038>.
114  // This should be TRUE.
115  clang_analyzer_eval(testObj->size == 0); // expected-warning{{UNKNOWN}}
116  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
117  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
118
119  free(testObj);
120}
121
122void PR14765_argument_int(IntCircle *testObj) {
123  int oldSize = testObj->size;
124  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
125
126  testObj->origin = makeIntPoint(1, 2);
127  clang_analyzer_eval(testObj->size == oldSize); // expected-warning{{TRUE}}
128  clang_analyzer_eval(testObj->origin.x == 1); // expected-warning{{TRUE}}
129  clang_analyzer_eval(testObj->origin.y == 2); // expected-warning{{TRUE}}
130}
131
132
133void rdar13292559(Circle input) {
134  extern void useCircle(Circle);
135
136  Circle obj = input;
137  useCircle(obj); // no-warning
138
139  // This generated an "uninitialized 'size' field" warning for a (short) while.
140  obj.origin = makePoint(0.0, 0.0);
141  useCircle(obj); // no-warning
142}
143
144