diff mbox series

[C++] Optimize void COND_EXPRs during cp_fold (PR c++/81675)

Message ID 20171124213500.GA14653@tucnak
State New
Headers show
Series [C++] Optimize void COND_EXPRs during cp_fold (PR c++/81675) | expand

Commit Message

Jakub Jelinek Nov. 24, 2017, 9:35 p.m. UTC
Hi!

The comment says that trying to fold VOID_TYPE_P COND_EXPRs is not worth
bothering, but as the following testcase shows, that is not the case.
fold_ternary can optimize COND_EXPRs where the condition is constant and
the unused branch doesn't have any labels, and not folding it early means
bogus warnings afterwards.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2017-11-24  Jakub Jelinek  <jakub@redhat.com>

	PR c++/81675
	* cp-gimplify.c (cp_fold) <case COND_EXPR>: Don't return immediately
	for VOID_TYPE_P COND_EXPRs, instead fold the operands and if op0 is
	INTEGER_CST, ensure that both op1 and op2 are non-NULL and fall
	through into normal folding, otherwise just rebuild x if any op
	changed.

	* g++.dg/warn/pr81675.C: New test.


	Jakub

Comments

Nathan Sidwell Nov. 27, 2017, 12:39 p.m. UTC | #1
On 11/24/2017 04:35 PM, Jakub Jelinek wrote:
> Hi!
> 
> The comment says that trying to fold VOID_TYPE_P COND_EXPRs is not worth
> bothering, but as the following testcase shows, that is not the case.
> fold_ternary can optimize COND_EXPRs where the condition is constant and
> the unused branch doesn't have any labels, and not folding it early means
> bogus warnings afterwards.
> 
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?

ok, thanks

nathan
diff mbox series

Patch

--- gcc/cp/cp-gimplify.c.jj	2017-11-21 20:23:01.000000000 +0100
+++ gcc/cp/cp-gimplify.c	2017-11-24 11:09:51.879647584 +0100
@@ -2299,13 +2299,6 @@  cp_fold (tree x)
 
     case VEC_COND_EXPR:
     case COND_EXPR:
-
-      /* Don't bother folding a void condition, since it can't produce a
-	 constant value.  Also, some statement-level uses of COND_EXPR leave
-	 one of the branches NULL, so folding would crash.  */
-      if (VOID_TYPE_P (TREE_TYPE (x)))
-	return x;
-
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_rvalue (TREE_OPERAND (x, 0));
       op1 = cp_fold (TREE_OPERAND (x, 1));
@@ -2319,6 +2312,29 @@  cp_fold (tree x)
 	  if (!VOID_TYPE_P (TREE_TYPE (op2)))
 	    op2 = cp_truthvalue_conversion (op2);
 	}
+      else if (VOID_TYPE_P (TREE_TYPE (x)))
+	{
+	  if (TREE_CODE (op0) == INTEGER_CST)
+	    {
+	      /* If the condition is constant, fold can fold away
+		 the COND_EXPR.  If some statement-level uses of COND_EXPR
+		 have one of the branches NULL, avoid folding crash.  */
+	      if (!op1)
+		op1 = build_empty_stmt (loc);
+	      if (!op2)
+		op2 = build_empty_stmt (loc);
+	    }
+	  else
+	    {
+	      /* Otherwise, don't bother folding a void condition, since
+		 it can't produce a constant value.  */
+	      if (op0 != TREE_OPERAND (x, 0)
+		  || op1 != TREE_OPERAND (x, 1)
+		  || op2 != TREE_OPERAND (x, 2))
+		x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+	      break;
+	    }
+	}
 
       if (op0 != TREE_OPERAND (x, 0)
 	  || op1 != TREE_OPERAND (x, 1)
--- gcc/testsuite/g++.dg/warn/pr81675.C.jj	2017-11-24 11:12:13.962912829 +0100
+++ gcc/testsuite/g++.dg/warn/pr81675.C	2017-11-24 11:11:56.000000000 +0100
@@ -0,0 +1,15 @@ 
+// PR c++/81675
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+struct S
+{
+  ~S () __attribute__((noreturn));
+  int a;
+};
+
+int
+foo ()
+{
+  false ? 5 : S ().a;
+}