News for hackers. Stuff that matters.
Re:Attention people who think UB is fine by omoikane on Sunday October 25, 2026 @01:02AM (#50228479)
The first example should have changed the heading to "C++ code" as opposed to "C code" due to the use of `std::unreachable()`. This matches the godbolt link.

Another alternative is to use `__builtin_unreachable()` (not standard, but available in GCC and Clang).

Re:Attention people who think UB is fine by zarakshR on Sunday October 25, 2026 @01:20AM (#50228571)
Re:Attention people who think UB is fine by munch117 on Sunday October 25, 2026 @07:00AM (#50230321)
C23 also has the "no time travel" stipulation. I expect C23 should be immune to the example 1 program issue, because of that. A quick trial on godbolt (https://godbolt.org/z/8K81PYoYE) seems to agree, with the caveat that I didn't work out the right compiler options to show for sure.
Re:Attention people who think UB is fine by thomashabets2 on Sunday October 25, 2026 @08:58AM (#50231079)
C++26, IIRC, adds "no time travel" to C++. But note that your example still creates exploding chocolate, so what do you mean by "immune"? C compiler with -std=c23 -O1 produces literally the exact same assembly output.
Re:Attention people who think UB is fine by munch117 on Sunday October 25, 2026 @11:57AM (#50232958)
Of course things go badly once we reach "unreachable()", continuing into the next function because the compiler didn't bother to add a "ret". That's no surprise, "unreachable()" is basically an instruction to the compiler to stop generating code from that point on, and the compiler obeyed.

Before that the observable side-effect, device_command=42, has already happened. With time travel allowed, could also have been omitted, which would have been a real problem.

I misread the article to think that is was about the latter problem. You are right, my mistake. I didn't consider that anyone could see the former as a problem at all: It's just the compiler doing exactly what it's told to do.

Re:Attention people who think UB is fine by mpyne on Sunday October 25, 2026 @12:02PM (#50233017)
> That's no surprise, "unreachable()" is basically an instruction to the compiler to stop generating code from that point on, and the compiler obeyed.

It's not a command to compiler to stop generating code.

It's a permission slip that allows the compiler to assume that code that follows is dead code, eligible to be optimized out, including eliminating potentially dead stores and loads.

Which is to say, it's precisely what any other UB is, which is why deliberate use of UB is very bad idea.

Re:Attention people who think UB is fine by munch117 on Monday October 26, 2026 @03:48AM (#50240449)
Compare with this:

  double f(void* p) {
    return * (double*) p;
  }
No one is surprised that defensive code isn't issued to guard against p being NULL, unaligned, or pointing to a uint16_t. You told the compiler that p is actually pointing to a double, and it generates code accordingly.

It's the same thing here: You told the compiler very explicitly that anything following this point is unreachable, and it generated code accordingly.

I'm not defending writing code with UB. I would have preferred the compiler issuing a warning saying "you say this is unreachable, I don't believe that it is", when it's this obvious. Maybe issue a trap instruction. But there's nothing wrong it, per se. When you choose to override the compiler's judgment and insist that this point in code is unreachable, then the compiler takes your word for it.

Re:Attention people who think UB is fine by thomashabets2 on Monday October 26, 2026 @05:29AM (#50241228)
Author here.

Of course I would also prefer a warning, or at least a guarding trap instruction. And maybe compilers should try harder to be friendly in this way.

But they can't be perfect, because the program specified something syntactically valid, but semantically invalid. The module/compiler pass that could theoretically detect it may simply not be issued the necessary information. E.g. a solver may be given the input that a value is in a given range, and from that simplify an operation. If the input is wrong, so is the output.

Reminds me of:

    On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
In the example from the article, though, there could be a pass that simply eliminated dead code. That pass is not a parser of the raw code, so how is it to know that actually, the "dead code" isn't?

And a standard that would require dead code elimination to replace not with empty, but with a trap instruction, could go very wrong. You don't want `if (false) { … }` to become `if (false) { trap(); }`. You want it just removed, if a previous pass deemed it dead. Or do you want `int main() { for(;;) {cli_loop();} }` to force adding a trap in the unreachable code after the loop? That's a lot of generated trap instructions.

So in general this means solving the halting problem. Yes, specifically in the post's example, "surely a sufficiently smart compiler could detect something this obvious". Maybe so, but how often is the bug actually this obvious?

Re:Attention people who think UB is fine by ameliaquining on Monday October 26, 2026 @01:17AM (#50239451)
Link to an explanation of the C++26 change? I can't find it.
Re:Attention people who think UB is fine by thomashabets2 on Monday October 26, 2026 @05:51AM (#50241367)
I believe this is https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p14... and seen in 4.1.2p6 of https://eel.is/c++draft/intro.abstract, and then p7 lists what the time travel gates (observable behavior) is.

Now if this actually made it into the C++26 standard, I've not paid to get the official one, but it's in the N5050 draft: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/n50...

Re:Attention people who think UB is fine by thomashabets2 on Sunday October 25, 2026 @09:02AM (#50231109)
Author here.

Yes, into the shame cube I go. It doesn't change anything, and it applies equally to C and C++, but you are correct. Thanks.