xref: /aosp_15_r20/external/clang/test/Analysis/array-struct-region.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
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