Search code examples
clanguage-lawyerinfinite-loopc11

C11 - omitting potentially infinite loop by the compiler


Assume the following code

struct a {
    unsigned cntr;
};

void boo(struct a *v) {
    v->cntr++;
    while(v->cntr > 1);
}

I wonder if the compiler is allowed to omit the while loop inside boo() due to the following statement in the C11 standard:

An iteration statement whose controlling expression is not a constant expression,156) 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-3, may be assumed by the implementation to terminate.157)


157)This is intended to allow compiler transformations such as removal of empty loops even when termination cannot be proven.

Can v->cntr, in the controlling expression, be considered as a synchronization since v may be a pointer to a global structure which can be modified externally (for example by another thread)?

Additional question. Is the compiler allowed not to re-read v->cntr on each iteration if v is not defined as volatile?


Solution

  • Can v->cntr, in the controlling expression, be considered as a synchronization

    No.

    From https://port70.net/~nsz/c/c11/n1570.html#5.1.2.4p5 :

    The library defines a number of atomic operations (7.17) and operations on mutexes (7.26.4) that are specially identified as synchronization operations.

    So basically, functions from stdatomic.h and mtx_* from thread.h are synchronization operations.

    since v may be a pointer to a global structure which can be modified externally (for example by another thread)?

    Does not matter. Assumptions like sound to me like they would disallow many sane optimizations, I wouldn't want my compiler to assume that.

    If v were modified in another thread, then it would be unsequenced, that would just result in undefined behavior https://port70.net/~nsz/c/c11/n1570.html#5.1.2.4p25 .

    Is the compiler allowed not to re-read v->cntr on each iteration if v is not defined as volatile?

    Yes.