Hi!

If the nothrow pass (which is GIMPLE, not IPA pass) determines that the
current function can't throw externally, it marks it nothrow.
But it fails to adjust self-recursive calls, which might change because of
that from possibly throwing to not being able to throw, so we need to
cleanup the EH region, purge dead eh edges and adjust CFG if needed.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-04-13  Jakub Jelinek  <ja...@redhat.com>

        PR c++/70641
        * ipa-pure-const.c (pass_nothrow::execute): Call maybe_clean_eh_stmt
        on all recursive call stmts.  Return TODO_cleanup_cfg if any dead
        eh edges have been purged.

        * g++.dg/opt/pr70641.C: New test.

--- gcc/ipa-pure-const.c.jj     2016-04-13 15:53:01.051799840 +0200
+++ gcc/ipa-pure-const.c        2016-04-13 16:03:10.715556547 +0200
@@ -1956,10 +1956,28 @@ pass_nothrow::execute (function *)
     }
 
   node->set_nothrow_flag (true);
+
+  bool cfg_changed = false;
+  if (self_recursive_p (node))
+    FOR_EACH_BB_FN (this_block, cfun)
+      for (gimple_stmt_iterator gsi = gsi_start_bb (this_block);
+           !gsi_end_p (gsi);
+       gsi_next (&gsi))
+       if (is_gimple_call (gsi_stmt (gsi)))
+         {
+           gimple *g = gsi_stmt (gsi);
+           tree callee_t = gimple_call_fndecl (g);
+           if (callee_t
+               && recursive_call_p (current_function_decl, callee_t)
+               && maybe_clean_eh_stmt (g)
+               && gimple_purge_dead_eh_edges (gimple_bb (g)))
+             cfg_changed = true;
+         }
+
   if (dump_file)
     fprintf (dump_file, "Function found to be nothrow: %s\n",
             current_function_name ());
-  return 0;
+  return cfg_changed ? TODO_cleanup_cfg : 0;
 }
 
 } // anon namespace
--- gcc/testsuite/g++.dg/opt/pr70641.C.jj       2016-04-13 16:01:16.381102468 
+0200
+++ gcc/testsuite/g++.dg/opt/pr70641.C  2016-04-13 16:01:16.381102468 +0200
@@ -0,0 +1,10 @@
+// PR c++/70641
+// { dg-do compile }
+// { dg-options "-O2" }
+
+void
+foo ()
+{
+  try { foo (); }
+  catch (...) { __builtin_abort (); }
+}

        Jakub

Reply via email to