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  <ja...@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

Reply via email to