* doc/invoke.texi: Document -Wuninitialized=1 and -Wuninitialized=2. * gcc/opts.c (decode_options): Adjust code which determines if a warning for using -Wuninitialized without -O is needed. (set_Wextra): Adjust setting of warn_uninitialized. * gcc/c-opts.c (c_common_handle_option, case OPT_Wall): Adjust setting of warn_uninitialized. * common.opt (Wuninitialized=): New warning option. * tree-ssa.c (warn_uninitialized_stmts): New. Extracted rom execute_early_warn_uninitialized. (warn_uninitialized_phis): New. Extracted from execute_late_warn_uninitialized. (execute_early_warn_uninitialized): Simplify. Call warn_uninitialized_phis if user has requested additional uninitialized warnings. (execute_late_warn_uninitialized): Simplify. * gcc.dg/pr18501.c: Use -Wuninitialized=2 and remove xfail. * gcc.dg/uninit-J.c: New test. * gcc.dg/uninit-K.c: New test. * gcc.dg/uninit-L.c: New test. * gcc.dg/uninit-M.c: New test. * gcc.dg/uninit-N.c: New test. Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 106605) +++ gcc/doc/invoke.texi (working copy) @@ -2733,6 +2733,19 @@ This warning is enabled by @option{-Wall}. +@item -Wuninitialized=1 +@opindex Wuninitialized=1 +This is a synonym for @option{-Wuninitialized}. + +@item -Wuninitialized=2 +@opindex Wuninitialized=2 +Similar to @option{-Wuninitialized} except that it generates warnings for +uninitialized variables before optimizing the program. Use this option +to generate uninitialized warnings when the uninitialized use occurs in +unreachable or dead code. This option will also generate spurious +uninitialized warnings in cases where optimization analysis would normally +prove the variable is always initialized. + @item -Wunknown-pragmas @opindex Wunknown-pragmas @cindex warning for unknown pragmas Index: gcc/testsuite/gcc.dg/pr18501.c =================================================================== --- gcc/testsuite/gcc.dg/pr18501.c (revision 106605) +++ gcc/testsuite/gcc.dg/pr18501.c (working copy) @@ -1,7 +1,7 @@ /* Expected uninitialized variable warning. */ /* { dg-do compile } */ -/* { dg-options "-O -Wuninitialized" } */ +/* { dg-options "-O -Wuninitialized=2" } */ unsigned bmp_iter_set (); int something (void); @@ -9,7 +9,7 @@ void bitmap_print_value_set (void) { - unsigned first; /* { dg-warning "may be used" "conditional in loop" { xfail *-*-* } } */ + unsigned first; /* { dg-warning "may be used" "conditional in loop" } */ for (; bmp_iter_set (); ) { Index: gcc/opts.c =================================================================== --- gcc/opts.c (revision 106605) +++ gcc/opts.c (working copy) @@ -663,9 +663,9 @@ warn_inline = 0; /* The c_decode_option function and decode_option hook set - this to `2' if -Wall is used, so we can avoid giving out + this to `-1' if -Wall is used, so we can avoid giving out lots of errors for people who don't realize what -Wall does. */ - if (warn_uninitialized == 1) + if (warn_uninitialized == 1 || warn_uninitialized == 2) warning (OPT_Wuninitialized, "-Wuninitialized is not supported without -O"); } @@ -1090,8 +1090,8 @@ warning about not using it without also specifying -O. */ if (setting == 0) warn_uninitialized = 0; - else if (warn_uninitialized != 1) - warn_uninitialized = 2; + else if (warn_uninitialized != 1 && warn_uninitialized != 2) + warn_uninitialized = -1; } /* Initialize unused warning flags. */ Index: gcc/c-opts.c =================================================================== --- gcc/c-opts.c (revision 106605) +++ gcc/c-opts.c (working copy) @@ -394,8 +394,8 @@ /* We save the value of warn_uninitialized, since if they put -Wuninitialized on the command line, we need to generate a warning about not using it without also specifying -O. */ - if (warn_uninitialized != 1) - warn_uninitialized = (value ? 2 : 0); + if (warn_uninitialized != 1 && warn_uninitialized != 2) + warn_uninitialized = (value ? -1 : 0); if (!c_dialect_cxx ()) /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 106605) +++ gcc/common.opt (working copy) @@ -145,6 +145,10 @@ Common Var(warn_uninitialized) Warn about uninitialized automatic variables +Wuninitialized= +Common Var(warn_uninitialized) Joined UInteger +Generate additional uninitialized automatic variable warnings + Wunreachable-code Common Var(warn_notreached) Warn about code that will never be executed Index: gcc/tree-ssa.c =================================================================== --- gcc/tree-ssa.c (revision 106605) +++ gcc/tree-ssa.c (working copy) @@ -1186,8 +1186,11 @@ } } +/* Search through all the statements and warn if any use of an + uninitialized variable is found. */ + static void -execute_early_warn_uninitialized (void) +warn_uninitialized_stmts (void) { block_stmt_iterator bsi; basic_block bb; @@ -1201,20 +1204,67 @@ } } +/* Search through all the PHIs any which may reference an + uninitialized variable. Warn if any such PHI is found. */ + static void -execute_late_warn_uninitialized (void) +warn_uninitialized_phis (void) { basic_block bb; tree phi; + FOR_EACH_BB (bb) + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + warn_uninitialized_phi (phi); +} + +/* This pass emits warnings for uninitialized variables before any + optimization occurs. + + We always identify and warn for variables which can be trivially + determined are uninitialized at one or more uses. + + We conditionally warn for "may be" uninitialized variables at this + time as well (dependent on user flags). + + By emitting "may be" warnings before optimization we can get warnings + for uninitialized variables in which uses are optimized away or + unreachable. However, we get more false positive "may be" uninitialized + warnings and some "may be" uninitialized warnings which really should + be "is" uninitialized warnings. */ + +static void +execute_early_warn_uninitialized (void) +{ + warn_uninitialized_stmts (); + + /* If explicitly requested, look for "may be" uninitialized variables + before optimizations as well. */ + if (warn_uninitialized == 2) + warn_uninitialized_phis (); +} + +/* This pass emits warnings for uninitialized variables after + optimization has been performed. + + By delaying warnings until after optimization we can turn more + "may be" uninitialized warnings into "is" uninitialized warnings. + We can also eliminate some false positive "may be" uninitialized + warnings. + + This pass also emits warnings for any variables exposed by the + optimizers. For example, if optimization removed the need to + take the address of a variable, then this pass will be the only + chance we have to get uninitialized warnings for such variables. */ +static void +execute_late_warn_uninitialized (void) +{ /* Re-do the plain uninitialized variable check, as optimization may have straightened control flow. Do this first so that we don't accidentally get a "may be" warning when we'd have seen an "is" warning later. */ - execute_early_warn_uninitialized (); + warn_uninitialized_stmts (); - FOR_EACH_BB (bb) - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) - warn_uninitialized_phi (phi); + warn_uninitialized_phis (); } static bool *** /dev/null Wed Sep 28 10:04:49 2005 --- gcc/testsuite/gcc.dg/uninit-J.c Tue Nov 8 09:58:09 2005 *************** *** 0 **** --- 1,27 ---- + /* PR 5035 */ + /* { dg-do compile } */ + /* { dg-options "-O2 -Wall -Werror" } */ + extern int f(void); + + + int main(void) + { + int a, b, c; /* { dg-bogus "b" "uninitialized variable warning" } */ + + a = f(); + + if (a) + { + b = 10; + } + + if (f()) + { + c = 151; + } + + if (a) + return b; + return 0; + } + *** /dev/null Wed Sep 28 10:04:49 2005 --- gcc/testsuite/gcc.dg/uninit-K.c Tue Nov 8 15:41:35 2005 *************** *** 0 **** --- 1,19 ---- + /* PR 19371 */ + /* Expected uninitialized variable warning. */ + + /* { dg-do compile } */ + /* { dg-options "-O -Wuninitialized=2" } */ + int bar(int n) { + return n + 1; + } + + + int main(void) { + int a = bar(a); /* { dg-warning "is used uninitialized" } */ + int b; + int c; + int d; + b = bar(b); /* { dg-warning "is used uninitialized" } */ + (void) bar(c); /* { dg-warning "is used uninitialized" } */ + return bar(d); /* { dg-warning "is used uninitialized" } */ + } *** /dev/null Wed Sep 28 10:04:49 2005 --- gcc/testsuite/gcc.dg/uninit-L.c Tue Nov 8 15:54:00 2005 *************** *** 0 **** --- 1,20 ---- + /* PR 20644 */ + /* { dg-do compile } */ + /* { dg-options "-O2 -Wall" } */ + + int foo () + { + int i; + int j; + + for ( ; ; ) { + i = 0; + if (0 == i) + break; + } + + if (1 == i) + return j; /* { dg-bogus "j" "is used uninitialized" { xfail *-*-* } } */ + + return 0; + } *** /dev/null Wed Sep 28 10:04:49 2005 --- gcc/testsuite/gcc.dg/uninit-M.c Tue Nov 8 16:10:57 2005 *************** *** 0 **** --- 1,34 ---- + /* PR 20968 */ + /* { dg-do compile } */ + /* { dg-options "-O2 -Wall" } */ + struct {int count;} *v1; + int c; + int k; + + extern void baz(int); + + static int bar(int *j) + { + if (k == 4) + { + *j = 1; + return 1; + } + return 0; + } + + void foo(void) + { + int i; /* { dg-bogus "i" "may be used uninitialized" { xfail *-*-* } } */ + + if (!bar(&i)) + { + if (!c) + return; + v1->count++; + } + if (!c) + { + baz(i); + } + } *** /dev/null Wed Sep 28 10:04:49 2005 --- gcc/testsuite/gcc.dg/uninit-N.c Tue Nov 8 10:58:57 2005 *************** *** 0 **** --- 1,8 ---- + /* PR 22456 */ + /* { dg-do compile } */ + /* { dg-options "-O2 -Wuninitialized=2" } */ + void foo() + { + int i; /* { dg-warning "may be used" } */ + while (i) ++i; + }