]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/82081 - tail call optimization breaks noexcept
authorJason Merrill <jason@redhat.com>
Fri, 19 Jul 2019 08:52:41 +0000 (04:52 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 19 Jul 2019 08:52:41 +0000 (04:52 -0400)
If a noexcept function calls a function that might throw, doing the tail
call optimization means that an exception thrown in the called function
will propagate out, breaking the noexcept specification.  So we need to
prevent the optimization in that case.

* tree-tailcall.c (find_tail_calls): Don't turn a call from a
nothrow function to a might-throw function into a tail call.

From-SVN: r273594

gcc/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/tail-call-1.C [new file with mode: 0644]
gcc/tree-tailcall.c

index 22716b0c0c0b8718b8e9a668589d92ca1e0d4d65..af38e8be96a3aec261ec939d1ad99858034ed910 100644 (file)
@@ -1,3 +1,9 @@
+2019-07-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/82081 - tail call optimization breaks noexcept
+       * tree-tailcall.c (find_tail_calls): Don't turn a call from a
+       nothrow function to a might-throw function into a tail call.
+
 2019-07-18  Kito Cheng  <kito.cheng@sifive.com>
 
        Backport from mainline
diff --git a/gcc/testsuite/g++.dg/tree-ssa/tail-call-1.C b/gcc/testsuite/g++.dg/tree-ssa/tail-call-1.C
new file mode 100644 (file)
index 0000000..c67af6e
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/82081
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-O2 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-not "tail call" "optimized" } }
+
+int g(int) ;
+
+int f() noexcept {
+    int i = 42, j = 43;
+    return g(i+j);
+}
index afe8931b5f09e1bd6aa4a1d7d4e755a71240a0ab..e0265b22dd5f85c91a004fbb813ffd89d311a2ec 100644 (file)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-into-ssa.h"
 #include "tree-dfa.h"
 #include "except.h"
+#include "tree-eh.h"
 #include "dbgcnt.h"
 #include "cfgloop.h"
 #include "common/common-target.h"
@@ -472,6 +473,12 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
       && !auto_var_in_fn_p (ass_var, cfun->decl))
     return;
 
+  /* If the call might throw an exception that wouldn't propagate out of
+     cfun, we can't transform to a tail or sibling call (82081).  */
+  if (stmt_could_throw_p (cfun, stmt)
+      && !stmt_can_throw_external (cfun, stmt))
+    return;
+
   /* We found the call, check whether it is suitable.  */
   tail_recursion = false;
   func = gimple_call_fndecl (call);