aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-04-29 13:27:13 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-04-29 13:27:13 -0400
commitd407e7f53b4a9c3f607b692d89b4ad7d87df5933 (patch)
tree3c9963eb4dd5887df09070c5d7199822d305c7d4 /gcc
parent348dd384c8f647ba56be21932d068d180be243e3 (diff)
downloadgcc-d407e7f53b4a9c3f607b692d89b4ad7d87df5933.zip
gcc-d407e7f53b4a9c3f607b692d89b4ad7d87df5933.tar.gz
gcc-d407e7f53b4a9c3f607b692d89b4ad7d87df5933.tar.bz2
PR c++/82081 - tail call optimization breaks noexcept
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: r270656
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/tail-call-1.C11
-rw-r--r--gcc/tree-tailcall.c7
3 files changed, 24 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e548281..b4554f6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2019-04-29 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-04-29 Richard Sandiford <richard.sandiford@arm.com>
* tree-data-ref.h (data_dependence_relation::inner_loop): Delete.
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
index 0000000..c67af6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/tail-call-1.C
@@ -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);
+}
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index afe8931..e0265b2 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -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);