Indeed a weird and wonderful example that I hadn't seen before.

But this also involves some implementation QOI decisions that seem questionable for other reasons. Should a compiler really remove the return instruction if it can deduce that the function always encounters undefined behavior? Clearly that's currently allowed. On the other hand, it always adds type and memory-safety violations to programs that previously had "less serious" UB. So as a QOI issue, I think I would argue against it.

Hans

On Wed, Feb 15, 2023 at 8:42 PM Robert Seacord <rcseacord@gmail.com> wrote:
I'm not sure if someone has posted this example yet, but here is a fun example that compiles in both C and C++ with different results:

#include <stdio.h>

int main() {
    while (1)
        ;
}

void unreachable() {
    puts("Hello world!");
} 

If you want to try it:  https://godbolt.org/z/1d3hzseh4

In C, this code produces an infinite loop while in C++ it does the following:

image.png

On Wed, Feb 15, 2023 at 11:31 PM Robert Seacord <rcseacord@gmail.com> wrote:
Hans,

I initiated this latest discussion on the WG14 reflector and I've recently become a bit more active in WG21 (and my boss is JF who wrote this paper).

Here is a recap of some of the history of this issue:

I can't find any forward progress guarantee in the C Standard.  The word "progress" does not appear anywhere in the standard. 
Subclause 6.8.5, "Iteration statements" paragraph 5  says:

An iteration statement may be assumed by the implementation to terminate if its controlling
expression is not a constant expression197), and none of the following operations are performed in its
body, controlling expression or (in the case of a for statement) its expression-3198):
— input/output operations
— accessing a volatile object
— synchronization or atomic operations.

197) An omitted controlling expression is replaced by a nonzero constant, which is a constant expression.
198) This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be
proven.

N1509 proposes to eliminate 6.8.5p6 in the current WP as the author believes it to be  incompatible with C99. See also N1528, Item 6.30, Response to N1509.

N1528 covers why the rules were added.  N1509 was written to show a compiler can determine  the opposite as well.
In https://open-std.org/jtc1/sc22/wg14/www/docs/n1509.pdf [Walls] contends that many C90/C99 programs rely on entrance to an unending loop to proceed no further (within that thread).  Those programs are relying on the semantics of C99 6.8.5p4: "An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0."

N1528 breaks existing conforming programs. Adding an exception may  solve the intent of both papers. That approach should be run by Hans. We can defer a decision  and not affect getting a CD out, then respond to an NB comment. We do want to be compatible  with WG21.

ACTION Douglas to work with Larry to come up with the proposed words are:

Change 6.8.5p6 as follows:
An iteration statement whose controlling expression is not a constant expression (or omitted), that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for
statement) its expression, may be assumed by the implementation to terminate.

Decision:  Adopt N1509, as modified above, to the C1X WP. result: 14, 0, 1

On Wed, Feb 15, 2023 at 8:29 PM Hans Boehm via Parallel <parallel@lists.isocpp.org> wrote:
I read the current C wording, and the one proposed here,  as saying that

while(true) {
  if (!cond) break;
  ...
}

may not be assumed to terminate, and is thus very different from

while(cond) {
   ...
}

This is a very confusing shorthand as "..." seems to imply any syntactically correct statements and thus the first pattern is a subset of the second pattern.
 
I don't remember considering that before. This seems to be completely at odds with Olivier's goals. I also don't think this is a good idea, for purely loop optimization and understandability reasons. OTOH, some people on the WG14 list seem to think it is intentional and desired.

Unlike what I said to JF at the meeting, it no longer sounds easy to me to remove this C vs. C++ divergence. There seem to be some substantive issues here.

There is a strong desire in C to remain compatible with C++ and it's less clear what the C requirement is.  There is a requirement that "while (1);" cannot be assumed to terminate as it is ubiquitous in environments where you don't have the luxury of calling exit() or yielding to the scheduler.  I certainly wouldn't give up on compatibility at this point, and there is still a small window to change the C23 language as we are going to a second CD.
 
Thanks,
rCs