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