------- Comment #11 from davidxl at gcc dot gnu dot org 2010-04-20 23:55 ------- (In reply to comment #2) > (In reply to comment #1) > > check() can return 1 on the first call and 0 on the second and if *argv is > > NULL > > then then "bug" will be used uninitialized. > > right, but this doesn't matter here. Better testcase: > > /* { dg-do compile } */ > /* { dg-options "-Os -Wuninitialized" } */ > void bail(void) __attribute__((noreturn)); > unsigned once(void); > int pr(char**argv) > { > char *bug; > unsigned check = once(); > if (check) { > if (*argv) > bug = *++argv; > } else { > bug = *argv++; > if (!*argv) > bail(); > } > /* now bug is set except if (check && !*argv) */ > if (check) { > if (!*argv) > return 0; > } > /* if we ever get here then bug is set */ > return *bug != 'X'; > } >
The example is a little tricky for the compiler to reason because of the '++argv'. Predicate analysis (http://gcc.gnu.org/ml/gcc-patches/2010-04/msg00706.html -- with additional fix to a never return handling) will catch the following case (while the trunk gcc does not): void bail(void) __attribute__((noreturn)); int foo(void); unsigned once(void); int pr(char**argv) { char *bug; unsigned check = once(); char * a = *argv; if (check) { if (a) bug = *++argv; } else { bug = *argv++; if (!*argv) bail(); } if (foo ()) once(); /* now bug is set except if (check && !*argv) */ if (check) { if (!a || !*argv) return 0; } /* if we ever get here then bug is set */ return *bug != 'X'; } -- davidxl at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |davidxl at gcc dot gnu dot | |org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36550