https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2019-11-07 Ever confirmed|0 |1 --- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The problem is in finalize_nrv_r which does: /* Change all cleanups for the NRV to only run when an exception is thrown. */ else if (TREE_CODE (*tp) == CLEANUP_STMT && CLEANUP_DECL (*tp) == dp->var) CLEANUP_EH_ONLY (*tp) = 1; The reason that is done is that when NRV optimizing some variable, we don't want to run the destructor if the scope is left through return statement, obviously we still need to run it if exception is thrown, but we need to run the destructor also if the scope is left through other means like goto in this testcase; unfortunately we don't have an IL construct that can do that, we have TRY_FINALLY_EXPR (coming from CLEANUP_STMT with !CLEANUP_EH_ONLY) where the cleanup is run always when leaving the scope, and TRY_CATCH_EXPR where the cleanup is run only when leaving the scope through exceptions. So, either we need some new construct that would run cleanup whenever not left through RETURN_EXPR, or need to use TRY_FINALLY_EXPR with some helper bool variable initialized to something and set to something else right before RETURN_EXPRs and conditionallize the cleanup on that bool. The worry here is whether it could be optimized to whatever we used to emit soon if there are no gotos and how much worse code it would emit at -O0.