re PR middle-end/71387 (ICE in emit_move_insn, at expr.c:3418 with -Og)
authorJakub Jelinek <jakub@gcc.gnu.org>
Fri, 3 Jun 2016 08:03:11 +0000 (10:03 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 3 Jun 2016 08:03:11 +0000 (10:03 +0200)
PR middle-end/71387
* cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): If redirecting
to noreturn e->callee->decl that has void return type and void
arguments, adjust gimple_call_fntype and remove lhs even if it had
previously addressable type.

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

From-SVN: r237053

gcc/ChangeLog
gcc/cgraph.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr71387.C [new file with mode: 0644]

index 2c6f6b1..c2eeb90 100644 (file)
@@ -1,8 +1,16 @@
+2016-06-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/71387
+       * cgraph.c (cgraph_edge::redirect_call_stmt_to_callee): If redirecting
+       to noreturn e->callee->decl that has void return type and void
+       arguments, adjust gimple_call_fntype and remove lhs even if it had
+       previously addressable type.
+
 2016-06-02  Jeff Law  <law@redhat.com>
 
        PR tree-optimization/71328
        * tree-ssa-threadupdate.c (duplicate_thread_path): Fix off-by-one
-       error when checking for a jump back onto the copied path.  */
+       error when checking for a jump back onto the copied path.
 
 2016-06-02  David Malcolm  <dmalcolm@redhat.com>
 
index 08bf9bf..e256dd0 100644 (file)
@@ -1512,8 +1512,20 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
       update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt);
     }
 
+  /* If changing the call to __cxa_pure_virtual or similar noreturn function,
+     adjust gimple_call_fntype too.  */
+  if (gimple_call_noreturn_p (new_stmt)
+      && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (e->callee->decl)))
+      && TYPE_ARG_TYPES (TREE_TYPE (e->callee->decl))
+      && (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (e->callee->decl)))
+         == void_type_node))
+    gimple_call_set_fntype (new_stmt, TREE_TYPE (e->callee->decl));
+
   /* If the call becomes noreturn, remove the LHS if possible.  */
-  if (gimple_call_noreturn_p (new_stmt) && should_remove_lhs_p (lhs))
+  if (lhs
+      && gimple_call_noreturn_p (new_stmt)
+      && (VOID_TYPE_P (TREE_TYPE (gimple_call_fntype (new_stmt)))
+         || should_remove_lhs_p (lhs)))
     {
       if (TREE_CODE (lhs) == SSA_NAME)
        {
index 263d91b..c6d6392 100644 (file)
@@ -1,3 +1,8 @@
+2016-06-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/71387
+       * g++.dg/opt/pr71387.C: New test.
+
 2016-06-02  Jeff Law  <law@redhat.com>
 
        PR tree-optimization/71328
diff --git a/gcc/testsuite/g++.dg/opt/pr71387.C b/gcc/testsuite/g++.dg/opt/pr71387.C
new file mode 100644 (file)
index 0000000..56f4a4d
--- /dev/null
@@ -0,0 +1,52 @@
+// PR middle-end/71387
+// { dg-do compile }
+// { dg-options "-Og" }
+
+struct A
+{
+  A ();
+  inline A (const A &);
+};
+
+struct B
+{
+  explicit B (unsigned long) : b(0), c(1) {}
+  A a;
+  unsigned long b;
+  int c;
+};
+
+struct C {};
+
+struct D
+{
+  explicit D (const C *) {}
+};
+
+struct E : public D
+{
+  E (const C *x) : D(x) {}
+  virtual A foo () const = 0;
+  virtual A bar () const = 0;
+};
+
+struct F : public B
+{
+  inline void baz ();
+  F (const E *);
+  const E *f;
+};
+
+inline void
+F::baz ()
+{
+  if (b == 0)
+    a = f->bar ();
+  else
+    a = f->foo ();
+}
+
+F::F (const E *) : B(4)
+{
+  baz ();
+}