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