re PR c++/49264 (Internal compiler error: segmentation fault)
authorJakub Jelinek <jakub@redhat.com>
Mon, 6 Jun 2011 17:12:25 +0000 (19:12 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 6 Jun 2011 17:12:25 +0000 (19:12 +0200)
PR c++/49264
* gimple-fold.c (fold_stmt_1): Don't try to fold *& on the lhs
if stmt folded into nothing.
* tree-inline.c (fold_marked_statements): If a builtin at the
end of a bb folded into nothing, just update cgraph edges
and move to next bb.
* cgraph.c (cgraph_update_edges_for_call_stmt_node): Allow new_stmt
to be NULL.  Don't compute count and frequency if new_call is NULL.

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

From-SVN: r174711

gcc/ChangeLog
gcc/cgraph.c
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr49264.C [new file with mode: 0644]
gcc/tree-inline.c

index 3166f93c28c7aedd99c37a713f381f4940505871..165783f85c7197929b1200b2737506fba184e382 100644 (file)
@@ -1,3 +1,14 @@
+2011-06-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/49264
+       * gimple-fold.c (fold_stmt_1): Don't try to fold *& on the lhs
+       if stmt folded into nothing.
+       * tree-inline.c (fold_marked_statements): If a builtin at the
+       end of a bb folded into nothing, just update cgraph edges
+       and move to next bb.
+       * cgraph.c (cgraph_update_edges_for_call_stmt_node): Allow new_stmt
+       to be NULL.  Don't compute count and frequency if new_call is NULL.
+
 2011-06-04  Diego Novillo  <dnovillo@google.com>
 
        * Makefile.in (lto-compress.o): Add dependency on LTO_STREAMER_H.
index a6d548239507de415daf6fc177e086a1a538cda3..02bf6ebeb2686d259954b0bb7246a79b1ea65989 100644 (file)
@@ -1233,13 +1233,17 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee,
 
 /* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
    OLD_STMT changed into NEW_STMT.  OLD_CALL is gimple_call_fndecl
-   of OLD_STMT if it was previously call statement.  */
+   of OLD_STMT if it was previously call statement.
+   If NEW_STMT is NULL, the call has been dropped without any
+   replacement.  */
 
 static void
 cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
-                                       gimple old_stmt, tree old_call, gimple new_stmt)
+                                       gimple old_stmt, tree old_call,
+                                       gimple new_stmt)
 {
-  tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fndecl (new_stmt) : 0;
+  tree new_call = (new_stmt && is_gimple_call (new_stmt))
+                 ? gimple_call_fndecl (new_stmt) : 0;
 
   /* We are seeing indirect calls, then there is nothing to update.  */
   if (!new_call && !old_call)
@@ -1277,7 +1281,7 @@ cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
          frequency = e->frequency;
          cgraph_remove_edge (e);
        }
-      else
+      else if (new_call)
        {
          /* We are seeing new direct call; compute profile info based on BB.  */
          basic_block bb = gimple_bb (new_stmt);
index c98fd6a0d40d453de3692eb02d2bc5c0c5c6feee..eaff1b3a4ee34d92061fb34d9700426247c9e27e 100644 (file)
@@ -1577,6 +1577,11 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
   bool changed = false;
   gimple stmt = gsi_stmt (*gsi);
   unsigned i;
+  gimple_stmt_iterator gsinext = *gsi;
+  gimple next_stmt;
+
+  gsi_next (&gsinext);
+  next_stmt = gsi_end_p (gsinext) ? NULL : gsi_stmt (gsinext);
 
   /* Fold the main computation performed by the statement.  */
   switch (gimple_code (stmt))
@@ -1665,10 +1670,19 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
     default:;
     }
 
+  /* If stmt folds into nothing and it was the last stmt in a bb,
+     don't call gsi_stmt.  */
+  if (gsi_end_p (*gsi))
+    {
+      gcc_assert (next_stmt == NULL);
+      return changed;
+    }
+
   stmt = gsi_stmt (*gsi);
 
-  /* Fold *& on the lhs.  */
-  if (gimple_has_lhs (stmt))
+  /* Fold *& on the lhs.  Don't do this if stmt folded into nothing,
+     as we'd changing the next stmt.  */
+  if (gimple_has_lhs (stmt) && stmt != next_stmt)
     {
       tree lhs = gimple_get_lhs (stmt);
       if (lhs && REFERENCE_CLASS_P (lhs))
index 1c0a71a6ec345097f2f54befbf55497895577a8e..6d27ed9ff437ce920ae8f7da9e9dd51e4c81d1e0 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/49264
+       * g++.dg/opt/pr49264.C: New test.
+
 2011-06-06  Mikael Pettersson  <mikpe@it.uu.se>
 
        PR tree-optimization/49243
diff --git a/gcc/testsuite/g++.dg/opt/pr49264.C b/gcc/testsuite/g++.dg/opt/pr49264.C
new file mode 100644 (file)
index 0000000..dc23740
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/49264
+// { dg-do compile }
+// { dg-options "-O2" }
+
+struct B { };
+struct A { char a[sizeof (B) + 1]; } a;
+
+static inline void
+foo (const B &b)
+{
+  __builtin_memcpy (&a, &b, sizeof (b));
+}
+
+void
+bar ()
+{
+  B c;
+  foo (c);
+}
index 0e553c8033f97f9f39e87d7b5ab75c2c9a408b30..dc3288b5b37e778b34d61811ac49fbe2cd32423c 100644 (file)
@@ -4055,6 +4055,14 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
                  if (fold_stmt (&gsi))
                    {
                      gimple new_stmt;
+                     /* If a builtin at the end of a bb folded into nothing,
+                        the following loop won't work.  */
+                     if (gsi_end_p (gsi))
+                       {
+                         cgraph_update_edges_for_call_stmt (old_stmt,
+                                                            old_decl, NULL);
+                         break;
+                       }
                      if (gsi_end_p (i2))
                        i2 = gsi_start_bb (BASIC_BLOCK (first));
                      else