re PR middle-end/77259 (ICE in emit_move_insn since r232167)
authorJakub Jelinek <jakub@redhat.com>
Wed, 17 Aug 2016 13:56:30 +0000 (15:56 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 17 Aug 2016 13:56:30 +0000 (15:56 +0200)
PR middle-end/77259
* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): If
turning a call into __builtin_unreachable-like noreturn call, adjust
gimple_call_set_fntype.
* tree-cfgcleanup.c (fixup_noreturn_call): Remove lhs also if
gimple_call_fntype has void return type.

* g++.dg/ipa/devirt-52.C: New test.

From-SVN: r239537

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/devirt-52.C [new file with mode: 0644]
gcc/tree-cfgcleanup.c
gcc/tree-ssa-pre.c

index 2f19c2585e1b97799f69037aaac415a4321c3efb..9bb3824437b08495e76a2e585f96a6611847aa46 100644 (file)
@@ -1,3 +1,12 @@
+2016-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/77259
+       * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): If
+       turning a call into __builtin_unreachable-like noreturn call, adjust
+       gimple_call_set_fntype.
+       * tree-cfgcleanup.c (fixup_noreturn_call): Remove lhs also if
+       gimple_call_fntype has void return type.
+
 2016-08-17  Chung-Lin Tang  <cltang@codesourcery.com>
 
        * omp-low.c (lower_oacc_reductions): Adjust variable lookup to use
index 0595ceb9d75e54b9036fddab9eef8ba5ff109086..36238859838c3ae4acedb2f9094c136ecbe637a7 100644 (file)
@@ -1,3 +1,8 @@
+2016-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/77259
+       * g++.dg/ipa/devirt-52.C: New test.
+
 2016-08-17  Chung-Lin Tang  <cltang@codesourcery.com>
 
        * c-c++-common/goacc/reduction-6.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-52.C b/gcc/testsuite/g++.dg/ipa/devirt-52.C
new file mode 100644 (file)
index 0000000..be0ab4c
--- /dev/null
@@ -0,0 +1,56 @@
+// PR middle-end/77259
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+template <typename, typename = int> class A;
+template <typename, typename> struct A
+{
+  A (A &&);
+};
+template <typename S, typename T, typename U>
+A<S> operator+(S *, const A<T, U> &);
+template <typename S, typename T, typename U>
+void operator+(const A<T, U> &, S *);
+struct B
+{
+  template <typename V> B (V);
+};
+template <typename V> V foo (B) {}
+class C;
+template <typename> struct D
+{
+  C *operator->() { return d; }
+  C *d;
+};
+struct C
+{
+  virtual A<int> bar ();
+};
+struct E
+{
+  ~E ();
+  virtual A<char> bar (const B &) const;
+};
+template <typename> struct F : E
+{
+};
+template <typename W> struct F<D<W>> : E
+{
+  A<char> bar (const B &) const try
+    {
+      D<W> a = baz ();
+    }
+  catch (int)
+    {
+    }
+  D<W> baz () const
+  {
+    D<C> b = foo<D<C>>(0);
+    "" + b->bar () + "";
+  }
+};
+struct G : F<D<int>>
+{
+  G (int);
+};
+void test () { G (0); }
index 3fe0d3e89941579348c01a94adcc83737d37e447..6052872cb575da1f09eae257f48868d5f0fec103 100644 (file)
@@ -602,9 +602,14 @@ fixup_noreturn_call (gimple *stmt)
   /* If there is an LHS, remove it, but only if its type has fixed size.
      The LHS will need to be recreated during RTL expansion and creating
      temporaries of variable-sized types is not supported.  Also don't
-     do this with TREE_ADDRESSABLE types, as assign_temp will abort.  */
+     do this with TREE_ADDRESSABLE types, as assign_temp will abort.
+     Drop LHS regardless of TREE_ADDRESSABLE, if the function call
+     has been changed into a call that does not return a value, like
+     __builtin_unreachable or __cxa_pure_virtual.  */
   tree lhs = gimple_call_lhs (stmt);
-  if (should_remove_lhs_p (lhs))
+  if (lhs
+      && (should_remove_lhs_p (lhs)
+         || VOID_TYPE_P (TREE_TYPE (gimple_call_fntype (stmt)))))
     {
       gimple_call_set_lhs (stmt, NULL_TREE);
 
index edc3fdf2a790e3ed3679187e5628ef4672fb84b6..5d21c80493a832e389b8ea69bc13b739b91a8639 100644 (file)
@@ -4543,6 +4543,15 @@ eliminate_dom_walker::before_dom_children (basic_block b)
                                       lang_hooks.decl_printable_name (fn, 2));
                    }
                  gimple_call_set_fndecl (call_stmt, fn);
+                 /* If changing the call to __builtin_unreachable
+                    or similar noreturn function, adjust gimple_call_fntype
+                    too.  */
+                 if (gimple_call_noreturn_p (call_stmt)
+                     && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
+                     && TYPE_ARG_TYPES (TREE_TYPE (fn))
+                     && (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fn)))
+                         == void_type_node))
+                   gimple_call_set_fntype (call_stmt, TREE_TYPE (fn));
                  maybe_remove_unused_call_args (cfun, call_stmt);
                  gimple_set_modified (stmt, true);
                }