[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 Jason Merrill changed: What|Removed |Added CC||joerg.rich...@pdv-fs.de --- Comment #14 from Jason Merrill --- *** Bug 113767 has been marked as a duplicate of this bug. ***
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #13 from GCC Commits --- The releases/gcc-12 branch has been updated by Jason Merrill : https://gcc.gnu.org/g:193321d2649a818c3b322c8db79a2805cfdd7095 commit r12-10109-g193321d2649a818c3b322c8db79a2805cfdd7095 Author: Jason Merrill Date: Sun Jun 4 12:00:55 2023 -0400 c++: NRV and goto [PR92407] Here our named return value optimization was breaking the required destructor when the goto takes 'a' out of scope. A simple fix for the release branches is to disable the optimization in the presence of backward goto. We could do better by disabling the optimization only if there is a backward goto across the variable declaration, but we don't track that, and in GCC 14 we instead make the goto work with NRV. PR c++/92407 gcc/cp/ChangeLog: * cp-tree.h (struct language_function): Add backward_goto. * decl.cc (check_goto): Set it. * typeck.cc (check_return_expr): Prevent NRV if set. gcc/testsuite/ChangeLog: * g++.dg/opt/nrv22.C: New test. (cherry picked from commit a645347c19b07cc7abd7bf276c6769fc41afc932)
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 Jason Merrill changed: What|Removed |Added Resolution|--- |FIXED Status|ASSIGNED|RESOLVED Target Milestone|--- |11.5 --- Comment #12 from Jason Merrill --- Fixed for 11.5/12.4/13.3/14.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #11 from GCC Commits --- The releases/gcc-11 branch has been updated by Jason Merrill : https://gcc.gnu.org/g:32bd8a1053d25cbb15172294e59a81bc134658aa commit r11-11162-g32bd8a1053d25cbb15172294e59a81bc134658aa Author: Jason Merrill Date: Sun Jun 4 12:00:55 2023 -0400 c++: NRV and goto [PR92407] Here our named return value optimization was breaking the required destructor when the goto takes 'a' out of scope. A simple fix for the release branches is to disable the optimization in the presence of backward goto. We could do better by disabling the optimization only if there is a backward goto across the variable declaration, but we don't track that, and in GCC 14 we instead make the goto work with NRV. PR c++/92407 gcc/cp/ChangeLog: * cp-tree.h (struct language_function): Add backward_goto. * decl.c (check_goto): Set it. * typeck.c (check_return_expr): Prevent NRV if set. gcc/testsuite/ChangeLog: * g++.dg/opt/nrv22.C: New test. (cherry picked from commit a645347c19b07cc7abd7bf276c6769fc41afc932)
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #10 from CVS Commits --- The releases/gcc-13 branch has been updated by Jason Merrill : https://gcc.gnu.org/g:a645347c19b07cc7abd7bf276c6769fc41afc932 commit r13-7770-ga645347c19b07cc7abd7bf276c6769fc41afc932 Author: Jason Merrill Date: Sun Jun 4 12:00:55 2023 -0400 c++: NRV and goto [PR92407] Here our named return value optimization was breaking the required destructor when the goto takes 'a' out of scope. A simple fix for the release branches is to disable the optimization in the presence of backward goto. We could do better by disabling the optimization only if there is a backward goto across the variable declaration, but we don't track that, and in GCC 14 we instead make the goto work with NRV. PR c++/92407 gcc/cp/ChangeLog: * cp-tree.h (struct language_function): Add backward_goto. * decl.cc (check_goto): Set it. * typeck.cc (check_return_expr): Prevent NRV if set. gcc/testsuite/ChangeLog: * g++.dg/opt/nrv22.C: New test.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #9 from Jason Merrill --- Fixed for GCC 14 so far.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #8 from CVS Commits --- The trunk branch has been updated by Jason Merrill : https://gcc.gnu.org/g:7e0b65b239c3a0d68ce94896b236b03de666ffd6 commit r14-1593-g7e0b65b239c3a0d68ce94896b236b03de666ffd6 Author: Jason Merrill Date: Sun Jun 4 12:09:11 2023 -0400 c++: enable NRVO from inner block [PR51571] Our implementation of the named return value optimization has been limited to variables declared in the outermost block of the function, to avoid needing to handle the case where the variable needs to be destroyed due to going out of scope. PR92407 pointed out a case we were missing, where the variable goes out of scope due to a goto and we were failing to destroy it. It occurred to me that this problem is the flip side of PR33799, where we need to be sure to destroy the return value if a cleanup throws on return; here we want to avoid destroying the return value when exiting the variable's scope on return. We can use the same flag to indicate to both cleanups that we're returning. This implements the guaranteed copy elision specified by P2025 (which is not yet part of the draft standard). PR c++/51571 PR c++/92407 gcc/cp/ChangeLog: * decl.cc (finish_function): Simplify NRV handling. * except.cc (maybe_set_retval_sentinel): Also set if NRV. (maybe_splice_retval_cleanup): Don't add the cleanup region if we don't need it. * semantics.cc (nrv_data): Add simple field. (finalize_nrv): Set it. (finalize_nrv_r): Check it and retval sentinel. * cp-tree.h (finalize_nrv): Adjust declaration. * typeck.cc (check_return_expr): Remove named_labels check. gcc/testsuite/ChangeLog: * g++.dg/opt/nrv23.C: New test.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #7 from CVS Commits --- The trunk branch has been updated by Jason Merrill : https://gcc.gnu.org/g:b192e2007e1c98b548f4aa878523b485968d24a4 commit r14-1592-gb192e2007e1c98b548f4aa878523b485968d24a4 Author: Jason Merrill Date: Sun Jun 4 12:00:55 2023 -0400 c++: NRV and goto [PR92407] Here our named return value optimization was breaking the required destructor when the goto takes 'a' out of scope. The simplest fix is to disable the optimization in the presence of user labels. We could do better by disabling the optimization only if there is a backward goto across the variable declaration, but we don't currently track that. PR c++/92407 gcc/cp/ChangeLog: * typeck.cc (check_return_expr): Prevent NRV in the presence of named labels. gcc/testsuite/ChangeLog: * g++.dg/opt/nrv22.C: New test.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 Jason Merrill changed: What|Removed |Added Assignee|unassigned at gcc dot gnu.org |jason at gcc dot gnu.org Status|NEW |ASSIGNED
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 Moritz Sichert changed: What|Removed |Added CC||sichert at in dot tum.de --- Comment #6 from Moritz Sichert --- We are also running into this bug when using RAII lock guards and goto to "retry" the section guarded by the lock. I think the standard is very clear that the destructor should be called: "Transfer out of a loop, out of a block, or back past an initialized variable with automatic storage duration involves the destruction of objects with automatic storage duration that are in scope at the point transferred from but not at the point transferred to." N4861: Section 8.7 (2)
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 Jakub Jelinek changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2019-11-07 Ever confirmed|0 |1 --- Comment #5 from Jakub Jelinek --- 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.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #4 from Dave Poston --- Yep, also changing problem()/foo() to void and not returning the struct, works properly
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org, ||jason at gcc dot gnu.org --- Comment #3 from Jakub Jelinek --- I think it is well defined. Simplified testcase: struct A { A () { a++; } A (const A &) { a++; } ~A () { a--; } static int a; }; int A::a = 0; A foo () { int cnt = 10; lab: A a; if (cnt--) goto lab; return a; } int main () { foo (); if (A::a) __builtin_abort (); } I believe the reason why this doesn't work is NRV, at least if return a; is changed to return A ();, so that the a variable is not NRV optimized, it works properly.
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #2 from Richard Biener --- The goto defeats finalization here but construction happens multiple times. Not sure if that's allowed by the standard, but I'd say you invoke undefined behavior here?
[Bug c++/92407] Destruction of objects returned from functions skipped by goto
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92407 --- Comment #1 from Dave Poston --- In fact, fill() isn't even needed. Smaller repro: https://godbolt.org/z/ubXl7Y --- #include struct MyStruct { MyStruct() { std::cout << "Constructed" << std::endl; } ~MyStruct() { std::cout << "Destructed" << std::endl; } int a; }; MyStruct problem() { int cnt = 100; start: MyStruct a; if( cnt-- ) goto start; return a; } int main( int argc, char** argv ) { problem(); return 0; }