https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120409
--- Comment #15 from Iain Sandoe <iains at gcc dot gnu.org> --- (In reply to H.J. Lu from comment #14) > (In reply to Iain Sandoe from comment #13) > > (In reply to H.J. Lu from comment #12) > > > (In reply to Iain Sandoe from comment #5) > > > > well .. the visible difference in gimple, but this is code outside of > > > > the > > > > coroutines changes (i.e. just a bit of regular C++). > > > > > > > > However, it does seem we create the return object correctly .. and then > > > > return an empty one. We seem to be failing to do copy elision. > > > > > > > > > > On x32, OptionalPromiseReturn is 16 bytes, which is returned in 2 > > > registers. > > > You can't assume that copy elision will happen. You need to prepare for > > > it. > > > > Hmm .. but I think copy elision is mandated by c++17 - so we need to figure > > out a solution< i guess. > > There is no guarantee that all ABIs will pass and return struct in the same > location, stack or register. I don't see how a high level language can > mandate copy elision for the incoming argument on stack and the return value > in > registers. Copy elision won't happen on x64-64 if the return struct size is > 16 > bytes or less. While the calling conventions need to be the same between C and C++, the decisions on how to pass entities need not be. Folly is a large library - it's not my code, and it is possible that the reduction of the test case has altered something, but assuming it has not, the clear intention of the authors was to depend on the mandated elision. IF I now add an empty user destructor to the class viz: ``` struct OptionalPromiseReturn { Optional storage_; Optional *&pointer_; OptionalPromiseReturn(OptionalPromise &p) : pointer_{p.value_} { pointer_ = &storage_; } operator Optional() { return storage_; } ~OptionalPromiseReturn() {} }; ``` and print the size of the object from main(): $ ./gcc/xg++ -Bgcc -std=c++23 /src-local/gcc-master/gcc/testsuite/g++.dg/coroutines/torture/pr119916.C -fdump-tree-gimple -mx32 -o t $ ./t sizeof OptionalPromiseReturn : 16 the test case passes - because now the object is not an aggregate and the C++ rules mandate that it is passed by reference. It seems that those rules need to be extended somehow to deal with this case. My guess (without having had time to look) is that this case is already handled by x86_64 and i?86 - since the original test case works (and the copy elision is performed) on both Linux and Darwin there.