diff mbox

Fix cgraph edge redirection with non-POD lhs (PR middle-end/71387)

Message ID 20160602191732.GO28550@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek June 2, 2016, 7:17 p.m. UTC
Hi!

Apparently my r236430 change (trunk) and r236431 (6.x) broke the following
testcase.  In the later similar change to gimple-fold.c in r236506
I've added code to tweak gimple_call_fntype if we have newly one of the
void something (void) __attribute__((noreturn)) functions like
__builtin_unreachable or __cxa_pure_virtual, and drop the lhs even if it
has been before non-POD, but the new fntype has void return type,
but apparently we need to do the same in cgraph.c as well.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2?

2016-06-02  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.

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


	Jakub

Comments

Richard Biener June 3, 2016, 7:34 a.m. UTC | #1
On Thu, 2 Jun 2016, Jakub Jelinek wrote:

> Hi!
> 
> Apparently my r236430 change (trunk) and r236431 (6.x) broke the following
> testcase.  In the later similar change to gimple-fold.c in r236506
> I've added code to tweak gimple_call_fntype if we have newly one of the
> void something (void) __attribute__((noreturn)) functions like
> __builtin_unreachable or __cxa_pure_virtual, and drop the lhs even if it
> has been before non-POD, but the new fntype has void return type,
> but apparently we need to do the same in cgraph.c as well.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/6.2?

Ok.

Thanks,
Richard.

> 2016-06-02  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.
> 
> 	* g++.dg/opt/pr71387.C: New test.
> 
> --- gcc/cgraph.c.jj	2016-05-26 10:37:54.000000000 +0200
> +++ gcc/cgraph.c	2016-06-02 17:17:58.963052785 +0200
> @@ -1512,8 +1512,20 @@ cgraph_edge::redirect_call_stmt_to_calle
>        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)
>  	{
> --- gcc/testsuite/g++.dg/opt/pr71387.C.jj	2016-06-02 17:37:59.868769557 +0200
> +++ gcc/testsuite/g++.dg/opt/pr71387.C	2016-06-02 17:23:51.000000000 +0200
> @@ -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 ();
> +}
> 
> 	Jakub
> 
>
diff mbox

Patch

--- gcc/cgraph.c.jj	2016-05-26 10:37:54.000000000 +0200
+++ gcc/cgraph.c	2016-06-02 17:17:58.963052785 +0200
@@ -1512,8 +1512,20 @@  cgraph_edge::redirect_call_stmt_to_calle
       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)
 	{
--- gcc/testsuite/g++.dg/opt/pr71387.C.jj	2016-06-02 17:37:59.868769557 +0200
+++ gcc/testsuite/g++.dg/opt/pr71387.C	2016-06-02 17:23:51.000000000 +0200
@@ -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 ();
+}