586 lines · c
1// RUN: %clang_cc1 -Wuninitialized -Wconditional-uninitialized -fsyntax-only -fblocks %s -verify2// RUN: %clang_cc1 -Wuninitialized -Wconditional-uninitialized -ftrivial-auto-var-init=pattern -fsyntax-only -fblocks %s -verify3 4typedef __typeof(sizeof(int)) size_t;5void *malloc(size_t);6 7int test1(void) {8 int x; // expected-note{{initialize the variable 'x' to silence this warning}}9 return x; // expected-warning{{variable 'x' is uninitialized when used here}}10}11 12int test2(void) {13 int x = 0;14 return x; // no-warning15}16 17int test3(void) {18 int x;19 x = 0;20 return x; // no-warning21}22 23int test4(void) {24 int x; // expected-note{{initialize the variable 'x' to silence this warning}}25 ++x; // expected-warning{{variable 'x' is uninitialized when used here}}26 return x; 27}28 29int test5(void) {30 int x, y; // expected-note{{initialize the variable 'y' to silence this warning}}31 x = y; // expected-warning{{variable 'y' is uninitialized when used here}}32 return x;33}34 35int test6(void) {36 int x; // expected-note{{initialize the variable 'x' to silence this warning}}37 x += 2; // expected-warning{{variable 'x' is uninitialized when used here}}38 return x;39}40 41int test7(int y) {42 int x; // expected-note{{initialize the variable 'x' to silence this warning}}43 if (y) // expected-warning{{variable 'x' is used uninitialized whenever 'if' condition is false}} \44 // expected-note{{remove the 'if' if its condition is always true}}45 x = 1;46 return x; // expected-note{{uninitialized use occurs here}}47}48 49int test7b(int y) {50 int x = x; // expected-note{{variable 'x' is declared here}}51 if (y)52 x = 1;53 // Warn with "may be uninitialized" here (not "is sometimes uninitialized"),54 // since the self-initialization is intended to suppress a -Wuninitialized55 // warning.56 return x; // expected-warning{{variable 'x' may be uninitialized when used here}}57}58 59int test8(int y) {60 int x;61 if (y)62 x = 1;63 else64 x = 0;65 return x;66}67 68int test9(int n) {69 int x; // expected-note{{initialize the variable 'x' to silence this warning}}70 for (unsigned i = 0 ; i < n; ++i) {71 if (i == n - 1)72 break;73 x = 1;74 }75 return x; // expected-warning{{variable 'x' may be uninitialized when used here}}76}77 78int test10(unsigned n) {79 int x; // expected-note{{initialize the variable 'x' to silence this warning}}80 for (unsigned i = 0 ; i < n; ++i) {81 x = 1;82 }83 return x; // expected-warning{{variable 'x' may be uninitialized when used here}}84}85 86int test11(unsigned n) {87 int x; // expected-note{{initialize the variable 'x' to silence this warning}}88 for (unsigned i = 0 ; i <= n; ++i) {89 x = 1;90 }91 return x; // expected-warning{{variable 'x' may be uninitialized when used here}}92}93 94void test12(unsigned n) {95 for (unsigned i ; n ; ++i) ; // expected-warning{{variable 'i' is uninitialized when used here}} expected-note{{initialize the variable 'i' to silence this warning}}96}97 98int test13(void) {99 static int i;100 return i; // no-warning101}102 103// Simply don't crash on this test case.104void test14(void) {105 const char *p = 0;106 for (;;) {}107}108 109void test15(void) {110 int x = x; // no-warning: signals intended lack of initialization.111}112 113int test15b(void) {114 // Warn here with the self-init, since it does result in a use of115 // an uninitialized variable and this is the root cause.116 int x = x; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}117 return x;118}119 120// Don't warn in the following example; shows dataflow confluence.121char *test16_aux(void);122void test16(void) {123 char *p = test16_aux();124 for (unsigned i = 0 ; i < 100 ; i++)125 p[i] = 'a'; // no-warning126}127 128void test17(void) {129 // Don't warn multiple times about the same uninitialized variable130 // along the same path.131 int *x; // expected-note{{initialize the variable 'x' to silence this warning}}132 *x = 1; // expected-warning{{variable 'x' is uninitialized when used here}}133 *x = 1; // no-warning134}135 136int test18(int x, int y) {137 int z;138 if (x && y && (z = 1)) {139 return z; // no-warning140 }141 return 0;142}143 144int test19_aux1(void);145int test19_aux2(void);146int test19_aux3(int *x);147int test19(void) {148 int z;149 if (test19_aux1() + test19_aux2() && test19_aux1() && test19_aux3(&z))150 return z; // no-warning151 return 0;152}153 154int test20(void) {155 int z; // expected-note{{initialize the variable 'z' to silence this warning}}156 if ((test19_aux1() + test19_aux2() && test19_aux1()) || test19_aux3(&z)) // expected-warning {{variable 'z' is used uninitialized whenever '||' condition is true}} expected-note {{remove the '||' if its condition is always false}}157 return z; // expected-note {{uninitialized use occurs here}}158 return 0;159}160 161int test21(int x, int y) {162 int z; // expected-note{{initialize the variable 'z' to silence this warning}}163 if ((x && y) || test19_aux3(&z) || test19_aux2()) // expected-warning {{variable 'z' is used uninitialized whenever '||' condition is true}} expected-note {{remove the '||' if its condition is always false}}164 return z; // expected-note {{uninitialized use occurs here}}165 return 0;166}167 168int test22(void) {169 int z;170 while (test19_aux1() + test19_aux2() && test19_aux1() && test19_aux3(&z))171 return z; // no-warning172 return 0;173}174 175int test23(void) {176 int z;177 for ( ; test19_aux1() + test19_aux2() && test19_aux1() && test19_aux3(&z) ; )178 return z; // no-warning179 return 0;180}181 182// The basic uninitialized value analysis doesn't have enough path-sensitivity183// to catch initializations relying on control-dependencies spanning multiple184// conditionals. This possibly can be handled by making the CFG itself185// represent such control-dependencies, but it is a niche case.186int test24(int flag) {187 unsigned val; // expected-note{{initialize the variable 'val' to silence this warning}}188 if (flag)189 val = 1;190 if (!flag)191 val = 1;192 return val; // expected-warning{{variable 'val' may be uninitialized when used here}}193}194 195float test25(void) {196 float x; // expected-note{{initialize the variable 'x' to silence this warning}}197 return x; // expected-warning{{variable 'x' is uninitialized when used here}}198}199 200typedef int MyInt;201MyInt test26(void) {202 MyInt x; // expected-note{{initialize the variable 'x' to silence this warning}}203 return x; // expected-warning{{variable 'x' is uninitialized when used here}}204}205 206// Test handling of sizeof().207int test27(void) {208 struct test_27 { int x; } *y;209 return sizeof(y->x); // no-warning210}211 212int test28(void) {213 int len; // expected-note{{initialize the variable 'len' to silence this warning}}214 return sizeof(int[len]); // expected-warning{{variable 'len' is uninitialized when used here}}215}216 217void test29(void) {218 int x; // expected-note{{initialize the variable 'x' to silence this warning}}219 (void) ^{ (void) x; }; // expected-warning{{variable 'x' is uninitialized when captured by block}}220}221 222void test30(void) {223 static int x; // no-warning224 (void) ^{ (void) x; };225}226 227void test31(void) {228 __block int x; // no-warning229 (void) ^{ (void) x; };230}231 232int test32_x;233void test32(void) {234 (void) ^{ (void) test32_x; }; // no-warning235}236 237void test_33(void) {238 int x; // no-warning239 (void) x;240}241 242int test_34(void) {243 int x; // expected-note{{initialize the variable 'x' to silence this warning}}244 (void) x;245 return x; // expected-warning{{variable 'x' is uninitialized when used here}}246}247 248// Test that this case doesn't crash.249void test35(int x) {250 __block int y = 0;251 ^{ y = (x == 0); }();252}253 254// Test handling of indirect goto.255void test36(void)256{257 void **pc; // expected-note{{initialize the variable 'pc' to silence this warning}}258 void *dummy[] = { &&L1, &&L2 };259 L1:260 goto *pc; // expected-warning{{variable 'pc' is uninitialized when used here}}261 L2:262 goto *pc;263}264 265// Test && nested in ||.266int test37_a(void);267int test37_b(void);268int test37(void)269{270 int identifier;271 if ((test37_a() && (identifier = 1)) ||272 (test37_b() && (identifier = 2))) {273 return identifier; // no-warning274 }275 return 0;276}277 278// Test merging of path-specific dataflow values (without asserting).279int test38(int r, int x, int y)280{281 int z;282 return ((r < 0) || ((r == 0) && (x < y)));283}284 285int test39(int x) {286 int y; // expected-note{{initialize the variable 'y' to silence this warning}}287 int z = x + y; // expected-warning {{variable 'y' is uninitialized when used here}}288 return z;289}290 291 292int test40(int x) {293 int y; // expected-note{{initialize the variable 'y' to silence this warning}}294 return x ? 1 : y; // expected-warning {{variable 'y' is uninitialized when used here}}295}296 297int test41(int x) {298 int y; // expected-note{{initialize the variable 'y' to silence this warning}}299 if (x) y = 1; // expected-warning{{variable 'y' is used uninitialized whenever 'if' condition is false}} \300 // expected-note{{remove the 'if' if its condition is always true}}301 return y; // expected-note{{uninitialized use occurs here}}302}303 304void test42(void) {305 int a;306 a = 30; // no-warning307}308 309void test43_aux(int x);310void test43(int i) {311 int x; // expected-note{{initialize the variable 'x' to silence this warning}}312 for (i = 0 ; i < 10; i++)313 test43_aux(x++); // expected-warning {{variable 'x' is uninitialized when used here}}314}315 316void test44(int i) {317 int x = i;318 int y; // expected-note{{initialize the variable 'y' to silence this warning}}319 for (i = 0; i < 10; i++ ) {320 test43_aux(x++); // no-warning321 x += y; // expected-warning {{variable 'y' is uninitialized when used here}}322 }323}324 325int test45(int j) {326 int x = 1, y = x + 1;327 if (y) // no-warning328 return x;329 return y;330}331 332void test46(void)333{334 int i; // expected-note{{initialize the variable 'i' to silence this warning}}335 int j = i ? : 1; // expected-warning {{variable 'i' is uninitialized when used here}}336}337 338void *test47(int *i)339{340 return i ? : 0; // no-warning341}342 343void *test49(int *i)344{345 int a;346 return &a ? : i; // no-warning347}348 349void test50(void)350{351 char c[1 ? : 2]; // no-warning352}353 354int test51(void)355{356 __block int a;357 ^(void) {358 a = 42;359 }();360 return a; // no-warning361}362 363// FIXME: This is a false positive, but it tests logical operations in switch statements.364int test52(int a, int b) {365 int x; // expected-note {{initialize the variable 'x' to silence this warning}}366 switch (a || b) { // expected-warning {{switch condition has boolean value}}367 case 0:368 x = 1;369 break;370 case 1:371 x = 2;372 break;373 }374 return x; // expected-warning {{variable 'x' may be uninitialized when used here}}375}376 377void test53(void) {378 int x; // expected-note {{initialize the variable 'x' to silence this warning}}379 int y = (x); // expected-warning {{variable 'x' is uninitialized when used here}}380}381 382// This CFG caused the uninitialized values warning to inf-loop.383extern int PR10379_g(void);384void PR10379_f(int *len) {385 int new_len; // expected-note{{initialize the variable 'new_len' to silence this warning}}386 for (int i = 0; i < 42 && PR10379_g() == 0; i++) {387 if (PR10379_g() == 1)388 continue;389 if (PR10379_g() == 2)390 PR10379_f(&new_len);391 else if (PR10379_g() == 3)392 PR10379_f(&new_len);393 *len += new_len; // expected-warning {{variable 'new_len' may be uninitialized when used here}}394 }395}396 397// Test that sizeof(VLA) doesn't trigger a warning.398void test_vla_sizeof(int x) {399 double (*memory)[2][x] = malloc(sizeof(*memory)); // no-warning400}401 402// Test absurd case of deadcode + use of blocks. This previously was a false positive403// due to an analysis bug.404int test_block_and_dead_code(void) {405 __block int x;406 ^{ x = 1; }();407 if (0)408 return x;409 return x; // no-warning410}411 412// This previously triggered an infinite loop in the analysis.413void PR11069(int a, int b) {414 unsigned long flags;415 for (;;) {416 if (a && !b)417 break;418 }419 for (;;) {420 // This does not trigger a warning because it isn't a real use.421 (void)(flags); // no-warning422 }423}424 425// Test uninitialized value used in loop condition.426void rdar9432305(float *P) {427 int i; // expected-note {{initialize the variable 'i' to silence this warning}}428 for (; i < 10000; ++i) // expected-warning {{variable 'i' is uninitialized when used here}}429 P[i] = 0.0f;430}431 432// Test that fixits are not emitted inside macros.433#define UNINIT(T, x, y) T x; T y = x;434#define ASSIGN(T, x, y) T y = x;435void test54(void) {436 UNINIT(int, a, b); // expected-warning {{variable 'a' is uninitialized when used here}} \437 // expected-note {{variable 'a' is declared here}}438 int c; // expected-note {{initialize the variable 'c' to silence this warning}}439 ASSIGN(int, c, d); // expected-warning {{variable 'c' is uninitialized when used here}}440}441 442// Taking the address is fine443struct { struct { void *p; } a; } test55 = { { &test55.a }}; // no-warning444struct { struct { void *p; } a; } test56 = { { &(test56.a) }}; // no-warning445 446void uninit_in_loop(void) {447 int produce(void);448 void consume(int);449 for (int n = 0; n < 100; ++n) {450 int k; // expected-note {{initialize}}451 consume(k); // expected-warning {{variable 'k' is uninitialized}}452 k = produce();453 }454}455 456void uninit_in_loop_goto(void) {457 int produce(void);458 void consume(int);459 for (int n = 0; n < 100; ++n) {460 goto skip_decl;461 int k; // expected-note {{initialize}}462skip_decl:463 // FIXME: This should produce the 'is uninitialized' diagnostic, but we464 // don't have enough information in the CFG to easily tell that the465 // variable's scope has been left and re-entered.466 consume(k); // expected-warning {{variable 'k' may be uninitialized}}467 k = produce();468 }469}470 471typedef char jmp_buf[256];472extern int setjmp(jmp_buf env); // implicitly returns_twice473 474void do_stuff_and_longjmp(jmp_buf env, int *result) __attribute__((noreturn));475 476int returns_twice(void) {477 int a; // expected-note {{initialize}}478 if (!a) { // expected-warning {{variable 'a' is uninitialized}}479 jmp_buf env;480 int b;481 if (setjmp(env) == 0) {482 do_stuff_and_longjmp(env, &b);483 } else {484 a = b; // no warning485 }486 }487 return a;488}489 490int compound_assign(int *arr, int n) {491 int sum; // expected-note {{initialize}}492 for (int i = 0; i < n; ++i)493 sum += arr[i]; // expected-warning {{variable 'sum' is uninitialized}}494 return sum / n;495}496 497int compound_assign_2(void) {498 int x; // expected-note {{initialize}}499 return x += 1; // expected-warning {{variable 'x' is uninitialized}}500}501 502int compound_assign_3(void) {503 int x; // expected-note {{initialize}}504 x *= 0; // expected-warning {{variable 'x' is uninitialized}}505 return x;506}507 508int self_init_in_cond(int *p) {509 int n = ((p && (0 || 1)) && (n = *p)) ? n : -1; // ok510 return n;511}512 513void test_analyzer_noreturn_aux(void) __attribute__((analyzer_noreturn));514 515void test_analyzer_noreturn(int y) {516 int x; // expected-note {{initialize the variable 'x' to silence this warning}}517 if (y) {518 test_analyzer_noreturn_aux();519 ++x; // no-warning520 }521 else {522 ++x; // expected-warning {{variable 'x' is uninitialized when used here}}523 }524}525void test_analyzer_noreturn_2(int y) {526 int x;527 if (y) {528 test_analyzer_noreturn_aux();529 }530 else {531 x = 1;532 }533 ++x; // no-warning534}535 536// Do not diagnose (functionally) empty structures as being uninitalized537// variables; see GH26842538struct empty {};539struct full_of_empty {540 int : 0;541 int : 12;542 struct empty e;543};544 545struct empty empty_test_1(void) {546 struct empty e;547 return e; // no-warning548}549 550struct full_of_empty empty_test_2(void) {551 struct full_of_empty e;552 return e; // no-warning553}554 555struct with_explicit_field {556 int x;557 int y [[clang::require_explicit_initialization]]; // #FIELD_Y558};559 560struct with_explicit_array {561 [[clang::require_explicit_initialization]] int arr[2]; // #FIELD_ARR562};563 564struct with_explicit_flex_array {565 int x;566 [[clang::require_explicit_initialization]] int flex_arr[]; // #FIELD_FLEX_ARR567};568 569void aggregate() {570 struct with_explicit_field a; // expected-warning {{field in 'with_explicit_field' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_Y {{'y' declared here}}571 struct with_explicit_field b = {1}; // expected-warning {{field 'y' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_Y {{'y' declared here}}572 (void)(&a != &b);573 574 struct with_explicit_field c = {1, 2};575 struct with_explicit_field d = {.y = 3};576 (void)(&c != &d);577 578 struct with_explicit_array e = {{1}}; // OK -- part of array is still initialized579 (void)e;580 581 struct with_explicit_flex_array f = {2}; // expected-warning {{field 'flex_arr' requires explicit initialization but is not explicitly initialized}} expected-note@#FIELD_FLEX_ARR {{'flex_arr' declared here}}582 (void)f;583 584 (void)sizeof({ struct with_explicit_field a; a; }); // no warning -- unevaluated operand585}586