dead-stores.c revision 2cfe28b6a061e72c6c8726d7ecb879093a1ab7a3
1// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s 2// RUN: %clang_cc1 -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 -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 -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 -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; 9 int abc=1; 10 long idx=abc+3*5; // expected-warning {{never read}} 11} 12 13void f2(void *b) { 14 char *c = (char*)b; // no-warning 15 char *d = b+1; // expected-warning {{never read}} 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}} 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{{never read}} 109 return 1; 110} 111int f12b(int y) { 112 int x __attribute__((unused)) = y; // no-warning 113 return 1; 114} 115 116// Filed with PR 2630. This code should produce no warnings. 117int f13(void) 118{ 119 int a = 1; 120 int b, c = b = a + a; 121 122 if (b > 0) 123 return (0); 124 125 return (a + b + c); 126} 127 128// Filed with PR 2763. 129int f14(int count) { 130 int index, nextLineIndex; 131 for (index = 0; index < count; index = nextLineIndex+1) { 132 nextLineIndex = index+1; // no-warning 133 continue; 134 } 135 return index; 136} 137 138// Test case for <rdar://problem/6248086> 139void f15(unsigned x, unsigned y) { 140 int count = x * y; // no-warning 141 int z[count]; 142} 143 144int f16(int x) { 145 x = x * 2; 146 x = sizeof(int [x = (x || x + 1) * 2]) // expected-warning{{Although the value stored to 'x' is used}} 147 ? 5 : 8; 148 return x; 149} 150 151// Self-assignments should not be flagged as dead stores. 152void f17() { 153 int x = 1; 154 x = x; // no-warning 155} 156 157// <rdar://problem/6506065> 158// The values of dead stores are only "consumed" in an enclosing expression 159// what that value is actually used. In other words, don't say "Although the 160// value stored to 'x' is used...". 161int f18() { 162 int x = 0; // no-warning 163 if (1) 164 x = 10; // expected-warning{{Value stored to 'x' is never read}} 165 while (1) 166 x = 10; // expected-warning{{Value stored to 'x' is never read}} 167 do 168 x = 10; // expected-warning{{Value stored to 'x' is never read}} 169 while (1); 170 171 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'}} 172} 173 174// PR 3514: false positive `dead initialization` warning for init to global 175// http://llvm.org/bugs/show_bug.cgi?id=3514 176extern const int MyConstant; 177int f19(void) { 178 int x = MyConstant; // no-warning 179 x = 1; 180 return x; 181} 182 183int f19b(void) { // This case is the same as f19. 184 const int MyConstant = 0; 185 int x = MyConstant; // no-warning 186 x = 1; 187 return x; 188} 189 190void f20(void) { 191 int x = 1; // no-warning 192#pragma unused(x) 193} 194 195void halt() __attribute__((noreturn)); 196int f21() { 197 int x = 4; 198 199 ++x; // expected-warning{{never read}} 200 if (1) { 201 halt(); 202 (void)x; 203 } 204 return 1; 205} 206 207int j; 208void f22() { 209 int x = 4; 210 int y1 = 4; 211 int y2 = 4; 212 int y3 = 4; 213 int y4 = 4; 214 int y5 = 4; 215 int y6 = 4; 216 int y7 = 4; 217 int y8 = 4; 218 int y9 = 4; 219 int y10 = 4; 220 int y11 = 4; 221 int y12 = 4; 222 int y13 = 4; 223 int y14 = 4; 224 int y15 = 4; 225 int y16 = 4; 226 int y17 = 4; 227 int y18 = 4; 228 int y19 = 4; 229 int y20 = 4; 230 231 ++x; // expected-warning{{never read}} 232 ++y1; 233 ++y2; 234 ++y3; 235 ++y4; 236 ++y5; 237 ++y6; 238 ++y7; 239 ++y8; 240 ++y9; 241 ++y10; 242 ++y11; 243 ++y12; 244 ++y13; 245 ++y14; 246 ++y15; 247 ++y16; 248 ++y17; 249 ++y18; 250 ++y19; 251 ++y20; 252 253 switch (j) { 254 case 1: 255 if (0) 256 (void)x; 257 if (1) { 258 (void)y1; 259 return; 260 } 261 (void)x; 262 break; 263 case 2: 264 if (0) 265 (void)x; 266 else { 267 (void)y2; 268 return; 269 } 270 (void)x; 271 break; 272 case 3: 273 if (1) { 274 (void)y3; 275 return; 276 } else 277 (void)x; 278 (void)x; 279 break; 280 case 4: 281 0 ? : ((void)y4, ({ return; })); 282 (void)x; 283 break; 284 case 5: 285 1 ? : (void)x; 286 0 ? (void)x : ((void)y5, ({ return; })); 287 (void)x; 288 break; 289 case 6: 290 1 ? ((void)y6, ({ return; })) : (void)x; 291 (void)x; 292 break; 293 case 7: 294 (void)(0 && x); 295 (void)y7; 296 (void)(0 || (y8, ({ return; }), 1)); 297 (void)x; 298 break; 299 case 8: 300 (void)(1 && (y9, ({ return; }), 1)); 301 (void)x; 302 break; 303 case 9: 304 (void)(1 || x); 305 (void)y10; 306 break; 307 case 10: 308 while (0) { 309 (void)x; 310 } 311 (void)y11; 312 break; 313 case 11: 314 while (1) { 315 (void)y12; 316 } 317 (void)x; 318 break; 319 case 12: 320 do { 321 (void)y13; 322 } while (0); 323 (void)y14; 324 break; 325 case 13: 326 do { 327 (void)y15; 328 } while (1); 329 (void)x; 330 break; 331 case 14: 332 for (;;) { 333 (void)y16; 334 } 335 (void)x; 336 break; 337 case 15: 338 for (;1;) { 339 (void)y17; 340 } 341 (void)x; 342 break; 343 case 16: 344 for (;0;) { 345 (void)x; 346 } 347 (void)y18; 348 break; 349 case 17: 350 __builtin_choose_expr(0, (void)x, ((void)y19, ({ return; }))); 351 (void)x; 352 break; 353 case 19: 354 __builtin_choose_expr(1, ((void)y20, ({ return; })), (void)x); 355 (void)x; 356 break; 357 } 358} 359 360void f23_aux(const char* s); 361void f23(int argc, char **argv) { 362 int shouldLog = (argc > 1); // no-warning 363 ^{ 364 if (shouldLog) f23_aux("I did too use it!\n"); 365 else f23_aux("I shouldn't log. Wait.. d'oh!\n"); 366 }(); 367} 368 369void f23_pos(int argc, char **argv) { 370 int shouldLog = (argc > 1); // expected-warning{{Value stored to 'shouldLog' during its initialization is never read}} 371 ^{ 372 f23_aux("I did too use it!\n"); 373 }(); 374} 375 376void f24_A(int y) { 377 // FIXME: One day this should be reported as dead since 'z = x + y' is dead. 378 int x = (y > 2); // no-warning 379 ^ { 380 int z = x + y; // expected-warning{{Value stored to 'z' during its initialization is never read}} 381 }(); 382} 383 384void f24_B(int y) { 385 // FIXME: One day this should be reported as dead since 'x' is just overwritten. 386 __block int x = (y > 2); // no-warning 387 ^{ 388 // FIXME: This should eventually be a dead store since it is never read either. 389 x = 5; // no-warning 390 }(); 391} 392 393int f24_C(int y) { 394 // FIXME: One day this should be reported as dead since 'x' is just overwritten. 395 __block int x = (y > 2); // no-warning 396 ^{ 397 x = 5; // no-warning 398 }(); 399 return x; 400} 401 402int f24_D(int y) { 403 __block int x = (y > 2); // no-warning 404 ^{ 405 if (y > 4) 406 x = 5; // no-warning 407 }(); 408 return x; 409} 410 411// This example shows that writing to a variable captured by a block means that it might 412// not be dead. 413int f25(int y) { 414 __block int x = (y > 2); 415 __block int z = 0; 416 void (^foo)() = ^{ z = x + y; }; 417 x = 4; // no-warning 418 foo(); 419 return z; 420} 421 422// This test is mostly the same as 'f25', but shows that the heuristic of pruning out dead 423// stores for variables that are just marked '__block' is overly conservative. 424int f25_b(int y) { 425 // FIXME: we should eventually report a dead store here. 426 __block int x = (y > 2); 427 __block int z = 0; 428 x = 4; // no-warning 429 return z; 430} 431 432int f26_nestedblocks() { 433 int z; 434 z = 1; 435 __block int y = 0; 436 ^{ 437 int k; 438 k = 1; // expected-warning{{Value stored to 'k' is never read}} 439 ^{ 440 y = z + 1; 441 }(); 442 }(); 443 return y; 444} 445 446