This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.

--- 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;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]