Patchwork Fix complex {*,/} real or real * complex handling in C FE (PR c/49644)

login
register
mail settings
Submitter Jakub Jelinek
Date July 7, 2011, 12:57 p.m.
Message ID <20110707125723.GO2687@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/103656/
State New
Headers show

Comments

Jakub Jelinek - July 7, 2011, 12:57 p.m.
Hi!

For MULT_EXPR and TRUNC_DIV_EXPR, both sides of COMPLEX_EXPR contain
a copy of the non-complex operand, which means its side-effects can be
evaluated twice.  For PLUS_EXPR/MINUS_EXPR they appear just in one of
the operands and thus it works fine as is.

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

2011-07-07  Jakub Jelinek  <jakub@redhat.com>

	PR c/49644
	* c-typeck.c (build_binary_op): For MULT_EXPR and TRUNC_DIV_EXPR with
	one non-complex and one complex argument, call c_save_expr on both
	operands.

	* gcc.c-torture/execute/pr49644.c: New test.


	Jakub
Joseph S. Myers - July 7, 2011, 2:55 p.m.
On Thu, 7 Jul 2011, Jakub Jelinek wrote:

> Hi!
> 
> For MULT_EXPR and TRUNC_DIV_EXPR, both sides of COMPLEX_EXPR contain
> a copy of the non-complex operand, which means its side-effects can be
> evaluated twice.  For PLUS_EXPR/MINUS_EXPR they appear just in one of
> the operands and thus it works fine as is.
> 
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
> ok for trunk/4.6?

OK, but I think you need a similar patch for the C++ front end as well.

Patch

--- gcc/c-typeck.c.jj	2011-05-31 08:03:10.000000000 +0200
+++ gcc/c-typeck.c	2011-07-07 11:47:31.000000000 +0200
@@ -10032,6 +10032,8 @@  build_binary_op (location_t location, en
 	  if (first_complex)
 	    {
 	      op0 = c_save_expr (op0);
+	      if (code == MULT_EXPR || code == TRUNC_DIV_EXPR)
+		op1 = c_save_expr (op1);
 	      real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
 				     op0, 1);
 	      imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
@@ -10052,6 +10054,8 @@  build_binary_op (location_t location, en
 	    }
 	  else
 	    {
+	      if (code == MULT_EXPR)
+		op0 = c_save_expr (op0);
 	      op1 = c_save_expr (op1);
 	      real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
 				     op1, 1);
--- gcc/testsuite/gcc.c-torture/execute/pr49644.c.jj	2011-07-07 11:48:34.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr49644.c	2011-07-07 11:35:52.000000000 +0200
@@ -0,0 +1,16 @@ 
+/* PR c/49644 */
+
+extern void abort (void);
+
+int
+main (void)
+{
+  _Complex double a[12], *c = a, s = 3.0 + 1.0i;
+  double b[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, *d = b;
+  int i;
+  for (i = 0; i < 6; i++)
+    *c++ = *d++ * s;
+  if (c != a + 6 || d != b + 6)
+    abort ();
+  return 0;
+}