3 ms·
> This was made non-binding in later versions of the standard, so optimiser engineers act as if these words don't exist. This is reminiscent of the argument in
by aw1621107 5y ago
> This was made non-binding in later versions of the standard, so optimiser engineers act as if these words don't exist.
This is reminiscent of the argument in "How One Word Broke C" [0, HN discussion at 1]. I'm not particularly convinced this argument is correct. In my opinion, it's "ignoring the situation completely" that's the phrase of interest; after all, what is assuming that UB cannot occur but "ignoring the situation completely"?
I'm a nobody, though, so take that with an appropriate grain of salt.
[0]: https://news.quelsolaar.com/2020/03/16/how-one-word-broke-c/ https://news.quelsolaar.com/2020/03/16/how-one-word-broke-c/ (currently broken; archive at https://web.archive.org/web/20210307213745/https://news.quelsolaar.com/2020/03/16/how-one-word-broke-c/ https://web.archive.org/web/20210307213745/https://news.quel...
[1]: https://news.ycombinator.com/item?id=22589657 https://news.ycombinator.com/item?id=22589657
- mpweiher 5y agoApologies, but "ignoring the situation completely" is the exact opposite of "assuming the situation cannot occur and acting on that assumption".
- aw1621107 5y agoI'm not sure how "acting on an assumption that the situation cannot occur" is distinguishable from "choosing to ignore situations completely whenever they come up". The former is a blanket description of how you treat individual instances. For example: int f(int* i) { int val = *i; if (i == NULL) { return 0; } return val; } I submit that there are two situations here: 1. i is NULL. Program flow will be caught by the NULL check and the return value is 0. 2. i is not NULL. The NULL check cannot be hit, and the return value is val. As allowed by the standard, I'll just ignore the situation with UB, leaving > i is not NULL. The NULL check cannot be hit, and the return value is val. Alternatively, I can assume that UB cannot occur, which eliminates option 1, leaving > i is not NULL. The NULL check cannot be hit, and the return value is val. You get the same result either way. And that gets to the root of the problem: What exactly does "ignoring the situation completely" mean? In particular, what is the scope of a "situation"?
- mpweiher 5y agoNot sure what such an absurd code example is supposed to show. However, ignoring the situation completely in this case is emitting the code as written. This is not hard at all, despite all the mental gymnastics expended to pretend that it were hard. That is the compiler's job: emit the code that the programmer wrote. Even if that code is stupid, as in this case. It is not the compiler's job to second guess the programmer and generate the code that it believes the programmer meant to write. In this case: 1. Dereference i. 2. Check i. 3. If i is null return 0. 4. return the value from line 1. If you want, I can also write it down as assembly code. Again, this isn't hard. "Ignoring the situation completely" means ignoring the fact that this is UB and just carrying on.
- aw1621107 5y ago> Not sure what such an absurd code example is supposed to show. I had a few things in mind: 1. Highlight that it's not the wording change from "permissible" to "possible" that enables UB-based optimization - it's the interpretation of one of the behaviors the standard lists 2. It's the vagueness of "the situation" that's at the heart of the issue. 3. "Ignoring the situation completely" can produce the same result as "assuming UB never happens", contrary to your assertion (albeit subject to an interpretation that you disagree with) (And absurd or not, similar code does show up in real life [0]. It's part of why -fno-delete-null-pointer-checks exists, after all). > However, ignoring the situation completely in this case is emitting the code as written. > "Ignoring the situation completely" means ignoring the fact that this is UB and just carrying on. Wouldn't "emitting the code as written" or "ignoring the fact that this is UB and just carrying on" fall under the "to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message)"? If it does, why have the "ignoring the situation completely with unpredictable results" wording in the first place? I'm not really convinced your definition of "ignoring the situation completely" is the only valid definition, either. Why wouldn't the standard's wording allow the interpretation in the example? > That is the compiler's job: emit the code that the programmer wrote. Why bother with optimizations, then? [0]: https://lwn.net/Articles/342330/ https://lwn.net/Articles/342330/