https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94021
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Keywords| |diagnostic Last reconfirmed| |2020-03-03 Component|c |tree-optimization CC| |msebor at gcc dot gnu.org Blocks| |85741 Ever confirmed|0 |1 Summary|-Werror=format-truncation= |-Wformat-truncation false |seems to cause incorrect |positive due to excessive |warning, thus error. |integer range Known to fail| |10.0, 9.2.0 --- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> --- Confirmed with the small test case below. The warning code works correctly but the integer conditionals are somehow confusing EVRP into thinking h's range is [0, 596523], which causes the warning to trigger. The dump shows that the warning thinks the result of the first %02i directive is between 2 and 6 characters: Directive 2 at offset 2: "%02i" Result: 2, 6, 6, 6 (3, 7, 7, 7) $ cat pr94021.c && gcc -O2 -S -Wall -fdump-tree-strlen=/dev/stdout pr94021.c char a[8]; void format_utc_offset (int x) { if (x < 0) x = -x; int h = x / 3600, m = (x % 3600) / 60; if (h < 0 || h >= 24 || m < 0 || m >= 60) __builtin_puts (""); if (0 <= m && m <= 60 && 0 <= h && h <= 24) __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m); } ;; Function format_utc_offset (format_utc_offset, funcdef_no=0, decl_uid=1931, cgraph_uid=1, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 3 4 5 6 ;; 2 succs { 3 6 } ;; 3 succs { 6 } ;; 4 succs { 5 } ;; 5 succs { 1 } ;; 6 succs { 4 5 } pr94021.c:14: __builtin_snprintf: objsize = 8, fmtstr = "%s%02i%02i" Directive 1 at offset 0: "%s" Result: 1, 1, 1, 1 (1, 1, 1, 1) Directive 2 at offset 2: "%02i" Result: 2, 6, 6, 6 (3, 7, 7, 7) Directive 3 at offset 6: "%02i" pr94021.c: In function ‘format_utc_offset’: pr94021.c:14:45: warning: ‘%02i’ directive output may be truncated writing 2 bytes into a region of size between 1 and 5 [-Wformat-truncation=] 14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m); | ^~~~ pr94021.c:14:38: note: directive argument in the range [0, 59] 14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m); | ^~~~~~~~~~~~ Result: 2, 2, 2, 2 (5, 9, 9, 9) Directive 4 at offset 10: "", length = 1 pr94021.c:14:5: note: ‘__builtin_snprintf’ output between 6 and 10 bytes into a destination of size 8 14 | __builtin_snprintf (a, sizeof a, "%s%02i%02i", "+", h, m); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Moving the test for hours etc. being out-of-bounds after the test for them being in-bounds avoids the warning (and streamlines the code so it seems like an overall improvement). Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85741 [Bug 85741] [meta-bug] bogus/missing -Wformat-overflow