On Thu, Jul 07, 2011 at 02:55:45PM +0000, Joseph S. Myers wrote:
> On Thu, 7 Jul 2011, Jakub Jelinek wrote:
> > 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.

Indeed, thanks.  Attached is the corresponding C++ patch and simplified
C patch (with c_save_expr calls right in the switch stmt for the cases
that need it instead of another condition before).

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

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

        * g++.dg/torture/pr49644.C: New test.

--- gcc/cp/typeck.c.jj  2011-06-21 16:45:52.000000000 +0200
+++ gcc/cp/typeck.c     2011-07-07 17:00:17.000000000 +0200
@@ -4338,6 +4338,7 @@ cp_build_binary_op (location_t location,
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -4356,6 +4357,7 @@ cp_build_binary_op (location_t location,
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
--- gcc/testsuite/g++.dg/torture/pr49644.C.jj   2011-07-07 17:01:21.000000000 
+0200
+++ gcc/testsuite/g++.dg/torture/pr49644.C      2011-07-07 17:01:27.000000000 
+0200
@@ -0,0 +1,17 @@
+// PR c/49644
+// { dg-do run }
+
+extern "C" void abort ();
+
+int
+main ()
+{
+  _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;
+}
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
@@ -10040,6 +10040,7 @@ build_binary_op (location_t location, en
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = c_save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -10060,6 +10061,7 @@ build_binary_op (location_t location, en
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = c_save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
--- 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 ()
+{
+  _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;
+}

Reply via email to