From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id D9E333857010; Mon, 15 Mar 2021 19:57:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D9E333857010 From: "msebor at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug middle-end/99578] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal Date: Mon, 15 Mar 2021 19:57:33 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: middle-end X-Bugzilla-Version: 11.0 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: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: 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: Mon, 15 Mar 2021 19:57:34 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D99578 --- Comment #8 from Martin Sebor --- (In reply to Arnd Bergmann from comment #6) > I figured out the qnx4 warning in the end: https://godbolt.org/z/hvqjr3 The false positive is a known problem caused by redundancy elimination (the FRE/PRE passes) substituting one member for another when they both refer to= the same address. It often happens with union members that share the same star= ting offset but can also happen with struct members in code that refers to both = the end of one and the beginning of the next member with no intervening padding. There's no particular reason why it picks one or the other member (maybe it picks whichever it sees first in some order, I don't know), but the warning only triggers when it substitutes the smaller of the two members in a larger access. In the strnlen test case w/o sanitization it happens to pick the bigger member. This can be seen in the output of -fdump-tree-pre-details: Inserted pretmp_12 =3D &de_9(D)->D.2393.D.2392.dl_fname; in predecessor 3 (0004) Replaced &de_9(D)->D.2393.D.2392.dl_fname with pretmp_12 in all uses of _5 = =3D &de_9(D)->D.2393.D.2392.dl_fname; Replaced &de_9(D)->D.2393.D.2389.di_fname with pretmp_12 in all uses of _3 = =3D &de_9(D)->D.2393.D.2389.di_fname; Removing dead stmt _3 =3D &de_9(D)->D.2393.D.2389.di_fname; Removing dead stmt _5 =3D &de_9(D)->D.2393.D.2392.dl_fname; The instrumentation introduced by the sanitizers changes the IL in ways that affect the choices made by subsequent transformations. In this case, the sanitizer first inserts a call to __builtin___tsan_read1() to record the ac= cess to di_fname[0]. The sanitizers run after PRE but before some FRE iteration= s.=20 The resulting IL from the thread sanitizer looks like this: [local count: 1073741824]: _13 =3D __builtin_return_address (0); __builtin___tsan_func_entry (_13); _5 =3D &de_9(D)->D.2390.D.2386.di_fname[0]; __builtin___tsan_read1 (_5); <<< record access to di_fname[0] _1 =3D de_9(D)->D.2390.D.2386.di_fname[0]; if (_1 =3D=3D 0) goto ; [34.00%] else goto ; [66.00%] [local count: 365072224]: goto ; [100.00%] [local count: 708669601]: _3 =3D &de_9(D)->di_status; __builtin___tsan_read1 (_3); _2 =3D de_9(D)->di_status; pretmp_12 =3D &de_9(D)->D.2390.D.2389.dl_fname; <<< temporary added by = PRE if (_2 !=3D 0) goto ; [50.00%] else goto ; [50.00%] [local count: 354334800]: _4 =3D __builtin_strnlen (pretmp_12, 16); _11 =3D (int) _4; goto ; [100.00%] [local count: 354334800]: _6 =3D __builtin_strnlen (pretmp_12, 48); _10 =3D (int) _6; [local count: 1073741824]: # _7 =3D PHI <0(7), _11(4), _10(5)> __builtin___tsan_func_exit (); return _7; } The IL above is then changed by FRE which replaces dl_fname with di_fname: Value numbering stmt =3D pretmp_12 =3D &de_9(D)->D.2390.D.2389.dl_fname; Setting value number of pretmp_12 to _5 (changed) _5 is available for _5 Replaced &de_9(D)->D.2390.D.2389.dl_fname with _5 in all uses of pretmp_12 = =3D &de_9(D)->D.2390.D.2389.dl_fname; The warning is then issued by the strlen pass that runs after FRE5 and that sees the IL below: [local count: 1073741824]: _13 =3D __builtin_return_address (0); __builtin___tsan_func_entry (_13); _5 =3D &de_9(D)->D.2393.D.2389.di_fname[0]; <<< inserted by sanitizer __builtin___tsan_read1 (_5); <<< record access to di_fname= [0]=20 _1 =3D de_9(D)->D.2393.D.2389.di_fname[0]; <<< inserted by FRE5 if (_1 =3D=3D 0) goto ; [34.00%] else goto ; [66.00%] [local count: 708669601]: _3 =3D &de_9(D)->di_status; __builtin___tsan_read1 (_3); _2 =3D de_9(D)->di_status; if (_2 !=3D 0) goto ; [50.00%] else goto ; [50.00%] [local count: 354334800]: _4 =3D strnlen (_5, 16); _11 =3D (int) _4; goto ; [100.00%] [local count: 354334800]: _6 =3D strnlen (_5, 48); <<< -Wstringop-overread _10 =3D (int) _6; [local count: 1073741824]: # _7 =3D PHI <0(2), _11(4), _10(5)> __builtin___tsan_func_exit (); return _7; } I'm hoping to change PRE/FRE in GCC 12 to replace the member substitution w= ith one involving &object + offsetof (type, memer). That will avoid the false positives in these cases with no adverse impact on optimization.=