Authors: Bogdan Barbu
Date: 2026-11-06
Submitted against: C23
Status: Open
C23 5.2.2.4p6 defines the observable behavior of a program in terms of volatile accesses, file contents, and interactions with interactive devices. It does not include whether execution terminates.
This omission is problematic because it appears to permit transformations that violate the intended semantics of the abstract machine.
Consider:
int main(void)
{
for (;;) ;
}
The program executes indefinitely according to the abstract machine. Nevertheless, it performs no operations classified as observable behavior by 5.2.2.4p6.
Under a literal application of the as-if rule, an implementation could therefore replace the program with one that terminates immediately, since doing so would not change any of the explicitly specified observable behavior.
C23 6.8.6.1p4 does not resolve this problem. It permits implementations to assume termination of certain loops, but does not explicitly prohibit their elimination on other grounds. In particular, the absence of permission to assume termination is not itself a normative requirement to preserve nontermination.
The problem extends to multithreaded programs. The execution of a thread that performs no observable operations could similarly be eliminated, even when doing so changes whether that thread terminates.
Nontermination should be explicitly recognized as observable behavior.
The definition in 5.2.2.4 should be amended to require implementations to preserve whether execution terminates, subject to the explicit permission to assume termination granted by 6.8.6.1p4.
The requirement should also account for individual threads, so that an implementation cannot disregard the continued execution of a thread merely because it performs no other observable operations.
This would establish a clear normative distinction between transformations expressly permitted by the iteration-statement rules and transformations that change the termination behavior of an execution without such permission.
The issue is related to WG14 N1509 (Optimizing away infinite loops) and N1528 (Why undefined behavior for infinite loops?).
The existing treatment of iteration statements demonstrates that the standard deliberately distinguishes between loops whose termination may be assumed and those whose termination may not. However, this distinction is not adequately reflected in the general definition of observable behavior.
The proposed correction would make that distinction explicit rather than leaving it dependent on an inference from the wording of 6.8.6.1p4.