The following introduces convert_to_complex_nofold, similarly to what
I've done with convert_to_pointer.  Nothing too surprising in the patch,
I suppose.

Now, what remains to do is to also introduce convert_to_real.  Then we
should be done with convert.c as convert_to_vector doesn't fold and
convert_to_fixed isn't used in the C++ FE at all.  More tomorrow.

Bootstrapped/regtested on x86_64-linux, ok for branch?

diff --git gcc/convert.c gcc/convert.c
index ab3eb20..ec6ff37 100644
--- gcc/convert.c
+++ gcc/convert.c
@@ -40,6 +40,9 @@ along with GCC; see the file COPYING3.  If not see
 #define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \
   ((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR)       \
    : build1_loc (LOC, CODE, TYPE, EXPR))
+#define maybe_fold_build2_loc(FOLD_P, LOC, CODE, TYPE, EXPR1, EXPR2) \
+  ((FOLD_P) ? fold_build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2)       \
+   : build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2))
 
 /* Convert EXPR to some pointer or reference type TYPE.
    EXPR must be pointer, reference, integer, enumeral, or literal zero;
@@ -968,11 +971,13 @@ convert_to_integer_nofold (tree type, tree expr)
   return convert_to_integer_1 (type, expr, CONSTANT_CLASS_P (expr));
 }
 
-/* Convert EXPR to the complex type TYPE in the usual ways.  */
+/* Convert EXPR to the complex type TYPE in the usual ways.  If FOLD_P is
+   true, try to fold the expression.  */
 
-tree
-convert_to_complex (tree type, tree expr)
+static tree
+convert_to_complex_1 (tree type, tree expr, bool fold_p)
 {
+  location_t loc = EXPR_LOCATION (expr);
   tree subtype = TREE_TYPE (type);
 
   switch (TREE_CODE (TREE_TYPE (expr)))
@@ -993,43 +998,63 @@ convert_to_complex (tree type, tree expr)
          return expr;
        else if (TREE_CODE (expr) == COMPOUND_EXPR)
          {
-           tree t = convert_to_complex (type, TREE_OPERAND (expr, 1));
+           tree t = convert_to_complex_1 (type, TREE_OPERAND (expr, 1),
+                                          fold_p);
            if (t == TREE_OPERAND (expr, 1))
              return expr;
            return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR,
                               TREE_TYPE (t), TREE_OPERAND (expr, 0), t);
-         }    
+         }
        else if (TREE_CODE (expr) == COMPLEX_EXPR)
-         return fold_build2 (COMPLEX_EXPR, type,
-                             convert (subtype, TREE_OPERAND (expr, 0)),
-                             convert (subtype, TREE_OPERAND (expr, 1)));
+         return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type,
+                                       convert (subtype,
+                                                TREE_OPERAND (expr, 0)),
+                                       convert (subtype,
+                                                TREE_OPERAND (expr, 1)));
        else
          {
            expr = save_expr (expr);
-           return
-             fold_build2 (COMPLEX_EXPR, type,
-                          convert (subtype,
-                                   fold_build1 (REALPART_EXPR,
-                                                TREE_TYPE (TREE_TYPE (expr)),
-                                                expr)),
-                          convert (subtype,
-                                   fold_build1 (IMAGPART_EXPR,
-                                                TREE_TYPE (TREE_TYPE (expr)),
-                                                expr)));
+           tree realp = maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR,
+                                               TREE_TYPE (TREE_TYPE (expr)),
+                                               expr);
+           tree imagp = maybe_fold_build1_loc (fold_p, loc, IMAGPART_EXPR,
+                                               TREE_TYPE (TREE_TYPE (expr)),
+                                               expr);
+           return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type,
+                                         convert (subtype, realp),
+                                         convert (subtype, imagp));
          }
       }
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       error ("pointer value used where a complex was expected");
-      return convert_to_complex (type, integer_zero_node);
+      return convert_to_complex_1 (type, integer_zero_node, fold_p);
 
     default:
       error ("aggregate value used where a complex was expected");
-      return convert_to_complex (type, integer_zero_node);
+      return convert_to_complex_1 (type, integer_zero_node, fold_p);
     }
 }
 
+/* A wrapper around convert_to_complex_1 that always folds the
+   expression.  */
+
+tree
+convert_to_complex (tree type, tree expr)
+{
+  return convert_to_complex_1 (type, expr, true);
+}
+
+/* A wrapper around convert_to_complex_1 that only folds the
+   expression if it is CONSTANT_CLASS_P.  */
+
+tree
+convert_to_complex_nofold (tree type, tree expr)
+{
+  return convert_to_complex_1 (type, expr, CONSTANT_CLASS_P (expr));
+}
+
 /* Convert EXPR to the vector type TYPE in the usual ways.  */
 
 tree
diff --git gcc/convert.h gcc/convert.h
index 24fa6bf..6cb439e 100644
--- gcc/convert.h
+++ gcc/convert.h
@@ -27,6 +27,7 @@ extern tree convert_to_pointer_nofold (tree, tree);
 extern tree convert_to_real (tree, tree);
 extern tree convert_to_fixed (tree, tree);
 extern tree convert_to_complex (tree, tree);
+extern tree convert_to_complex_nofold (tree, tree);
 extern tree convert_to_vector (tree, tree);
 
 #endif /* GCC_CONVERT_H */
diff --git gcc/cp/cvt.c gcc/cp/cvt.c
index 04f6b81..1368f15 100644
--- gcc/cp/cvt.c
+++ gcc/cp/cvt.c
@@ -710,7 +710,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       /* For complex data types, we need to perform componentwise
         conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
-       return convert_to_complex (type, e);
+       return convert_to_complex_nofold (type, e);
       else if (VECTOR_TYPE_P (type))
        return convert_to_vector (type, e);
       else if (TREE_CODE (e) == TARGET_EXPR)
@@ -848,7 +848,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       if (code == REAL_TYPE)
        return convert_to_real (type, e);
       else if (code == COMPLEX_TYPE)
-       return convert_to_complex (type, e);
+       return convert_to_complex_nofold (type, e);
     }
 
   /* New C++ semantics:  since assignment is now based on

        Marek

Reply via email to