Index: gcc/testsuite/gcc.dg/uninit-B.c =================================================================== --- gcc/testsuite/gcc.dg/uninit-B.c (revision 138903) +++ gcc/testsuite/gcc.dg/uninit-B.c (working copy) @@ -7,9 +7,18 @@ extern void bar (int); void baz (void) { int i; - if (i) /* { dg-warning "uninit" "uninit i warning" { xfail *-*-* } } */ + if (i) /* { dg-warning "is used uninitialized" "uninit i warning" } */ bar (i); foo (&i); } + +void +baz2 (void) +{ + int i; + foo (&i); + if (i) + bar (i); +} Index: gcc/testsuite/gcc.dg/uninit-pr19430-O0.c =================================================================== --- gcc/testsuite/gcc.dg/uninit-pr19430-O0.c (revision 0) +++ gcc/testsuite/gcc.dg/uninit-pr19430-O0.c (revision 0) @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wuninitialized" } */ +extern int bar (int); +extern void baz (int *); + +int +foo (int i) +{ + int j; /* { dg-warning "'j' may be used uninitialized in this function" "uninitialized" { xfail *-*-* } 9 } */ + + if (bar (i)) { + baz (&j); + } else { + } + + return j; +} + + +int foo2( void ) { + int rc; /* { dg-warning "'rc' is used uninitialized in this function" "uninitialized" { xfail *-*-* } 21 } */ + return rc; + *&rc = 0; +} + +extern int printf(const char *, ...); +void frob(int *pi); + +int main(void) +{ + int i; + printf("i = %d\n", i); /* { dg-warning "'i' is used uninitialized in this function" "uninitialized" { xfail *-*-* } 32 } */ + frob(&i); + + return 0; +} + +void foo3(int*); +void bar3(void) { + int x; + if(x) /* { dg-warning "'x' is used uninitialized in this function" "uninitialized" { xfail *-*-* } 41 } */ + foo3(&x); +} Index: gcc/testsuite/gcc.dg/uninit-pr19430.c =================================================================== --- gcc/testsuite/gcc.dg/uninit-pr19430.c (revision 0) +++ gcc/testsuite/gcc.dg/uninit-pr19430.c (revision 0) @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wuninitialized" } */ +extern int bar (int); +extern void baz (int *); +int +foo (int i) +{ + int j; /* { dg-warning "'j' may be used uninitialized in this function" "uninitialized" { xfail *-*-* } 8 } */ + + if (bar (i)) { + baz (&j); + } else { + } + + return j; +} + + + +int foo2( void ) { + int rc; /* { dg-warning "'rc' is used uninitialized in this function" } */ + return rc; + *&rc = 0; +} + +extern int printf(const char *, ...); +void frob(int *pi); + +int main(void) +{ + int i; + printf("i = %d\n", i); /* { dg-warning "'i' is used uninitialized in this function" } */ + frob(&i); + + return 0; +} + +void foo3(int*); +void bar3(void) { + int x; + if(x) /* { dg-warning "'x' is used uninitialized in this function" "uninitialized" } */ + foo3(&x); +} Index: gcc/tree-ssa.c =================================================================== --- gcc/tree-ssa.c (revision 138903) +++ gcc/tree-ssa.c (working copy) @@ -1375,10 +1375,58 @@ ssa_undefined_value_p (tree t) /* The value is undefined iff its definition statement is empty. */ return gimple_nop_p (SSA_NAME_DEF_STMT (t)); } +static bool +ssa_maybe_uninitialized_var_p (tree var) +{ + /* TREE_NO_WARNING either means we already warned, or the front end + wishes to suppress the warning. */ + if (TREE_NO_WARNING (var)) + return false; + + /* Parameters get their initial value from the function entry. */ + if (TREE_CODE (var) == PARM_DECL) + return false; + + /* Hard register variables get their initial value from the ether. */ + if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var)) + return false; + + /* We do not warn for memory tags. */ + if (MTAG_P (var)) + return false; + + /* Do not warn if it can be initialized outside this module. */ + if (TREE_PUBLIC (var)) + return false; + + if (is_global_var (var)) + return false; + + /* Do not warn if it is initialized. */ + if (TREE_CODE (var) == VAR_DECL && DECL_INITIAL (var)) + return false; + + if (TYPE_MODE (TREE_TYPE (var)) == BLKmode) + return false; + + if (is_call_clobbered (var)) + { + var_ann_t va = var_ann (var); + unsigned int escape_mask = va->escape_mask; + if (escape_mask & ESCAPE_TO_ASM) + return false; + if (escape_mask & ESCAPE_IS_GLOBAL) + return false; + if (escape_mask & ESCAPE_IS_PARM) + return false; + } + return true; +} + /* Emit warnings for uninitialized variables. This is done in two passes. The first pass notices real uses of SSA names with undefined values. Such uses are unconditionally uninitialized, and we can be certain that such a use is a mistake. This pass is run before most optimizations, @@ -1402,15 +1450,49 @@ warn_uninit (tree t, const char *gmsgid, gimple context = (gimple) data; location_t location; expanded_location xloc, floc; if (!ssa_undefined_value_p (t)) - return; + { + /*struct voptype_d *vdefs;*/ + struct voptype_d *vuses; + /* Recurse into SSA virtual operands to check whether T is using + a VDEF with default definition or it is VUSing another + uninitialized variable. */ + gimple def = SSA_NAME_DEF_STMT (t); + tree op; - /* TREE_NO_WARNING either means we already warned, or the front end - wishes to suppress the warning. */ - if (TREE_NO_WARNING (var)) + if (!gimple_references_memory_p (def)) + return; + + vuses = gimple_vuse_ops (def); + while (vuses) + { + int i, n; + n = VUSE_NUM (vuses); + if (n > 1) return; + for (i = 0; i < n; i++) + { + op = VUSE_OP (vuses, i); + /* The def_stmt of this variable is VUSEing a + uninitialized variable. Warn about it. */ + if (TREE_CODE (op) == SSA_NAME + && SSA_NAME_IS_DEFAULT_DEF (op)) + { + var = SSA_NAME_VAR (op); + goto warn; + } + } + vuses = vuses->next; + } + + return; + } + + warn: + + if (!ssa_maybe_uninitialized_var_p (var)) return; location = (context != NULL && gimple_has_location (context)) ? gimple_location (context) : DECL_SOURCE_LOCATION (var); @@ -1479,13 +1561,13 @@ warn_uninitialized_var (tree *tp, int *w static void warn_uninitialized_phi (gimple phi) { size_t i, n = gimple_phi_num_args (phi); + tree t = gimple_phi_result (phi); - /* Don't look at memory tags. */ - if (!is_gimple_reg (gimple_phi_result (phi))) + if (!is_gimple_reg (t)) return; for (i = 0; i < n; ++i) { tree op = gimple_phi_arg_def (phi, i);