Hi,

The expression that caused the ICE

        ++(a += 1.0);

The D front-end rewrites and applies implicit type conversions so the
expression gets simplified as

        (int)((double) a += 1.0) += 1

The codegen pass would subsequently generate the following invalid code

        (int)(double) a = (int)((double) a + 1.0) + 1

The LHS expression `(int)(double) a', represented as a FIX_TRUNC_EXPR
being what trips as it is not a valid lvalue for assignment.

While LHS casts are stripped away, convert_expr adds a double cast
because it converts the expression to its original type before
converting it to its target type.  There is no valid reason why this
is done, so it has been removed.

Bootstrapped and regression tested on x86_64-linux-gnu.

Committed to trunk as r274263.

-- 
Iain
---
gcc/d/ChangeLog:

        PR d/90601
        * d-convert.cc (convert_expr): Don't convert an expression to its
        original front-end type before converting to its target type.

gcc/testsuite/ChangeLog:

        PR d/90601
        * gdc.dg/pr90601.d: New test.

---
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index b020eab902f..fd4fc3c692d 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -588,7 +588,6 @@ convert_expr (tree exp, Type *etype, Type *totype)
 	  return compound_expr (exp, build_zero_cst (build_ctype (tbtype)));
 	}
 
-      exp = fold_convert (build_ctype (etype), exp);
       gcc_assert (TREE_CODE (exp) != STRING_CST);
       break;
     }
diff --git a/gcc/testsuite/gdc.dg/pr90601.d b/gcc/testsuite/gdc.dg/pr90601.d
new file mode 100644
index 00000000000..88cdaf8c99d
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr90601.d
@@ -0,0 +1,22 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90601
+// { dg-do compile }
+
+int postincr(int a)
+{
+    return (a += 1.0)++;
+}
+
+int postdecr(int a)
+{
+    return (a -= 1.0)--;
+}
+
+int preincr(int a)
+{
+    return ++(a += 1.0);
+}
+
+int predecr(int a)
+{
+    return --(a -= 1.0);
+}

Reply via email to