https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79692
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |diagnostic Status|UNCONFIRMED |NEW Last reconfirmed| |2017-02-23 CC| |msebor at gcc dot gnu.org Assignee|unassigned at gcc dot gnu.org |msebor at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- Confirmed. A small test case is below. When an integer directive's argument is in a known range the checker assumes the result of the directive is also in a known range even if the width or precision is not. When the range of the directive's output is known the checker uses its upper bound to determine whether or not to warn, even at level 1. The solution (until this is fixed) is to constrain the width (or precision) range, e.g., by adding the following above the sprintf call. if (w < 0 || w > 7) __builtin_unreachable (); $ cat u.c && gcc -O2 -S -Wall -Wunused -Wpedantic -fdump-tree-printf-return-value=/dev/stdout u.c char d[8]; void f (int w, unsigned x) { if (x > 9) x = 0; __builtin_sprintf (d, "%*x", w, x); } ;; Function f (f, funcdef_no=0, decl_uid=1797, cgraph_uid=0, symbol_order=1) u.c:8: __builtin_sprintf: objsize = 8, fmtstr = "%*x" Directive 1 at offset 0: "%*x", width in range [0, 2147483648] u.c: In function ‘f’: u.c:8:26: warning: ‘%*x’ directive writing between 1 and 2147483648 bytes into a region of size 8 [-Wformat-overflow=] __builtin_sprintf (d, "%*x", w, x); ^~~ u.c:8:25: note: directive argument in the range [0, 9] __builtin_sprintf (d, "%*x", w, x); ^~~~~ Result: 1, 2147483648, 2147483648, 2147483648 (1, 2147483648, 2147483648, 2147483648) Directive 2 at offset 3: "", length = 1 u.c:8:3: note: ‘__builtin_sprintf’ output between 2 and 2147483649 bytes into a destination of size 8 __builtin_sprintf (d, "%*x", w, x); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ f (int w, unsigned int x) { <bb 2> [100.00%]: if (x_2(D) > 9) goto <bb 3>; [54.00%] else goto <bb 4>; [46.00%] <bb 3> [54.00%]: <bb 4> [100.00%]: # x_1 = PHI <x_2(D)(2), 0(3)> __builtin_sprintf (&d, "%*x", w_4(D), x_1); return; }