https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103827
--- Comment #8 from Jason Merrill <jason at gcc dot gnu.org> --- (In reply to Jason Merrill from comment #6) > (In reply to Jonathan Wakely from comment #5) > > (In reply to Jan Hubicka from comment #4) > > > What about escape bits? Is it OK to save the address to global memory > > > and then check it in the destructor? > > > > Yes, but does that matter? After the function returns the pointer is invalid > > and can't be used for anything. It's just an invalid pointer value that > > happens to be correctly aligned for the parameter type. > > To be precise, in our implementation the pointer is invalid after the end of > the full-expression that contains the call (implementation-defined per > https://eel.is/c++draft/expr.call#6). However, we don't support something like struct A { int i; A(int i): i(i) { } A(const A& a): i(a.i) { } // force pass by invisiref int val() { return i; } }; A& f(A a) { return a; } int main() { return f(42).val(); } because cp_gimplify_r (since GCC 5) changes a return of a local variable address to return null instead, and the call to val segfaults. Clang and EDG return 42. Without the user-provided copy constructor, it fails on all compilers because there's no invisiref, the parameter actually lives in the callee. I suspect we're wrong here, though this is of course extremely dubious code.