Hi,

the compiler started to segfault on this ACATS test very recently, probably 
when the large Pointer Bounds Checker patch went in, although the issue had 
been latent.  For the attached reduced testcase, the backtrace is:

Starting program: /home/eric/build/gcc/native/stage1-gcc/gnat1 -quiet 
opt43.adb -O
opt43.adb:8:05: warning: "return" statement missing following this statement
opt43.adb:8:05: warning: Program_Error may be raised at run time

Program received signal SIGSEGV, Segmentation fault.
stmt_could_throw_1_p (stmt=0x7ffff6d2e460)
    at /home/eric/svn/gcc/gcc/tree-eh.c:2722
warning: Source file is more recent than executable.
2722          fp_operation = FLOAT_TYPE_P (t);
(gdb) bt
#0  stmt_could_throw_1_p (stmt=0x7ffff6d2e460)
    at /home/eric/svn/gcc/gcc/tree-eh.c:2722
#1  stmt_could_throw_p (stmt=0x7ffff6d2e460)
    at /home/eric/svn/gcc/gcc/tree-eh.c:2772
#2  0x0000000000ec81ad in maybe_clean_eh_stmt_fn (ifun=0x7ffff69b45e8, 
    stmt=0x7ffff6d2e460) at /home/eric/svn/gcc/gcc/tree-eh.c:2846
#3  0x0000000000ec81e7 in maybe_clean_eh_stmt (stmt=<optimized out>)
    at /home/eric/svn/gcc/gcc/tree-eh.c:2856
#4  0x0000000000ea9160 in execute_fixup_cfg ()

The problem is in fixup_noreturn_call; it contains this block of code:

      /* We need to remove SSA name to avoid checking errors.
         All uses are dominated by the noreturn and thus will
         be removed afterwards.
         We proactively remove affected non-PHI statements to avoid
         fixup_cfg from trying to update them and crashing.  */
      if (TREE_CODE (op) == SSA_NAME)
        {
          use_operand_p use_p;
          imm_use_iterator iter;
          gimple use_stmt;
          bitmap_iterator bi;
          unsigned int bb_index;

          bitmap blocks = BITMAP_ALLOC (NULL);

          FOR_EACH_IMM_USE_STMT (use_stmt, iter, op)
            {
              if (gimple_code (use_stmt) != GIMPLE_PHI)
                bitmap_set_bit (blocks, gimple_bb (use_stmt)->index);
              else
                FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
                  SET_USE (use_p, error_mark_node);
            }
          EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi)
            delete_basic_block (BASIC_BLOCK_FOR_FN (cfun, bb_index));
          BITMAP_FREE (blocks);
          release_ssa_name (op);
        }

The .ssa dump of the affected function starts with:

;; Function Opt43 (_ada_opt43, funcdef_no=1, decl_uid=4096, cgraph_uid=1, 
symbol_order=1)

Opt43 ()
{
  void * EXPTR;
  integer _5;
  integer _6;
  integer _8;
  integer _9;

  <bb 2>:
  _5 = opt43.func ();

  <bb 3>:
  _6 = _5;
  _8 = opt43.func ();

  <bb 4>:
  _9 = _8;
  if (_6 == _9)
    goto <bb 5>;
  else
    goto <bb 6>;

When the above code processes the first call to opt43.func, it frees _5 and 
deletes bb 3, which in turn frees _6.  But _6 is still referenced in the 
comparison statement in bb 4 and stmt_could_throw_1_p chokes because of that.
The proposed fix is to avoid doing such a poor DCE in fixup_noreturn_call.

Tested on x86_64-suse-linux, OK for the mainline?


2014-11-06  Eric Botcazou  <ebotca...@adacore.com>

        * tree-cfgcleanup. (fixup_noreturn_call): Do not perform DCE here.


2014-11-06  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt43.adb: New test.


-- 
Eric Botcazou
Index: tree-cfgcleanup.c
===================================================================
--- tree-cfgcleanup.c	(revision 217148)
+++ tree-cfgcleanup.c	(working copy)
@@ -568,7 +568,6 @@ bool
 fixup_noreturn_call (gimple stmt)
 {
   basic_block bb = gimple_bb (stmt);
-  bool changed = false;
 
   if (gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
     return false;
@@ -590,46 +589,29 @@ fixup_noreturn_call (gimple stmt)
 	split_block (bb, stmt);
     }
 
-  changed |= remove_fallthru_edge (bb->succs);
-
-  /* If there is LHS, remove it.  */
-  if (gimple_call_lhs (stmt))
+  /* If there is an LHS, remove it.  */
+  tree lhs = gimple_call_lhs (stmt);
+  if (lhs)
     {
-      tree op = gimple_call_lhs (stmt);
       gimple_call_set_lhs (stmt, NULL_TREE);
 
-      /* We need to remove SSA name to avoid checking errors.
-	 All uses are dominated by the noreturn and thus will
-	 be removed afterwards.
-	 We proactively remove affected non-PHI statements to avoid
-	 fixup_cfg from trying to update them and crashing.  */
-      if (TREE_CODE (op) == SSA_NAME)
+      /* We need to initialize the SSA name to avoid checking errors.  */
+      if (TREE_CODE (lhs) == SSA_NAME)
 	{
-	  use_operand_p use_p;
-          imm_use_iterator iter;
-	  gimple use_stmt;
-	  bitmap_iterator bi;
-	  unsigned int bb_index;
-
-	  bitmap blocks = BITMAP_ALLOC (NULL);
-
-          FOR_EACH_IMM_USE_STMT (use_stmt, iter, op)
+	  edge e = find_fallthru_edge (bb->succs);
+	  if (e)
 	    {
-	      if (gimple_code (use_stmt) != GIMPLE_PHI)
-	        bitmap_set_bit (blocks, gimple_bb (use_stmt)->index);
-	      else
-		FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-		  SET_USE (use_p, error_mark_node);
+	      tree zero = build_zero_cst (TREE_TYPE (lhs));
+	      gimple init_stmt = gimple_build_assign (lhs, zero);
+	      gsi_insert_on_edge (e, init_stmt);
+	      gsi_commit_one_edge_insert (e, NULL);
 	    }
-	  EXECUTE_IF_SET_IN_BITMAP (blocks, 0, bb_index, bi)
-	    delete_basic_block (BASIC_BLOCK_FOR_FN (cfun, bb_index));
-	  BITMAP_FREE (blocks);
-	  release_ssa_name (op);
 	}
+
       update_stmt (stmt);
-      changed = true;
     }
-  return changed;
+
+  return remove_fallthru_edge (bb->succs);
 }
 
 
-- { dg-do compile }
-- { dg-options "-O -gnatws" }

procedure Opt43 is

  function Func return Integer is
  begin
    if False then
       return 0;
    end if;
  end;

begin

  if Func = Func then
    raise Program_Error;
  end if;

exception
  when Program_Error => null;
end;

Reply via email to