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, 3:10 p.m.
Message ID <20110707151014.GQ2687@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/103681/
State New
Headers show

Comments

Jakub Jelinek - July 7, 2011, 3:10 p.m.
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  <jakub@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.
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
@@ -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;
+}
Joseph S. Myers - July 7, 2011, 3:14 p.m.
On Thu, 7 Jul 2011, Jakub Jelinek wrote:

> 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).

This C patch is also OK.

Patch

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