This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GCC turns &~ into | due to undefined bit-shift without warning


On 22/03/2019 11:20, Allan Sandfeld Jensen wrote:
> On Freitag, 22. März 2019 11:02:39 CET Andrew Haley wrote:
>> On 3/21/19 10:19 PM, Allan Sandfeld Jensen wrote:
>>> From having fixed UBSAN warnings, I have seen many cases where undefined
>>> behavior was performed, but where the code was aware of it and the final
>>> result of the expression was well defined nonetheless.
>>
>> Is this belief about undefined behaviour commonplace among C programmers?
>> There's nothing in the standard to justify it: any expression which contains
>> UB is undefined.
> 
> Yes, even GCC uses undefined behavior when it is considered defined for 
> specific architecture, whether it be the result of unaligned access, negative 
> shifts, etc. There is a lot of the warnings that UBSAN warns about that you 
> will find both in GCC itself, the Linux kernel and many other places.
> 

You are mixing up several things here.

Behaviour can be undefined by the C standard, but defined elsewhere - in
the implementation (i.e., compiler - with whatever flags are choosen),
in the target ABI, in additional standards such as POSIX.

If you compile C code with "gcc -fwrapv", then signed integer overflow
is fully defined (as wrapping behaviour), regardless of what is written
in the C standards.

If you compile a "hello, world!" C program, then the C standards do not
define how those words get on your screen.  As far as /C/ is concerned,
the workings of "printf" are undefined behaviour - because the C
standard does not define them.

Clearly, virtually any C program relies strongly on behaviour that is
not defined by the C standards.


However, expressions such as an overflowing signed shift are generally
not defined /anywhere/.  (It is, of course, possible for a particular C
compiler to define them.)


Unfortunately, it is true that some C programmers think it is fine to
rely on undefined behaviour if it all seems to work fine in their tests
- even when they /know/ it is undefined and unsafe.  All we can do here
is try to educate them - teach them that this is not good practice.

It is also unfortunately the case that with older and weaker compilers,
you could rely on their undocumented treatment of some kinds of
undefined behaviour, and that this was the only way to get efficient
results for certain coding problems.  Correct, fully defined code was
much slower on such compilers, while on better compilers the safe code
works efficiently.  If you can't avoid such old compilers, then at least
use conditional compilation and pre-processor checks to ensure that the
bad code is only used on the poor tools.

And of course there are also lots of programmers whose knowledge of C is
imperfect, or who make mistakes (and very, very few who don't!) - some
code accidentally relies on the results of undefined behaviour.  Even
the gcc and Linux authors are not immune to the occasional bug in their
code.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]