]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/59119 (Segfault in -fisolate-erroneous-paths pass)
authorJeff Law <law@redhat.com>
Wed, 13 Nov 2013 23:10:34 +0000 (16:10 -0700)
committerJeff Law <law@gcc.gnu.org>
Wed, 13 Nov 2013 23:10:34 +0000 (16:10 -0700)
* PR middle-end/59119
* gimple-ssa-isolate-paths.c (find_implicit_erroneous_behaviour): New
function, extracted from gimple_ssa_isolate_erroneous_paths.
(find_explicit_erroneous_behaviour): Similarly.
(insert_trap_and_remove_trailing_statements): Remove statements
in reverse order.

* PR middle-end/59119
* gcc.c-torture/compile/pr59119.c: New test.

From-SVN: r204760

gcc/ChangeLog
gcc/gimple-ssa-isolate-paths.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr59119.c [new file with mode: 0644]

index c5448784624fed42e4c11af823e741a0ec4610a8..ecc7aed56d4193edbf95c66694cdaeed8bfcc3f4 100644 (file)
@@ -1,3 +1,12 @@
+2013-11-13  Jeff Law  <law@redhat.com>
+
+       * PR middle-end/59119
+       * gimple-ssa-isolate-paths.c (find_implicit_erroneous_behaviour): New
+       function, extracted from gimple_ssa_isolate_erroneous_paths.
+       (find_explicit_erroneous_behaviour): Similarly.
+       (insert_trap_and_remove_trailing_statements): Remove statements
+       in reverse order.
+
 2013-11-13  Steven Bosscher  <steven@gcc.gnu.org>
 
        * cfgrtl.c (can_fallthru): Reorder code to move tablejump check up.
index 2d8f176c4b9af741900f27571d226493fc602d72..0051da2126f51746dd859893e63673a3ea4b0299 100644 (file)
@@ -100,14 +100,16 @@ insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p, tree op)
   else
     gsi_insert_before (si_p, seq, GSI_NEW_STMT);
 
-  /* The iterator points to the __builtin_trap.  Advance the iterator
-     and delete everything else in the block.  */
-  gsi_next (si_p);
-  for (; !gsi_end_p (*si_p);)
+  /* We must remove statements from the end of the block so that we
+     never reference a released SSA_NAME.  */
+  basic_block bb = gimple_bb (gsi_stmt (*si_p));
+  for (gimple_stmt_iterator si = gsi_last_bb (bb);
+       gsi_stmt (si) != gsi_stmt (*si_p);
+       si = gsi_last_bb (bb))
     {
-      stmt = gsi_stmt (*si_p);
+      stmt = gsi_stmt (si);
       unlink_stmt_vdef (stmt);
-      gsi_remove (si_p, true);
+      gsi_remove (&si, true);
       release_defs (stmt);
     }
 }
@@ -192,40 +194,19 @@ isolate_path (basic_block bb, basic_block duplicate,
   return duplicate;
 }
 
-/* Search the function for statements which, if executed, would cause
-   the program to fault such as a dereference of a NULL pointer.
-
-   Such a program can't be valid if such a statement was to execute
-   according to ISO standards.
-
-   We detect explicit NULL pointer dereferences as well as those implied
-   by a PHI argument having a NULL value which unconditionally flows into
-   a dereference in the same block as the PHI.
-
-   In the former case we replace the offending statement with an
-   unconditional trap and eliminate the outgoing edges from the statement's
-   basic block.  This may expose secondary optimization opportunities.
-
-   In the latter case, we isolate the path(s) with the NULL PHI 
-   feeding the dereference.  We can then replace the offending statement
-   and eliminate the outgoing edges in the duplicate.  Again, this may
-   expose secondary optimization opportunities.
+/* Look for PHI nodes which feed statements in the same block where
+   the value of the PHI node implies the statement is erroneous.
 
-   A warning for both cases may be advisable as well.
+   For example, a NULL PHI arg value which then feeds a pointer
+   dereference.
 
-   Other statically detectable violations of the ISO standard could be
-   handled in a similar way, such as out-of-bounds array indexing.  */
-
-static unsigned int
-gimple_ssa_isolate_erroneous_paths (void)
+   When found isolate and optimize the path associated with the PHI
+   argument feeding the erroneous statement.  */
+static void
+find_implicit_erroneous_behaviour (void)
 {
   basic_block bb;
 
-  initialize_original_copy_tables ();
-
-  /* Search all the blocks for edges which, if traversed, will
-     result in undefined behaviour.  */
-  cfg_altered = false;
   FOR_EACH_BB (bb)
     {
       gimple_stmt_iterator si;
@@ -288,6 +269,21 @@ gimple_ssa_isolate_erroneous_paths (void)
                }
            }
        }
+    }
+}
+
+/* Look for statements which exhibit erroneous behaviour.  For example
+   a NULL pointer dereference. 
+
+   When found, optimize the block containing the erroneous behaviour.  */
+static void
+find_explicit_erroneous_behaviour (void)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      gimple_stmt_iterator si;
 
       /* Now look at the statements in the block and see if any of
         them explicitly dereference a NULL pointer.  This happens
@@ -318,6 +314,56 @@ gimple_ssa_isolate_erroneous_paths (void)
            }
        }
     }
+}
+/* Search the function for statements which, if executed, would cause
+   the program to fault such as a dereference of a NULL pointer.
+
+   Such a program can't be valid if such a statement was to execute
+   according to ISO standards.
+
+   We detect explicit NULL pointer dereferences as well as those implied
+   by a PHI argument having a NULL value which unconditionally flows into
+   a dereference in the same block as the PHI.
+
+   In the former case we replace the offending statement with an
+   unconditional trap and eliminate the outgoing edges from the statement's
+   basic block.  This may expose secondary optimization opportunities.
+
+   In the latter case, we isolate the path(s) with the NULL PHI 
+   feeding the dereference.  We can then replace the offending statement
+   and eliminate the outgoing edges in the duplicate.  Again, this may
+   expose secondary optimization opportunities.
+
+   A warning for both cases may be advisable as well.
+
+   Other statically detectable violations of the ISO standard could be
+   handled in a similar way, such as out-of-bounds array indexing.  */
+
+static unsigned int
+gimple_ssa_isolate_erroneous_paths (void)
+{
+  initialize_original_copy_tables ();
+
+  /* Search all the blocks for edges which, if traversed, will
+     result in undefined behaviour.  */
+  cfg_altered = false;
+
+  /* First handle cases where traversal of a particular edge
+     triggers undefined behaviour.  These cases require creating
+     duplicate blocks and thus new SSA_NAMEs.
+
+     We want that process complete prior to the phase where we start
+     removing edges from the CFG.  Edge removal may ultimately result in
+     removal of PHI nodes and thus releasing SSA_NAMEs back to the
+     name manager.
+
+     If the two processes run in parallel we could release an SSA_NAME
+     back to the manager but we could still have dangling references
+     to the released SSA_NAME in unreachable blocks.
+     that any released names not have dangling references in the IL.  */
+  find_implicit_erroneous_behaviour ();
+  find_explicit_erroneous_behaviour ();
+
   free_original_copy_tables ();
 
   /* We scramble the CFG and loop structures a bit, clean up 
index 31b952b5f9e02982aba28f952aa5c59aa1c95f3e..36f48fd17f9306aee9eb43796149c39ac64c5057 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-12  Jeff Law  <law@redhat.com>
+
+       * PR middle-end/59119
+       * gcc.c-torture/compile/pr59119.c: New test.
+
 2013-11-13  Martin Jambor  <mjambor@suse.cz>
 
        * gcc.dg/ira-shrinkwrap-prep-1.c: Add lp64 to target requirements.
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59119.c b/gcc/testsuite/gcc.c-torture/compile/pr59119.c
new file mode 100644 (file)
index 0000000..b026ba5
--- /dev/null
@@ -0,0 +1,23 @@
+extern void *memmove (void *, const void *, __SIZE_TYPE__);
+extern void *memset (void *, int, __SIZE_TYPE__);
+
+typedef struct {
+    long n_prefix;
+    long n_spadding;
+} NumberFieldWidths;
+
+void
+fill_number(char *buf, const NumberFieldWidths *spec)
+{
+    if (spec->n_prefix) {
+        memmove(buf,
+                (char *) 0,
+                spec->n_prefix * sizeof(char));
+        buf += spec->n_prefix;
+    }
+    if (spec->n_spadding) {
+        memset(buf, 0, spec->n_spadding);
+        buf += spec->n_spadding;
+    }
+}
+