Patchwork Fix complex -> complex C conversions (PR c/47150)

login
register
mail settings
Submitter Jakub Jelinek
Date Jan. 6, 2011, 12:11 a.m.
Message ID <20110106001133.GO16156@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/77648/
State New
Headers show

Comments

Jakub Jelinek - Jan. 6, 2011, 12:11 a.m.
Hi!

As discussed in the PR, convert for COMPLEX_TYPE calls convert_to_complex
(a generic FE function), which calls save_expr.  This is sometimes
undesirable for the C (and ObjC) FEs, where c_save_expr needs to be
called instead to fully fold the argument.  Given that we are in stage4,
this patch just duplicates part of the convert_to_complex in convert
so that it can call c_save_expr.  c_save_expr can't be called always,
as then a couple of tests in the testsuite crash (when the convert is
called from convert_to_assignment, i.e. after it is already fully folded,
save_expr needs to be called instead).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
4.5 after a while?

2011-01-05  Jakub Jelinek  <jakub@redhat.com>

	PR c/47150
	* c-convert.c (convert): When converting a complex expression
	other than COMPLEX_EXPR to a different complex type, ensure
	c_save_expr is called instead of save_expr, unless in_late_binary_op.
	* c-typeck.c (convert_for_assignment): Set in_late_binary_op also
	when converting COMPLEX_TYPE.

	* gcc.c-torture/compile/pr47150.c: New test.


	Jakub
Joseph S. Myers - Jan. 6, 2011, 12:18 a.m.
On Thu, 6 Jan 2011, Jakub Jelinek wrote:

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 4.5 after a while?
> 
> 2011-01-05  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c/47150
> 	* c-convert.c (convert): When converting a complex expression
> 	other than COMPLEX_EXPR to a different complex type, ensure
> 	c_save_expr is called instead of save_expr, unless in_late_binary_op.
> 	* c-typeck.c (convert_for_assignment): Set in_late_binary_op also
> 	when converting COMPLEX_TYPE.
> 
> 	* gcc.c-torture/compile/pr47150.c: New test.

OK.

Patch

--- gcc/c-convert.c.jj	2010-12-02 11:51:32.000000000 +0100
+++ gcc/c-convert.c	2011-01-05 14:09:02.000000000 +0100
@@ -130,6 +130,32 @@  convert (tree type, tree expr)
       goto maybe_fold;
 
     case COMPLEX_TYPE:
+      /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
+	 and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
+	 but for the C FE c_save_expr needs to be called instead.  */
+      if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
+	{
+	  tree subtype = TREE_TYPE (type);
+	  tree elt_type = TREE_TYPE (TREE_TYPE (e));
+
+	  if (TYPE_MAIN_VARIANT (elt_type) != TYPE_MAIN_VARIANT (subtype)
+	      && TREE_CODE (e) != COMPLEX_EXPR)
+	    {
+	      if (in_late_binary_op)
+		e = save_expr (e);
+	      else
+		e = c_save_expr (e);
+	      ret
+		= fold_build2 (COMPLEX_EXPR, type,
+			       convert (subtype,
+					fold_build1 (REALPART_EXPR,
+						     elt_type, e)),
+			       convert (subtype,
+					fold_build1 (IMAGPART_EXPR,
+						     elt_type, e)));
+	      goto maybe_fold;
+	    }
+	}
       ret = convert_to_complex (type, e);
       goto maybe_fold;
 
--- gcc/c-typeck.c.jj	2010-12-14 08:11:39.000000000 +0100
+++ gcc/c-typeck.c	2011-01-05 13:51:54.000000000 +0100
@@ -5272,10 +5272,10 @@  convert_for_assignment (location_t locat
     {
       tree ret;
       bool save = in_late_binary_op;
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
 	in_late_binary_op = true;
       ret = convert_and_check (type, orig_rhs);
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
 	in_late_binary_op = save;
       return ret;
     }
--- gcc/testsuite/gcc.c-torture/compile/pr47150.c.jj	2011-01-04 19:41:17.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr47150.c	2011-01-04 19:40:59.000000000 +0100
@@ -0,0 +1,11 @@ 
+/* PR c/47150 */
+
+float _Complex foo (float, float);
+
+void
+bar ()
+{
+  float w = 2;
+  float _Complex b;
+  b = 0.5 * (foo (0, w) + foo (1, w) / w);
+}