Is the following C program guaranteed to exit with 0 or is the compiler allowed to identify the objects s and t with one another as is permitted in C++ as the so-called named return value optimization (NRVO) form of copy elision?
typedef struct {
int i, j;
double a, b;
} S;
int result;
S test(S *q) {
S s = {0, 0, 0, 0};
result = &s == q;
return s;
}
int main(void)
{
S t = test(&t);
return result;
}
Clang exits with 1 against my expectations, see https://godbolt.org/z/ME8sPGn3n.
(In C++, both 0 and 1 are valid outcomes due to explicit permission to perform NRVO.)
It is guaranteed to exit with 0. t and s are different objects, pointers to them can't compare equal.
About the code that you removed:
What about the following variation in which relevant lifetime considerations may be different?
From https://port70.net/~nsz/c/c11/n1570.html#6.2.4p2 :
The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
It may return 1 or 0 or perform a trap.
Copy / move elision is a C++ concept, defined in section 15.8.3 of C++17. It allows for optimizing away constructor and destructor calls in some cases in which case the source and destination objects are one in the same:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object.
C has no such provision, although as of C17 it allows an object with temporary lifetime, e.g. an array contained in a struct in a non-lvalue expression, to not have a unique address. This isn't applicable to this case however.
The fact that this optimization was performed on a C program changes the observable behavior of the program in violation of the C standard. Specifically, t and s are distinct objects whose lifetime overlaps and as such they must have different addresses.
So this is a bug in clang that copy elision is being applied to a C program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With