Dear all, In order to fix PR 179, I need help either understanding why exactly the warning is triggered or obtaining a small self-contained testcase to reproduce it.
Thanks in advance, Manuel. The attached patch triggers the warnings: /home/manuel/src/trunk/gcc/builtins.c: In function 'fold_builtin_strchr': /home/manuel/src/trunk/gcc/builtins.c:11095: error: 'c' is used uninitialized in this function /home/manuel/src/trunk/gcc/builtins.c: In function 'fold_builtin_memchr': /home/manuel/src/trunk/gcc/builtins.c:8963: error: 'c' is used uninitialized in this function Uncommenting the following avoids the warning: + /* + 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; + } + */ The alias dump is: fold_builtin_strchr (union tree_node * s1D.68612, union tree_node * s2D.68613, union tree_node * typeD.68614) { union tree_node * temD.68620; const charD.1 * rD.68619; charD.1 cD.68618; const charD.1 * p1D.68617; union tree_node * D.68650; union tree_node * D.68649; long intD.2 D.68648; long intD.2 p1.2917D.68647; long intD.2 r.2916D.68646; union tree_node * D.68644; intD.0 D.68641; charD.1 c.2915D.68640; intD.0 D.68637; short unsigned intD.8 D.68631; union tree_node * D.68630; unsigned charD.10 D.68629; unsigned charD.10 D.68627; # BLOCK 2 freq:10000 # PRED: ENTRY [100.0%] (fallthru,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11095] # VUSE <cD.68618_34(D)> { cD.68618 } D.68627_3 = validate_argD.45737 (s1D.68612_2(D), 10); [/home/manuel/src/trunk/gcc/builtins.c : 11095] if (D.68627_3 == 0) goto <bb 10>; else goto <bb 3>; # SUCC: 10 [95.7%] (true,exec) 3 [4.3%] (false,exec) # BLOCK 3 freq:434 # PRED: 2 [4.3%] (false,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11095] # VUSE <cD.68618_34(D)> { cD.68618 } D.68629_5 = validate_argD.45737 (s2D.68613_4(D), 8); [/home/manuel/src/trunk/gcc/builtins.c : 11095] if (D.68629_5 == 0) goto <bb 10>; else goto <bb 4>; # SUCC: 10 [90.0%] (true,exec) 4 [10.0%] (false,exec) # BLOCK 4 freq:43 # PRED: 3 [10.0%] (false,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11102] # VUSE <cD.68618_34(D), SMT.3811D.75594_35(D)> { cD.68618 SMT.3811D.75594 } D.68631_6 = s2D.68613_4(D)->baseD.20795.codeD.19700; [/home/manuel/src/trunk/gcc/builtins.c : 11102] if (D.68631_6 != 23) goto <bb 10>; else goto <bb 5>; # SUCC: 10 [98.3%] (true,exec) 5 [1.7%] (false,exec) # BLOCK 5 freq:1 # PRED: 4 [1.7%] (false,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11105] # cD.68618_37 = VDEF <cD.68618_34(D)> # SMT.3811D.75594_38 = VDEF <SMT.3811D.75594_35(D)> # SMT.3812D.75595_39 = VDEF <SMT.3812D.75595_36(D)> { cD.68618 SMT.3811D.75594 SMT.3812D.75595 } p1D.68617_8 = c_getstrD.45477 (s1D.68612_2(D)); [/home/manuel/src/trunk/gcc/builtins.c : 11106] if (p1D.68617_8 != 0B) goto <bb 6>; else goto <bb 10>; # SUCC: 6 [20.5%] (true,exec) 10 [79.5%] (false,exec) # BLOCK 6 # PRED: 5 [20.5%] (true,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11112] # cD.68618_40 = VDEF <cD.68618_37> # SMT.3811D.75594_41 = VDEF <SMT.3811D.75594_38> # SMT.3812D.75595_42 = VDEF <SMT.3812D.75595_39> { cD.68618 SMT.3811D.75594 SMT.3812D.75595 } D.68637_10 = target_char_castD.45483 (s2D.68613_4(D), &cD.68618); [/home/manuel/src/trunk/gcc/builtins.c : 11112] if (D.68637_10 != 0) goto <bb 10>; else goto <bb 7>; # SUCC: 10 [39.0%] (true,exec) 7 [61.0%] (false,exec) # BLOCK 7 # PRED: 6 [61.0%] (false,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11115] # VUSE <cD.68618_40> { cD.68618 } c.2915D.68640_12 = cD.68618; [/home/manuel/src/trunk/gcc/builtins.c : 11115] D.68641_13 = (intD.0) c.2915D.68640_12; [/home/manuel/src/trunk/gcc/builtins.c : 11115] # VUSE <cD.68618_40> { cD.68618 } rD.68619_14 = strchrD.689 (p1D.68617_8, D.68641_13); [/home/manuel/src/trunk/gcc/builtins.c : 11117] if (rD.68619_14 == 0B) goto <bb 8>; else goto <bb 9>; # SUCC: 8 [10.1%] (true,exec) 9 [89.9%] (false,exec) # BLOCK 9 # PRED: 7 [89.9%] (false,exec) [/home/manuel/src/trunk/gcc/builtins.c : 11121] r.2916D.68646_20 = (long intD.2) rD.68619_14; [/home/manuel/src/trunk/gcc/builtins.c : 11121] p1.2917D.68647_21 = (long intD.2) p1D.68617_8; [/home/manuel/src/trunk/gcc/builtins.c : 11121] D.68648_22 = r.2916D.68646_20 - p1.2917D.68647_21; [/home/manuel/src/trunk/gcc/builtins.c : 11121] # cD.68618_46 = VDEF <cD.68618_40> # SMT.3811D.75594_47 = VDEF <SMT.3811D.75594_41> # SMT.3812D.75595_48 = VDEF <SMT.3812D.75595_42> { cD.68618 SMT.3811D.75594 SMT.3812D.75595 } D.68649_23 = size_int_kindD.21427 (D.68648_22, 0); [/home/manuel/src/trunk/gcc/builtins.c : 11121] # VUSE <cD.68618_46, SMT.3811D.75594_47> { cD.68618 SMT.3811D.75594 } D.68650_26 = s1D.68612_2(D)->commonD.20796.typeD.19731; [/home/manuel/src/trunk/gcc/builtins.c : 11121] # cD.68618_49 = VDEF <cD.68618_46> # SMT.3811D.75594_50 = VDEF <SMT.3811D.75594_47> # SMT.3812D.75595_51 = VDEF <SMT.3812D.75595_48> { cD.68618 SMT.3811D.75594 SMT.3812D.75595 } temD.68620_27 = fold_build2_statD.21716 (67, D.68650_26, s1D.68612_2(D), D.68649_23); [/home/manuel/src/trunk/gcc/builtins.c : 11123] # cD.68618_52 = VDEF <cD.68618_49> # SMT.3811D.75594_53 = VDEF <SMT.3811D.75594_50> # SMT.3812D.75595_54 = VDEF <SMT.3812D.75595_51> { cD.68618 SMT.3811D.75594 SMT.3812D.75595 } D.68630_30 = fold_convertD.21753 (typeD.68614_29(D), temD.68620_27); # SUCC: 10 [100.0%] (fallthru,exec) # BLOCK 10 freq:10000, starting at line 0 # PRED: 3 [90.0%] (true,exec) 4 [98.3%] (true,exec) 6 [39.0%] (true,exec) 8 [100.0%] (fallthru,exec) 9 [100.0%] (fallthru,exec) 5 [79.5%] (false,exec) 2 [95.7%]\ (true,exec) # D.68630_1 = PHI <0B(3), 0B(4), 0B(6), D.68630_18(8), D.68630_30(9), 0B(5), 0B(2)> return D.68630_1; # SUCC: EXIT [100.0%] }
Index: gcc/testsuite/gcc.dg/uninit-B.c =================================================================== --- gcc/testsuite/gcc.dg/uninit-B.c (revision 139006) +++ 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-2.c =================================================================== --- gcc/testsuite/gcc.dg/uninit-pr19430-2.c (revision 0) +++ gcc/testsuite/gcc.dg/uninit-pr19430-2.c (revision 0) @@ -0,0 +1,15 @@ +int *p, *q; + +int foo (int b) +{ + int i, j = 0; + int *x; + p = &i; + q = &j; + if (b) + x = p; + else + x = q; + return *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 139006) +++ gcc/tree-ssa.c (working copy) @@ -1375,10 +1375,60 @@ 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,16 +1452,41 @@ warn_uninit (tree t, const char *gmsgid, gimple context = (gimple) data; location_t location; expanded_location xloc, floc; if (!ssa_undefined_value_p (t)) + { + /* 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); + use_operand_p vuse; + tree op; + + if (!gimple_references_memory_p (def)) + return; + + vuse = SINGLE_SSA_USE_OPERAND (def, SSA_OP_VUSE); + if (vuse == NULL_USE_OPERAND_P) + return; + + op = USE_FROM_PTR (vuse); + /* 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); + if (!ssa_maybe_uninitialized_var_p (var)) + return; + goto warn; + } + return; + } + if (!ssa_maybe_uninitialized_var_p (var)) return; - - /* TREE_NO_WARNING either means we already warned, or the front end - wishes to suppress the warning. */ - if (TREE_NO_WARNING (var)) - return; + warn: location = (context != NULL && gimple_has_location (context)) ? gimple_location (context) : DECL_SOURCE_LOCATION (var); xloc = expand_location (location); @@ -1480,13 +1555,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);