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