xref: /llvm-project/clang/test/Analysis/dead-stores.c (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
1 // RUN: %check_analyzer_fixit %s %t \
2 // RUN:   -Wunused-variable -fblocks -Wno-unreachable-code \
3 // RUN:   -analyzer-checker=core,deadcode.DeadStores \
4 // RUN:   -analyzer-config deadcode.DeadStores:ShowFixIts=true \
5 // RUN:   -analyzer-config \
6 // RUN:       deadcode.DeadStores:WarnForDeadNestedAssignments=false \
7 // RUN:   -verify=non-nested
8 
9 // RUN: %check_analyzer_fixit %s %t \
10 // RUN:   -Wunused-variable -fblocks -Wno-unreachable-code \
11 // RUN:   -analyzer-checker=core,deadcode.DeadStores \
12 // RUN:   -analyzer-config deadcode.DeadStores:ShowFixIts=true \
13 // RUN:   -verify=non-nested,nested
14 
15 extern int printf(const char *, ...);
16 
f1(void)17 void f1(void) {
18   int k, y; // non-nested-warning {{unused variable 'k'}}
19             // non-nested-warning@-1 {{unused variable 'y'}}
20   int abc = 1;
21   long idx = abc + 3 * 5; // non-nested-warning {{never read}}
22                           // non-nested-warning@-1 {{unused variable 'idx'}}
23   // CHECK-FIXES:      int abc = 1;
24   // CHECK-FIXES-NEXT: long idx;
25 }
26 
f2(void * b)27 void f2(void *b) {
28   char *c = (char *)b; // no-warning
29   char *d = b + 1;     // non-nested-warning {{never read}}
30                        // non-nested-warning@-1 {{unused variable 'd'}}
31   // CHECK-FIXES:      char *c = (char *)b;
32   // CHECK-FIXES-NEXT: char *d;
33 
34   printf("%s", c);
35 }
36 
37 int f(void);
f3(void)38 void f3(void) {
39   int r;
40   if ((r = f()) != 0) { // no-warning
41     int y = r;          // no-warning
42     printf("the error is: %d\n", y);
43   }
44 }
45 
f4(int k)46 void f4(int k) {
47   k = 1;
48   if (k)
49     f1();
50   k = 2; // non-nested-warning {{never read}}
51 }
52 
f5(void)53 void f5(void) {
54   int x = 4;   // no-warning
55   int *p = &x; // non-nested-warning {{never read}}
56                // non-nested-warning@-1 {{unused variable 'p'}}
57   // CHECK-FIXES:      int x = 4;
58   // CHECK-FIXES-NEXT: int *p;
59 }
60 
f6(void)61 int f6(void) {
62   int x = 4;
63   ++x; // no-warning
64   return 1;
65 }
66 
f7(int * p)67 int f7(int *p) {
68   // This is allowed for defensive programming.
69   p = 0; // no-warning
70   return 1;
71 }
72 
f7b(int * p)73 int f7b(int *p) {
74   // This is allowed for defensive programming.
75   p = (0); // no-warning
76   return 1;
77 }
78 
f7c(int * p)79 int f7c(int *p) {
80   // This is allowed for defensive programming.
81   p = (void *)0; // no-warning
82   return 1;
83 }
84 
f7d(int * p)85 int f7d(int *p) {
86   // This is allowed for defensive programming.
87   p = (void *)(0); // no-warning
88   return 1;
89 }
90 
91 // Warn for dead stores in nested expressions.
f8(int * p)92 int f8(int *p) {
93   extern int *baz(void);
94   if ((p = baz())) // nested-warning {{Although the value stored}}
95     return 1;
96   return 0;
97 }
98 
f9(void)99 int f9(void) {
100   int x = 4;
101   x = x + 10; // non-nested-warning {{never read}}
102   return 1;
103 }
104 
f10(void)105 int f10(void) {
106   int x = 4;
107   x = 10 + x; // non-nested-warning {{never read}}
108   return 1;
109 }
110 
f11(void)111 int f11(void) {
112   int x = 4;
113   return x++; // non-nested-warning {{never read}}
114 }
115 
f11b(void)116 int f11b(void) {
117   int x = 4;
118   return ((((++x)))); // no-warning
119 }
120 
f12a(int y)121 int f12a(int y) {
122   int x = y; // non-nested-warning {{unused variable 'x'}}
123   return 1;
124 }
125 
f12b(int y)126 int f12b(int y) {
127   int x __attribute__((unused)) = y; // no-warning
128   return 1;
129 }
130 
f12c(int y)131 int f12c(int y) {
132   // Allow initialiation of scalar variables by parameters as a form of
133   // defensive programming.
134   int x = y; // no-warning
135   x = 1;
136   return x;
137 }
138 
139 // Filed with PR 2630.  This code should produce no warnings.
f13(void)140 int f13(void) {
141   int a = 1;
142   int b, c = b = a + a;
143 
144   if (b > 0)
145     return (0);
146   return (a + b + c);
147 }
148 
149 // Filed with PR 2763.
f14(int count)150 int f14(int count) {
151   int index, nextLineIndex;
152   for (index = 0; index < count; index = nextLineIndex + 1) {
153     nextLineIndex = index + 1; // no-warning
154     continue;
155   }
156   return index;
157 }
158 
f15(unsigned x,unsigned y)159 void f15(unsigned x, unsigned y) {
160   int count = x * y; // no-warning
161   int z[count];      // non-nested-warning {{unused variable 'z'}}
162 }
163 
164 // Warn for dead stores in nested expressions.
f16(int x)165 int f16(int x) {
166   x = x * 2;
167   x = sizeof(int[x = (x || x + 1) * 2]) ? 5 : 8;
168   // nested-warning@-1 {{Although the value stored}}
169   return x;
170 }
171 
172 // Self-assignments should not be flagged as dead stores.
f17(void)173 void f17(void) {
174   int x = 1;
175   x = x;
176 }
177 
178 // The values of dead stores are only "consumed" in an enclosing expression
179 // what that value is actually used.  In other words, don't say "Although the
180 // value stored to 'x' is used...".
f18(void)181 int f18(void) {
182   int x = 0; // no-warning
183   if (1)
184     x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
185   while (1)
186     x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
187   // unreachable.
188   do
189     x = 10; // no-warning
190   while (1);
191   return (x = 10); // no-warning
192 }
193 
f18_a(void)194 int f18_a(void) {
195   int x = 0;       // no-warning
196   return (x = 10); // nested-warning {{Although the value stored}}
197 }
198 
f18_b(void)199 void f18_b(void) {
200   int x = 0; // no-warning
201   if (1)
202     x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
203 }
204 
f18_c(void)205 void f18_c(void) {
206   int x = 0;
207   while (1)
208     x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
209 }
210 
f18_d(void)211 void f18_d(void) {
212   int x = 0; // no-warning
213   do
214     x = 10; // non-nested-warning {{Value stored to 'x' is never read}}
215   while (1);
216 }
217 
218 // PR 3514: false positive `dead initialization` warning for init to global
219 //  http://llvm.org/bugs/show_bug.cgi?id=3514
220 extern const int MyConstant;
f19(void)221 int f19(void) {
222   int x = MyConstant; // no-warning
223   x = 1;
224   return x;
225 }
226 
f19b(void)227 int f19b(void) { // This case is the same as f19.
228   const int MyConstant = 0;
229   int x = MyConstant; // no-warning
230   x = 1;
231   return x;
232 }
233 
f20(void)234 void f20(void) {
235   int x = 1; // no-warning
236 #pragma unused(x)
237 }
238 
239 void halt(void) __attribute__((noreturn));
f21(void)240 int f21(void) {
241   int x = 4;
242   x = x + 1; // non-nested-warning {{never read}}
243   if (1) {
244     halt();
245     (void)x;
246   }
247   return 1;
248 }
249 
250 int j;
f22(void)251 void f22(void) {
252   int x = 4;
253   int y1 = 4;
254   int y2 = 4;
255   int y3 = 4;
256   int y4 = 4;
257   int y5 = 4;
258   int y6 = 4;
259   int y7 = 4;
260   int y8 = 4;
261   int y9 = 4;
262   int y10 = 4;
263   int y11 = 4;
264   int y12 = 4;
265   int y13 = 4;
266   int y14 = 4;
267   int y15 = 4;
268   int y16 = 4;
269   int y17 = 4;
270   int y18 = 4;
271   int y19 = 4;
272   int y20 = 4;
273 
274   x = x + 1; // non-nested-warning {{never read}}
275   ++y1;
276   ++y2;
277   ++y3;
278   ++y4;
279   ++y5;
280   ++y6;
281   ++y7;
282   ++y8;
283   ++y9;
284   ++y10;
285   ++y11;
286   ++y12;
287   ++y13;
288   ++y14;
289   ++y15;
290   ++y16;
291   ++y17;
292   ++y18;
293   ++y19;
294   ++y20;
295 
296   switch (j) {
297   case 1:
298     if (0)
299       (void)x;
300     if (1) {
301       (void)y1;
302       return;
303     }
304     (void)x;
305     break;
306   case 2:
307     if (0)
308       (void)x;
309     else {
310       (void)y2;
311       return;
312     }
313     (void)x;
314     break;
315   case 3:
316     if (1) {
317       (void)y3;
318       return;
319     } else
320       (void)x;
321     (void)x;
322     break;
323   case 4:
324     0 ?: ((void)y4, ({ return; }));
325     (void)x;
326     break;
327   case 5:
328     1 ?: (void)x;
329     0 ? (void)x : ((void)y5, ({ return; }));
330     (void)x;
331     break;
332   case 6:
333     1 ? ((void)y6, ({ return; })) : (void)x;
334     (void)x;
335     break;
336   case 7:
337     (void)(0 && x);
338     (void)y7;
339     (void)(0 || (y8, ({ return; }), 1));
340     // non-nested-warning@-1 {{left operand of comma operator has no effect}}
341     (void)x;
342     break;
343   case 8:
344     (void)(1 && (y9, ({ return; }), 1));
345     // non-nested-warning@-1 {{left operand of comma operator has no effect}}
346     (void)x;
347     break;
348   case 9:
349     (void)(1 || x);
350     (void)y10;
351     break;
352   case 10:
353     while (0) {
354       (void)x;
355     }
356     (void)y11;
357     break;
358   case 11:
359     while (1) {
360       (void)y12;
361     }
362     (void)x;
363     break;
364   case 12:
365     do {
366       (void)y13;
367     } while (0);
368     (void)y14;
369     break;
370   case 13:
371     do {
372       (void)y15;
373     } while (1);
374     (void)x;
375     break;
376   case 14:
377     for (;;) {
378       (void)y16;
379     }
380     (void)x;
381     break;
382   case 15:
383     for (; 1;) {
384       (void)y17;
385     }
386     (void)x;
387     break;
388   case 16:
389     for (; 0;) {
390       (void)x;
391     }
392     (void)y18;
393     break;
394   case 17:
395     __builtin_choose_expr(0, (void)x, ((void)y19, ({ return; })));
396     (void)x;
397     break;
398   case 19:
399     __builtin_choose_expr(1, ((void)y20, ({ return; })), (void)x);
400     (void)x;
401     break;
402   }
403 }
404 
405 void f23_aux(const char *s);
f23(int argc,char ** argv)406 void f23(int argc, char **argv) {
407   int shouldLog = (argc > 1); // no-warning
408   ^{
409     if (shouldLog)
410       f23_aux("I did too use it!\n");
411     else
412       f23_aux("I shouldn't log.  Wait.. d'oh!\n");
413   }();
414 }
415 
f23_pos(int argc,char ** argv)416 void f23_pos(int argc, char **argv) {
417   int shouldLog = (argc > 1);
418   // non-nested-warning@-1 {{Value stored to 'shouldLog' during its initialization is never read}}
419   // non-nested-warning@-2 {{unused variable 'shouldLog'}}
420   // CHECK-FIXES:      void f23_pos(int argc, char **argv) {
421   // CHECK-FIXES-NEXT:   int shouldLog;
422   ^{
423     f23_aux("I did too use it!\n");
424   }();
425 }
426 
f24_A(int y)427 void f24_A(int y) {
428   // FIXME: One day this should be reported as dead since 'z = x + y' is dead.
429   int x = (y > 2); // no-warning
430   ^{
431     int z = x + y;
432     // non-nested-warning@-1 {{Value stored to 'z' during its initialization is never read}}
433     // non-nested-warning@-2 {{unused variable 'z'}}
434     // CHECK-FIXES:      void f24_A(int y) {
435     // CHECK-FIXES-NEXT:   //
436     // CHECK-FIXES-NEXT:   int x = (y > 2);
437     // CHECK-FIXES-NEXT:   ^{
438     // CHECK-FIXES-NEXT:     int z;
439   }();
440 }
441 
f24_B(int y)442 void f24_B(int y) {
443   // FIXME: One day this should be reported as dead since 'x' is just overwritten.
444   __block int x = (y > 2); // no-warning
445   ^{
446     // FIXME: This should eventually be a dead store since it is never read either.
447     x = 5; // no-warning
448   }();
449 }
450 
f24_C(int y)451 int f24_C(int y) {
452   // FIXME: One day this should be reported as dead since 'x' is just overwritten.
453   __block int x = (y > 2); // no-warning
454   ^{
455     x = 5; // no-warning
456   }();
457   return x;
458 }
459 
f24_D(int y)460 int f24_D(int y) {
461   __block int x = (y > 2); // no-warning
462   ^{
463     if (y > 4)
464       x = 5; // no-warning
465   }();
466   return x;
467 }
468 
469 // This example shows that writing to a variable captured by a block means that
470 // it might not be dead.
f25(int y)471 int f25(int y) {
472   __block int x = (y > 2);
473   __block int z = 0;
474   void (^foo)(void) = ^{
475     z = x + y;
476   };
477   x = 4; // no-warning
478   foo();
479   return z;
480 }
481 
482 // This test is mostly the same as 'f25', but shows that the heuristic of
483 // pruning out dead stores for variables that are just marked '__block' is
484 // overly conservative.
f25_b(int y)485 int f25_b(int y) {
486   // FIXME: we should eventually report a dead store here.
487   __block int x = (y > 2);
488   __block int z = 0;
489   x = 4; // no-warning
490   return z;
491 }
492 
f26_nestedblocks(void)493 int f26_nestedblocks(void) {
494   int z;
495   z = 1;
496   __block int y = 0;
497   ^{
498     int k;
499     k = 1; // non-nested-warning {{Value stored to 'k' is never read}}
500     ^{
501       y = z + 1;
502     }();
503   }();
504   return y;
505 }
506 
507 // The FOREACH macro in QT uses 'break' statements within statement expressions
508 // placed within the increment code of for loops.
rdar8014335(void)509 void rdar8014335(void) {
510   for (int i = 0 ; i != 10 ; ({ break; })) {
511     for (;; ({ ++i; break; }))
512       ;
513     // non-nested-warning@-2 {{'break' is bound to current loop, GCC binds it to the enclosing loop}}
514     // Note that the next value stored to 'i' is never executed
515     // because the next statement to be executed is the 'break'
516     // in the increment code of the first loop.
517     i = i * 3; // non-nested-warning {{Value stored to 'i' is never read}}
518   }
519 }
520 
521 // NullStmts followed by do...while() can lead to disconnected CFG
522 //
523 // This previously caused bogus dead-stores warnings because the body of the first do...while was
524 // disconnected from the entry of the function.
525 typedef struct { float r; float i; } s_rdar8320674;
526 typedef struct { s_rdar8320674 x[1]; } s2_rdar8320674;
527 
rdar8320674(s_rdar8320674 * z,unsigned y,s2_rdar8320674 * st,int m)528 void rdar8320674(s_rdar8320674 *z, unsigned y, s2_rdar8320674 *st, int m)
529 {
530     s_rdar8320674 * z2;
531     s_rdar8320674 * tw1 = st->x;
532     s_rdar8320674 t;
533     z2 = z + m;
534     do{
535         ; ;
536         do{ (t).r = (*z2).r*(*tw1).r - (*z2).i*(*tw1).i; (t).i = (*z2).r*(*tw1).i + (*z2).i*(*tw1).r; }while(0);
537         tw1 += y;
538         do { (*z2).r=(*z).r-(t).r; (*z2).i=(*z).i-(t).i; }while(0);
539         do { (*z).r += (t).r; (*z).i += (t).i; }while(0);
540         ++z2;
541         ++z;
542     }while (--m);
543 }
544 
545 // Avoid dead stores resulting from an assignment (and use) being unreachable.
546 void rdar8405222_aux(int i);
rdar8405222(void)547 void rdar8405222(void) {
548   const int show = 0;
549   int i = 0;
550   if (show)
551     i = 5; // no-warning
552   if (show)
553     rdar8405222_aux(i);
554 }
555 
556 // Look through chains of assignments, e.g.: int x = y = 0, when employing
557 // silencing heuristics.
radar11185138_foo(void)558 int radar11185138_foo(void) {
559   int x, y;
560   x = y = 0; // non-nested-warning {{never read}}
561   return y;
562 }
563 
rdar11185138_bar(void)564 int rdar11185138_bar(void) {
565   int y;
566   int x = y = 0; // nested-warning {{Although the value stored}}
567   x = 2;
568   y = 2;
569   return x + y;
570 }
571 
radar11185138_baz(void)572 int *radar11185138_baz(void) {
573   int *x, *y;
574   x = y = 0; // no-warning
575   return y;
576 }
577 
578 int getInt(void);
579 int *getPtr(void);
testBOComma(void)580 void testBOComma(void) {
581   int x0 = (getInt(), 0); // non-nested-warning {{unused variable 'x0'}}
582   int x1 = (getInt(), getInt());
583   // non-nested-warning@-1 {{Value stored to 'x1' during its initialization is never read}}
584   // non-nested-warning@-2 {{unused variable 'x1'}}
585 
586   int x2 = (getInt(), getInt(), getInt());
587   // non-nested-warning@-1 {{Value stored to 'x2' during its initialization is never read}}
588   // non-nested-warning@-2 {{unused variable 'x2'}}
589 
590   int x3;
591   x3 = (getInt(), getInt(), 0);
592   // non-nested-warning@-1 {{Value stored to 'x3' is never read}}
593 
594   int x4 = (getInt(), (getInt(), 0));
595   // non-nested-warning@-1 {{unused variable 'x4'}}
596 
597   int y;
598   int x5 = (getInt(), (y = 0));
599   // non-nested-warning@-1 {{unused variable 'x5'}}
600   // nested-warning@-2 {{Although the value stored}}
601 
602   int x6 = (getInt(), (y = getInt()));
603   // non-nested-warning@-1 {{Value stored to 'x6' during its initialization is never read}}
604   // non-nested-warning@-2 {{unused variable 'x6'}}
605   // nested-warning@-3 {{Although the value stored}}
606 
607   int x7 = 0, x8 = getInt();
608   // non-nested-warning@-1 {{Value stored to 'x8' during its initialization is never read}}
609   // non-nested-warning@-2 {{unused variable 'x8'}}
610   // non-nested-warning@-3 {{unused variable 'x7'}}
611 
612   int x9 = getInt(), x10 = 0;
613   // non-nested-warning@-1 {{Value stored to 'x9' during its initialization is never read}}
614   // non-nested-warning@-2 {{unused variable 'x9'}}
615   // non-nested-warning@-3 {{unused variable 'x10'}}
616 
617   int m = getInt(), mm, mmm;
618   // non-nested-warning@-1 {{Value stored to 'm' during its initialization is never read}}
619   // non-nested-warning@-2 {{unused variable 'm'}}
620   // non-nested-warning@-3 {{unused variable 'mm'}}
621   // non-nested-warning@-4 {{unused variable 'mmm'}}
622 
623   int n, nn = getInt();
624   // non-nested-warning@-1 {{Value stored to 'nn' during its initialization is never read}}
625   // non-nested-warning@-2 {{unused variable 'n'}}
626   // non-nested-warning@-3 {{unused variable 'nn'}}
627 
628   int *p;
629   p = (getPtr(), (int *)0); // no warning
630 }
631 
testVolatile(void)632 void testVolatile(void) {
633   volatile int v;
634   v = 0; // no warning
635 }
636 
637 struct Foo {
638   int x;
639   int y;
640 };
641 
642 struct Foo rdar34122265_getFoo(void);
643 
rdar34122265_test(int input)644 int rdar34122265_test(int input) {
645   // This is allowed for defensive programming.
646   struct Foo foo = {0, 0};
647   if (input > 0) {
648     foo = rdar34122265_getFoo();
649   } else {
650     return 0;
651   }
652   return foo.x + foo.y;
653 }
654 
rdar34122265_test_cast(void)655 void rdar34122265_test_cast(void) {
656   // This is allowed for defensive programming.
657   struct Foo foo = {0, 0};
658   (void)foo;
659 }
660 
661 struct Bar {
662   struct Foo x, y;
663 };
664 
665 struct Bar rdar34122265_getBar(void);
666 
rdar34122265_test_nested(int input)667 int rdar34122265_test_nested(int input) {
668   // This is allowed for defensive programming.
669   struct Bar bar = {{0, 0}, {0, 0}};
670   if (input > 0) {
671     bar = rdar34122265_getBar();
672   } else {
673     return 0;
674   }
675   return bar.x.x + bar.y.y;
676 }
677