summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/c-convert.c26
-rw-r--r--gcc/c-typeck.c4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr47150.c11
5 files changed, 53 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 33945a3b518..19b40807052 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2011-01-06 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.
+
2011-01-06 Ira Rosen <irar@il.ibm.com>
PR tree-optimization/47139
diff --git a/gcc/c-convert.c b/gcc/c-convert.c
index f67aecf64ba..f4583c549c9 100644
--- a/gcc/c-convert.c
+++ b/gcc/c-convert.c
@@ -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;
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 149235a8e77..689423ea028 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -5274,10 +5274,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
{
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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 564be0f86a6..3c634409ce2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/47150
+ * gcc.c-torture/compile/pr47150.c: New test.
+
2011-01-06 Ira Rosen <irar@il.ibm.com>
PR tree-optimization/47139
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr47150.c b/gcc/testsuite/gcc.c-torture/compile/pr47150.c
new file mode 100644
index 00000000000..559ddd70fdf
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr47150.c
@@ -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);
+}