aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-06-04 12:00:55 -0400
committerJason Merrill <jason@redhat.com>2023-06-06 21:30:59 -0400
commitb192e2007e1c98b548f4aa878523b485968d24a4 (patch)
tree4f16ac9cd7306be8fb08fe623ef1fd00cd1e436b
parent08cea4e56a094ff9cc7c65fdc9ce8c4d7aff64be (diff)
downloadgcc-b192e2007e1c98b548f4aa878523b485968d24a4.zip
gcc-b192e2007e1c98b548f4aa878523b485968d24a4.tar.gz
gcc-b192e2007e1c98b548f4aa878523b485968d24a4.tar.bz2
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.
-rw-r--r--gcc/cp/typeck.cc3
-rw-r--r--gcc/testsuite/g++.dg/opt/nrv22.C30
2 files changed, 33 insertions, 0 deletions
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 11fcc7f..6618c6a 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11155,6 +11155,9 @@ check_return_expr (tree retval, bool *no_warning)
if (fn_returns_value_p && flag_elide_constructors)
{
if (named_return_value_okay_p
+ /* The current NRV implementation breaks if a backward goto needs to
+ destroy the object (PR92407). */
+ && !cp_function_chain->x_named_labels
&& (current_function_return_value == NULL_TREE
|| current_function_return_value == bare_retval))
current_function_return_value = bare_retval;
diff --git a/gcc/testsuite/g++.dg/opt/nrv22.C b/gcc/testsuite/g++.dg/opt/nrv22.C
new file mode 100644
index 0000000..eb889fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/nrv22.C
@@ -0,0 +1,30 @@
+// PR c++/92407
+// { dg-do run }
+
+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 ();
+}