The C++20 standard says in Function Call, 7.6.1.3/8:
The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.
Indeterminately sequenced (as opposed to unsequenced) ensures that side effects affecting the same memory region are not undefined behavior. Cppreference gives the following examples:
f(i = -2, i = -2); // undefined behavior until C++17 f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
The change in C++17 doesn't seem to be in the quoted section though whose wording essentially stayed the same through the centuries decades. (OK; in n3337 it is only a note.)
And a simple example elicits warnings from both gcc and clang:
void f(int fa, int fb);
void m() // contains code calling f()
{
int a = 11;
f(++a, ++a);
cout << "after f(): a=" << a << '\n';
}
<source>:6:7: warning: multiple unsequenced modifications to 'a' [-Wunsequenced]
f(++a, ++a);
^ ~~
gcc also produces unintuitive code, incrementing a
twice before moving its value into both parameter registers. That contradicts my understanding of the standard wording.
Fellow stackoverflow user Davis Herring mentioned in a comment that while the initialization is sequenced, the evaluation of the argument expressions is not.
Am I misinterpreting this wording? Is cppreference wrong? Are the compilers wrong, especially gcc? What, if anything, changed in C++17 regarding specifically function parameters?
f
with two equal values in the parameter. – Nosewheel