1 | // RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wconditional-uninitialized -fsyntax-only -fblocks %s -verify |
2 | // RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wconditional-uninitialized -ftrivial-auto-var-init=pattern -fsyntax-only -fblocks %s -verify |
3 | |
4 | typedef __typeof(sizeof(int)) size_t; |
5 | void *malloc(size_t); |
6 | |
7 | int test1() { |
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 | |
12 | int test2() { |
13 | int x = 0; |
14 | return x; // no-warning |
15 | } |
16 | |
17 | int test3() { |
18 | int x; |
19 | x = 0; |
20 | return x; // no-warning |
21 | } |
22 | |
23 | int test4() { |
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 | |
29 | int test5() { |
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 | |
35 | int test6() { |
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 | |
41 | int 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 | |
49 | int 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 -Wuninitialized |
55 | // warning. |
56 | return x; // expected-warning{{variable 'x' may be uninitialized when used here}} |
57 | } |
58 | |
59 | int test8(int y) { |
60 | int x; |
61 | if (y) |
62 | x = 1; |
63 | else |
64 | x = 0; |
65 | return x; |
66 | } |
67 | |
68 | int 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 | |
78 | int 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 | |
86 | int 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 | |
94 | void 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 | |
98 | int test13() { |
99 | static int i; |
100 | return i; // no-warning |
101 | } |
102 | |
103 | // Simply don't crash on this test case. |
104 | void test14() { |
105 | const char *p = 0; |
106 | for (;;) {} |
107 | } |
108 | |
109 | void test15() { |
110 | int x = x; // no-warning: signals intended lack of initialization. |
111 | } |
112 | |
113 | int test15b() { |
114 | // Warn here with the self-init, since it does result in a use of |
115 | // 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. |
121 | char *test16_aux(); |
122 | void test16() { |
123 | char *p = test16_aux(); |
124 | for (unsigned i = 0 ; i < 100 ; i++) |
125 | p[i] = 'a'; // no-warning |
126 | } |
127 | |
128 | void test17() { |
129 | // Don't warn multiple times about the same uninitialized variable |
130 | // 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-warning |
134 | } |
135 | |
136 | int test18(int x, int y) { |
137 | int z; |
138 | if (x && y && (z = 1)) { |
139 | return z; // no-warning |
140 | } |
141 | return 0; |
142 | } |
143 | |
144 | int test19_aux1(); |
145 | int test19_aux2(); |
146 | int test19_aux3(int *x); |
147 | int test19() { |
148 | int z; |
149 | if (test19_aux1() + test19_aux2() && test19_aux1() && test19_aux3(&z)) |
150 | return z; // no-warning |
151 | return 0; |
152 | } |
153 | |
154 | int test20() { |
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 | |
161 | int 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 | |
168 | int test22() { |
169 | int z; |
170 | while (test19_aux1() + test19_aux2() && test19_aux1() && test19_aux3(&z)) |
171 | return z; // no-warning |
172 | return 0; |
173 | } |
174 | |
175 | int test23() { |
176 | int z; |
177 | for ( ; test19_aux1() + test19_aux2() && test19_aux1() && test19_aux3(&z) ; ) |
178 | return z; // no-warning |
179 | return 0; |
180 | } |
181 | |
182 | // The basic uninitialized value analysis doesn't have enough path-sensitivity |
183 | // to catch initializations relying on control-dependencies spanning multiple |
184 | // conditionals. This possibly can be handled by making the CFG itself |
185 | // represent such control-dependencies, but it is a niche case. |
186 | int 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 | |
195 | float test25() { |
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 | |
200 | typedef int MyInt; |
201 | MyInt test26() { |
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(). |
207 | int test27() { |
208 | struct test_27 { int x; } *y; |
209 | return sizeof(y->x); // no-warning |
210 | } |
211 | |
212 | int test28() { |
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 | |
217 | void test29() { |
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 | |
222 | void test30() { |
223 | static int x; // no-warning |
224 | (void) ^{ (void) x; }; |
225 | } |
226 | |
227 | void test31() { |
228 | __block int x; // no-warning |
229 | (void) ^{ (void) x; }; |
230 | } |
231 | |
232 | int test32_x; |
233 | void test32() { |
234 | (void) ^{ (void) test32_x; }; // no-warning |
235 | } |
236 | |
237 | void test_33() { |
238 | int x; // no-warning |
239 | (void) x; |
240 | } |
241 | |
242 | int test_34() { |
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. |
249 | void test35(int x) { |
250 | __block int y = 0; |
251 | ^{ y = (x == 0); }(); |
252 | } |
253 | |
254 | // Test handling of indirect goto. |
255 | void test36() |
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 ||. |
266 | int test37_a(); |
267 | int test37_b(); |
268 | int test37() |
269 | { |
270 | int identifier; |
271 | if ((test37_a() && (identifier = 1)) || |
272 | (test37_b() && (identifier = 2))) { |
273 | return identifier; // no-warning |
274 | } |
275 | return 0; |
276 | } |
277 | |
278 | // Test merging of path-specific dataflow values (without asserting). |
279 | int test38(int r, int x, int y) |
280 | { |
281 | int z; |
282 | return ((r < 0) || ((r == 0) && (x < y))); |
283 | } |
284 | |
285 | int 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 | |
292 | int 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 | |
297 | int 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 | |
304 | void test42() { |
305 | int a; |
306 | a = 30; // no-warning |
307 | } |
308 | |
309 | void test43_aux(int x); |
310 | void 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 | |
316 | void 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-warning |
321 | x += y; // expected-warning {{variable 'y' is uninitialized when used here}} |
322 | } |
323 | } |
324 | |
325 | int test45(int j) { |
326 | int x = 1, y = x + 1; |
327 | if (y) // no-warning |
328 | return x; |
329 | return y; |
330 | } |
331 | |
332 | void test46() |
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 | |
338 | void *test47(int *i) |
339 | { |
340 | return i ? : 0; // no-warning |
341 | } |
342 | |
343 | void *test49(int *i) |
344 | { |
345 | int a; |
346 | return &a ? : i; // no-warning |
347 | } |
348 | |
349 | void test50() |
350 | { |
351 | char c[1 ? : 2]; // no-warning |
352 | } |
353 | |
354 | int test51(void) |
355 | { |
356 | __block int a; |
357 | ^(void) { |
358 | a = 42; |
359 | }(); |
360 | return a; // no-warning |
361 | } |
362 | |
363 | // FIXME: This is a false positive, but it tests logical operations in switch statements. |
364 | int 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 | |
377 | void test53() { |
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. |
383 | extern int PR10379_g(); |
384 | void 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. |
398 | void test_vla_sizeof(int x) { |
399 | double (*memory)[2][x] = malloc(sizeof(*memory)); // no-warning |
400 | } |
401 | |
402 | // Test absurd case of deadcode + use of blocks. This previously was a false positive |
403 | // due to an analysis bug. |
404 | int test_block_and_dead_code() { |
405 | __block int x; |
406 | ^{ x = 1; }(); |
407 | if (0) |
408 | return x; |
409 | return x; // no-warning |
410 | } |
411 | |
412 | // This previously triggered an infinite loop in the analysis. |
413 | void 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-warning |
422 | } |
423 | } |
424 | |
425 | // Test uninitialized value used in loop condition. |
426 | void 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; |
435 | void test54() { |
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 fine |
443 | struct { struct { void *p; } a; } test55 = { { &test55.a }}; // no-warning |
444 | struct { struct { void *p; } a; } test56 = { { &(test56.a) }}; // no-warning |
445 | |
446 | void uninit_in_loop() { |
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 | |
456 | void uninit_in_loop_goto() { |
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}} |
462 | skip_decl: |
463 | // FIXME: This should produce the 'is uninitialized' diagnostic, but we |
464 | // don't have enough information in the CFG to easily tell that the |
465 | // 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 | |
471 | typedef char jmp_buf[256]; |
472 | extern int setjmp(jmp_buf env); // implicitly returns_twice |
473 | |
474 | void do_stuff_and_longjmp(jmp_buf env, int *result) __attribute__((noreturn)); |
475 | |
476 | int returns_twice() { |
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 warning |
485 | } |
486 | } |
487 | return a; |
488 | } |
489 | |
490 | int 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 | |
497 | int compound_assign_2() { |
498 | int x; // expected-note {{initialize}} |
499 | return x += 1; // expected-warning {{variable 'x' is uninitialized}} |
500 | } |
501 | |
502 | int compound_assign_3() { |
503 | int x; // expected-note {{initialize}} |
504 | x *= 0; // expected-warning {{variable 'x' is uninitialized}} |
505 | return x; |
506 | } |
507 | |
508 | int self_init_in_cond(int *p) { |
509 | int n = ((p && (0 || 1)) && (n = *p)) ? n : -1; // ok |
510 | return n; |
511 | } |
512 | |
513 | void test_analyzer_noreturn_aux() __attribute__((analyzer_noreturn)); |
514 | |
515 | void 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-warning |
520 | } |
521 | else { |
522 | ++x; // expected-warning {{variable 'x' is uninitialized when used here}} |
523 | } |
524 | } |
525 | void 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-warning |
534 | } |
535 | |