dead-stores.c revision 25973455aed1cdc9c40b208c792b5db4f8f1297d
1// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
2// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
3// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
4// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
5// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
6
7void f1() {
8  int k, y; // expected-warning{{unused variable 'k'}} expected-warning{{unused variable 'y'}}
9  int abc=1;
10  long idx=abc+3*5; // expected-warning {{never read}} expected-warning{{unused variable 'idx'}}
11}
12
13void f2(void *b) {
14 char *c = (char*)b; // no-warning
15 char *d = b+1; // expected-warning {{never read}} expected-warning{{unused variable 'd'}}
16 printf("%s", c); // expected-warning{{implicitly declaring C library function 'printf' with type 'int (char const *, ...)'}} \
17 // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}}
18}
19
20int f();
21
22void f3() {
23  int r;
24  if ((r = f()) != 0) { // no-warning
25    int y = r; // no-warning
26    printf("the error is: %d\n", y);
27  }
28}
29
30void f4(int k) {
31
32  k = 1;
33
34  if (k)
35    f1();
36
37  k = 2;  // expected-warning {{never read}}
38}
39
40void f5() {
41
42  int x = 4; // no-warning
43  int *p = &x; // expected-warning{{never read}} expected-warning{{unused variable 'p'}}
44
45}
46
47int f6() {
48
49  int x = 4;
50  ++x; // expected-warning{{never read}}
51  return 1;
52}
53
54int f7(int *p) {
55  // This is allowed for defensive programming.
56  p = 0; // no-warning
57  return 1;
58}
59
60int f7b(int *p) {
61  // This is allowed for defensive programming.
62  p = (0); // no-warning
63  return 1;
64}
65
66int f7c(int *p) {
67  // This is allowed for defensive programming.
68  p = (void*) 0; // no-warning
69  return 1;
70}
71
72int f7d(int *p) {
73  // This is allowed for defensive programming.
74  p = (void*) (0); // no-warning
75  return 1;
76}
77
78int f8(int *p) {
79  extern int *baz();
80  if ((p = baz())) // expected-warning{{Although the value}}
81    return 1;
82  return 0;
83}
84
85int f9() {
86  int x = 4;
87  x = x + 10; // expected-warning{{never read}}
88  return 1;
89}
90
91int f10() {
92  int x = 4;
93  x = 10 + x; // expected-warning{{never read}}
94  return 1;
95}
96
97int f11() {
98  int x = 4;
99  return x++; // expected-warning{{never read}}
100}
101
102int f11b() {
103  int x = 4;
104  return ((((++x)))); // no-warning
105}
106
107int f12a(int y) {
108  int x = y;  // expected-warning{{unused variable 'x'}}
109  return 1;
110}
111int f12b(int y) {
112  int x __attribute__((unused)) = y;  // no-warning
113  return 1;
114}
115int f12c(int y) {
116  // Allow initialiation of scalar variables by parameters as a form of
117  // defensive programming.
118  int x = y;  // no-warning
119  x = 1;
120  return x;
121}
122
123// Filed with PR 2630.  This code should produce no warnings.
124int f13(void)
125{
126  int a = 1;
127  int b, c = b = a + a;
128
129  if (b > 0)
130    return (0);
131
132  return (a + b + c);
133}
134
135// Filed with PR 2763.
136int f14(int count) {
137  int index, nextLineIndex;
138  for (index = 0; index < count; index = nextLineIndex+1) {
139    nextLineIndex = index+1;  // no-warning
140    continue;
141  }
142  return index;
143}
144
145// Test case for <rdar://problem/6248086>
146void f15(unsigned x, unsigned y) {
147  int count = x * y;   // no-warning
148  int z[count]; // expected-warning{{unused variable 'z'}}
149}
150
151int f16(int x) {
152  x = x * 2;
153  x = sizeof(int [x = (x || x + 1) * 2]) // expected-warning{{Although the value stored to 'x' is used}}
154      ? 5 : 8;
155  return x;
156}
157
158// Self-assignments should not be flagged as dead stores.
159void f17() {
160  int x = 1;
161  x = x; // no-warning
162}
163
164// <rdar://problem/6506065>
165// The values of dead stores are only "consumed" in an enclosing expression
166// what that value is actually used.  In other words, don't say "Although the
167// value stored to 'x' is used...".
168int f18() {
169   int x = 0; // no-warning
170   if (1)
171      x = 10;  // expected-warning{{Value stored to 'x' is never read}}
172   while (1)
173      x = 10;  // expected-warning{{Value stored to 'x' is never read}}
174   do
175      x = 10;   // expected-warning{{Value stored to 'x' is never read}}
176   while (1);
177
178   return (x = 10); // expected-warning{{Although the value stored to 'x' is used in the enclosing expression, the value is never actually read from 'x'}}
179}
180
181// PR 3514: false positive `dead initialization` warning for init to global
182//  http://llvm.org/bugs/show_bug.cgi?id=3514
183extern const int MyConstant;
184int f19(void) {
185  int x = MyConstant;  // no-warning
186  x = 1;
187  return x;
188}
189
190int f19b(void) { // This case is the same as f19.
191  const int MyConstant = 0;
192  int x = MyConstant; // no-warning
193  x = 1;
194  return x;
195}
196
197void f20(void) {
198  int x = 1; // no-warning
199#pragma unused(x)
200}
201
202void halt() __attribute__((noreturn));
203int f21() {
204  int x = 4;
205
206  ++x; // expected-warning{{never read}}
207  if (1) {
208    halt();
209    (void)x;
210  }
211  return 1;
212}
213
214int j;
215void f22() {
216  int x = 4;
217  int y1 = 4;
218  int y2 = 4;
219  int y3 = 4;
220  int y4 = 4;
221  int y5 = 4;
222  int y6 = 4;
223  int y7 = 4;
224  int y8 = 4;
225  int y9 = 4;
226  int y10 = 4;
227  int y11 = 4;
228  int y12 = 4;
229  int y13 = 4;
230  int y14 = 4;
231  int y15 = 4;
232  int y16 = 4;
233  int y17 = 4;
234  int y18 = 4;
235  int y19 = 4;
236  int y20 = 4;
237
238  ++x; // expected-warning{{never read}}
239  ++y1;
240  ++y2;
241  ++y3;
242  ++y4;
243  ++y5;
244  ++y6;
245  ++y7;
246  ++y8;
247  ++y9;
248  ++y10;
249  ++y11;
250  ++y12;
251  ++y13;
252  ++y14;
253  ++y15;
254  ++y16;
255  ++y17;
256  ++y18;
257  ++y19;
258  ++y20;
259
260  switch (j) {
261  case 1:
262    if (0)
263      (void)x;
264    if (1) {
265      (void)y1;
266      return;
267    }
268    (void)x;
269    break;
270  case 2:
271    if (0)
272      (void)x;
273    else {
274      (void)y2;
275      return;
276    }
277    (void)x;
278    break;
279  case 3:
280    if (1) {
281      (void)y3;
282      return;
283    } else
284      (void)x;
285    (void)x;
286  break;
287  case 4:
288    0 ? : ((void)y4, ({ return; }));
289    (void)x;
290    break;
291  case 5:
292    1 ? : (void)x;
293    0 ? (void)x : ((void)y5, ({ return; }));
294    (void)x;
295    break;
296  case 6:
297    1 ? ((void)y6, ({ return; })) : (void)x;
298    (void)x;
299    break;
300  case 7:
301    (void)(0 && x);
302    (void)y7;
303    (void)(0 || (y8, ({ return; }), 1));  // expected-warning {{expression result unused}}
304    (void)x;
305    break;
306  case 8:
307    (void)(1 && (y9, ({ return; }), 1));  // expected-warning {{expression result unused}}
308    (void)x;
309    break;
310  case 9:
311    (void)(1 || x);
312    (void)y10;
313    break;
314  case 10:
315    while (0) {
316      (void)x;
317    }
318    (void)y11;
319    break;
320  case 11:
321    while (1) {
322      (void)y12;
323    }
324    (void)x;
325    break;
326  case 12:
327    do {
328      (void)y13;
329    } while (0);
330    (void)y14;
331    break;
332  case 13:
333    do {
334      (void)y15;
335    } while (1);
336    (void)x;
337    break;
338  case 14:
339    for (;;) {
340      (void)y16;
341    }
342    (void)x;
343    break;
344  case 15:
345    for (;1;) {
346      (void)y17;
347    }
348    (void)x;
349    break;
350  case 16:
351    for (;0;) {
352      (void)x;
353    }
354    (void)y18;
355    break;
356  case 17:
357    __builtin_choose_expr(0, (void)x, ((void)y19, ({ return; })));
358    (void)x;
359    break;
360  case 19:
361    __builtin_choose_expr(1, ((void)y20, ({ return; })), (void)x);
362    (void)x;
363    break;
364  }
365}
366
367void f23_aux(const char* s);
368void f23(int argc, char **argv) {
369  int shouldLog = (argc > 1); // no-warning
370  ^{
371     if (shouldLog) f23_aux("I did too use it!\n");
372     else f23_aux("I shouldn't log.  Wait.. d'oh!\n");
373  }();
374}
375
376void f23_pos(int argc, char **argv) {
377  int shouldLog = (argc > 1); // expected-warning{{Value stored to 'shouldLog' during its initialization is never read}} expected-warning{{unused variable 'shouldLog'}}
378  ^{
379     f23_aux("I did too use it!\n");
380  }();
381}
382
383void f24_A(int y) {
384  // FIXME: One day this should be reported as dead since 'z = x + y' is dead.
385  int x = (y > 2); // no-warning
386  ^ {
387      int z = x + y; // expected-warning{{Value stored to 'z' during its initialization is never read}} expected-warning{{unused variable 'z'}}
388  }();
389}
390
391void f24_B(int y) {
392  // FIXME: One day this should be reported as dead since 'x' is just overwritten.
393  __block int x = (y > 2); // no-warning
394  ^{
395    // FIXME: This should eventually be a dead store since it is never read either.
396    x = 5; // no-warning
397  }();
398}
399
400int f24_C(int y) {
401  // FIXME: One day this should be reported as dead since 'x' is just overwritten.
402  __block int x = (y > 2); // no-warning
403  ^{
404    x = 5; // no-warning
405  }();
406  return x;
407}
408
409int f24_D(int y) {
410  __block int x = (y > 2); // no-warning
411  ^{
412    if (y > 4)
413      x = 5; // no-warning
414  }();
415  return x;
416}
417
418// This example shows that writing to a variable captured by a block means that it might
419// not be dead.
420int f25(int y) {
421  __block int x = (y > 2);
422  __block int z = 0;
423  void (^foo)() = ^{ z = x + y; };
424  x = 4; // no-warning
425  foo();
426  return z;
427}
428
429// This test is mostly the same as 'f25', but shows that the heuristic of pruning out dead
430// stores for variables that are just marked '__block' is overly conservative.
431int f25_b(int y) {
432  // FIXME: we should eventually report a dead store here.
433  __block int x = (y > 2);
434  __block int z = 0;
435  x = 4; // no-warning
436  return z;
437}
438
439int f26_nestedblocks() {
440  int z;
441  z = 1;
442  __block int y = 0;
443  ^{
444    int k;
445    k = 1; // expected-warning{{Value stored to 'k' is never read}}
446    ^{
447        y = z + 1;
448     }();
449  }();
450  return y;
451}
452
453// The FOREACH macro in QT uses 'break' statements within statement expressions
454// placed within the increment code of for loops.
455void rdar8014335() {
456  for (int i = 0 ; i != 10 ; ({ break; })) {
457    for ( ; ; ({ ++i; break; })) ;
458    // Note that the next value stored to 'i' is never executed
459    // because the next statement to be executed is the 'break'
460    // in the increment code of the first loop.
461    i = i * 3; // expected-warning{{Value stored to 'i' is never read}}
462  }
463}
464
465