From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id A1AFB3858413; Tue, 16 Aug 2022 16:00:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A1AFB3858413 From: "msebor at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/106559] [10/11/12/13 Regression] Spurious warning -Wformat-truncation (regression from 9) Date: Tue, 16 Aug 2022 16:00:54 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 10.3.1 X-Bugzilla-Keywords: diagnostic X-Bugzilla-Severity: normal X-Bugzilla-Who: msebor at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: 10.5 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc blocked Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Aug 2022 16:00:54 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D106559 Martin Sebor changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |msebor at gcc dot gnu.org Blocks| |85741 --- Comment #2 from Martin Sebor --- The warning triggers because it considers the size of the whole `string' ar= ray passed as an argument to the %s directive. It does that because the analys= is is unable to determine which array element the argument points to and it's = not "smart" enough to see that all the elements are strings of the same length.= =20 The output of the -fdump-tree-strlen option below helps see what's gooing on (the numbers next to each Result: show the minimum, maximum, likely, and unlikely amount of output produced by the directive, with the corresponding running totals in parentheses). The problem can be reduced to a missed optimization opportunity in the test following test case: the condition in each iteration of the loop is false so the loop can be optimized away, but because of the incomplete analysis abov= e it is not. void f (void) { static const char string[16][3]=3D{ "01","02","03","04","05","06","07","08", "09","10","11","12","13","14","15","16"}; for(unsigned int i=3D0; i<16; ++i) if (__builtin_strlen (string[i]) !=3D 2) __builtin_abort (); } Short of improving the strlen optimization the warning could also be suppre= ssed by considering the cast in the assignment `_2 =3D (const char[3] *) ivtmp.1= 1_15;' and using the size of the array as the upper bound on the length of the str= ing. (This wouldn't be safe for the optimization.) Until this is fixed in GCC, the warning can be suppressed and the emitted c= ode improved by asserting in each iteration that the length of the string is (at most) two, like so: if (__builtin_strlen (string[i]) !=3D 2) __builtin_unreachable (); pr106559.c:11: __builtin_snprintf: objsize =3D 64, fmtstr =3D "%u (%s): %= 8x" Directive 1 at offset 0: "%u" Result: 1, 2, 2, 2 (1, 2, 2, 2) Directive 2 at offset 2: " (", length =3D 2 Result: 2, 2, 2, 2 (3, 4, 4, 4) Directive 3 at offset 4: "%s" Result: 0, 47, 47, 9223372036854775807 (3, 51, 51, -9223372036854775805) Directive 4 at offset 6: "): ", length =3D 5 Result: 5, 5, 5, 5 (8, 56, 56, -9223372036854775800) Directive 5 at offset 11: "%8x" Result: 8, 8, 8, 8 (16, 64, 64, -9223372036854775792) Directive 6 at offset 14: "", length =3D 1 pr106559.c: In function =E2=80=98f=E2=80=99: pr106559.c:11:61: warning: =E2=80=98__builtin_snprintf=E2=80=99 output may = be truncated before the last format character [-Wformat-truncation=3D] 11 | __builtin_snprintf(buffer,sizeof(buffer),"%u (%s): %8x", | ^ pr106559.c:11:5: note: =E2=80=98__builtin_snprintf=E2=80=99 output between = 17 and 65 bytes into a destination of size 64 11 | __builtin_snprintf(buffer,sizeof(buffer),"%u (%s): %8x", | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | i,string[i],number[i]); | ~~~~~~~~~~~~~~~~~~~~~~ void f () { unsigned long ivtmp.11; unsigned long ivtmp.5; unsigned int i; static const char string[16][3] =3D {"01", "02", "03", "04", "05", "06", = "07", "08", "09", "10", "11", "12", "13", "14", "15", "16"}; unsigned int _1; const char[3] * _2; unsigned int _18; [local count: 63136016]: ivtmp.11_17 =3D (unsigned long) &string; [local count: 1010605809]: # ivtmp.5_13 =3D PHI # ivtmp.11_15 =3D PHI _18 =3D (unsigned int) ivtmp.5_13; _1 =3D MEM[(unsigned int *)&number + ivtmp.5_13 * 4]; _2 =3D (const char[3] *) ivtmp.11_15; <<< = cast not considered __builtin_snprintf (&buffer, 64, "%u (%s): %8x", _18, _2, _1); <<< warning here for _2 Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D85741 [Bug 85741] [meta-bug] bogus/missing -Wformat-overflow=