This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: GCC turns &~ into | due to undefined bit-shift without warning
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Moritz Strübe <moritz dot struebe at redheads dot de>
- Cc: "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>, Nicolai Steinkamp <nicolai dot steinkamp at redheads dot de>
- Date: Mon, 11 Mar 2019 12:17:02 +0100
- Subject: Re: GCC turns &~ into | due to undefined bit-shift without warning
- References: <4af9e251-f4c3-a5a4-e33d-fb8750c87e36@redheads.de> <20190311091449.GB7611@tucnak> <9085342b-41a6-851c-28e3-08a40cc30103@redheads.de>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Mon, Mar 11, 2019 at 11:06:37AM +0000, Moritz Strübe wrote:
> On 11.03.2019 at 10:14 Jakub Jelinek wrote:
> > You could build with -fsanitize=undefined, that would tell you at runtime you
> > have undefined behavior in your code (if the SingleDiff has bit ever 0x20
> > set).
>
> Yes, that helps. Unfortunately I'm on an embedded system, thus the code
> size increase is just too big.
You can -fsanitize-undefined-trap-on-error, which doesn't increase size too
much, it is less user-friendly, but still should catch the UB.
> > The fact that negative or >= bit precision shifts are UB is widely known,
> > and even if it wouldn't, for the compiler all the UBs are just UBs, the
> > compiler optimizes on the assumption that UB does not happen, so when it
> > sees 32-bit int << (x & 32), it can assume x must be 0 at that point,
> > anything else is UB.
>
> Thanks for that explanation. None the less, a compile time warning would
> be nice. Especially as I this was caused by a library provided by ST. :(
> Seems like we really need to add more sophisticated static analysis to
> our CI.
What you think the code would do for int << 32? The probable reason why it
is UB in the standard is that each CPU handles that differently, on some
shift left by large count results in 0, on others the shift count is modulo
the bitsize, on yet others the shift count is also masked, but e.g. by
wordsize even when the shifted count is smaller (say int << 32 is 0, but int
<< 64 is like int << 0).
A warning is a bad idea generally, we'd need to warn for all cases where the
shift count is not compile time constant, all of those could be out of
bounds in theory.
Jakub