Maybe I should suggest avoiding the same fate for Rust's unchecked_shl and unchecked_shr. (These aren't stabilized yet unlike the safe options and the rotates)
Why is it too late? Changing it in a later version of the standard wouldn't be a further constraint on any written code; any code which is currently correct will remain correct, and some code which could have done literally anything will now only be able to have one of a few possible behaviours.
But I'd also suppose there aren't many such CPUs. Does anyone know of any?
Maybe not?
I'm pretty sure that "trap" is an allowed behaviour for NaNs in some parts of the standard already, if properly documented. I don't see why unspecified/implementation-defined behaviour for shifts couldn't be allowed to do the same, on appropriate targets?
But also, the new behaviour should only be required of compilers in the to-be-written `--std=c++3X` (or whatever) mode. Any compilers conforming to an earlier version of the standard can already do whatever they're currently doing.
Consider how long it took C++ to deprecate support for integers that are not two's complement, when every piece of silicon for many decades has been a two's complement design. In the case of shift instructions, it is defined differently across ISAs used today.
When this operation is undefined, you must always put a branch instruction in front of it, on any architecture, regardless if it happens to do what you want.
Even when you know precisely the type of CPU on which the program will be run, you would need to use inline assembly to be sure of the behavior of the program.
When you can guarantee that the operand will never have the undesired value, then no branch instruction would be used on any architecture, regardless how the C standard would define the operation.
It is always better when the programming language standard defines completely all operations.
In the worst case, when two possible operation definitions are widespread in hardware implementations, two distinct operations should be defined in the language, allowing the programmer to choose the one that is more efficient on the intended target, but knowing that the program will remain correct regardless for which target it is compiled.
Surely under those circumstances, the compiler can document doing whatever the target ISA does as its behaviour, and just output the shift as-is?
It's never too late to replace Undefined Behaviour with Unspecified Behaviour.