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