This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix complex {*,/} real or real * complex handling in C FE (PR c/49644)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: "Joseph S. Myers" <joseph at codesourcery dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 7 Jul 2011 14:57:23 +0200
- Subject: [PATCH] Fix complex {*,/} real or real * complex handling in C FE (PR c/49644)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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