On Sun, Feb 27, 2022 at 07:10:45AM +0000, David Laight wrote: > From: Segher Boessenkool > > Sent: 27 February 2022 01:10 > > On Sat, Feb 26, 2022 at 11:14:15PM +0100, Arnd Bergmann wrote: > > > On Sat, Feb 26, 2022 at 1:42 PM Segher Boessenkool > > > <segher@xxxxxxxxxxxxxxxxxxx> wrote: > > > > The only reason the warning exists is because it is undefined behaviour > > > > (not implementation-defined or anything). The reason it is that in the > > > > standard is that it is hard to implement and even describe for machines > > > > that are not two's complement. However relevant that is today :-) > > I thought only right shifts of negative values were 'undefined'. All shifts by a negative amount, or an amount greater or equal to the width of the first operand (after the integer promotions). Right shifts of a negative value. Left shifts of a negative value where E1*2**E2 is not expressable in the result type. C90 (aka C89) had those right shifts merely implementation-defined behaviour, and the left shifts perfectly well-defined. > And that was to allow cpu that only had logical shift right > (ie ones that didn't propagate the sign) to be conformant. The C99 rationale says The C89 Committee affirmed the freedom in implementation granted by K&R in not requiring the signed right shift operation to sign extend, since such a requirement might slow down fast code and since the usefulness of sign extended shifts is marginal. (Shifting a negative two’s-complement integer arithmetically right one place is not the same as dividing by two!) > I wonder when the last cpu like that was? There still are one-off cores without such an instruction. If you have right shifts at all (if you have shifts at all!) it quickly becomes apparent what a hassle it is not to have an SRA/ASR/SAR instruction, and it is easy to implement, so :-) The last widely spread ones' complement machine was the 6600 I guess, which disappeared somewhere in the 80's. Sign-magnitude machines are still made: all FP is like that, and some (simple, embedded, etc.) machines have no separate integer register set. C is available for most such fringe CPUs :-) > Quite why the standards keeps using the term 'undefined behaviour' > beats me - there ought to be something for 'undefined value'. It is pretty much impossible to not have *some* undefined behaviour. How will you define dividing by zero so that its behaviour is reasonable for every program, for example? Invoking an error handler at runtime has most of the same unwanted effects, except is is never silent. You can get that via UBSAN for example. Defining some arbitrary value as the "correct" answer when that is not at all obvious *does* give silent, unexpected results. C does have "unspecified value"s and "unspecified behaviour". It requires the implementation to document the choice made here. At least some effort was made not to have undefined behaviour everywhere. Perhaps C does have the concept you are after in 6.3.2/2, where it talks about using uninitialised objects? Of course, using an uninitialised object is undefined behaviour :-P C has much more undefined behaviours than most other languages. On one hand there was no clear, formal definition of the language (and testsuites for it etc.) before it became popular. On the other hand, it was implemented on widely different architectures, back in the days when there was a lot more variety in implementation choices than there is now. When the language was standardised (and all the way to this day) the sentiment was to not unnecessarily break existing implementations. Segher