The wording of the C23 working draft on unsequenced functions is unclear to me. Among other properties, unsequenced functions have to be independent:
(6) An object X is observed by a function call
- (6.1) if both synchronize,
- (6.2) if X is not local to the call,
- (6.3) if X has a lifetime that starts before the function call, and
- (6.4) if an access of X is sequenced during the call;
the last value of X, if any, that is stored before the call is said to be the value of X that is observed by the call.
A function pointer value f is independent if
- (6.5) for any object X that is observed by some call to f through an lvalue that is not based on a parameter of the call, then all accesses to X in all calls to f during the same program execution observe the same value;
- (6.6) otherwise if the access is based on a pointer parameter, there shall be a unique such pointer parameter P such that any access to X shall be to an lvalue that is based on P.
A function definition is independent if the derived function pointer value is independent.
- N3096 $6.7.12.7 p6, re-formatted for the sake of readability
My question is whether functions like strlen
can be independent. Consider this minimal implementation:
size_t strlen(const char* s) {
size_t len = 0;
for (; *s; ++s) { ++len; }
return len;
}
Firstly, is *s
considered to be access that is based on a parameter? I believe the access is based on a parameter, namely a pointer parameter, so only the restrictions of (6.6) are relevant.
However, (6.6) could be an issue. Notice that (6.5) says "all accesses to X in all calls to f", whereas (6.6) says "all accesses to X", which is broader, and may apply to access outside the function too. The following scenario is a problem then:
struct string {
char data[N];
} str;
// ...
strlen(str.data); // A
str = ...;
strlen(str.data); // B
Not all accesses to str
globally take place through a unique pointer parameter s
to strlen
. Some of them (str = ...
) don't even involve pointers whatsoever. If my understanding is correct, this disqualifies strlen
from being independent, and thus unsequenced.
In summary, are my interpretations correct, and strlen
cannot be unsequenced? Is this perhaps just a wording issue, but it was intended to be a unsequenced?
Note on possible intent
The proposal for [[unsequenced]]
claims that unlike GCC's [[gnu::const]]
, pointer parameters are supported. However, I am not certain whether the wording reflects that, and to what extent.