Almost Always Unsigned (2022)

19 points by intelfx


intelfx

Previously discussed on Lobsters a few years ago.

Re-submitting prompted by by a complementary article posted recently.

ralfj

Unfortunately, for languages based on LLVM, no amount of hand-waving and wanting signed wrapping to be defined will work no matter how hard you try, so such statements about safety are factually incorrect. Here’s a somewhat non-exhaustive list of all the undefined behavior of signed integer arithmetic in LLVM which applies to all languages which use LLVM:

This is completely wrong. A compiler can compile its code in a way that prevents the LLVM-level UB, and that's exactly what Rust does. In fact it's even more wrong for the subtraction example which is by default not UB in LLVM -- sub has wrapping semantics. One has to add an attribute to get "overflow is UB".

Most of the motivation of this article applies to C and C++, but examples for other languages such as Go, Rust and Odin will also be presented in an attempt to establish that this concept applies to all languages, regardless of their choices (for instance C and C++ leave signed integer wrap undefined), but rather is intrinsic to the arithmetic itself.

Unfortunately, the article does not live up to the expectation of providing language-independent arguments. The C/C++-specific UB on signed integer overflow is mentioned 8 times. The "Checking for overflow and underflow is easier and safer" section is entirely language-specific; just because C/C++ have no good APIs to check for signed overflow doesn't mean such an API is impossible (and I would argue x + y < x is still a bad way to check for overflow as it is far from self-explaining). It's also outdated, C23 added some APIs for this purpose (ckd_add etc).

If we disregard that part, the only arguments that seem to remain are