• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-constraints=range -verify %s
2  
3  void clang_analyzer_eval(int);
4  
string_literal_init()5  int string_literal_init() {
6    char a[] = "abc";
7    char b[2] = "abc"; // expected-warning{{too long}}
8    char c[5] = "abc";
9  
10    clang_analyzer_eval(a[1] == 'b'); // expected-warning{{TRUE}}
11    clang_analyzer_eval(b[1] == 'b'); // expected-warning{{TRUE}}
12    clang_analyzer_eval(c[1] == 'b'); // expected-warning{{TRUE}}
13  
14    clang_analyzer_eval(a[3] == 0); // expected-warning{{TRUE}}
15    clang_analyzer_eval(c[3] == 0); // expected-warning{{TRUE}}
16  
17    clang_analyzer_eval(c[4] == 0); // expected-warning{{TRUE}}
18  
19    return 42;
20  }
21  
nested_compound_literals(int rad)22  void nested_compound_literals(int rad) {
23    int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},  // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}}
24                     {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}}
25    int a;
26  
27    for (a = 0; a < 6; ++a) {
28        vec[a][0] *= rad; // no-warning
29        vec[a][1] *= rad; // no-warning
30    }
31  }
32  
nested_compound_literals_float(float rad)33  void nested_compound_literals_float(float rad) {
34    float vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
35                       {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
36    int a;
37  
38    for (a = 0; a < 6; ++a) {
39        vec[a][0] *= rad; // no-warning
40        vec[a][1] *= rad; // no-warning
41    }
42  }
43  
44  
struct_as_array()45  void struct_as_array() {
46    struct simple { int x; int y; };
47    struct simple a;
48    struct simple *p = &a;
49  
50    p->x = 5;
51    clang_analyzer_eval(a.x == 5); // expected-warning{{TRUE}}
52    clang_analyzer_eval(p[0].x == 5); // expected-warning{{TRUE}}
53  
54    p[0].y = 5;
55    clang_analyzer_eval(a.y == 5); // expected-warning{{TRUE}}
56    clang_analyzer_eval(p->y == 5); // expected-warning{{TRUE}}
57  }
58  
59  
60  // PR13264 / <rdar://problem/11802440>
61  struct point { int x; int y; };
62  struct circle { struct point o; int r; };
get_circle()63  struct circle get_circle() {
64    struct circle result;
65    result.r = 5;
66    result.o = (struct point){0, 0};
67    return result;
68  }
69  
struct_in_struct()70  void struct_in_struct() {
71    struct circle c;
72    c = get_circle();
73    // This used to think c.r was undefined because c.o is a LazyCompoundVal.
74    clang_analyzer_eval(c.r == 5); // expected-warning{{TRUE}}
75  }
76  
77  // We also test with floats because we don't model floats right now,
78  // and the original bug report used a float.
79  struct circle_f { struct point o; float r; };
get_circle_f()80  struct circle_f get_circle_f() {
81    struct circle_f result;
82    result.r = 5.0;
83    result.o = (struct point){0, 0};
84    return result;
85  }
86  
struct_in_struct_f()87  float struct_in_struct_f() {
88    struct circle_f c;
89    c = get_circle_f();
90  
91    return c.r; // no-warning
92  }
93  
94  
95  int randomInt();
96  
testSymbolicInvalidation(int index)97  int testSymbolicInvalidation(int index) {
98    int vals[10];
99  
100    vals[0] = 42;
101    clang_analyzer_eval(vals[0] == 42); // expected-warning{{TRUE}}
102  
103    vals[index] = randomInt();
104    clang_analyzer_eval(vals[0] == 42); // expected-warning{{UNKNOWN}}
105  
106    return vals[index]; // no-warning
107  }
108  
testConcreteInvalidation(int index)109  int testConcreteInvalidation(int index) {
110    int vals[10];
111  
112    vals[index] = 42;
113    clang_analyzer_eval(vals[index] == 42); // expected-warning{{TRUE}}
114    vals[0] = randomInt();
115    clang_analyzer_eval(vals[index] == 42); // expected-warning{{UNKNOWN}}
116  
117    return vals[0]; // no-warning
118  }
119  
120  
121  typedef struct {
122    int x, y, z;
123  } S;
124  
125  S makeS();
126  
testSymbolicInvalidationStruct(int index)127  int testSymbolicInvalidationStruct(int index) {
128    S vals[10];
129  
130    vals[0].x = 42;
131    clang_analyzer_eval(vals[0].x == 42); // expected-warning{{TRUE}}
132  
133    vals[index] = makeS();
134    clang_analyzer_eval(vals[0].x == 42); // expected-warning{{UNKNOWN}}
135  
136    return vals[index].x; // no-warning
137  }
138  
testConcreteInvalidationStruct(int index)139  int testConcreteInvalidationStruct(int index) {
140    S vals[10];
141  
142    vals[index].x = 42;
143    clang_analyzer_eval(vals[index].x == 42); // expected-warning{{TRUE}}
144    vals[0] = makeS();
145    clang_analyzer_eval(vals[index].x == 42); // expected-warning{{UNKNOWN}}
146  
147    return vals[0].x; // no-warning
148  }
149  
150  typedef struct {
151    S a[5];
152    S b[5];
153  } SS;
154  
testSymbolicInvalidationDoubleStruct(int index)155  int testSymbolicInvalidationDoubleStruct(int index) {
156    SS vals;
157  
158    vals.a[0].x = 42;
159    vals.b[0].x = 42;
160    clang_analyzer_eval(vals.a[0].x == 42); // expected-warning{{TRUE}}
161    clang_analyzer_eval(vals.b[0].x == 42); // expected-warning{{TRUE}}
162  
163    vals.a[index] = makeS();
164    clang_analyzer_eval(vals.a[0].x == 42); // expected-warning{{UNKNOWN}}
165    clang_analyzer_eval(vals.b[0].x == 42); // expected-warning{{TRUE}}
166  
167    return vals.b[index].x; // no-warning
168  }
169  
testConcreteInvalidationDoubleStruct(int index)170  int testConcreteInvalidationDoubleStruct(int index) {
171    SS vals;
172  
173    vals.a[index].x = 42;
174    vals.b[index].x = 42;
175    clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{TRUE}}
176    clang_analyzer_eval(vals.b[index].x == 42); // expected-warning{{TRUE}}
177  
178    vals.a[0] = makeS();
179    clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
180    clang_analyzer_eval(vals.b[index].x == 42); // expected-warning{{TRUE}}
181  
182    return vals.b[0].x; // no-warning
183  }
184  
185  
testNonOverlappingStructFieldsSimple()186  int testNonOverlappingStructFieldsSimple() {
187    S val;
188  
189    val.x = 1;
190    val.y = 2;
191    clang_analyzer_eval(val.x == 1); // expected-warning{{TRUE}}
192    clang_analyzer_eval(val.y == 2); // expected-warning{{TRUE}}
193  
194    return val.z; // expected-warning{{garbage}}
195  }
196  
testNonOverlappingStructFieldsSymbolicBase(int index,int anotherIndex)197  int testNonOverlappingStructFieldsSymbolicBase(int index, int anotherIndex) {
198    SS vals;
199  
200    vals.a[index].x = 42;
201    vals.a[index].y = 42;
202    clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{TRUE}}
203    clang_analyzer_eval(vals.a[index].y == 42); // expected-warning{{TRUE}}
204  
205    vals.a[anotherIndex].x = 42;
206    clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
207    clang_analyzer_eval(vals.a[index].y == 42); // expected-warning{{TRUE}}
208  
209    // FIXME: False negative. No bind ever set a field 'z'.
210    return vals.a[index].z; // no-warning
211  }
212  
testStructFieldChains(int index,int anotherIndex)213  int testStructFieldChains(int index, int anotherIndex) {
214    SS vals[4];
215  
216    vals[index].a[0].x = 42;
217    vals[anotherIndex].a[1].y = 42;
218    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
219    clang_analyzer_eval(vals[anotherIndex].a[1].y == 42); // expected-warning{{TRUE}}
220  
221    // This doesn't affect anything in the 'a' array field.
222    vals[anotherIndex].b[1].x = 42;
223    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
224    clang_analyzer_eval(vals[anotherIndex].a[1].y == 42); // expected-warning{{TRUE}}
225    clang_analyzer_eval(vals[anotherIndex].b[1].x == 42); // expected-warning{{TRUE}}
226  
227    // This doesn't affect anything in the 'b' array field.
228    vals[index].a[anotherIndex].x = 42;
229    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}}
230    clang_analyzer_eval(vals[anotherIndex].a[0].x == 42); // expected-warning{{UNKNOWN}}
231    clang_analyzer_eval(vals[anotherIndex].a[1].y == 42); // expected-warning{{TRUE}}
232    clang_analyzer_eval(vals[anotherIndex].b[1].x == 42); // expected-warning{{TRUE}}
233  
234    // FIXME: False negative. No bind ever set a field 'z'.
235    return vals[index].a[0].z; // no-warning
236  }
237  
testStructFieldChainsNested(int index,int anotherIndex)238  int testStructFieldChainsNested(int index, int anotherIndex) {
239    SS vals[4];
240  
241    vals[index].a[0].x = 42;
242    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
243  
244    vals[index].b[0] = makeS();
245    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
246  
247    vals[index].a[0] = makeS();
248    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}}
249  
250    vals[index].a[0].x = 42;
251    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
252  
253    return 0;
254  }
255  
256  typedef struct {
257    int zoomLevel;
258    struct point center;
259  } Outer;
260  
261  extern int test13116945(struct point x);
radar13116945(struct point centerCoordinate)262  static void radar13116945(struct point centerCoordinate) {
263    Outer zoomRegion;
264    zoomRegion.zoomLevel = 0;
265    zoomRegion.center = centerCoordinate;
266    Outer r = zoomRegion;
267    test13116945(r.center); // no-warning
268  }
269  
270  
271  typedef struct {
272    char data[4];
273  } ShortString;
274  
275  typedef struct {
276    ShortString str;
277    int length;
278  } ShortStringWrapper;
279  
testArrayStructCopy()280  void testArrayStructCopy() {
281    ShortString s = { "abc" };
282    ShortString s2 = s;
283    ShortString s3 = s2;
284  
285    clang_analyzer_eval(s3.data[0] == 'a'); // expected-warning{{TRUE}}
286    clang_analyzer_eval(s3.data[1] == 'b'); // expected-warning{{TRUE}}
287    clang_analyzer_eval(s3.data[2] == 'c'); // expected-warning{{TRUE}}
288  
289    s3.data[0] = 'z';
290    ShortString s4 = s3;
291  
292    clang_analyzer_eval(s4.data[0] == 'z'); // expected-warning{{TRUE}}
293    clang_analyzer_eval(s4.data[1] == 'b'); // expected-warning{{TRUE}}
294    clang_analyzer_eval(s4.data[2] == 'c'); // expected-warning{{TRUE}}
295  }
296  
testArrayStructCopyNested()297  void testArrayStructCopyNested() {
298    ShortString s = { "abc" };
299    ShortString s2 = s;
300  
301    ShortStringWrapper w = { s2, 0 };
302  
303    clang_analyzer_eval(w.str.data[0] == 'a'); // expected-warning{{TRUE}}
304    clang_analyzer_eval(w.str.data[1] == 'b'); // expected-warning{{TRUE}}
305    clang_analyzer_eval(w.str.data[2] == 'c'); // expected-warning{{TRUE}}
306    clang_analyzer_eval(w.length == 0); // expected-warning{{TRUE}}
307  
308    ShortStringWrapper w2 = w;
309    clang_analyzer_eval(w2.str.data[0] == 'a'); // expected-warning{{TRUE}}
310    clang_analyzer_eval(w2.str.data[1] == 'b'); // expected-warning{{TRUE}}
311    clang_analyzer_eval(w2.str.data[2] == 'c'); // expected-warning{{TRUE}}
312    clang_analyzer_eval(w2.length == 0); // expected-warning{{TRUE}}
313  
314    ShortStringWrapper w3 = w2;
315    clang_analyzer_eval(w3.str.data[0] == 'a'); // expected-warning{{TRUE}}
316    clang_analyzer_eval(w3.str.data[1] == 'b'); // expected-warning{{TRUE}}
317    clang_analyzer_eval(w3.str.data[2] == 'c'); // expected-warning{{TRUE}}
318    clang_analyzer_eval(w3.length == 0); // expected-warning{{TRUE}}
319  }
320  
321  // --------------------
322  // False positives
323  // --------------------
324  
testMixSymbolicAndConcrete(int index,int anotherIndex)325  int testMixSymbolicAndConcrete(int index, int anotherIndex) {
326    SS vals;
327  
328    vals.a[index].x = 42;
329    vals.a[0].y = 42;
330  
331    // FIXME: Should be TRUE.
332    clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
333    // Should be TRUE; we set this explicitly.
334    clang_analyzer_eval(vals.a[0].y == 42); // expected-warning{{TRUE}}
335  
336    vals.a[anotherIndex].y = 42;
337  
338    // Should be UNKNOWN; we set an 'x'.
339    clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
340    // FIXME: Should be TRUE.
341    clang_analyzer_eval(vals.a[0].y == 42); // expected-warning{{UNKNOWN}}
342  
343    return vals.a[0].x; // no-warning
344  }
345  
testFieldChainIsNotEnough(int index)346  void testFieldChainIsNotEnough(int index) {
347    SS vals[4];
348  
349    vals[index].a[0].x = 42;
350    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
351  
352    vals[index].a[1] = makeS();
353    // FIXME: Should be TRUE.
354    clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}}
355  }
356