dead-stores.c revision df4ca423ec7d9b62842e112d1b824faa08b64810
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 (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; // expected-warning{{idempotent operation}} 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}} expected-warning{{idempotent operation}} 462 } 463} 464 465