https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77721
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2016-09-27 CC| |msebor at gcc dot gnu.org Ever confirmed|0 |1 Known to fail| |7.0 --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- Confirmed. The warning is a false positive (and with -Wformat-length=2 is issued for both functions). The output of the -ftree-dump-vrp option shows that the Value Range Propagation pass correctly determines each variable's range to be [0, 999] but, as the note printed after the warning indicates, the range made available to the gimple-ssa-sprintf pass (via the get_range_info API) is that of unsigned int. Unfortunately, this is a general limitation in the current implementation of ranges in GCC and not something that can be fixed in the warning pass. A new implementation of VRP is in progress but it doesn't seem likely that it will make it into GCC 7. $ cat zzz.c && /build/gcc-trunk-svn/gcc/xgcc -B /build/gcc-trunk-svn/gcc -O2 -O2 -S -Wall -Wformat-length=2 zzz.c int snprintf (char*, __SIZE_TYPE__, const char*, ...); void foo(unsigned j, char *p) { if(j > 999) return; snprintf(p, 4, "%3u", j); } void bar(int j, char *p) { const unsigned k = (unsigned) j; if(k > 999) return; snprintf(p, 4, "%3u", k); } zzz.c: In function ‘foo’: zzz.c:7:21: warning: ‘%3u’ directive output may be truncated writing between 3 and 10 bytes into a region of size 4 [-Wformat-length=] snprintf(p, 4, "%3u", j); ^~~ zzz.c:7:20: note: using the range [‘1u’, ‘2147483648u’] for directive argument snprintf(p, 4, "%3u", j); ^~~~~ zzz.c:7:5: note: format output between 4 and 11 bytes into a destination of size 4 snprintf(p, 4, "%3u", j); ^~~~~~~~~~~~~~~~~~~~~~~~ zzz.c: In function ‘bar’: zzz.c:15:21: warning: ‘%3u’ directive output may be truncated writing between 3 and 10 bytes into a region of size 4 [-Wformat-length=] snprintf(p, 4, "%3u", k); ^~~ zzz.c:15:20: note: directive argument in the range [0u, 4294967295u] snprintf(p, 4, "%3u", k); ^~~~~ zzz.c:15:5: note: format output between 4 and 11 bytes into a destination of size 4 snprintf(p, 4, "%3u", k); ^~~~~~~~~~~~~~~~~~~~~~~~